From c758a8ad27aa21946082b69085ee852570f0d67c Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 17 Oct 2023 01:22:47 -0700 Subject: [PATCH 01/88] Try to correctly interpolate chase camera viewpoint as angle changes --- src/r_fps.c | 10 ++++++---- src/r_fps.h | 1 + src/r_main.cpp | 11 +++++++++-- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/r_fps.c b/src/r_fps.c index 1418b2a22..61c3eb192 100644 --- a/src/r_fps.c +++ b/src/r_fps.c @@ -140,10 +140,6 @@ void R_InterpolateView(fixed_t frac) prevview = newview; } - viewx = R_LerpFixed(prevview->x, newview->x, frac); - viewy = R_LerpFixed(prevview->y, newview->y, frac); - viewz = R_LerpFixed(prevview->z, newview->z, frac); - viewangle = R_LerpAngle(prevview->angle, newview->angle, frac); aimingangle = R_LerpAngle(prevview->aim, newview->aim, frac); viewroll = R_LerpAngle(prevview->roll, newview->roll, frac); @@ -151,6 +147,12 @@ void R_InterpolateView(fixed_t frac) viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT); viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT); + fixed_t zoom = R_LerpFixed(prevview->zoom, newview->zoom, frac); + + viewx = R_LerpFixed(prevview->x, newview->x, frac) - FixedMul(viewcos, zoom); + viewy = R_LerpFixed(prevview->y, newview->y, frac) - FixedMul(viewsin, zoom); + viewz = R_LerpFixed(prevview->z, newview->z, frac); + viewplayer = newview->player; viewsector = R_PointInSubsector(viewx, viewy)->sector; diff --git a/src/r_fps.h b/src/r_fps.h index 969c427fa..f2df84cd9 100644 --- a/src/r_fps.h +++ b/src/r_fps.h @@ -48,6 +48,7 @@ struct viewvars_t { fixed_t x; fixed_t y; fixed_t z; + fixed_t zoom; boolean sky; sector_t *sector; player_t *player; diff --git a/src/r_main.cpp b/src/r_main.cpp index 7277c2ace..e05c88fe3 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -1244,6 +1244,7 @@ void R_SetupFrame(int s) newview->x = r_viewmobj->x; newview->y = r_viewmobj->y; newview->z = r_viewmobj->z; + newview->zoom = 0; R_SetupCommonFrame(player, r_viewmobj->subsector); } @@ -1252,9 +1253,13 @@ void R_SetupFrame(int s) { r_viewmobj = NULL; - newview->x = thiscam->x; - newview->y = thiscam->y; + fixed_t x = player->mo ? player->mo->x : thiscam->x; + fixed_t y = player->mo ? player->mo->y : thiscam->y; + + newview->x = x; + newview->y = y; newview->z = thiscam->z + (thiscam->height>>1); + newview->zoom = FixedHypot(thiscam->x - x, thiscam->y - y); R_SetupCommonFrame(player, thiscam->subsector); } @@ -1267,6 +1272,7 @@ void R_SetupFrame(int s) newview->x = r_viewmobj->x; newview->y = r_viewmobj->y; newview->z = player->viewz; + newview->zoom = 0; R_SetupCommonFrame(player, r_viewmobj->subsector); } @@ -1297,6 +1303,7 @@ void R_SkyboxFrame(int s) newview->x = r_viewmobj->x; newview->y = r_viewmobj->y; newview->z = r_viewmobj->z; // 26/04/17: use actual Z position instead of spawnpoint angle! + newview->zoom = 0; if (mapheaderinfo[gamemap-1]) { From 0e57da56b0f0752cebbaff8ad3139ca8cee337c8 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 15 Oct 2023 23:33:43 -0700 Subject: [PATCH 02/88] Loop camera It zooms out, pans to the side and toward the player. Loop Center thing: - arg2: zoom-out speed in tics (zooms out when entering the loop) - arg3: zoom-in speed in tics (zooms in when exiting the loop) - arg4: zoom-out distance in fracunits (multiply by 65536) - arg5: angle to pan to the side of the loop in degrees fracunits (multiply by 65536) - This will be flipped depending on where the camera was facing before entering the loop. - arg6: panning speed in degrees fracunits (multiply by 65536) - arg7: panning acceleration in tics (camera gradually pans to side of loop) - arg8: panning deceleration in tics (camera gradually pans back to normal) --- src/d_player.h | 10 +++++++ src/objects/loops.cpp | 12 +++++++++ src/p_loop.c | 1 + src/p_saveg.c | 22 ++++++++++++++++ src/p_user.c | 61 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 106 insertions(+) diff --git a/src/d_player.h b/src/d_player.h index 1b9744efb..fff4eab9c 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -465,6 +465,15 @@ typedef enum BOT_ITEM_PR__MAX } botItemPriority_e; +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; @@ -474,6 +483,7 @@ typedef struct { vector2_t origin_shift; vector2_t shift; boolean flip; + sonicloopcamvars_t camera; } sonicloopvars_t; // player_t struct for power-ups diff --git a/src/objects/loops.cpp b/src/objects/loops.cpp index c54103f9d..9d2262848 100644 --- a/src/objects/loops.cpp +++ b/src/objects/loops.cpp @@ -295,6 +295,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; @@ -352,6 +353,17 @@ Obj_LoopEndpointCollide s->flip = center_has_flip(center); + cam->enter_tic = leveltime; + cam->exit_tic = INFTICS; + + cam->zoom_out_speed = center->thing_args[2]; + cam->zoom_in_speed = center->thing_args[3]; + cam->dist = center->thing_args[4] * FRACUNIT; + cam->pan = FixedAngle(center->thing_args[5] * FRACUNIT); + cam->pan_speed = center->thing_args[6] * FRACUNIT; + cam->pan_accel = center->thing_args[7]; + cam->pan_back = center->thing_args[8]; + player->speed = 3 * (player->speed + toucher->momz) / 2; diff --git a/src/p_loop.c b/src/p_loop.c index bc1454a5d..67ba60f02 100644 --- a/src/p_loop.c +++ b/src/p_loop.c @@ -37,6 +37,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 4a8fd3027..097057ef7 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -682,6 +682,17 @@ static void P_NetArchivePlayers(savebuffer_t *save) 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); + // ACS has read access to this, so it has to be net-communicated. // It is the ONLY roundcondition that is sent over the wire and I'd like it to stay that way. WRITEUINT32(save->p, players[i].roundconditions.unlocktriggers); @@ -1208,6 +1219,17 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) 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); + // ACS has read access to this, so it has to be net-communicated. // It is the ONLY roundcondition that is sent over the wire and I'd like it to stay that way. players[i].roundconditions.unlocktriggers = READUINT32(save->p); diff --git a/src/p_user.c b/src/p_user.c index 17f04c76f..070cfcee8 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -3072,6 +3072,10 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall fixed_t scaleDiff; fixed_t cameraScale = mapobjectscale; + 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; @@ -3196,6 +3200,58 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall camdist = FixedMul(cv_cam_dist[num].value, cameraScale); camheight = FixedMul(cv_cam_height[num].value, cameraScale); + 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)); @@ -3878,6 +3934,11 @@ DoABarrelRoll (player_t *player) fixed_t smoothing; + if (player->loop.radius) + { + return; + } + if (player->respawn.state != RESPAWNST_NONE) { player->tilt = 0; From 44245a18d0405e829983c844579a0cde15ff0760 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 17 Oct 2023 20:19:05 -0700 Subject: [PATCH 03/88] Default loop camera settings if camera distance is not set --- src/objects/loops.cpp | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/objects/loops.cpp b/src/objects/loops.cpp index 9d2262848..930fc6cd3 100644 --- a/src/objects/loops.cpp +++ b/src/objects/loops.cpp @@ -356,13 +356,26 @@ Obj_LoopEndpointCollide cam->enter_tic = leveltime; cam->exit_tic = INFTICS; - cam->zoom_out_speed = center->thing_args[2]; - cam->zoom_in_speed = center->thing_args[3]; - cam->dist = center->thing_args[4] * FRACUNIT; - cam->pan = FixedAngle(center->thing_args[5] * FRACUNIT); - cam->pan_speed = center->thing_args[6] * FRACUNIT; - cam->pan_accel = center->thing_args[7]; - cam->pan_back = center->thing_args[8]; + if (center->thing_args[4]) // is camera distance set? + { + cam->zoom_out_speed = center->thing_args[2]; + cam->zoom_in_speed = center->thing_args[3]; + cam->dist = center->thing_args[4] * FRACUNIT; + cam->pan = FixedAngle(center->thing_args[5] * FRACUNIT); + cam->pan_speed = center->thing_args[6] * FRACUNIT; + cam->pan_accel = center->thing_args[7]; + cam->pan_back = center->thing_args[8]; + } + else + { + cam->zoom_out_speed = 20; + cam->zoom_in_speed = 60; + cam->dist = radius; + cam->pan = ANGLE_22h; + cam->pan_speed = 6*FRACUNIT; + cam->pan_accel = 10; + cam->pan_back = 40; + } player->speed = 3 * (player->speed + toucher->momz) / 2; From 7dba0c9aba8164516a52d6e1d2b5f21bb9bcce3d Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Fri, 27 Oct 2023 23:31:08 -0700 Subject: [PATCH 04/88] Don't do gameplay controller vibration after finishing --- src/p_tick.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/p_tick.c b/src/p_tick.c index 1ad1c8dd2..feb14be86 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -708,6 +708,9 @@ static inline void P_DeviceRumbleTick(void) if (player->mo == NULL) continue; + if (player->exiting) + continue; + if ((player->mo->eflags & MFE_DAMAGEHITLAG) && player->mo->hitlag) { low = high = 65536 / 2; From c7299274e1595a37067fffaf82782c198d10422d Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Thu, 2 Nov 2023 22:44:34 -0700 Subject: [PATCH 05/88] Start with 20 rings if using attack start --- src/g_game.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index e65baacd1..dd53e91e5 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2145,7 +2145,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) { rings = 0; } - else if (modeattacking & ATTACKING_SPB) + else if (G_TimeAttackStart()) { rings = 20; } From 4db18b122515219e9e505fd94622894b8f53d9de Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Fri, 3 Nov 2023 22:51:14 -0700 Subject: [PATCH 06/88] Easier ballhog tapfire --- src/d_player.h | 1 + src/k_kart.c | 15 +++++++++++++-- src/lua_playerlib.c | 4 ++++ src/p_saveg.c | 2 ++ 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index cc176671c..460d7e4b0 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -716,6 +716,7 @@ struct player_t UINT8 flamelength; // Flame Shield dash meter, number of segments UINT16 ballhogcharge; // Ballhog charge up -- the higher this value, the more projectiles + boolean ballhogtap; // Ballhog released during charge: used to allow semirapid tapfire UINT16 hyudorotimer; // Duration of the Hyudoro offroad effect itself SINT8 stealingtimer; // if >0 you are stealing, if <0 you are being stolen from diff --git a/src/k_kart.c b/src/k_kart.c index 8f6337a08..0ab773fd7 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -11493,8 +11493,19 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { INT32 ballhogmax = (player->itemamount) * BALLHOGINCREMENT; - if ((cmd->buttons & BT_ATTACK) && (player->pflags & PF_HOLDREADY) - && (player->ballhogcharge < ballhogmax)) + // This construct looks a little goofy, but we're basically just + // trying to prevent rapid taps from restarting a charge, while + // still allowing quick tapfire. + // (The player still has to pace their shots like this, it's not + // semi-auto, but that's probably kind of okay.) + if (player->ballhogcharge && !(cmd->buttons & BT_ATTACK)) + player->ballhogtap = true; + + if (player->ballhogcharge == 0) + player->ballhogtap = false; + + boolean realcharge = (cmd->buttons & BT_ATTACK) && (player->pflags & PF_HOLDREADY) && (player->ballhogcharge < ballhogmax); + if ((realcharge && !player->ballhogtap) || (player->ballhogtap && player->ballhogcharge < BALLHOGINCREMENT)) { player->ballhogcharge++; if (player->ballhogcharge % BALLHOGINCREMENT == 0) diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 6fe1e325d..145c26d4b 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -381,6 +381,8 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->flamelength); else if (fastcmp(field,"ballhogcharge")) lua_pushinteger(L, plr->ballhogcharge); + else if (fastcmp(field,"ballhogtap")) + lua_pushinteger(L, plr->ballhogtap); else if (fastcmp(field,"hyudorotimer")) lua_pushinteger(L, plr->hyudorotimer); else if (fastcmp(field,"stealingtimer")) @@ -863,6 +865,8 @@ static int player_set(lua_State *L) plr->flamelength = luaL_checkinteger(L, 3); else if (fastcmp(field,"ballhogcharge")) plr->ballhogcharge = luaL_checkinteger(L, 3); + else if (fastcmp(field,"ballhogtap")) + plr->ballhogtap = luaL_checkinteger(L, 3); else if (fastcmp(field,"hyudorotimer")) plr->hyudorotimer = luaL_checkinteger(L, 3); else if (fastcmp(field,"stealingtimer")) diff --git a/src/p_saveg.c b/src/p_saveg.c index f6f8880dc..3e34860f8 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -478,6 +478,7 @@ static void P_NetArchivePlayers(savebuffer_t *save) WRITEUINT8(save->p, players[i].flamelength); WRITEUINT16(save->p, players[i].ballhogcharge); + WRITEUINT8(save->p, players[i].ballhogtap); WRITEUINT16(save->p, players[i].hyudorotimer); WRITESINT8(save->p, players[i].stealingtimer); @@ -992,6 +993,7 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) players[i].flamelength = READUINT8(save->p); players[i].ballhogcharge = READUINT16(save->p); + players[i].ballhogtap = READUINT8(save->p); players[i].hyudorotimer = READUINT16(save->p); players[i].stealingtimer = READSINT8(save->p); From c9d72499f1cdb807dff63a33266892e45f904069 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Sat, 4 Nov 2023 22:56:58 -0700 Subject: [PATCH 07/88] Allow half-speed turning for side tricks --- src/k_kart.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 8f6337a08..128f930a4 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -9415,9 +9415,9 @@ INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue) return 0; } - if (player->trickpanel != 0 && player->trickpanel < 4) + if (player->trickpanel == 1 || player->trickpanel == 5) { - // No turning during trick panel unless you did the upwards trick (4) + // Forward trick or rising from trickpanel return 0; } @@ -9513,6 +9513,12 @@ INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue) // Weight has a small effect on turning turnfixed = FixedMul(turnfixed, weightadjust); + // Side trick + if (player->trickpanel == 2 || player->trickpanel == 3) + { + turnfixed /= 2; + } + return (turnfixed / FRACUNIT); } @@ -12025,7 +12031,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } P_InstaThrust(player->mo, player->mo->angle, max(basespeed, speed*3)); - player->trickpanel = 2; + player->trickpanel = 5; } else if (cmd->throwdir < 0) { From 208601e38d8f18850748557482e31e5ff317b650 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Sun, 5 Nov 2023 13:52:23 +0100 Subject: [PATCH 08/88] Cache and reuse removed mobjs when spawning mobjs --- src/d_think.h | 1 + src/p_local.h | 1 + src/p_mobj.c | 17 +++++++++++++++-- src/p_setup.c | 1 + src/p_tick.c | 12 +++++++++++- 5 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/d_think.h b/src/d_think.h index d833f4ca0..29b67718e 100644 --- a/src/d_think.h +++ b/src/d_think.h @@ -55,6 +55,7 @@ struct thinker_t // killough 11/98: count of how many other objects reference // this one using pointers. Used for garbage collection. INT32 references; + boolean cachable; #ifdef PARANOIA INT32 debug_mobjtype; diff --git a/src/p_local.h b/src/p_local.h index fccc0287f..0e0a3fb23 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -77,6 +77,7 @@ typedef enum NUM_THINKERLISTS } thinklistnum_t; /**< Thinker lists. */ extern thinker_t thlist[]; +extern mobj_t *mobjcache; void P_InitThinkers(void); void P_AddThinker(const thinklistnum_t n, thinker_t *thinker); diff --git a/src/p_mobj.c b/src/p_mobj.c index 1ada630c8..f0baa74e1 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -63,6 +63,8 @@ mobj_t *waypointcap = NULL; // general purpose. mobj_t *trackercap = NULL; +mobj_t *mobjcache = NULL; + void P_InitCachedActions(void) { actioncachehead.prev = actioncachehead.next = &actioncachehead; @@ -10951,7 +10953,16 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) type = MT_RAY; } - mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL); + if (mobjcache != NULL) + { + mobj = mobjcache; + mobjcache = mobjcache->hnext; + memset(mobj, 0, sizeof(*mobj)); + } + else + { + mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL); + } // this is officially a mobj, declared as soon as possible. mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker; @@ -11859,7 +11870,9 @@ void P_RemoveMobj(mobj_t *mobj) INT32 prevreferences; if (!mobj->thinker.references) { - Z_Free(mobj); // No refrrences? Can be removed immediately! :D + // no references, dump it directly in the mobj cache + mobj->hnext = mobjcache; + mobjcache = mobj; return; } diff --git a/src/p_setup.c b/src/p_setup.c index 4ba02f340..0bc686292 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -8363,6 +8363,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) Patch_FreeTag(PU_PATCH_LOWPRIORITY); Patch_FreeTag(PU_PATCH_ROTATED); Z_FreeTags(PU_LEVEL, PU_PURGELEVEL - 1); + mobjcache = NULL; R_InitializeLevelInterpolators(); diff --git a/src/p_tick.c b/src/p_tick.c index 1ad1c8dd2..167a1c160 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -310,6 +310,7 @@ void P_AddThinker(const thinklistnum_t n, thinker_t *thinker) thlist[n].prev = thinker; thinker->references = 0; // killough 11/98: init reference counter to 0 + thinker->cachable = n == THINK_MOBJ; #ifdef PARANOIA thinker->debug_mobjtype = MT_NULL; @@ -427,7 +428,16 @@ void P_UnlinkThinker(thinker_t *thinker) I_Assert(thinker->references == 0); (next->prev = thinker->prev)->next = next; - Z_Free(thinker); + if (thinker->cachable) + { + // put cachable thinkers in the mobj cache, so we can avoid allocations + ((mobj_t *)thinker)->hnext = mobjcache; + mobjcache = (mobj_t *)thinker; + } + else + { + Z_Free(thinker); + } } // From 120b567ba2514d67104d5a08a810ea1d833a55c0 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 6 Nov 2023 01:09:06 +0000 Subject: [PATCH 09/88] K_DoPogoSpring: Handle player->trickpanel set directly --- src/k_kart.c | 3 +++ src/k_terrain.c | 2 -- src/objects/dash-rings.c | 2 -- src/p_map.c | 6 ------ 4 files changed, 3 insertions(+), 10 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 088421b2b..af197a578 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -6253,6 +6253,9 @@ void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, UINT8 sound) if (mo->player) { + mo->player->trickpanel = 1; + mo->player->pflags |= PF_TRICKDELAY; + if (mo->player->sneakertimer) { thrust = FixedMul(thrust, 5*FRACUNIT/4); diff --git a/src/k_terrain.c b/src/k_terrain.c index 36edb5261..6c114d343 100644 --- a/src/k_terrain.c +++ b/src/k_terrain.c @@ -485,8 +485,6 @@ void K_ProcessTerrainEffect(mobj_t *mo) fixed_t speed = FixedHypot(mo->momx, mo->momy); fixed_t upwards = 16 * terrain->trickPanel; - player->trickpanel = 1; - player->pflags |= PF_TRICKDELAY; K_DoPogoSpring(mo, upwards, 1); // Reduce speed diff --git a/src/objects/dash-rings.c b/src/objects/dash-rings.c index d40e341bb..0a09d5831 100644 --- a/src/objects/dash-rings.c +++ b/src/objects/dash-rings.c @@ -199,8 +199,6 @@ static void RegularDashRingLaunch(player_t *player, mobj_t *ring) static void RainbowDashRingLaunch(player_t *player, mobj_t *ring) { player->mo->eflags &= ~MFE_SPRUNG; - player->trickpanel = 1; - player->pflags |= PF_TRICKDELAY; K_DoPogoSpring(player->mo, 0, 0); DashRingLaunch(player, ring); } diff --git a/src/p_map.c b/src/p_map.c index 79b9ba59e..c096dab60 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -512,12 +512,6 @@ static void P_DoFanAndGasJet(mobj_t *spring, mobj_t *object) if (spring->thing_args[1]) { - if (object->player) - { - object->player->trickpanel = 1; - object->player->pflags |= PF_TRICKDELAY; - } - K_DoPogoSpring(object, 32< Date: Mon, 6 Nov 2023 01:11:29 +0000 Subject: [PATCH 10/88] Adjust PlayerPointerRemove macros + associated to check validity before removal --- src/d_clisrv.c | 2 +- src/g_game.c | 2 +- src/k_kart.c | 4 ++-- src/p_inter.c | 15 +++++++++++---- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 2bfc47f24..a48bb344d 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2540,7 +2540,7 @@ void CL_ClearPlayer(INT32 playernum) } #define PlayerPointerRemove(field) \ - if (field) \ + if (P_MobjWasRemoved(field) == false) \ { \ P_RemoveMobj(field); \ P_SetTarget(&field, NULL); \ diff --git a/src/g_game.c b/src/g_game.c index b42085fc9..3c796cae4 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2234,7 +2234,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) K_RemoveFollower(&players[player]); #define PlayerPointerRemove(field) \ - if (field) \ + if (P_MobjWasRemoved(field) == false) \ { \ P_RemoveMobj(field); \ P_SetTarget(&field, NULL); \ diff --git a/src/k_kart.c b/src/k_kart.c index af197a578..40298dbaf 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -4063,7 +4063,7 @@ void K_InitStumbleIndicator(player_t *player) return; } - if (player->stumbleIndicator != NULL && P_MobjWasRemoved(player->stumbleIndicator) == false) + if (P_MobjWasRemoved(player->stumbleIndicator) == false) { P_RemoveMobj(player->stumbleIndicator); } @@ -4088,7 +4088,7 @@ void K_InitSliptideZipIndicator(player_t *player) return; } - if (player->stumbleIndicator != NULL && P_MobjWasRemoved(player->sliptideZipIndicator) == false) + if (P_MobjWasRemoved(player->sliptideZipIndicator) == false) { P_RemoveMobj(player->sliptideZipIndicator); } diff --git a/src/p_inter.c b/src/p_inter.c index f3b66694d..447744aaa 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2550,10 +2550,17 @@ static boolean P_KillPlayer(player_t *player, mobj_t *inflictor, mobj_t *source, P_SetPlayerMobjState(player->mo, player->mo->info->deathstate); - if (player->sliptideZipIndicator && !P_MobjWasRemoved(player->sliptideZipIndicator)) - P_RemoveMobj(player->sliptideZipIndicator); - if (player->stumbleIndicator && !P_MobjWasRemoved(player->stumbleIndicator)) - P_RemoveMobj(player->stumbleIndicator); +#define PlayerPointerRemove(field) \ + if (P_MobjWasRemoved(field) == false) \ + { \ + P_RemoveMobj(field); \ + P_SetTarget(&field, NULL); \ + } + + PlayerPointerRemove(player->stumbleIndicator); + PlayerPointerRemove(player->sliptideZipIndicator); + +#undef PlayerPointerRemove if (type == DMG_TIMEOVER) { From 5ffae81b0860f45b67bbeb4084fc515199c2dbb8 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 6 Nov 2023 01:13:13 +0000 Subject: [PATCH 11/88] Trick Indicator first pass The author of this commit doesn't know what it's doing --- src/d_clisrv.c | 1 + src/d_player.h | 1 + src/deh_tables.c | 7 +++ src/g_game.c | 1 + src/info.c | 39 +++++++++++++++ src/info.h | 13 +++++ src/k_kart.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++- src/k_kart.h | 2 + src/p_inter.c | 1 + src/p_mobj.c | 2 +- src/p_saveg.c | 19 ++++++- src/p_user.c | 1 + 12 files changed, 211 insertions(+), 3 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index a48bb344d..abcdb7580 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2551,6 +2551,7 @@ void CL_ClearPlayer(INT32 playernum) PlayerPointerRemove(players[playernum].followmobj); PlayerPointerRemove(players[playernum].stumbleIndicator); PlayerPointerRemove(players[playernum].sliptideZipIndicator); + PlayerPointerRemove(players[playernum].trickIndicator); #undef PlayerPointerRemove diff --git a/src/d_player.h b/src/d_player.h index cc176671c..c132ca4e9 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -893,6 +893,7 @@ struct player_t mobj_t *stumbleIndicator; mobj_t *sliptideZipIndicator; + mobj_t *trickIndicator; mobj_t *whip; mobj_t *hand; mobj_t *flickyAttacker; diff --git a/src/deh_tables.c b/src/deh_tables.c index 3023b70eb..5a7930152 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -3892,6 +3892,12 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_SMOOTHLANDING", + "S_TRICKINDICATOR_OVERLAY", + "S_TRICKINDICATOR_UNDERLAY", + "S_TRICKINDICATOR_OVERLAY_ARROW", + "S_TRICKINDICATOR_UNDERLAY_ARROW", + "S_TRICKINDICATOR_UNDERLAY_ARROW2", + // DEZ Ring Shooter "S_TIREGRABBER", "S_RINGSHOOTER_SIDE", @@ -5649,6 +5655,7 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t "MT_TRIPWIREBOOST", "MT_SMOOTHLANDING", + "MT_TRICKINDICATOR", "MT_TIREGRABBER", "MT_RINGSHOOTER", diff --git a/src/g_game.c b/src/g_game.c index 3c796cae4..3b4ca5125 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2244,6 +2244,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) PlayerPointerRemove(players[player].followmobj); PlayerPointerRemove(players[player].stumbleIndicator); PlayerPointerRemove(players[player].sliptideZipIndicator); + PlayerPointerRemove(players[player].trickIndicator); #undef PlayerPointerRemove diff --git a/src/info.c b/src/info.c index 23c3225ee..3b1ade0e5 100644 --- a/src/info.c +++ b/src/info.c @@ -631,6 +631,12 @@ char sprnames[NUMSPRITES + 1][5] = "TWBT", // Tripwire BLASTER "SMLD", // Smooth landing + // Trick Indicator + "TRK1", + "TRK2", + "TRK3", + "TRK4", + "TIRG", // Tire grabbers "RSHT", // DEZ Ring Shooter @@ -4662,6 +4668,12 @@ state_t states[NUMSTATES] = {SPR_SMLD, FF_FULLBRIGHT|FF_ADD|FF_ANIMATE, -1, {NULL}, 7, 2, S_NULL}, // S_SMOOTHLANDING + {SPR_TRK1, FF_FULLBRIGHT|FF_ANIMATE|FF_PAPERSPRITE|FF_ADD, -1, {NULL}, 3, 3, S_NULL}, // S_TRICKINDICATOR_OVERLAY, + {SPR_TRK2, FF_FULLBRIGHT|FF_ANIMATE|FF_PAPERSPRITE, -1, {NULL}, 3, 3, S_NULL}, // S_TRICKINDICATOR_UNDERLAY, + {SPR_TRK3, FF_FULLBRIGHT|FF_ANIMATE|FF_PAPERSPRITE|FF_ADD, 13, {NULL}, 12, 1, S_INVISIBLE}, // S_TRICKINDICATOR_OVERLAY_ARROW, + {SPR_NULL, 0, 1, {NULL}, 12, 1, S_TRICKINDICATOR_UNDERLAY_ARROW2}, // S_TRICKINDICATOR_UNDERLAY_ARROW, + {SPR_TRK4, FF_FULLBRIGHT|FF_ANIMATE|FF_PAPERSPRITE, 13, {NULL}, 12, 1, S_INVISIBLE}, // S_TRICKINDICATOR_UNDERLAY_ARROW2, + {SPR_TIRG, FF_ANIMATE, -1, {NULL}, 1, 1, S_NULL}, // S_TIREGRABBER {SPR_RSHT, FF_PAPERSPRITE|0, -1, {NULL}, 0, 0, S_NULL}, // S_RINGSHOOTER_SIDE {SPR_RSHT, FF_SEMIBRIGHT|FF_PAPERSPRITE|2, -1, {NULL}, 0, 0, S_NULL}, // S_RINGSHOOTER_NIPPLES @@ -25329,6 +25341,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_TRICKINDICATOR + -1, // doomednum + S_INVISIBLE, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 128*FRACUNIT, // radius + 128*FRACUNIT, // height + -1, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_DONTENCOREMAP, // flags + S_NULL // raisestate + }, + { // MT_TIREGRABBER -1, // doomednum S_TIREGRABBER, // spawnstate diff --git a/src/info.h b/src/info.h index b57082a5f..0686c8262 100644 --- a/src/info.h +++ b/src/info.h @@ -1188,6 +1188,12 @@ typedef enum sprite SPR_TWBT, // Tripwire BLASTER SPR_SMLD, // Smooth landing + // Trick Indicator + SPR_TRK1, + SPR_TRK2, + SPR_TRK3, + SPR_TRK4, + SPR_TIRG, // Tire grabbers SPR_RSHT, // DEZ Ring Shooter @@ -5106,6 +5112,12 @@ typedef enum state S_SMOOTHLANDING, + S_TRICKINDICATOR_OVERLAY, + S_TRICKINDICATOR_UNDERLAY, + S_TRICKINDICATOR_OVERLAY_ARROW, + S_TRICKINDICATOR_UNDERLAY_ARROW, + S_TRICKINDICATOR_UNDERLAY_ARROW2, + // DEZ Ring Shooter S_TIREGRABBER, S_RINGSHOOTER_SIDE, @@ -6902,6 +6914,7 @@ typedef enum mobj_type MT_TRIPWIREBOOST, MT_SMOOTHLANDING, + MT_TRICKINDICATOR, MT_TIREGRABBER, MT_RINGSHOOTER, diff --git a/src/k_kart.c b/src/k_kart.c index 40298dbaf..34d635560 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -4099,6 +4099,44 @@ void K_InitSliptideZipIndicator(player_t *player) P_SetTarget(&new->target, player->mo); } +void K_InitTrickIndicator(player_t *player) +{ + mobj_t *new = NULL; + + if (player == NULL) + { + return; + } + + if (player->mo == NULL || P_MobjWasRemoved(player->mo) == true) + { + return; + } + + if (P_MobjWasRemoved(player->trickIndicator) == false) + { + if (P_MobjWasRemoved(player->trickIndicator->tracer) == false) + { + P_RemoveMobj(player->trickIndicator->tracer); + } + + P_RemoveMobj(player->trickIndicator); + } + + new = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_TRICKINDICATOR); + + P_SetTarget(&player->trickIndicator, new); + P_SetTarget(&new->target, player->mo); + + mobj_t *secondlayer = P_SpawnMobjFromMobj(new, 0, 0, 0, MT_OVERLAY); + + P_SetTarget(&new->tracer, secondlayer); + P_SetTarget(&secondlayer->target, new); + + secondlayer->dispoffset = 1; + secondlayer->flags |= MF_DONTENCOREMAP; +} + void K_UpdateStumbleIndicator(player_t *player) { const angle_t fudge = ANG15; @@ -4282,6 +4320,49 @@ void K_UpdateSliptideZipIndicator(player_t *player) } } +void K_UpdateTrickIndicator(player_t *player) +{ + mobj_t *mobj = NULL; + + if (player == NULL) + { + return; + } + + if (player->mo == NULL || P_MobjWasRemoved(player->mo) == true) + { + return; + } + + if (player->trickIndicator == NULL + || P_MobjWasRemoved(player->trickIndicator) == true + || player->trickIndicator->tracer == NULL + || P_MobjWasRemoved(player->trickIndicator->tracer) == true) + { + K_InitTrickIndicator(player); + return; + } + + mobj = player->trickIndicator; + + const fixed_t onidistance = 200*mapobjectscale; + + P_MoveOrigin( + mobj, + player->mo->x + P_ReturnThrustX(player->mo, player->mo->angle, onidistance), + player->mo->y + P_ReturnThrustY(player->mo, player->mo->angle, onidistance), + player->mo->z + (player->mo->height / 2)); + mobj->angle = player->mo->angle + ANGLE_90; + + if (player->trickpanel == 0) + { + P_SetScale(mobj, mobj->destscale = player->mo->scale); + + P_SetMobjState(mobj, S_INVISIBLE); + P_SetMobjState(mobj->tracer, S_INVISIBLE); + } +} + static boolean K_LastTumbleBounceCondition(player_t *player) { return (player->tumbleBounces > TUMBLEBOUNCES && player->tumbleHeight < 60); @@ -6256,6 +6337,16 @@ void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, UINT8 sound) mo->player->trickpanel = 1; mo->player->pflags |= PF_TRICKDELAY; + if (P_MobjWasRemoved(mo->player->trickIndicator) == false) + { + mo->player->trickIndicator->rollangle = 0; + P_SetMobjState(mo->player->trickIndicator, S_TRICKINDICATOR_UNDERLAY); + if (P_MobjWasRemoved(mo->player->trickIndicator->tracer) == false) + { + P_SetMobjState(mo->player->trickIndicator->tracer, S_TRICKINDICATOR_OVERLAY); + } + } + if (mo->player->sneakertimer) { thrust = FixedMul(thrust, 5*FRACUNIT/4); @@ -8700,8 +8791,8 @@ void K_KartPlayerAfterThink(player_t *player) K_KartResetPlayerColor(player); K_UpdateStumbleIndicator(player); - K_UpdateSliptideZipIndicator(player); + K_UpdateTrickIndicator(player); // Move held objects (Bananas, Orbinaut, etc) K_MoveHeldObjects(player); @@ -11966,6 +12057,11 @@ void K_MoveKartPlayer(player_t *player, boolean onground) K_trickPanelTimingVisual(player, momz); + if (P_MobjWasRemoved(player->trickIndicator) == false) + { + player->trickIndicator->destscale = FixedMul(speedmult + FRACUNIT, mapobjectscale); + } + // streaks: if (momz*P_MobjFlip(player->mo) > 0) // only spawn those while you're going upwards relative to your current gravity { @@ -12031,11 +12127,21 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { P_InstaThrust(player->mo, player->mo->angle + lr, max(basespeed, speed*5/2)); player->trickpanel = 2; + + if (P_MobjWasRemoved(player->trickIndicator) == false) + { + player->trickIndicator->rollangle = ANGLE_270; + } } else { P_InstaThrust(player->mo, player->mo->angle - lr, max(basespeed, speed*5/2)); player->trickpanel = 3; + + if (P_MobjWasRemoved(player->trickIndicator) == false) + { + player->trickIndicator->rollangle = ANGLE_90; + } } } else if (aimingcompare > TRICKTHRESHOLD) // forward/back trick @@ -12049,6 +12155,11 @@ void K_MoveKartPlayer(player_t *player, boolean onground) P_InstaThrust(player->mo, player->mo->angle, max(basespeed, speed*3)); player->trickpanel = 2; + + if (P_MobjWasRemoved(player->trickIndicator) == false) + { + player->trickIndicator->rollangle = 0; + } } else if (cmd->throwdir < 0) { @@ -12068,6 +12179,11 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->mo->momz += P_MobjFlip(player->mo)*48*mapobjectscale; player->trickpanel = 4; + + if (P_MobjWasRemoved(player->trickIndicator) == false) + { + player->trickIndicator->rollangle = ANGLE_180; + } } } #undef TRICKTHRESHOLD @@ -12084,6 +12200,15 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { player->karthud[khud_trickcool] = TICRATE; } + + if (P_MobjWasRemoved(player->trickIndicator) == false) + { + P_SetMobjState(player->trickIndicator, S_TRICKINDICATOR_UNDERLAY_ARROW); + if (P_MobjWasRemoved(player->trickIndicator->tracer) == false) + { + P_SetMobjState(player->trickIndicator->tracer, S_TRICKINDICATOR_OVERLAY_ARROW); + } + } } } } diff --git a/src/k_kart.h b/src/k_kart.h index 7a4424f08..3f6293bba 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -120,8 +120,10 @@ void K_StumblePlayer(player_t *player); boolean K_CheckStumble(player_t *player, angle_t oldPitch, angle_t oldRoll, boolean fromAir); void K_InitStumbleIndicator(player_t *player); void K_InitSliptideZipIndicator(player_t *player); +void K_InitTrickIndicator(player_t *player); void K_UpdateStumbleIndicator(player_t *player); void K_UpdateSliptideZipIndicator(player_t *player); +void K_UpdateTrickIndicator(player_t *player); INT32 K_ExplodePlayer(player_t *player, mobj_t *inflictor, mobj_t *source); void K_DebtStingPlayer(player_t *player, mobj_t *source); void K_GiveBumpersToPlayer(player_t *player, player_t *victim, UINT8 amount); diff --git a/src/p_inter.c b/src/p_inter.c index 447744aaa..18a2f5e7c 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2559,6 +2559,7 @@ static boolean P_KillPlayer(player_t *player, mobj_t *inflictor, mobj_t *source, PlayerPointerRemove(player->stumbleIndicator); PlayerPointerRemove(player->sliptideZipIndicator); + PlayerPointerRemove(player->trickIndicator); #undef PlayerPointerRemove diff --git a/src/p_mobj.c b/src/p_mobj.c index 1ada630c8..168fc86ac 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -12448,8 +12448,8 @@ void P_SpawnPlayer(INT32 playernum) p->griefValue = 0; K_InitStumbleIndicator(p); - K_InitSliptideZipIndicator(p); + K_InitTrickIndicator(p); if (gametyperules & GTR_ITEMARROWS) { diff --git a/src/p_saveg.c b/src/p_saveg.c index a1c3d1f64..865732692 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -65,7 +65,7 @@ savedata_cup_t cupsavedata; #define ARCHIVEBLOCK_RNG 0x7FAAB5BD // Note: This cannot be bigger -// than an UINT16 +// than an UINT16 (for now) typedef enum { AWAYVIEW = 0x0001, @@ -81,6 +81,7 @@ typedef enum HAND = 0x0400, FLICKYATTACKER = 0x0800, FLICKYCONTROLLER = 0x1000, + TRICKINDICATOR = 0x2000, } player_saveflags; static inline void P_ArchivePlayer(savebuffer_t *save) @@ -313,6 +314,9 @@ static void P_NetArchivePlayers(savebuffer_t *save) if (players[i].sliptideZipIndicator) flags |= SLIPTIDEZIP; + if (players[i].trickIndicator) + flags |= TRICKINDICATOR; + if (players[i].whip) flags |= WHIP; @@ -351,6 +355,9 @@ static void P_NetArchivePlayers(savebuffer_t *save) if (flags & SLIPTIDEZIP) WRITEUINT32(save->p, players[i].sliptideZipIndicator->mobjnum); + if (flags & TRICKINDICATOR) + WRITEUINT32(save->p, players[i].trickIndicator->mobjnum); + if (flags & WHIP) WRITEUINT32(save->p, players[i].whip->mobjnum); @@ -864,6 +871,9 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) if (flags & SLIPTIDEZIP) players[i].sliptideZipIndicator = (mobj_t *)(size_t)READUINT32(save->p); + if (flags & TRICKINDICATOR) + players[i].trickIndicator = (mobj_t *)(size_t)READUINT32(save->p); + if (flags & WHIP) players[i].whip = (mobj_t *)(size_t)READUINT32(save->p); @@ -5595,6 +5605,13 @@ static void P_RelinkPointers(void) if (!P_SetTarget(&players[i].sliptideZipIndicator, P_FindNewPosition(temp))) CONS_Debug(DBG_GAMELOGIC, "sliptideZipIndicator not found on player %d\n", i); } + if (players[i].trickIndicator) + { + temp = (UINT32)(size_t)players[i].trickIndicator; + players[i].trickIndicator = NULL; + if (!P_SetTarget(&players[i].trickIndicator, P_FindNewPosition(temp))) + CONS_Debug(DBG_GAMELOGIC, "trickIndicator not found on player %d\n", i); + } if (players[i].whip) { temp = (UINT32)(size_t)players[i].whip; diff --git a/src/p_user.c b/src/p_user.c index 419e78ab6..3d2aa4b37 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -3996,6 +3996,7 @@ void P_PlayerThink(player_t *player) PlayerPointerErase(player->followmobj); PlayerPointerErase(player->stumbleIndicator); PlayerPointerErase(player->sliptideZipIndicator); + PlayerPointerErase(player->trickIndicator); PlayerPointerErase(player->whip); PlayerPointerErase(player->hand); PlayerPointerErase(player->ringShooter); From bbe247733185defcf817e135edac27c2967ae0fc Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 6 Nov 2023 14:47:54 +0000 Subject: [PATCH 12/88] Obj_RainbowDashRingSpawn: Fix copypaste error that could have resulted in out-of-bounds access --- src/objects/dash-rings.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objects/dash-rings.c b/src/objects/dash-rings.c index 0a09d5831..ba9fed39e 100644 --- a/src/objects/dash-rings.c +++ b/src/objects/dash-rings.c @@ -66,7 +66,7 @@ void Obj_RainbowDashRingSpawn(mobj_t *mobj) void Obj_DashRingSetup(mobj_t *mobj, mapthing_t *mthing) { - static const UINT8 numColors = sizeof(rainbow_colors) / sizeof(skincolornum_t); + static const UINT8 numColors = sizeof(ring_colors) / sizeof(skincolornum_t); const UINT8 additionalThrust = mthing->thing_args[1]; statenum_t ringState, overlayState; From b051ff4741f8ce5f3244fc5890ca8f27cb7ade5b Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 6 Nov 2023 14:48:23 +0000 Subject: [PATCH 13/88] P_SpawnGhostMobj: Set old_scale too --- src/p_user.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/p_user.c b/src/p_user.c index 3d2aa4b37..34ffc414c 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1163,6 +1163,7 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj) ghost->old_angle = (mobj->player ? mobj->player->old_drawangle2 : mobj->old_angle2); ghost->old_pitch = mobj->old_pitch2; ghost->old_roll = mobj->old_roll2; + ghost->old_scale = mobj->old_scale2; K_ReduceVFX(ghost, mobj->player); From e06d961574bbe4a26034fc0b3fe7ddd8ee2dcbd4 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 6 Nov 2023 14:54:46 +0000 Subject: [PATCH 14/88] Further refinement to Trick Indicator behaviour - Set colour in K_DoPogoSpring based on relevant vertical momentum - Similar but seperate colour list to Dash Rings - Improve interp state handling when starting a Trick - Don't set to S_INVISIBLE every non-tricking frame - Don't follow the player's movement during the very end of a swipe animation - Add a catholocism blast of the outer D-Pad ring while tricking --- src/k_kart.c | 74 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 60 insertions(+), 14 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 34d635560..9095af29a 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -4125,11 +4125,13 @@ void K_InitTrickIndicator(player_t *player) new = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_TRICKINDICATOR); + P_SetMobjState(new, S_INVISIBLE); P_SetTarget(&player->trickIndicator, new); P_SetTarget(&new->target, player->mo); mobj_t *secondlayer = P_SpawnMobjFromMobj(new, 0, 0, 0, MT_OVERLAY); + P_SetMobjState(secondlayer, S_INVISIBLE); P_SetTarget(&new->tracer, secondlayer); P_SetTarget(&secondlayer->target, new); @@ -4345,6 +4347,11 @@ void K_UpdateTrickIndicator(player_t *player) mobj = player->trickIndicator; + statenum_t test = (mobj->state-states); + + if (test >= S_TRICKINDICATOR_UNDERLAY_ARROW) + return; + const fixed_t onidistance = 200*mapobjectscale; P_MoveOrigin( @@ -4354,10 +4361,9 @@ void K_UpdateTrickIndicator(player_t *player) player->mo->z + (player->mo->height / 2)); mobj->angle = player->mo->angle + ANGLE_90; - if (player->trickpanel == 0) + if (player->trickpanel == 0 + && test != S_INVISIBLE) { - P_SetScale(mobj, mobj->destscale = player->mo->scale); - P_SetMobjState(mobj, S_INVISIBLE); P_SetMobjState(mobj->tracer, S_INVISIBLE); } @@ -6322,16 +6328,14 @@ void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, UINT8 sound) mo->eflags |= MFE_SPRUNG; - if (vertispeed == 0) + if (vertispeed <= 0) { - thrust = P_AproxDistance(mo->momx, mo->momy) * P_MobjFlip(mo); - thrust = FixedMul(thrust, FINESINE(ANGLE_22h >> ANGLETOFINESHIFT)); - } - else - { - thrust = vertispeed * P_MobjFlip(mo); + vertispeed = P_AproxDistance(mo->momx, mo->momy); + vertispeed = FixedMul(vertispeed, FINESINE(ANGLE_22h >> ANGLETOFINESHIFT)); } + thrust = vertispeed * P_MobjFlip(mo); + if (mo->player) { mo->player->trickpanel = 1; @@ -6339,11 +6343,46 @@ void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, UINT8 sound) if (P_MobjWasRemoved(mo->player->trickIndicator) == false) { - mo->player->trickIndicator->rollangle = 0; - P_SetMobjState(mo->player->trickIndicator, S_TRICKINDICATOR_UNDERLAY); - if (P_MobjWasRemoved(mo->player->trickIndicator->tracer) == false) + mobj_t *trickIndicator = mo->player->trickIndicator; + + P_SetScale(trickIndicator, + trickIndicator->destscale + = trickIndicator->old_scale + = trickIndicator->old_scale2 + = mo->scale/4); + trickIndicator->rollangle = 0; + + static const skincolornum_t trick_colors[] = { + SKINCOLOR_GREY, // trickPanel == 1 + SKINCOLOR_TAN, + SKINCOLOR_YELLOW, // trickPanel == 2 + SKINCOLOR_TANGERINE, + SKINCOLOR_KETCHUP, // trickPanel == 3 + SKINCOLOR_MOONSET, + SKINCOLOR_ULTRAMARINE, // trickPanel == 4 + }; + static const UINT8 numColors = sizeof(trick_colors) / sizeof(skincolornum_t); + + const fixed_t step = 8*FRACUNIT; + fixed_t trickcol = ((vertispeed - (step/2)) / step) - 1; + if (trickcol < 0) + trickcol = 0; + trickIndicator->color = trick_colors[min(trickcol, numColors - 1)]; + + P_SetMobjState(trickIndicator, S_TRICKINDICATOR_UNDERLAY); + + if (P_MobjWasRemoved(trickIndicator->tracer) == false) { - P_SetMobjState(mo->player->trickIndicator->tracer, S_TRICKINDICATOR_OVERLAY); + P_SetScale(trickIndicator->tracer, + trickIndicator->tracer->destscale + = trickIndicator->tracer->old_scale + = trickIndicator->tracer->old_scale2 + = trickIndicator->destscale); + trickIndicator->tracer->rollangle = 0; + + trickIndicator->tracer->color = mo->player->trickIndicator->color; + + P_SetMobjState(trickIndicator->tracer, S_TRICKINDICATOR_OVERLAY); } } @@ -12203,6 +12242,13 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (P_MobjWasRemoved(player->trickIndicator) == false) { + mobj_t *catholocismBlast = P_SpawnGhostMobj(player->trickIndicator); + catholocismBlast->height = 1; + catholocismBlast->destscale *= 2; + catholocismBlast->fuse = 12; + catholocismBlast->rollangle = 0; + catholocismBlast->dispoffset = -1; + P_SetMobjState(player->trickIndicator, S_TRICKINDICATOR_UNDERLAY_ARROW); if (P_MobjWasRemoved(player->trickIndicator->tracer) == false) { From 2ecfe2f50fd37f232c153be920600d32841fcaa2 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 6 Nov 2023 14:55:28 +0000 Subject: [PATCH 15/88] K_DoPogoSpring: Don't set Trick state if Player is in pain --- src/k_kart.c | 83 +++++++++++++++++++++++++++------------------------- 1 file changed, 43 insertions(+), 40 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 9095af29a..e4ca70aff 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -6338,51 +6338,54 @@ void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, UINT8 sound) if (mo->player) { - mo->player->trickpanel = 1; - mo->player->pflags |= PF_TRICKDELAY; - - if (P_MobjWasRemoved(mo->player->trickIndicator) == false) + if (!P_PlayerInPain(mo->player)) { - mobj_t *trickIndicator = mo->player->trickIndicator; + mo->player->trickpanel = 1; + mo->player->pflags |= PF_TRICKDELAY; - P_SetScale(trickIndicator, - trickIndicator->destscale - = trickIndicator->old_scale - = trickIndicator->old_scale2 - = mo->scale/4); - trickIndicator->rollangle = 0; - - static const skincolornum_t trick_colors[] = { - SKINCOLOR_GREY, // trickPanel == 1 - SKINCOLOR_TAN, - SKINCOLOR_YELLOW, // trickPanel == 2 - SKINCOLOR_TANGERINE, - SKINCOLOR_KETCHUP, // trickPanel == 3 - SKINCOLOR_MOONSET, - SKINCOLOR_ULTRAMARINE, // trickPanel == 4 - }; - static const UINT8 numColors = sizeof(trick_colors) / sizeof(skincolornum_t); - - const fixed_t step = 8*FRACUNIT; - fixed_t trickcol = ((vertispeed - (step/2)) / step) - 1; - if (trickcol < 0) - trickcol = 0; - trickIndicator->color = trick_colors[min(trickcol, numColors - 1)]; - - P_SetMobjState(trickIndicator, S_TRICKINDICATOR_UNDERLAY); - - if (P_MobjWasRemoved(trickIndicator->tracer) == false) + if (P_MobjWasRemoved(mo->player->trickIndicator) == false) { - P_SetScale(trickIndicator->tracer, - trickIndicator->tracer->destscale - = trickIndicator->tracer->old_scale - = trickIndicator->tracer->old_scale2 - = trickIndicator->destscale); - trickIndicator->tracer->rollangle = 0; + mobj_t *trickIndicator = mo->player->trickIndicator; - trickIndicator->tracer->color = mo->player->trickIndicator->color; + P_SetScale(trickIndicator, + trickIndicator->destscale + = trickIndicator->old_scale + = trickIndicator->old_scale2 + = mo->scale/4); + trickIndicator->rollangle = 0; - P_SetMobjState(trickIndicator->tracer, S_TRICKINDICATOR_OVERLAY); + static const skincolornum_t trick_colors[] = { + SKINCOLOR_GREY, // trickPanel == 1 + SKINCOLOR_TAN, + SKINCOLOR_YELLOW, // trickPanel == 2 + SKINCOLOR_TANGERINE, + SKINCOLOR_KETCHUP, // trickPanel == 3 + SKINCOLOR_MOONSET, + SKINCOLOR_ULTRAMARINE, // trickPanel == 4 + }; + static const UINT8 numColors = sizeof(trick_colors) / sizeof(skincolornum_t); + + const fixed_t step = 8*FRACUNIT; + fixed_t trickcol = ((vertispeed - (step/2)) / step) - 1; + if (trickcol < 0) + trickcol = 0; + trickIndicator->color = trick_colors[min(trickcol, numColors - 1)]; + + P_SetMobjState(trickIndicator, S_TRICKINDICATOR_UNDERLAY); + + if (P_MobjWasRemoved(trickIndicator->tracer) == false) + { + P_SetScale(trickIndicator->tracer, + trickIndicator->tracer->destscale + = trickIndicator->tracer->old_scale + = trickIndicator->tracer->old_scale2 + = trickIndicator->destscale); + trickIndicator->tracer->rollangle = 0; + + trickIndicator->tracer->color = mo->player->trickIndicator->color; + + P_SetMobjState(trickIndicator->tracer, S_TRICKINDICATOR_OVERLAY); + } } } From 2f62c0ff6b51ce5070c61d3645aeb252bc7e8cc8 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 6 Nov 2023 15:00:38 +0000 Subject: [PATCH 16/88] P_SpawnGhostMobj: Also copy scalespeed --- src/p_user.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/p_user.c b/src/p_user.c index 34ffc414c..b348ad7b9 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1109,6 +1109,7 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj) P_SetTarget(&ghost->target, mobj); P_SetScale(ghost, mobj->scale); + ghost->scalespeed = mobj->scalespeed; ghost->destscale = mobj->scale; if (mobj->eflags & MFE_VERTICALFLIP) From e412b6ddd83e9614abe0dbf27cb34f3a27a2b03c Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 6 Nov 2023 19:12:26 +0000 Subject: [PATCH 17/88] Call K_trickPanelTimingVisual only once per tic, to prevent pie duplication --- src/k_kart.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index e4ca70aff..83d646425 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -12097,8 +12097,6 @@ void K_MoveKartPlayer(player_t *player, boolean onground) fixed_t basespeed = FixedMul(invertscale, K_GetKartSpeed(player, false, false)); // at WORSE, keep your normal speed when tricking. fixed_t speed = FixedMul(invertscale, FixedMul(speedmult, P_AproxDistance(player->mo->momx, player->mo->momy))); - K_trickPanelTimingVisual(player, momz); - if (P_MobjWasRemoved(player->trickIndicator) == false) { player->trickIndicator->destscale = FixedMul(speedmult + FRACUNIT, mapobjectscale); @@ -12148,7 +12146,6 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->pflags &= ~PF_TUMBLESOUND; player->tumbleHeight = 30; // Base tumble bounce height player->trickpanel = 0; - K_trickPanelTimingVisual(player, momz); // fail trick visual P_SetPlayerMobjState(player->mo, S_KART_SPINOUT); if (player->pflags & (PF_ITEMOUT|PF_EGGMANOUT)) { @@ -12236,8 +12233,6 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->mo->hitlag = TRICKLAG; player->mo->eflags &= ~MFE_DAMAGEHITLAG; - K_trickPanelTimingVisual(player, momz); - if (abs(momz) < FRACUNIT*99) // Let's use that as baseline for PERFECT trick. { player->karthud[khud_trickcool] = TICRATE; @@ -12260,6 +12255,8 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } } } + + K_trickPanelTimingVisual(player, momz); } else if (player->trickpanel == 4 && P_IsObjectOnGround(player->mo)) // Upwards trick landed! { From f8a6449033d1d303ba945c73020b8cd93b75fb45 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 6 Nov 2023 19:22:21 +0000 Subject: [PATCH 18/88] Further Trick Indicator refinement - Abstract K_TrickCatholocismBlast into its own function - Spawn one at an askance angle when you fail a trick for any reason - Indicator is slightly closer to the player - Smaller indicator base scale - Indicator becomes more translucent the larger it is - Swipe is at 1.5 scale relative to the indicator --- src/k_kart.c | 44 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 83d646425..4b0238114 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -4322,6 +4322,20 @@ void K_UpdateSliptideZipIndicator(player_t *player) } } +static mobj_t *K_TrickCatholocismBlast(mobj_t *trickIndicator, fixed_t destscale, angle_t rollangle) +{ + // It's my last minute visual effect and I get to choose the ridiculous function name - toast 061123 + + mobj_t *catholocismBlast = P_SpawnGhostMobj(trickIndicator); // HOLY? + catholocismBlast->height = 1; + catholocismBlast->destscale = destscale; + catholocismBlast->fuse = 12; + catholocismBlast->rollangle = rollangle; + catholocismBlast->dispoffset = -1; + + return catholocismBlast; +} + void K_UpdateTrickIndicator(player_t *player) { mobj_t *mobj = NULL; @@ -4352,7 +4366,7 @@ void K_UpdateTrickIndicator(player_t *player) if (test >= S_TRICKINDICATOR_UNDERLAY_ARROW) return; - const fixed_t onidistance = 200*mapobjectscale; + const fixed_t onidistance = 150*mapobjectscale; P_MoveOrigin( mobj, @@ -4364,6 +4378,8 @@ void K_UpdateTrickIndicator(player_t *player) if (player->trickpanel == 0 && test != S_INVISIBLE) { + K_TrickCatholocismBlast(mobj, 1, ANGLE_22h); + P_SetMobjState(mobj, S_INVISIBLE); P_SetMobjState(mobj->tracer, S_INVISIBLE); } @@ -12099,7 +12115,18 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (P_MobjWasRemoved(player->trickIndicator) == false) { - player->trickIndicator->destscale = FixedMul(speedmult + FRACUNIT, mapobjectscale); + const fixed_t indicatormult = 3*(mapobjectscale/5); + player->trickIndicator->destscale = FixedMul(speedmult + FRACUNIT, indicatormult); + + fixed_t trans = ((player->trickIndicator->scale * 9)/indicatormult) - 9; + if (trans < 10) // it's fine if it stays barely visible imo + { + UINT32 renderflags = player->trickIndicator->renderflags & ~RF_TRANSMASK; + if (trans > 0) + renderflags |= (trans << RF_TRANSSHIFT); + + player->trickIndicator->renderflags = renderflags; + } } // streaks: @@ -12240,16 +12267,17 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (P_MobjWasRemoved(player->trickIndicator) == false) { - mobj_t *catholocismBlast = P_SpawnGhostMobj(player->trickIndicator); - catholocismBlast->height = 1; - catholocismBlast->destscale *= 2; - catholocismBlast->fuse = 12; - catholocismBlast->rollangle = 0; - catholocismBlast->dispoffset = -1; + K_TrickCatholocismBlast(player->trickIndicator, player->trickIndicator->scale*10, 0); + + P_InstaScale(player->trickIndicator, 3*mapobjectscale/2); + player->trickIndicator->old_scale = player->trickIndicator->scale; P_SetMobjState(player->trickIndicator, S_TRICKINDICATOR_UNDERLAY_ARROW); if (P_MobjWasRemoved(player->trickIndicator->tracer) == false) { + P_InstaScale(player->trickIndicator->tracer, player->trickIndicator->scale); + player->trickIndicator->tracer->old_scale = player->trickIndicator->tracer->scale; + P_SetMobjState(player->trickIndicator->tracer, S_TRICKINDICATOR_OVERLAY_ARROW); } } From 4ecc378bb6e67a603560dad4aaa331d6e11d9558 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 6 Nov 2023 19:27:24 +0000 Subject: [PATCH 19/88] Make weakest Trick Indicator colour white instead of grey More opaque, due to additive behaviour --- src/k_kart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index 4b0238114..78b7f32e8 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -6371,7 +6371,7 @@ void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, UINT8 sound) trickIndicator->rollangle = 0; static const skincolornum_t trick_colors[] = { - SKINCOLOR_GREY, // trickPanel == 1 + SKINCOLOR_WHITE, // trickPanel == 1 -- was SKINCOLOR_GREY SKINCOLOR_TAN, SKINCOLOR_YELLOW, // trickPanel == 2 SKINCOLOR_TANGERINE, From b417c0655e558de13e486ba18e9ce83a4520ed4e Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 6 Nov 2023 21:44:55 +0000 Subject: [PATCH 20/88] Map command: If you provide `-force` and the level has no associated gametype, safely assume Race as the default instead of requiring a `-gt race` addition --- src/d_netcmd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index b51f1408a..d5384170f 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2422,13 +2422,15 @@ static void Command_Map_f(void) // Let's just guess so we don't have to specify the gametype EVERY time... newgametype = G_GuessGametypeByTOL(mapheaderinfo[newmapnum-1]->typeoflevel); - if (newgametype == -1) + if (!option_force && newgametype == -1) { CONS_Alert(CONS_WARNING, M_GetText("%s (%s) doesn't support any known gametype!\n"), realmapname, G_BuildMapName(newmapnum)); Z_Free(realmapname); Z_Free(mapname); return; } + + newgametype = GT_RACE; // sensible default } } From aa0b626467a10dad85c5ce4eeff549c0bb8485c7 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 6 Nov 2023 21:47:16 +0000 Subject: [PATCH 21/88] Trick catholic swipe needs to have all layers be fully visible, even at the peak of the arc --- src/k_kart.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/k_kart.c b/src/k_kart.c index 78b7f32e8..a88aceb54 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -12269,6 +12269,8 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { K_TrickCatholocismBlast(player->trickIndicator, player->trickIndicator->scale*10, 0); + player->trickIndicator->renderflags &= ~RF_TRANSMASK; + P_InstaScale(player->trickIndicator, 3*mapobjectscale/2); player->trickIndicator->old_scale = player->trickIndicator->scale; From 8885a335e7889a2739afcbe5bb0bb35efd89d3a7 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 6 Nov 2023 21:49:28 +0000 Subject: [PATCH 22/88] MT_MAGICIANBOX: Support gravflip --- src/p_mobj.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/p_mobj.c b/src/p_mobj.c index 168fc86ac..4b606bee0 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8420,6 +8420,12 @@ static boolean P_MobjRegularThink(mobj_t *mobj) { destx += FixedMul(mobj->radius*2, FINECOSINE((mobj->angle+ANGLE_90) >> ANGLETOFINESHIFT)); desty += FixedMul(mobj->radius*2, FINESINE((mobj->angle+ANGLE_90) >> ANGLETOFINESHIFT)); + + mobj->eflags = (mobj->eflags & ~MFE_VERTICALFLIP)|(mobj->target->eflags & MFE_VERTICALFLIP); + mobj->flags2 = (mobj->flags2 & ~MF2_OBJECTFLIP)|(mobj->target->flags2 & MF2_OBJECTFLIP); + + if (mobj->eflags & MFE_VERTICALFLIP) + zoff += mobj->target->height - mobj->height; } else if (mobj->state == &states[S_MAGICIANBOX_TOP]) // top { From 48d93ec9f6d8d71893026ba4bd1f76fd3845a597 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 6 Nov 2023 21:54:40 +0000 Subject: [PATCH 23/88] Side Trick effect - Copiously reuses from MT_MAGICIANBOX, gomen - Also set the lookback frame, for extra toaster-swag zaza - Because this feature is so old it predates lookback!? --- src/deh_tables.c | 3 +++ src/info.c | 32 +++++++++++++++++++++++++++- src/info.h | 6 +++++- src/k_kart.c | 33 +++++++++++++++++++++++++++++ src/p_mobj.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++ src/p_user.c | 4 ++-- 6 files changed, 129 insertions(+), 4 deletions(-) diff --git a/src/deh_tables.c b/src/deh_tables.c index 5a7930152..1025c8d58 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -3898,6 +3898,8 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_TRICKINDICATOR_UNDERLAY_ARROW", "S_TRICKINDICATOR_UNDERLAY_ARROW2", + "S_SIDETRICK", + // DEZ Ring Shooter "S_TIREGRABBER", "S_RINGSHOOTER_SIDE", @@ -5656,6 +5658,7 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t "MT_SMOOTHLANDING", "MT_TRICKINDICATOR", + "MT_SIDETRICK", "MT_TIREGRABBER", "MT_RINGSHOOTER", diff --git a/src/info.c b/src/info.c index 3b1ade0e5..da38478cf 100644 --- a/src/info.c +++ b/src/info.c @@ -631,11 +631,12 @@ char sprnames[NUMSPRITES + 1][5] = "TWBT", // Tripwire BLASTER "SMLD", // Smooth landing - // Trick Indicator + // Trick Effects "TRK1", "TRK2", "TRK3", "TRK4", + "TRK5", "TIRG", // Tire grabbers "RSHT", // DEZ Ring Shooter @@ -4674,6 +4675,8 @@ state_t states[NUMSTATES] = {SPR_NULL, 0, 1, {NULL}, 12, 1, S_TRICKINDICATOR_UNDERLAY_ARROW2}, // S_TRICKINDICATOR_UNDERLAY_ARROW, {SPR_TRK4, FF_FULLBRIGHT|FF_ANIMATE|FF_PAPERSPRITE, 13, {NULL}, 12, 1, S_INVISIBLE}, // S_TRICKINDICATOR_UNDERLAY_ARROW2, + {SPR_TRK5, FF_FULLBRIGHT|FF_ANIMATE|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_SIDETRICK, + {SPR_TIRG, FF_ANIMATE, -1, {NULL}, 1, 1, S_NULL}, // S_TIREGRABBER {SPR_RSHT, FF_PAPERSPRITE|0, -1, {NULL}, 0, 0, S_NULL}, // S_RINGSHOOTER_SIDE {SPR_RSHT, FF_SEMIBRIGHT|FF_PAPERSPRITE|2, -1, {NULL}, 0, 0, S_NULL}, // S_RINGSHOOTER_NIPPLES @@ -25368,6 +25371,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_SIDETRICK + -1, // doomednum + S_SIDETRICK, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 36*FRACUNIT, // radius + 40*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPTHING|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags + S_NULL // raisestate + }, + { // MT_TIREGRABBER -1, // doomednum S_TIREGRABBER, // spawnstate diff --git a/src/info.h b/src/info.h index 0686c8262..0963e1c93 100644 --- a/src/info.h +++ b/src/info.h @@ -1188,11 +1188,12 @@ typedef enum sprite SPR_TWBT, // Tripwire BLASTER SPR_SMLD, // Smooth landing - // Trick Indicator + // Trick Effects SPR_TRK1, SPR_TRK2, SPR_TRK3, SPR_TRK4, + SPR_TRK5, SPR_TIRG, // Tire grabbers SPR_RSHT, // DEZ Ring Shooter @@ -5118,6 +5119,8 @@ typedef enum state S_TRICKINDICATOR_UNDERLAY_ARROW, S_TRICKINDICATOR_UNDERLAY_ARROW2, + S_SIDETRICK, + // DEZ Ring Shooter S_TIREGRABBER, S_RINGSHOOTER_SIDE, @@ -6915,6 +6918,7 @@ typedef enum mobj_type MT_SMOOTHLANDING, MT_TRICKINDICATOR, + MT_SIDETRICK, MT_TIREGRABBER, MT_RINGSHOOTER, diff --git a/src/k_kart.c b/src/k_kart.c index a88aceb54..e892aa851 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -12189,6 +12189,10 @@ void K_MoveKartPlayer(player_t *player, boolean onground) #define TRICKTHRESHOLD (KART_FULLTURN/4) if (aimingcompare < -TRICKTHRESHOLD) // side trick { + angle_t sidetrickspeed = ANG30; + const angle_t angledelta = FixedAngle(36*FRACUNIT); + angle_t baseangle = player->mo->angle + angledelta/2; + if (cmd->turning > 0) { P_InstaThrust(player->mo, player->mo->angle + lr, max(basespeed, speed*5/2)); @@ -12198,6 +12202,9 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { player->trickIndicator->rollangle = ANGLE_270; } + + player->drawangle -= ANGLE_45; + P_SetPlayerMobjState(player->mo, S_KART_FAST_LOOK_L); } else { @@ -12208,6 +12215,32 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { player->trickIndicator->rollangle = ANGLE_90; } + + sidetrickspeed = InvAngle(sidetrickspeed); + + player->drawangle += ANGLE_45; + P_SetPlayerMobjState(player->mo, S_KART_FAST_LOOK_R); + } + + INT32 j; + + for (j = 0; j < 8; j++, baseangle += angledelta) + { + mobj_t *swipe = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_SIDETRICK); + P_SetTarget(&swipe->target, player->mo); + swipe->hitlag = TRICKLAG; + swipe->color = player->trickIndicator->color; + swipe->angle = baseangle + ANGLE_90; + swipe->renderflags |= RF_DONTDRAW; + swipe->flags2 |= MF2_AMBUSH; // don't interp on first think + swipe->movedir = sidetrickspeed; + swipe->frame |= (j % 4); + + // This is so they make a 10-sided shape with one-sprite gap + if (j != 3) + continue; + + baseangle += angledelta; } } else if (aimingcompare > TRICKTHRESHOLD) // forward/back trick diff --git a/src/p_mobj.c b/src/p_mobj.c index 4b606bee0..5c9f1f301 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8446,6 +8446,61 @@ static boolean P_MobjRegularThink(mobj_t *mobj) } break; } + case MT_SIDETRICK: + { + fixed_t destx, desty; + fixed_t zoff = 0; + + if (!mobj->target + || !mobj->target->health + || !mobj->target->player + || (mobj->target->player->trickpanel != 2 + && mobj->target->player->trickpanel != 3) + ) + { + P_RemoveMobj(mobj); + return false; + } + + if (leveltime & 1) + { + mobj->renderflags |= RF_DONTDRAW; + } + else + { + mobj->renderflags &= ~RF_DONTDRAW; + mobj->renderflags |= (mobj->target->renderflags & RF_DONTDRAW); + } + + mobj->angle += mobj->movedir; + P_SetScale(mobj, mobj->target->scale); + + destx = mobj->target->x; + desty = mobj->target->y; + + destx += P_ReturnThrustX(mobj, mobj->angle - ANGLE_90, mobj->radius*2); + desty += P_ReturnThrustY(mobj, mobj->angle - ANGLE_90, mobj->radius*2); + + mobj->eflags = (mobj->eflags & ~MFE_VERTICALFLIP)|(mobj->target->eflags & MFE_VERTICALFLIP); + mobj->flags2 = (mobj->flags2 & ~MF2_OBJECTFLIP)|(mobj->target->flags2 & MF2_OBJECTFLIP); + + if (mobj->eflags & MFE_VERTICALFLIP) + zoff += mobj->target->height - mobj->height; + + // Necessary to "ride" on Garden Top + zoff += mobj->target->sprzoff; + + if (mobj->flags2 & MF2_AMBUSH) + { + P_SetOrigin(mobj, destx, desty, mobj->target->z + zoff); + mobj->flags2 &= ~MF2_AMBUSH; + } + else + { + P_MoveOrigin(mobj, destx, desty, mobj->target->z + zoff); + } + break; + } case MT_LIGHTNINGSHIELD: { if (!mobj->target || !mobj->target->health || !mobj->target->player diff --git a/src/p_user.c b/src/p_user.c index b348ad7b9..2c9023e49 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2467,8 +2467,6 @@ void P_MovePlayer(player_t *player) } else { - K_KartMoveAnimation(player); - if (player->trickpanel == 2) { player->drawangle += ANGLE_22h; @@ -2479,6 +2477,8 @@ void P_MovePlayer(player_t *player) } else { + K_KartMoveAnimation(player); + player->drawangle = player->mo->angle; if (player->aizdriftturn) From 0016e8b9ec52b3a7e02d3983a4ca1699026aa8b1 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 6 Nov 2023 22:17:53 +0000 Subject: [PATCH 24/88] Boost the Trick Panel boost gotten from sneakers/invinc to 2* --- src/k_kart.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index e892aa851..e3367a250 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -6405,13 +6405,9 @@ void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, UINT8 sound) } } - if (mo->player->sneakertimer) + if (mo->player->sneakertimer || mo->player->invincibilitytimer) { - thrust = FixedMul(thrust, 5*FRACUNIT/4); - } - else if (mo->player->invincibilitytimer) - { - thrust = FixedMul(thrust, 9*FRACUNIT/8); + thrust = FixedMul(thrust, 2*FRACUNIT); } mo->player->tricktime = 0; // Reset post-hitlag timer From af24fcd4bd05e35a854bba83d282f78220b51288 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 6 Nov 2023 22:18:27 +0000 Subject: [PATCH 25/88] Don't draw catholocism for other players Your relationship with christ is personal --- src/k_kart.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/k_kart.c b/src/k_kart.c index e3367a250..7beb2896b 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -4123,17 +4123,21 @@ void K_InitTrickIndicator(player_t *player) P_RemoveMobj(player->trickIndicator); } + UINT32 invis = (RF_DONTDRAW & ~K_GetPlayerDontDrawFlag(player)); + new = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_TRICKINDICATOR); P_SetMobjState(new, S_INVISIBLE); P_SetTarget(&player->trickIndicator, new); P_SetTarget(&new->target, player->mo); + new->renderflags |= invis; mobj_t *secondlayer = P_SpawnMobjFromMobj(new, 0, 0, 0, MT_OVERLAY); P_SetMobjState(secondlayer, S_INVISIBLE); P_SetTarget(&new->tracer, secondlayer); P_SetTarget(&secondlayer->target, new); + secondlayer->renderflags |= invis; secondlayer->dispoffset = 1; secondlayer->flags |= MF_DONTENCOREMAP; From 49fb2fe6b63ce67d4cd9078e9b7fb35f2fbb115d Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Tue, 7 Nov 2023 03:46:11 -0700 Subject: [PATCH 26/88] WIP: Trick Panel crack --- src/d_netcmd.c | 3 ++- src/d_player.h | 1 + src/k_kart.c | 39 +++++++++++++++++++++++++++++++++------ src/lua_playerlib.c | 4 ++++ src/p_saveg.c | 2 ++ src/sounds.c | 4 ++++ src/sounds.h | 4 ++++ 7 files changed, 50 insertions(+), 7 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index d5384170f..776d8568d 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2430,7 +2430,8 @@ static void Command_Map_f(void) return; } - newgametype = GT_RACE; // sensible default + if (newgametype == -1) + newgametype = GT_RACE; // sensible default } } diff --git a/src/d_player.h b/src/d_player.h index c132ca4e9..d079de9a8 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -909,6 +909,7 @@ struct player_t INT16 incontrol; // -1 to -175 when spinning out or tumbling, 1 to 175 when not. Use to check for combo hits or emergency inputs. boolean markedfordeath; + boolean dotrickfx; UINT8 ringboxdelay; // Delay until Ring Box auto-activates UINT8 ringboxaward; // Where did we stop? diff --git a/src/k_kart.c b/src/k_kart.c index 7beb2896b..33a9ae545 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -8498,6 +8498,12 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->instaWhipCooldown--; } + if (player->dotrickfx && !player->mo->hitlag) + { + S_StartSound(player->mo, sfx_trick1); + player->dotrickfx = false; + } + // Don't screw up chain ring pickup/usage with instawhip charge. // If the button stays held, delay charge a bit. if (player->instaWhipChargeLockout) @@ -10920,9 +10926,10 @@ boolean K_FastFallBounce(player_t *player) player->pflags |= PF_UPDATEMYRESPAWN; + player->fastfall = 0; + player->mo->momz = bounce * P_MobjFlip(player->mo); - player->fastfall = 0; return true; } @@ -12193,6 +12200,9 @@ void K_MoveKartPlayer(player_t *player, boolean onground) const angle_t angledelta = FixedAngle(36*FRACUNIT); angle_t baseangle = player->mo->angle + angledelta/2; + S_StartSound(player->mo, sfx_trick0); + player->dotrickfx = true; + if (cmd->turning > 0) { P_InstaThrust(player->mo, player->mo->angle + lr, max(basespeed, speed*5/2)); @@ -12245,6 +12255,9 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } else if (aimingcompare > TRICKTHRESHOLD) // forward/back trick { + S_StartSound(player->mo, sfx_trick0); + player->dotrickfx = true; + if (cmd->throwdir > 0) // back trick { if (player->mo->momz * P_MobjFlip(player->mo) > 0) @@ -12321,12 +12334,26 @@ void K_MoveKartPlayer(player_t *player, boolean onground) K_trickPanelTimingVisual(player, momz); } - else if (player->trickpanel == 4 && P_IsObjectOnGround(player->mo)) // Upwards trick landed! + else if (player->trickpanel && P_IsObjectOnGround(player->mo)) // Landed from trick { - //CONS_Printf("apply boost\n"); - S_StartSound(player->mo, sfx_s23c); - K_SpawnDashDustRelease(player); - player->trickboost = TICRATE - player->trickboostdecay; + if (player->fastfall) + { + player->mo->hitlag = 3; + K_SpawnDashDustRelease(player); + P_InstaThrust(player->mo, player->mo->angle, 30*FRACUNIT); + S_StartSound(player->mo, sfx_gshce); + player->fastfall = 0; // intentionally skip bounce + } + + if (player->trickpanel == 4) // upward trick + { + S_StartSound(player->mo, sfx_s23c); + K_SpawnDashDustRelease(player); + player->trickboost = TICRATE - player->trickboostdecay; + } + + player->sliptideZip += 300; + player->sliptideZipDelay = 0; player->trickpanel = player->trickboostdecay = 0; } diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 6fe1e325d..0bda04838 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -255,6 +255,8 @@ static int player_get(lua_State *L) lua_pushboolean(L, plr->flipDI); else if (fastcmp(field,"markedfordeath")) lua_pushboolean(L, plr->markedfordeath); + else if (fastcmp(field,"dotrickfx")) + lua_pushboolean(L, plr->dotrickfx); else if (fastcmp(field,"ringboxdelay")) lua_pushinteger(L, plr->ringboxdelay); else if (fastcmp(field,"ringboxaward")) @@ -737,6 +739,8 @@ static int player_set(lua_State *L) plr->flipDI = luaL_checkboolean(L, 3); else if (fastcmp(field,"markedfordeath")) plr->markedfordeath = luaL_checkboolean(L, 3); + else if (fastcmp(field,"dotrickfx")) + plr->dotrickfx = luaL_checkboolean(L, 3); else if (fastcmp(field,"ringboxdelay")) plr->ringboxdelay = luaL_checkinteger(L, 3); else if (fastcmp(field,"ringboxaward")) diff --git a/src/p_saveg.c b/src/p_saveg.c index 865732692..1860b84e8 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -560,6 +560,7 @@ static void P_NetArchivePlayers(savebuffer_t *save) WRITEINT16(save->p, players[i].incontrol); WRITEUINT8(save->p, players[i].markedfordeath); + WRITEUINT8(save->p, players[i].dotrickfx); WRITEUINT8(save->p, players[i].ringboxdelay); WRITEUINT8(save->p, players[i].ringboxaward); @@ -1077,6 +1078,7 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) players[i].incontrol = READINT16(save->p); players[i].markedfordeath = READUINT8(save->p); + players[i].dotrickfx = READUINT8(save->p); players[i].ringboxdelay = READUINT8(save->p); players[i].ringboxaward = READUINT8(save->p); diff --git a/src/sounds.c b/src/sounds.c index cbb5836a2..dcfa01cc3 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -1119,6 +1119,10 @@ sfxinfo_t S_sfx[NUMSFX] = {"fshld2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flame Shield burst"}, {"fshld3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flame Shield cooldown"}, + // RR - Trick Panel + {"trick0", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Trick confirm"}, + {"trick1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Trick"}, + // RR - Ballhog Charge {"bhog00", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Ballhog charging"}, {"bhog01", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Ballhog charging"}, diff --git a/src/sounds.h b/src/sounds.h index a19d2b4ed..0d686b3c2 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -1187,6 +1187,10 @@ typedef enum sfx_fshld2, sfx_fshld3, + // RR - Trick panels + sfx_trick0, + sfx_trick1, + // RR - Ballhog Charge sfx_bhog00, sfx_bhog01, From 73f67f4c94cbde829d714b276c63c716f863aef3 Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 7 Nov 2023 14:53:03 +0000 Subject: [PATCH 27/88] MT_MAGICIANBOX, MT_SIDETRICK: Fix some more interp issues Also guarantees that MT_SIDETRICK will be visible for the first frame of the trick, since it was invisible for the entire duration of catholocism. --- src/p_mobj.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 5c9f1f301..546d447aa 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8408,10 +8408,9 @@ static boolean P_MobjRegularThink(mobj_t *mobj) return true; } - mobj->extravalue1 += 1; - mobj->angle += ANG1*mobj->extravalue1; - P_SetScale(mobj, mobj->target->scale); + mobj->extravalue1 += 1; + P_InstaScale(mobj, mobj->target->scale); destx = mobj->target->x; desty = mobj->target->y; @@ -8438,6 +8437,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) if (mobj->flags2 & MF2_AMBUSH) { P_SetOrigin(mobj, destx, desty, mobj->target->z + zoff); + mobj->old_angle = mobj->angle; mobj->flags2 &= ~MF2_AMBUSH; } else @@ -8462,7 +8462,8 @@ static boolean P_MobjRegularThink(mobj_t *mobj) return false; } - if (leveltime & 1) + // Flicker every other frame from first visibility + if (mobj->flags2 & MF2_BOSSDEAD) { mobj->renderflags |= RF_DONTDRAW; } @@ -8472,8 +8473,13 @@ static boolean P_MobjRegularThink(mobj_t *mobj) mobj->renderflags |= (mobj->target->renderflags & RF_DONTDRAW); } + mobj->eflags = (mobj->eflags & ~MFE_VERTICALFLIP)|(mobj->target->eflags & MFE_VERTICALFLIP); + mobj->flags2 = ((mobj->flags2 & ~MF2_OBJECTFLIP)|(mobj->target->flags2 & MF2_OBJECTFLIP)) ^ MF2_BOSSDEAD; + + fixed_t scale = mobj->target->scale; + mobj->angle += mobj->movedir; - P_SetScale(mobj, mobj->target->scale); + P_InstaScale(mobj, scale); destx = mobj->target->x; desty = mobj->target->y; @@ -8481,9 +8487,6 @@ static boolean P_MobjRegularThink(mobj_t *mobj) destx += P_ReturnThrustX(mobj, mobj->angle - ANGLE_90, mobj->radius*2); desty += P_ReturnThrustY(mobj, mobj->angle - ANGLE_90, mobj->radius*2); - mobj->eflags = (mobj->eflags & ~MFE_VERTICALFLIP)|(mobj->target->eflags & MFE_VERTICALFLIP); - mobj->flags2 = (mobj->flags2 & ~MF2_OBJECTFLIP)|(mobj->target->flags2 & MF2_OBJECTFLIP); - if (mobj->eflags & MFE_VERTICALFLIP) zoff += mobj->target->height - mobj->height; @@ -8493,6 +8496,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) if (mobj->flags2 & MF2_AMBUSH) { P_SetOrigin(mobj, destx, desty, mobj->target->z + zoff); + mobj->old_angle = mobj->angle; mobj->flags2 &= ~MF2_AMBUSH; } else From c1f7546f9987358843fc119cf5426630cdf7f53b Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 7 Nov 2023 20:10:01 +0000 Subject: [PATCH 28/88] Sneaker/invincibility: Trick Panel launch multiplier is 1.5x, nerfed from 2x --- src/k_kart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index 33a9ae545..53aaaf58a 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -6411,7 +6411,7 @@ void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, UINT8 sound) if (mo->player->sneakertimer || mo->player->invincibilitytimer) { - thrust = FixedMul(thrust, 2*FRACUNIT); + thrust = FixedMul(thrust, (3*FRACUNIT)/2); } mo->player->tricktime = 0; // Reset post-hitlag timer From c3d34e937755df365634678cef89b38cc730c0c7 Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 7 Nov 2023 20:24:01 +0000 Subject: [PATCH 29/88] Back Trick effect A rising tornado swirling the opposite direction. Sprites do not currently exist, but it's a one-line emergency-break-glass change if there's any danger of not shopping with them --- src/deh_tables.c | 1 + src/info.c | 2 ++ src/info.h | 2 ++ src/k_kart.c | 74 ++++++++++++++++++++++++++++++------------------ src/p_mobj.c | 36 +++++++++++++++++++++-- 5 files changed, 84 insertions(+), 31 deletions(-) diff --git a/src/deh_tables.c b/src/deh_tables.c index 1025c8d58..5a087fcb0 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -3899,6 +3899,7 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_TRICKINDICATOR_UNDERLAY_ARROW2", "S_SIDETRICK", + "S_BACKTRICK", // DEZ Ring Shooter "S_TIREGRABBER", diff --git a/src/info.c b/src/info.c index da38478cf..a5fc9677d 100644 --- a/src/info.c +++ b/src/info.c @@ -637,6 +637,7 @@ char sprnames[NUMSPRITES + 1][5] = "TRK3", "TRK4", "TRK5", + "TRK6", "TIRG", // Tire grabbers "RSHT", // DEZ Ring Shooter @@ -4676,6 +4677,7 @@ state_t states[NUMSTATES] = {SPR_TRK4, FF_FULLBRIGHT|FF_ANIMATE|FF_PAPERSPRITE, 13, {NULL}, 12, 1, S_INVISIBLE}, // S_TRICKINDICATOR_UNDERLAY_ARROW2, {SPR_TRK5, FF_FULLBRIGHT|FF_ANIMATE|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_SIDETRICK, + {SPR_TRK6, FF_FULLBRIGHT|FF_ANIMATE|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_BACKTRICK, {SPR_TIRG, FF_ANIMATE, -1, {NULL}, 1, 1, S_NULL}, // S_TIREGRABBER {SPR_RSHT, FF_PAPERSPRITE|0, -1, {NULL}, 0, 0, S_NULL}, // S_RINGSHOOTER_SIDE diff --git a/src/info.h b/src/info.h index 0963e1c93..01642bb20 100644 --- a/src/info.h +++ b/src/info.h @@ -1194,6 +1194,7 @@ typedef enum sprite SPR_TRK3, SPR_TRK4, SPR_TRK5, + SPR_TRK6, SPR_TIRG, // Tire grabbers SPR_RSHT, // DEZ Ring Shooter @@ -5120,6 +5121,7 @@ typedef enum state S_TRICKINDICATOR_UNDERLAY_ARROW2, S_SIDETRICK, + S_BACKTRICK, // DEZ Ring Shooter S_TIREGRABBER, diff --git a/src/k_kart.c b/src/k_kart.c index 53aaaf58a..351fbb112 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -12190,16 +12190,18 @@ void K_MoveKartPlayer(player_t *player, boolean onground) else if (!(player->pflags & PF_TRICKDELAY)) // don't allow tricking at the same frame you tumble obv { + // For tornado trick effects + angle_t tornadotrickspeed = ANG30; + const angle_t angledelta = FixedAngle(36*FRACUNIT); + angle_t baseangle = player->mo->angle + angledelta/2; + boolean fronttrick = false; + INT16 aimingcompare = abs(cmd->throwdir) - abs(cmd->turning); // Uses cmd->turning over steering intentionally. #define TRICKTHRESHOLD (KART_FULLTURN/4) if (aimingcompare < -TRICKTHRESHOLD) // side trick { - angle_t sidetrickspeed = ANG30; - const angle_t angledelta = FixedAngle(36*FRACUNIT); - angle_t baseangle = player->mo->angle + angledelta/2; - S_StartSound(player->mo, sfx_trick0); player->dotrickfx = true; @@ -12226,39 +12228,18 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->trickIndicator->rollangle = ANGLE_90; } - sidetrickspeed = InvAngle(sidetrickspeed); + tornadotrickspeed = InvAngle(tornadotrickspeed); player->drawangle += ANGLE_45; P_SetPlayerMobjState(player->mo, S_KART_FAST_LOOK_R); } - - INT32 j; - - for (j = 0; j < 8; j++, baseangle += angledelta) - { - mobj_t *swipe = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_SIDETRICK); - P_SetTarget(&swipe->target, player->mo); - swipe->hitlag = TRICKLAG; - swipe->color = player->trickIndicator->color; - swipe->angle = baseangle + ANGLE_90; - swipe->renderflags |= RF_DONTDRAW; - swipe->flags2 |= MF2_AMBUSH; // don't interp on first think - swipe->movedir = sidetrickspeed; - swipe->frame |= (j % 4); - - // This is so they make a 10-sided shape with one-sprite gap - if (j != 3) - continue; - - baseangle += angledelta; - } } else if (aimingcompare > TRICKTHRESHOLD) // forward/back trick { S_StartSound(player->mo, sfx_trick0); player->dotrickfx = true; - if (cmd->throwdir > 0) // back trick + if (cmd->throwdir > 0) // forward trick { if (player->mo->momz * P_MobjFlip(player->mo) > 0) { @@ -12272,8 +12253,12 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { player->trickIndicator->rollangle = 0; } + + P_SetPlayerMobjState(player->mo, S_KART_FAST); + + fronttrick = true; } - else if (cmd->throwdir < 0) + else if (cmd->throwdir < 0) // back trick { player->mo->momx /= 3; player->mo->momy /= 3; @@ -12296,6 +12281,11 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { player->trickIndicator->rollangle = ANGLE_180; } + + //tornadotrickspeed = InvAngle(tornadotrickspeed); + + //player->drawangle += ANGLE_45; + P_SetPlayerMobjState(player->mo, S_KART_FAST); } } #undef TRICKTHRESHOLD @@ -12311,6 +12301,34 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->karthud[khud_trickcool] = TICRATE; } + INT32 j; + + if (fronttrick == true) + ; // Not yet sprited + else for (j = 0; j < 8; j++, baseangle += angledelta) + { + mobj_t *swipe = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_SIDETRICK); + + if (player->trickpanel == 4) + P_SetMobjState(swipe, S_BACKTRICK); + + P_SetTarget(&swipe->target, player->mo); + swipe->hitlag = TRICKLAG; + swipe->color = player->trickIndicator->color; + swipe->angle = baseangle + ANGLE_90; + swipe->renderflags |= RF_DONTDRAW; + swipe->flags2 |= MF2_AMBUSH; // don't interp on first think + swipe->movedir = tornadotrickspeed; + swipe->frame |= (j % 4); + swipe->threshold = 0; + + // This is so they make a 10-sided shape with one-sprite gap + if (j != 3) + continue; + + baseangle += angledelta; + } + if (P_MobjWasRemoved(player->trickIndicator) == false) { K_TrickCatholocismBlast(player->trickIndicator, player->trickIndicator->scale*10, 0); diff --git a/src/p_mobj.c b/src/p_mobj.c index 546d447aa..46c42d9ca 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8454,9 +8454,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) if (!mobj->target || !mobj->target->health || !mobj->target->player - || (mobj->target->player->trickpanel != 2 - && mobj->target->player->trickpanel != 3) - ) + || mobj->target->player->trickpanel <= 1) { P_RemoveMobj(mobj); return false; @@ -8478,6 +8476,38 @@ static boolean P_MobjRegularThink(mobj_t *mobj) fixed_t scale = mobj->target->scale; + // sweeping effect + if (mobj->target->player->trickpanel == 4) + { + const fixed_t saferange = (20*FRACUNIT)/21; + if (mobj->threshold < -saferange) + { + mobj->threshold = -saferange; + mobj->flags2 |= MF2_AMBUSH; + } + else while (mobj->threshold > saferange) + { + mobj->threshold -= 2*saferange; + mobj->flags2 |= MF2_AMBUSH; + } + + scale = P_ReturnThrustX(mobj, FixedAngle(90*mobj->threshold), scale); + + // This funny dealie is to make it so default + // scale is placed as standard, + // but variant threshold shifts upwards + fixed_t extraoffset = FixedMul(mobj->info->height, mobj->target->scale - scale); + if (mobj->threshold < 0) + extraoffset /= 2; + + // And this makes it swooce across the object. + extraoffset += FixedMul(mobj->threshold, mobj->target->height); + + zoff += P_MobjFlip(mobj) * extraoffset; + + mobj->threshold += (saferange/8); + } + mobj->angle += mobj->movedir; P_InstaScale(mobj, scale); From 6f22c5261e5e96c1ef03f76490a4033f5331ead8 Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 7 Nov 2023 22:50:51 +0000 Subject: [PATCH 30/88] MT_POGOSPRING: Guarantee spawn of catholocism --- src/k_kart.c | 19 ++++++++++++++----- src/p_map.c | 8 ++------ 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index f875b96e0..628924e75 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -6336,6 +6336,7 @@ static void K_DoShrink(player_t *user) void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, UINT8 sound) { fixed_t thrust = 0; + boolean dontapplymomz = false; if (mo->player && mo->player->spectator) return; @@ -6348,11 +6349,16 @@ void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, UINT8 sound) mo->eflags |= MFE_SPRUNG; - if (vertispeed <= 0) + if (vertispeed == 0) { vertispeed = P_AproxDistance(mo->momx, mo->momy); vertispeed = FixedMul(vertispeed, FINESINE(ANGLE_22h >> ANGLETOFINESHIFT)); } + else if (vertispeed < 0) + { + dontapplymomz = 0; + vertispeed = -vertispeed; + } thrust = vertispeed * P_MobjFlip(mo); @@ -6422,11 +6428,14 @@ void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, UINT8 sound) mo->player->fastfall = 0; } - mo->momz = FixedMul(thrust, mapobjectscale); - - if (mo->eflags & MFE_UNDERWATER) + if (dontapplymomz == false) { - mo->momz = FixedDiv(mo->momz, FixedSqrt(3*FRACUNIT)); + mo->momz = FixedMul(thrust, mapobjectscale); + + if (mo->eflags & MFE_UNDERWATER) + { + mo->momz = FixedDiv(mo->momz, FixedSqrt(3*FRACUNIT)); + } } P_ResetPitchRoll(mo); diff --git a/src/p_map.c b/src/p_map.c index c096dab60..b2693a122 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -427,12 +427,8 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) { if (spring->reactiontime == 0) { - object->player->tricktime = 0; // Reset post-hitlag timer - // Setup the boost for potential upwards trick, at worse, make it your regular max speed. (boost = curr speed*1.25) - object->player->trickboostpower = max(FixedDiv(object->player->speed, K_GetKartSpeed(object->player, false, false)) - FRACUNIT, 0)*125/100; - //CONS_Printf("Got boost: %d%\n", mo->player->trickboostpower*100 / FRACUNIT); - object->player->trickpanel = 1; - object->player->pflags |= PF_TRICKDELAY; + object->eflags &= ~MFE_SPRUNG; // needed to permit the following + K_DoPogoSpring(object, -vertispeed, 0); // negative so momz isn't modified } else { From 239388a1faa6b706177e1f18e3ce2f65faf23203 Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 7 Nov 2023 23:06:50 +0000 Subject: [PATCH 31/88] Add TRICKSTATE_ constants Replaces the magic numpers <-- typo I have left in for posterity --- src/d_player.h | 12 +++++++++++- src/k_bot.cpp | 4 ++-- src/k_director.cpp | 2 +- src/k_kart.c | 43 ++++++++++++++++++++++--------------------- src/k_terrain.c | 2 +- src/p_inter.c | 2 +- src/p_mobj.c | 6 +++--- src/p_user.c | 17 ++++++++++------- 8 files changed, 51 insertions(+), 37 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index d079de9a8..b4777e67c 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -261,6 +261,16 @@ typedef enum TRIPWIRE_BLASTER, } tripwirepass_t; +typedef enum +{ + TRICKSTATE_NONE = 0, + TRICKSTATE_READY, + TRICKSTATE_FORWARD, + TRICKSTATE_RIGHT, + TRICKSTATE_LEFT, + TRICKSTATE_BACK, +} trickstate_t; + typedef enum { // Unsynced, HUD or clientsided effects @@ -740,7 +750,7 @@ struct player_t UINT8 confirmVictim; // Player ID that you dealt damage to UINT8 confirmVictimDelay; // Delay before playing the sound - UINT8 trickpanel; // Trick panel state + UINT8 trickpanel; // Trick panel state - see trickstate_t UINT8 tricktime; // Increases while you're tricking. You can't input any trick until it's reached a certain threshold fixed_t trickboostpower; // Save the rough speed multiplier. Used for upwards tricks. UINT8 trickboostdecay; // used to know how long you've waited diff --git a/src/k_bot.cpp b/src/k_bot.cpp index 2d796758e..8c1894fba 100644 --- a/src/k_bot.cpp +++ b/src/k_bot.cpp @@ -1109,7 +1109,7 @@ static void K_BotTrick(player_t *player, ticcmd_t *cmd, const botcontroller_t *b return; } - if (player->trickpanel == 1) + if (player->trickpanel == TRICKSTATE_READY) { switch (botController->trick) { @@ -1521,7 +1521,7 @@ static void K_BuildBotTiccmdNormal(player_t *player, ticcmd_t *cmd) // Actual gameplay behaviors below this block! const botcontroller_t *botController = K_GetBotController(player->mo); - if (player->trickpanel != 0) + if (player->trickpanel != TRICKSTATE_NONE) { K_BotTrick(player, cmd, botController); diff --git a/src/k_director.cpp b/src/k_director.cpp index f04d2dfca..118786d63 100644 --- a/src/k_director.cpp +++ b/src/k_director.cpp @@ -221,7 +221,7 @@ private: bool can_change() const { - if (viewplayer()->trickpanel > 0) + if (viewplayer()->trickpanel != TRICKSTATE_NONE) { return false; } diff --git a/src/k_kart.c b/src/k_kart.c index 628924e75..15f0e28f7 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -4379,7 +4379,7 @@ void K_UpdateTrickIndicator(player_t *player) player->mo->z + (player->mo->height / 2)); mobj->angle = player->mo->angle + ANGLE_90; - if (player->trickpanel == 0 + if (player->trickpanel == TRICKSTATE_NONE && test != S_INVISIBLE) { K_TrickCatholocismBlast(mobj, 1, ANGLE_22h); @@ -6366,7 +6366,7 @@ void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, UINT8 sound) { if (!P_PlayerInPain(mo->player)) { - mo->player->trickpanel = 1; + mo->player->trickpanel = TRICKSTATE_READY; mo->player->pflags |= PF_TRICKDELAY; if (P_MobjWasRemoved(mo->player->trickIndicator) == false) @@ -8674,11 +8674,11 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) K_FlameDashLeftoverSmoke(player->mo); } - if (P_IsObjectOnGround(player->mo) && player->trickpanel != 0) + if (P_IsObjectOnGround(player->mo) && player->trickpanel != TRICKSTATE_NONE) { if (P_MobjFlip(player->mo) * player->mo->momz <= 0) { - player->trickpanel = 0; + player->trickpanel = TRICKSTATE_NONE; } } @@ -9589,7 +9589,7 @@ INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue) return 0; } - if (player->trickpanel == 1 || player->trickpanel == 5) + if (player->trickpanel == TRICKSTATE_READY || player->trickpanel == TRICKSTATE_FORWARD) { // Forward trick or rising from trickpanel return 0; @@ -9688,7 +9688,7 @@ INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue) turnfixed = FixedMul(turnfixed, weightadjust); // Side trick - if (player->trickpanel == 2 || player->trickpanel == 3) + if (player->trickpanel == TRICKSTATE_LEFT || player->trickpanel == TRICKSTATE_RIGHT) { turnfixed /= 2; } @@ -11140,7 +11140,7 @@ static void K_trickPanelTimingVisual(player_t *player, fixed_t momz) flame->sprite = SPR_TRCK; flame->frame = i|FF_FULLBRIGHT; - if (player->trickpanel <= 1 && !player->tumbleBounces) + if (player->trickpanel <= TRICKSTATE_READY && !player->tumbleBounces) { flame->tics = 2; flame->momx = player->mo->momx; @@ -11151,7 +11151,7 @@ static void K_trickPanelTimingVisual(player_t *player, fixed_t momz) { flame->tics = TICRATE; - if (player->trickpanel > 1) // we tricked + if (player->trickpanel > TRICKSTATE_READY) // we tricked { // Send the thing outwards via ghetto maths which involves redoing the whole 3d sphere again, witht the "vertical" angle shifted by 90 degrees. // There's probably a simplier way to do this the way I want to but this works. @@ -12015,7 +12015,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } break; case KITEM_POGOSPRING: - if (ATTACK_IS_DOWN && !HOLDING_ITEM && onground && NO_HYUDORO && player->trickpanel == 0) + if (ATTACK_IS_DOWN && !HOLDING_ITEM && onground && NO_HYUDORO && player->trickpanel == TRICKSTATE_NONE) { K_PlayBoostTaunt(player->mo); //K_DoPogoSpring(player->mo, 32<mo->renderflags &= ~RF_BLENDMASK; } - if (player->trickpanel == 1) + if (player->trickpanel == TRICKSTATE_READY) { const angle_t lr = ANGLE_45; fixed_t momz = FixedDiv(player->mo->momz, mapobjectscale); // bring momz back to scale... @@ -12194,7 +12194,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->tumbleBounces = 1; player->pflags &= ~PF_TUMBLESOUND; player->tumbleHeight = 30; // Base tumble bounce height - player->trickpanel = 0; + player->trickpanel = TRICKSTATE_NONE; P_SetPlayerMobjState(player->mo, S_KART_SPINOUT); if (player->pflags & (PF_ITEMOUT|PF_EGGMANOUT)) { @@ -12222,7 +12222,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (cmd->turning > 0) { P_InstaThrust(player->mo, player->mo->angle + lr, max(basespeed, speed*5/2)); - player->trickpanel = 2; + player->trickpanel = TRICKSTATE_RIGHT; if (P_MobjWasRemoved(player->trickIndicator) == false) { @@ -12235,7 +12235,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) else { P_InstaThrust(player->mo, player->mo->angle - lr, max(basespeed, speed*5/2)); - player->trickpanel = 3; + player->trickpanel = TRICKSTATE_LEFT; if (P_MobjWasRemoved(player->trickIndicator) == false) { @@ -12261,7 +12261,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } P_InstaThrust(player->mo, player->mo->angle, max(basespeed, speed*3)); - player->trickpanel = 5; + player->trickpanel = TRICKSTATE_FORWARD; if (P_MobjWasRemoved(player->trickIndicator) == false) { @@ -12287,7 +12287,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) //CONS_Printf("decay: %d\n", player->trickboostdecay); player->mo->momz += P_MobjFlip(player->mo)*48*mapobjectscale; - player->trickpanel = 4; + player->trickpanel = TRICKSTATE_BACK; if (P_MobjWasRemoved(player->trickIndicator) == false) { @@ -12303,7 +12303,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) #undef TRICKTHRESHOLD // Finalise everything. - if (player->trickpanel != 1) // just changed from 1? + if (player->trickpanel != TRICKSTATE_READY) // just changed from 1? { player->mo->hitlag = TRICKLAG; player->mo->eflags &= ~MFE_DAMAGEHITLAG; @@ -12315,13 +12315,13 @@ void K_MoveKartPlayer(player_t *player, boolean onground) INT32 j; - if (player->trickpanel == 5) + if (player->trickpanel == TRICKSTATE_FORWARD) ; // Not yet sprited else for (j = 0; j < 8; j++, baseangle += angledelta) { mobj_t *swipe = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_SIDETRICK); - if (player->trickpanel == 4) + if (player->trickpanel == TRICKSTATE_BACK) P_SetMobjState(swipe, S_BACKTRICK); P_SetTarget(&swipe->target, player->mo); @@ -12364,7 +12364,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) K_trickPanelTimingVisual(player, momz); } - else if (player->trickpanel && P_IsObjectOnGround(player->mo)) // Landed from trick + else if ((player->trickpanel != TRICKSTATE_NONE) && P_IsObjectOnGround(player->mo)) // Landed from trick { if (player->fastfall) { @@ -12375,7 +12375,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->fastfall = 0; // intentionally skip bounce } - if (player->trickpanel == 4) // upward trick + if (player->trickpanel == TRICKSTATE_BACK) // upward trick { S_StartSound(player->mo, sfx_s23c); K_SpawnDashDustRelease(player); @@ -12385,7 +12385,8 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->sliptideZip += 300; player->sliptideZipDelay = 0; - player->trickpanel = player->trickboostdecay = 0; + player->trickpanel = TRICKSTATE_NONE; + player->trickboostdecay = 0; } // Wait until we let go off the control stick to remove the delay diff --git a/src/k_terrain.c b/src/k_terrain.c index 6c114d343..d2d9a3f8a 100644 --- a/src/k_terrain.c +++ b/src/k_terrain.c @@ -549,7 +549,7 @@ void K_ProcessTerrainEffect(mobj_t *mo) P_InstaThrust(player->mo, thrustAngle, max(thrustSpeed, 2*playerSpeed)); player->dashpadcooldown = TICRATE/3; - player->trickpanel = 0; + player->trickpanel = TRICKSTATE_NONE; player->floorboost = 2; S_StartSound(player->mo, sfx_cdfm62); diff --git a/src/p_inter.c b/src/p_inter.c index 18a2f5e7c..fc7458ad6 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1692,7 +1692,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget target->player->roundscore = 0; } - target->player->trickpanel = 0; + target->player->trickpanel = TRICKSTATE_NONE; ACS_RunPlayerDeathScript(target->player); } diff --git a/src/p_mobj.c b/src/p_mobj.c index 46c42d9ca..efb668fec 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1147,7 +1147,7 @@ fixed_t P_GetMobjGravity(mobj_t *mo) P_PlayerFlip(mo); } - if (mo->player->trickpanel >= 2) + if (mo->player->trickpanel > TRICKSTATE_READY) { gravityadd = (5*gravityadd)/2; } @@ -8454,7 +8454,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) if (!mobj->target || !mobj->target->health || !mobj->target->player - || mobj->target->player->trickpanel <= 1) + || mobj->target->player->trickpanel <= TRICKSTATE_FORWARD) { P_RemoveMobj(mobj); return false; @@ -8477,7 +8477,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) fixed_t scale = mobj->target->scale; // sweeping effect - if (mobj->target->player->trickpanel == 4) + if (mobj->target->player->trickpanel == TRICKSTATE_BACK) { const fixed_t saferange = (20*FRACUNIT)/21; if (mobj->threshold < -saferange) diff --git a/src/p_user.c b/src/p_user.c index 1c7ce4ee6..81a5cd555 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -478,7 +478,7 @@ void P_ResetPlayer(player_t *player) player->onconveyor = 0; //player->drift = player->driftcharge = 0; - player->trickpanel = 0; + player->trickpanel = TRICKSTATE_NONE; player->glanceDir = 0; player->fastfall = 0; @@ -2467,13 +2467,16 @@ void P_MovePlayer(player_t *player) } else { - if (player->trickpanel == 2 || player->trickpanel == 5) // right/forward + if (player->trickpanel > TRICKSTATE_READY) { - player->drawangle += ANGLE_22h; - } - else if (player->trickpanel == 3 || player->trickpanel == 4) // left/back - { - player->drawangle -= ANGLE_22h; + if (player->trickpanel <= TRICKSTATE_RIGHT) // right/forward + { + player->drawangle += ANGLE_22h; + } + else //if (player->trickpanel >= TRICKSTATE_LEFT) // left/back + { + player->drawangle -= ANGLE_22h; + } } else { From 954bd85139740b8585614820c3327f42829eb24d Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Wed, 8 Nov 2023 01:52:07 -0700 Subject: [PATCH 32/88] WIP: Trickpanel crack experiments --- src/d_clisrv.c | 2 +- src/d_player.h | 10 +-- src/deh_tables.c | 4 +- src/g_game.c | 2 +- src/info.c | 9 +-- src/info.h | 7 +- src/k_kart.c | 154 ++++++++++++++++++++++++++++---------------- src/k_kart.h | 4 +- src/k_respawn.c | 3 +- src/lua_playerlib.c | 32 +++++---- src/p_inter.c | 2 +- src/p_mobj.c | 2 +- src/p_saveg.c | 40 ++++++------ src/p_user.c | 2 +- 14 files changed, 165 insertions(+), 108 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index abcdb7580..ce142ffd1 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2550,7 +2550,7 @@ void CL_ClearPlayer(INT32 playernum) PlayerPointerRemove(players[playernum].mo); PlayerPointerRemove(players[playernum].followmobj); PlayerPointerRemove(players[playernum].stumbleIndicator); - PlayerPointerRemove(players[playernum].sliptideZipIndicator); + PlayerPointerRemove(players[playernum].wavedashIndicator); PlayerPointerRemove(players[playernum].trickIndicator); #undef PlayerPointerRemove diff --git a/src/d_player.h b/src/d_player.h index b4777e67c..bd951e7c7 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -895,14 +895,16 @@ struct player_t UINT8 tripwireReboundDelay; // When failing Tripwire, brieftly lock out speed-based tripwire pass (anti-cheese) - UINT16 sliptideZip; // How long is our chained sliptide? Grant a proportional boost when it's over. - UINT8 sliptideZipDelay; // How long since the last sliptide? Only boost once you've been straightened out for a bit. - UINT16 sliptideZipBoost; // The actual boost granted from sliptideZip. + UINT16 wavedash; // How long is our chained sliptide? Grant a proportional boost when it's over. + UINT8 wavedashdelay; // How long since the last sliptide? Only boost once you've been straightened out for a bit. + UINT16 wavedashboost; // The actual boost granted from wavedash. + UINT16 trickdashboost; // The actual boost granted from wavedash. + boolean trickdash; UINT8 lastsafelap; mobj_t *stumbleIndicator; - mobj_t *sliptideZipIndicator; + mobj_t *wavedashIndicator; mobj_t *trickIndicator; mobj_t *whip; mobj_t *hand; diff --git a/src/deh_tables.c b/src/deh_tables.c index 5a087fcb0..c0d35b1b5 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -3314,7 +3314,7 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_MAGICIANBOXTOP", "S_MAGICIANBOXBOTTOM", - "S_SLIPTIDEZIP", + "S_WAVEDASH", "S_INSTAWHIP", "S_INSTAWHIP_RECHARGE1", @@ -5547,7 +5547,7 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t "MT_MONITOR_SHARD", "MT_MAGICIANBOX", - "MT_SLIPTIDEZIP", + "MT_WAVEDASH", "MT_INSTAWHIP", "MT_INSTAWHIP_RECHARGE", diff --git a/src/g_game.c b/src/g_game.c index 3b4ca5125..687af8a7f 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2243,7 +2243,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) // These are mostly subservient to the player, and may not clean themselves up. PlayerPointerRemove(players[player].followmobj); PlayerPointerRemove(players[player].stumbleIndicator); - PlayerPointerRemove(players[player].sliptideZipIndicator); + PlayerPointerRemove(players[player].wavedashIndicator); PlayerPointerRemove(players[player].trickIndicator); #undef PlayerPointerRemove diff --git a/src/info.c b/src/info.c index a5fc9677d..8e3b38bb9 100644 --- a/src/info.c +++ b/src/info.c @@ -558,7 +558,8 @@ char sprnames[NUMSPRITES + 1][5] = "IMDB", // Item Monitor Small Shard (Debris) "MTWK", // Item Monitor Glass Twinkle - "SLPT", // Sliptide zip indicator + "SLPT", // Wavedash indicator + "TRBS", // Trickdash indicator "IWHP", // Instawhip "WPRE", // Instawhip Recharge @@ -4126,7 +4127,7 @@ state_t states[NUMSTATES] = {SPR_MGBT, FF_FLOORSPRITE|0, -1, {NULL}, 0, 0, S_NULL}, // S_MAGICIANBOX_TOP {SPR_MGBB, FF_FLOORSPRITE|0, -1, {NULL}, 0, 0, S_NULL}, // S_MAGICIANBOX_BOTTOM - {SPR_SLPT, FF_PAPERSPRITE|0, -1, {NULL}, 0, 0, S_NULL}, // S_SLIPTIDEZIP + {SPR_SLPT, FF_PAPERSPRITE|0, -1, {NULL}, 0, 0, S_NULL}, // S_WAVEDASH {SPR_IWHP, FF_FLOORSPRITE|FF_ANIMATE|0, -1, {NULL}, 6, 2, S_NULL}, // S_INSTAWHIP {SPR_NULL, 0, 1, {NULL}, 0, 0, S_INSTAWHIP_RECHARGE2}, // S_INSTAWHIP_RECHARGE1 @@ -23078,9 +23079,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_SLIPTIDEZIP + { // MT_WAVEDASH -1, // doomednum - S_SLIPTIDEZIP, // spawnstate + S_WAVEDASH, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound diff --git a/src/info.h b/src/info.h index 01642bb20..f27c34e85 100644 --- a/src/info.h +++ b/src/info.h @@ -1115,7 +1115,8 @@ typedef enum sprite SPR_IMDB, // Item Monitor Small Shard (Debris) SPR_MTWK, // Item Monitor Glass Twinkle - SPR_SLPT, // Sliptide zip indicator + SPR_SLPT, // Wavedash indicator + SPR_TRBS, // Trickdash indicator SPR_IWHP, // Instawhip SPR_WPRE, // Instawhip Recharge @@ -4537,7 +4538,7 @@ typedef enum state S_MAGICIANBOX_TOP, S_MAGICIANBOX_BOTTOM, - S_SLIPTIDEZIP, + S_WAVEDASH, S_INSTAWHIP, S_INSTAWHIP_RECHARGE1, @@ -6808,7 +6809,7 @@ typedef enum mobj_type MT_MONITOR_PART, MT_MONITOR_SHARD, MT_MAGICIANBOX, - MT_SLIPTIDEZIP, + MT_WAVEDASH, MT_INSTAWHIP, MT_INSTAWHIP_RECHARGE, diff --git a/src/k_kart.c b/src/k_kart.c index 15f0e28f7..ff5d6e34f 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1263,6 +1263,9 @@ static boolean K_HasInfiniteTether(player_t *player) if (player->eggmanexplode > 0) return true; + if (player->trickdash) + return true; + return false; } @@ -1881,9 +1884,9 @@ static void K_SpawnGenericSpeedLines(player_t *player, boolean top) fast->colorized = true; fast->renderflags |= RF_ADD; } - else if (player->sliptideZipBoost) + else if (player->wavedashboost || player->trickdashboost) { - fast->color = SKINCOLOR_WHITE; + fast->color = (player->trickdashboost) ? K_RainbowColor(leveltime) : SKINCOLOR_WHITE; fast->colorized = true; } else if (player->ringboost) @@ -3231,12 +3234,17 @@ static void K_GetKartBoostPower(player_t *player) ); } - if (player->sliptideZipBoost) + if (player->wavedashboost) { - // NB: This is intentionally under the 25% threshold required to initiate a sliptide + // NB: This is intentionally under the 25% handleboost threshold required to initiate a sliptide ADDBOOST(8*FRACUNIT/10, 4*FRACUNIT, 2*SLIPTIDEHANDLING/5); // + 80% top speed, + 400% acceleration, +20% handling } + if (player->trickdashboost) + { + ADDBOOST(8*FRACUNIT/10, 8*FRACUNIT, 3*SLIPTIDEHANDLING/5); // + 80% top speed, + 800% acceleration, +30% handling + } + if (player->spindashboost) // Spindash boost { const fixed_t MAXCHARGESPEED = K_GetSpindashChargeSpeed(player); @@ -4074,7 +4082,7 @@ void K_InitStumbleIndicator(player_t *player) P_SetTarget(&new->target, player->mo); } -void K_InitSliptideZipIndicator(player_t *player) +void K_InitWavedashIndicator(player_t *player) { mobj_t *new = NULL; @@ -4088,14 +4096,14 @@ void K_InitSliptideZipIndicator(player_t *player) return; } - if (P_MobjWasRemoved(player->sliptideZipIndicator) == false) + if (P_MobjWasRemoved(player->wavedashIndicator) == false) { - P_RemoveMobj(player->sliptideZipIndicator); + P_RemoveMobj(player->wavedashIndicator); } - new = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_SLIPTIDEZIP); + new = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_WAVEDASH); - P_SetTarget(&player->sliptideZipIndicator, new); + P_SetTarget(&player->wavedashIndicator, new); P_SetTarget(&new->target, player->mo); } @@ -4250,11 +4258,11 @@ void K_UpdateStumbleIndicator(player_t *player) #define MIN_WAVEDASH_CHARGE ((7*TICRATE/16)*9) -static boolean K_IsLosingSliptideZip(player_t *player) +static boolean K_IsLosingWavedash(player_t *player) { if (player->mo == NULL || P_MobjWasRemoved(player->mo) == true) return true; - if (!K_Sliptiding(player) && player->sliptideZip < MIN_WAVEDASH_CHARGE) + if (!K_Sliptiding(player) && player->wavedash < MIN_WAVEDASH_CHARGE) return true; if (!K_Sliptiding(player) && player->drift == 0 && P_IsObjectOnGround(player->mo) && player->sneakertimer == 0 @@ -4263,7 +4271,7 @@ static boolean K_IsLosingSliptideZip(player_t *player) return false; } -void K_UpdateSliptideZipIndicator(player_t *player) +void K_UpdateWavedashIndicator(player_t *player) { mobj_t *mobj = NULL; @@ -4277,13 +4285,13 @@ void K_UpdateSliptideZipIndicator(player_t *player) return; } - if (player->sliptideZipIndicator == NULL || P_MobjWasRemoved(player->sliptideZipIndicator) == true) + if (player->wavedashIndicator == NULL || P_MobjWasRemoved(player->wavedashIndicator) == true) { - K_InitSliptideZipIndicator(player); + K_InitWavedashIndicator(player); return; } - mobj = player->sliptideZipIndicator; + mobj = player->wavedashIndicator; angle_t momentumAngle = K_MomentumAngle(player->mo); P_MoveOrigin(mobj, player->mo->x - FixedMul(40*mapobjectscale, FINECOSINE(momentumAngle >> ANGLETOFINESHIFT)), @@ -4293,7 +4301,7 @@ void K_UpdateSliptideZipIndicator(player_t *player) P_SetScale(mobj, 3 * player->mo->scale / 2); // No stored boost (or negligible enough that it might be a mistake) - if (player->sliptideZip <= HIDEWAVEDASHCHARGE) + if (player->wavedash <= HIDEWAVEDASHCHARGE) { mobj->renderflags |= RF_DONTDRAW; mobj->frame = 7; @@ -4302,8 +4310,8 @@ void K_UpdateSliptideZipIndicator(player_t *player) mobj->renderflags &= ~RF_DONTDRAW; - UINT32 chargeFrame = 7 - min(7, player->sliptideZip / 100); - UINT32 decayFrame = min(7, player->sliptideZipDelay / 2); + UINT32 chargeFrame = 7 - min(7, player->wavedash / 100); + UINT32 decayFrame = min(7, player->wavedashdelay / 2); if (max(chargeFrame, decayFrame) > mobj->frame) mobj->frame++; else if (max(chargeFrame, decayFrame) < mobj->frame) @@ -4312,7 +4320,7 @@ void K_UpdateSliptideZipIndicator(player_t *player) mobj->renderflags &= ~RF_TRANSMASK; mobj->renderflags |= RF_PAPERSPRITE; - if (K_IsLosingSliptideZip(player)) + if (K_IsLosingWavedash(player)) { // Decay timer's ticking mobj->rollangle += 3*ANG30/4; @@ -4324,6 +4332,17 @@ void K_UpdateSliptideZipIndicator(player_t *player) // Storing boost mobj->rollangle += 3*ANG15/4; } + + if (player->trickdash) + { + mobj->sprite = SPR_TRBS; + mobj->renderflags |= RF_ADD; + } + else + { + mobj->sprite = SPR_SLPT; + mobj->renderflags &= ~RF_ADD; + } } static mobj_t *K_TrickCatholocismBlast(mobj_t *trickIndicator, fixed_t destscale, angle_t rollangle) @@ -8107,7 +8126,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->sneakertimer || player->ringboost || player->driftboost || player->startboost || player->eggmanexplode || player->trickboost - || player->gateBoost || player->sliptideZipBoost) + || player->gateBoost || player->wavedashboost || player->trickdashboost) { #if 0 if (player->invincibilitytimer) @@ -8393,9 +8412,14 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->dropdashboost) player->dropdashboost--; - if (player->sliptideZipBoost > 0 && onground == true) + if (player->wavedashboost > 0 && onground == true) { - player->sliptideZipBoost--; + player->wavedashboost--; + } + + if (player->trickdashboost > 0 && onground == true) + { + player->trickdashboost--; } if (player->spindashboost) @@ -8864,7 +8888,7 @@ void K_KartPlayerAfterThink(player_t *player) K_KartResetPlayerColor(player); K_UpdateStumbleIndicator(player); - K_UpdateSliptideZipIndicator(player); + K_UpdateWavedashIndicator(player); K_UpdateTrickIndicator(player); // Move held objects (Bananas, Orbinaut, etc) @@ -9925,8 +9949,9 @@ static void K_KartDrift(player_t *player, boolean onground) player->drift = player->driftcharge = player->aizdriftstrat = 0; player->pflags &= ~(PF_BRAKEDRIFT|PF_GETSPARKS); // And take away wavedash properties: advanced cornering demands advanced finesse - player->sliptideZip = 0; - player->sliptideZipBoost = 0; + player->wavedash = 0; + player->wavedashboost = 0; + player->trickdashboost = 0; } else if ((player->pflags & PF_DRIFTINPUT) && player->drift != 0) { @@ -10028,11 +10053,11 @@ static void K_KartDrift(player_t *player, boolean onground) || (!player->aizdriftstrat) || (player->steering > 0) != (player->aizdriftstrat > 0)) { - if (!player->drift && player->steering && player->aizdriftstrat && player->sliptideZip // If we were sliptiding last tic, + if (!player->drift && player->steering && player->aizdriftstrat && player->wavedash // If we were sliptiding last tic, && (player->steering > 0) == (player->aizdriftstrat > 0) // we're steering in the right direction, && player->speed >= K_GetKartSpeed(player, false, true)) // and we're above the threshold to spawn dust... { - keepsliptide = true; // Then keep your current sliptide, but note the behavior change for sliptidezip handling. + keepsliptide = true; // Then keep your current sliptide, but note the behavior change for wavedash handling. } else { @@ -10060,9 +10085,9 @@ static void K_KartDrift(player_t *player, boolean onground) // This makes wavedash charge noticeably slower on even modest delay, despite the magnitude of the turn seeming the same. // So we only require 90% of a turn to get full charge strength. - player->sliptideZip += addCharge; + player->wavedash += addCharge; - if (player->sliptideZip >= MIN_WAVEDASH_CHARGE && (player->sliptideZip - addCharge) < MIN_WAVEDASH_CHARGE) + if (player->wavedash >= MIN_WAVEDASH_CHARGE && (player->wavedash - addCharge) < MIN_WAVEDASH_CHARGE) S_StartSound(player->mo, sfx_waved5); } @@ -10088,16 +10113,16 @@ static void K_KartDrift(player_t *player, boolean onground) if (!K_Sliptiding(player) || keepsliptide) { - if (!keepsliptide && K_IsLosingSliptideZip(player) && player->sliptideZip > 0) + if (!keepsliptide && K_IsLosingWavedash(player) && player->wavedash > 0) { - if (player->sliptideZip > HIDEWAVEDASHCHARGE && !S_SoundPlaying(player->mo, sfx_waved2)) + if (player->wavedash > HIDEWAVEDASHCHARGE && !S_SoundPlaying(player->mo, sfx_waved2)) S_StartSoundAtVolume(player->mo, sfx_waved2, 255); // Losing combo time, going to boost S_StopSoundByID(player->mo, sfx_waved1); S_StopSoundByID(player->mo, sfx_waved4); - player->sliptideZipDelay++; - if (player->sliptideZipDelay > TICRATE/2) + player->wavedashdelay++; + if (player->wavedashdelay > TICRATE/2) { - if (player->sliptideZip >= MIN_WAVEDASH_CHARGE) + if (player->wavedash >= MIN_WAVEDASH_CHARGE) { fixed_t maxZipPower = 2*FRACUNIT; fixed_t minZipPower = 1*FRACUNIT; @@ -10112,30 +10137,36 @@ static void K_KartDrift(player_t *player, boolean onground) fixed_t yourPowerReduction = FixedDiv(yourPenalty * FRACUNIT, penaltySpread * FRACUNIT); fixed_t yourPower = maxZipPower - FixedMul(yourPowerReduction, powerSpread); - int yourBoost = FixedInt(FixedMul(yourPower, player->sliptideZip/10 * FRACUNIT)); + int yourBoost = FixedInt(FixedMul(yourPower, player->wavedash/10 * FRACUNIT)); - /* - CONS_Printf("SZ %d MZ %d mZ %d pwS %d mP %d MP %d peS %d yPe %d yPR %d yPw %d yB %d\n", - player->sliptideZip, maxZipPower, minZipPower, powerSpread, minPenalty, maxPenalty, penaltySpread, yourPenalty, yourPowerReduction, yourPower, yourBoost); - */ + if (player->trickdash) + { + player->trickdashboost += 3*yourBoost/2; + S_StartSoundAtVolume(player->mo, sfx_gshba, 255); + } + else + { + player->wavedashboost += yourBoost; + } - player->sliptideZipBoost += yourBoost; + S_StartSoundAtVolume(player->mo, sfx_waved3, 255); // Boost + + player->trickdash = 0; K_SpawnDriftBoostExplosion(player, 0); - S_StartSoundAtVolume(player->mo, sfx_waved3, 255); // Boost } S_StopSoundByID(player->mo, sfx_waved1); S_StopSoundByID(player->mo, sfx_waved2); S_StopSoundByID(player->mo, sfx_waved4); - player->sliptideZip = 0; - player->sliptideZipDelay = 0; + player->wavedash = 0; + player->wavedashdelay = 0; } } else { S_StopSoundByID(player->mo, sfx_waved1); S_StopSoundByID(player->mo, sfx_waved2); - if (player->sliptideZip > 0 && !S_SoundPlaying(player->mo, sfx_waved4)) + if (player->wavedash > 0 && !S_SoundPlaying(player->mo, sfx_waved4)) S_StartSoundAtVolume(player->mo, sfx_waved4, 255); // Passive woosh } @@ -10149,10 +10180,10 @@ static void K_KartDrift(player_t *player, boolean onground) } else { - player->sliptideZipDelay = 0; + player->wavedashdelay = 0; S_StopSoundByID(player->mo, sfx_waved2); S_StopSoundByID(player->mo, sfx_waved4); - if (player->sliptideZip > HIDEWAVEDASHCHARGE && !S_SoundPlaying(player->mo, sfx_waved1)) + if (player->wavedash > HIDEWAVEDASHCHARGE && !S_SoundPlaying(player->mo, sfx_waved1)) S_StartSoundAtVolume(player->mo, sfx_waved1, 255); // Charging } @@ -10711,7 +10742,7 @@ static void K_KartSpindashWind(mobj_t *parent) P_SetTarget(&wind->target, parent); - if (parent->player && parent->player->sliptideZipBoost) + if (parent->player && parent->player->wavedashboost) P_SetScale(wind, wind->scale * 2); if (parent->momx || parent->momy) @@ -10775,7 +10806,7 @@ static void K_KartSpindash(player_t *player) K_KartSpindashWind(player->mo); } - if ((player->sliptideZipBoost > 0) && (spawnWind == true)) + if ((player->wavedashboost > 0 || player->trickdashboost > 0) && (spawnWind == true)) { K_KartSpindashWind(player->mo); } @@ -11885,7 +11916,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (player->throwdir == -1) { P_InstaThrust(player->mo, player->mo->angle, player->speed + (80 * mapobjectscale)); - player->sliptideZipBoost += TICRATE; // Just for keeping speed briefly vs. tripwire etc. + player->wavedashboost += TICRATE; // Just for keeping speed briefly vs. tripwire etc. // If this doesn't turn out to be reliable, I'll change it to directly set leniency or something. } K_PlayAttackTaunt(player->mo); @@ -12218,6 +12249,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { S_StartSound(player->mo, sfx_trick0); player->dotrickfx = true; + player->trickboostdecay = min(TICRATE*3/4, abs(momz/FRACUNIT)); if (cmd->turning > 0) { @@ -12252,6 +12284,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { S_StartSound(player->mo, sfx_trick0); player->dotrickfx = true; + player->trickboostdecay = min(TICRATE*3/4, abs(momz/FRACUNIT)); if (cmd->throwdir > 0) // forward trick { @@ -12366,24 +12399,31 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } else if ((player->trickpanel != TRICKSTATE_NONE) && P_IsObjectOnGround(player->mo)) // Landed from trick { + K_SpawnDashDustRelease(player); + if (player->fastfall) { + P_InstaThrust(player->mo, player->mo->angle, 2*abs(player->fastfall)/3 + 15*FRACUNIT); player->mo->hitlag = 3; - K_SpawnDashDustRelease(player); - P_InstaThrust(player->mo, player->mo->angle, 30*FRACUNIT); - S_StartSound(player->mo, sfx_gshce); + S_StartSound(player->mo, sfx_gshac); // TODO player->fastfall = 0; // intentionally skip bounce } - - if (player->trickpanel == TRICKSTATE_BACK) // upward trick + else { S_StartSound(player->mo, sfx_s23c); K_SpawnDashDustRelease(player); player->trickboost = TICRATE - player->trickboostdecay; - } + player->wavedash += 150; // bonus for the slow fall + //player->wavedashdelay = TICRATE/2 - 2; + player->wavedashdelay = 0; - player->sliptideZip += 300; - player->sliptideZipDelay = 0; + if (player->trickpanel == TRICKSTATE_FORWARD) + player->trickboostpower /= 18; + else if (player->trickpanel != TRICKSTATE_BACK) + player->trickboostpower /= 9; + + player->trickdash = true; + } player->trickpanel = TRICKSTATE_NONE; player->trickboostdecay = 0; diff --git a/src/k_kart.h b/src/k_kart.h index 3f6293bba..d5782e550 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -119,10 +119,10 @@ angle_t K_StumbleSlope(angle_t angle, angle_t pitch, angle_t roll); void K_StumblePlayer(player_t *player); boolean K_CheckStumble(player_t *player, angle_t oldPitch, angle_t oldRoll, boolean fromAir); void K_InitStumbleIndicator(player_t *player); -void K_InitSliptideZipIndicator(player_t *player); +void K_InitWavedashIndicator(player_t *player); void K_InitTrickIndicator(player_t *player); void K_UpdateStumbleIndicator(player_t *player); -void K_UpdateSliptideZipIndicator(player_t *player); +void K_UpdateWavedashIndicator(player_t *player); void K_UpdateTrickIndicator(player_t *player); INT32 K_ExplodePlayer(player_t *player, mobj_t *inflictor, mobj_t *source); void K_DebtStingPlayer(player_t *player, mobj_t *source); diff --git a/src/k_respawn.c b/src/k_respawn.c index 21af8253d..107e7c7ed 100644 --- a/src/k_respawn.c +++ b/src/k_respawn.c @@ -156,7 +156,8 @@ void K_DoIngameRespawn(player_t *player) player->ringboost = 0; player->driftboost = player->strongdriftboost = 0; player->gateBoost = 0; - player->sliptideZip = player->sliptideZipBoost = player->sliptideZipDelay = 0; + player->trickdash = 0; + player->wavedash = player->wavedashboost = player->wavedashdelay = player->trickdashboost = 0; K_TumbleInterrupt(player); P_ResetPlayer(player); diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 0bda04838..6314665b9 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -325,12 +325,16 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->tripwireLeniency); else if (fastcmp(field,"tripwireReboundDelay")) lua_pushinteger(L, plr->tripwireReboundDelay); - else if (fastcmp(field,"sliptideZip")) - lua_pushinteger(L, plr->sliptideZip); - else if (fastcmp(field,"sliptideZipDelay")) - lua_pushinteger(L, plr->sliptideZipDelay); - else if (fastcmp(field,"sliptideZipBoost")) - lua_pushinteger(L, plr->sliptideZipBoost); + else if (fastcmp(field,"wavedash")) + lua_pushinteger(L, plr->wavedash); + else if (fastcmp(field,"wavedashdelay")) + lua_pushinteger(L, plr->wavedashdelay); + else if (fastcmp(field,"wavedashboost")) + lua_pushinteger(L, plr->wavedashboost); + else if (fastcmp(field,"trickdashboost")) + lua_pushinteger(L, plr->trickdashboost); + else if (fastcmp(field,"trickdash")) + lua_pushinteger(L, plr->trickdash); else if (fastcmp(field,"lastsafelap")) lua_pushinteger(L, plr->lastsafelap); else if (fastcmp(field,"instaWhipCharge")) @@ -809,12 +813,16 @@ static int player_set(lua_State *L) plr->tripwireLeniency = luaL_checkinteger(L, 3); else if (fastcmp(field,"tripwireReboundDelay")) plr->tripwireReboundDelay = luaL_checkinteger(L, 3); - else if (fastcmp(field,"sliptideZip")) - plr->sliptideZip = luaL_checkinteger(L, 3); - else if (fastcmp(field,"sliptideZipDelay")) - plr->sliptideZipDelay = luaL_checkinteger(L, 3); - else if (fastcmp(field,"sliptideZipBoost")) - plr->sliptideZipBoost = luaL_checkinteger(L, 3); + else if (fastcmp(field,"wavedash")) + plr->wavedash = luaL_checkinteger(L, 3); + else if (fastcmp(field,"wavedashdelay")) + plr->wavedashdelay = luaL_checkinteger(L, 3); + else if (fastcmp(field,"wavedashboost")) + plr->wavedashboost = luaL_checkinteger(L, 3); + else if (fastcmp(field,"trickdashboost")) + plr->trickdashboost = luaL_checkinteger(L, 3); + else if (fastcmp(field,"trickdash")) + plr->trickdash = luaL_checkinteger(L, 3); else if (fastcmp(field,"lastsafelap")) plr->lastsafelap = luaL_checkinteger(L, 3); else if (fastcmp(field,"instaWhipCharge")) diff --git a/src/p_inter.c b/src/p_inter.c index fc7458ad6..2d1f7b0ff 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2558,7 +2558,7 @@ static boolean P_KillPlayer(player_t *player, mobj_t *inflictor, mobj_t *source, } PlayerPointerRemove(player->stumbleIndicator); - PlayerPointerRemove(player->sliptideZipIndicator); + PlayerPointerRemove(player->wavedashIndicator); PlayerPointerRemove(player->trickIndicator); #undef PlayerPointerRemove diff --git a/src/p_mobj.c b/src/p_mobj.c index efb668fec..565647cb7 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -12543,7 +12543,7 @@ void P_SpawnPlayer(INT32 playernum) p->griefValue = 0; K_InitStumbleIndicator(p); - K_InitSliptideZipIndicator(p); + K_InitWavedashIndicator(p); K_InitTrickIndicator(p); if (gametyperules & GTR_ITEMARROWS) diff --git a/src/p_saveg.c b/src/p_saveg.c index 1860b84e8..f86cf2c3d 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -75,7 +75,7 @@ typedef enum SKYBOXCENTER = 0x0010, HOVERHYUDORO = 0x0020, STUMBLE = 0x0040, - SLIPTIDEZIP = 0x0080, + WAVEDASH = 0x0080, RINGSHOOTER = 0x0100, WHIP = 0x0200, HAND = 0x0400, @@ -311,8 +311,8 @@ static void P_NetArchivePlayers(savebuffer_t *save) if (players[i].stumbleIndicator) flags |= STUMBLE; - if (players[i].sliptideZipIndicator) - flags |= SLIPTIDEZIP; + if (players[i].wavedashIndicator) + flags |= WAVEDASH; if (players[i].trickIndicator) flags |= TRICKINDICATOR; @@ -352,8 +352,8 @@ static void P_NetArchivePlayers(savebuffer_t *save) if (flags & STUMBLE) WRITEUINT32(save->p, players[i].stumbleIndicator->mobjnum); - if (flags & SLIPTIDEZIP) - WRITEUINT32(save->p, players[i].sliptideZipIndicator->mobjnum); + if (flags & WAVEDASH) + WRITEUINT32(save->p, players[i].wavedashIndicator->mobjnum); if (flags & TRICKINDICATOR) WRITEUINT32(save->p, players[i].trickIndicator->mobjnum); @@ -542,9 +542,11 @@ static void P_NetArchivePlayers(savebuffer_t *save) WRITEUINT8(save->p, players[i].tripwireReboundDelay); - WRITEUINT16(save->p, players[i].sliptideZip); - WRITEUINT8(save->p, players[i].sliptideZipDelay); - WRITEUINT16(save->p, players[i].sliptideZipBoost); + WRITEUINT16(save->p, players[i].wavedash); + WRITEUINT8(save->p, players[i].wavedashdelay); + WRITEUINT16(save->p, players[i].wavedashboost); + WRITEUINT8(save->p, players[i].trickdash); + WRITEUINT16(save->p, players[i].trickdashboost); WRITEUINT8(save->p, players[i].lastsafelap); @@ -869,8 +871,8 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) if (flags & STUMBLE) players[i].stumbleIndicator = (mobj_t *)(size_t)READUINT32(save->p); - if (flags & SLIPTIDEZIP) - players[i].sliptideZipIndicator = (mobj_t *)(size_t)READUINT32(save->p); + if (flags & WAVEDASH) + players[i].wavedashIndicator = (mobj_t *)(size_t)READUINT32(save->p); if (flags & TRICKINDICATOR) players[i].trickIndicator = (mobj_t *)(size_t)READUINT32(save->p); @@ -1060,9 +1062,11 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) players[i].tripwireReboundDelay = READUINT8(save->p); - players[i].sliptideZip = READUINT16(save->p); - players[i].sliptideZipDelay = READUINT8(save->p); - players[i].sliptideZipBoost = READUINT16(save->p); + players[i].wavedash = READUINT16(save->p); + players[i].wavedashdelay = READUINT8(save->p); + players[i].wavedashboost = READUINT16(save->p); + players[i].trickdash = READUINT8(save->p); + players[i].trickdashboost = READUINT16(save->p); players[i].lastsafelap = READUINT8(save->p); @@ -5600,12 +5604,12 @@ static void P_RelinkPointers(void) if (!P_SetTarget(&players[i].stumbleIndicator, P_FindNewPosition(temp))) CONS_Debug(DBG_GAMELOGIC, "stumbleIndicator not found on player %d\n", i); } - if (players[i].sliptideZipIndicator) + if (players[i].wavedashIndicator) { - temp = (UINT32)(size_t)players[i].sliptideZipIndicator; - players[i].sliptideZipIndicator = NULL; - if (!P_SetTarget(&players[i].sliptideZipIndicator, P_FindNewPosition(temp))) - CONS_Debug(DBG_GAMELOGIC, "sliptideZipIndicator not found on player %d\n", i); + temp = (UINT32)(size_t)players[i].wavedashIndicator; + players[i].wavedashIndicator = NULL; + if (!P_SetTarget(&players[i].wavedashIndicator, P_FindNewPosition(temp))) + CONS_Debug(DBG_GAMELOGIC, "wavedashIndicator not found on player %d\n", i); } if (players[i].trickIndicator) { diff --git a/src/p_user.c b/src/p_user.c index 81a5cd555..ef505d934 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4000,7 +4000,7 @@ void P_PlayerThink(player_t *player) PlayerPointerErase(player->followmobj); PlayerPointerErase(player->stumbleIndicator); - PlayerPointerErase(player->sliptideZipIndicator); + PlayerPointerErase(player->wavedashIndicator); PlayerPointerErase(player->trickIndicator); PlayerPointerErase(player->whip); PlayerPointerErase(player->hand); From c11394ce835006a31f9c71e5f5c4d3807e7a1a65 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Thu, 9 Nov 2023 00:45:50 -0700 Subject: [PATCH 33/88] WIP: Trick panel decrackening --- src/d_player.h | 6 ++++-- src/k_kart.c | 47 +++++++++++++++++++++++++++++++++++++++------ src/k_respawn.c | 1 + src/lua_playerlib.c | 20 +++++++++++-------- src/p_saveg.c | 2 ++ 5 files changed, 60 insertions(+), 16 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index bd951e7c7..a021290cf 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -898,8 +898,10 @@ struct player_t UINT16 wavedash; // How long is our chained sliptide? Grant a proportional boost when it's over. UINT8 wavedashdelay; // How long since the last sliptide? Only boost once you've been straightened out for a bit. UINT16 wavedashboost; // The actual boost granted from wavedash. - UINT16 trickdashboost; // The actual boost granted from wavedash. - boolean trickdash; + UINT16 trickdashboost; // Trickdashes grant a snappier boost that permits sliptide. [UNUSED, TOO MUCH CRACK] + boolean trickdash; // Is the wavedash we're charging right now getting upgraded to a trickdash? [UNUSED] + + UINT16 trickcharge; // Landed normally from a trick panel? Get the benefits package! UINT8 lastsafelap; diff --git a/src/k_kart.c b/src/k_kart.c index ff5d6e34f..e212dc6ae 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1266,6 +1266,9 @@ static boolean K_HasInfiniteTether(player_t *player) if (player->trickdash) return true; + if (player->trickcharge) + return true; + return false; } @@ -3245,6 +3248,11 @@ static void K_GetKartBoostPower(player_t *player) ADDBOOST(8*FRACUNIT/10, 8*FRACUNIT, 3*SLIPTIDEHANDLING/5); // + 80% top speed, + 800% acceleration, +30% handling } + if (player->trickcharge) + { + ADDBOOST(0, 0, 2*SLIPTIDEHANDLING/10); // 0% speed 0% accel 20% handle + } + if (player->spindashboost) // Spindash boost { const fixed_t MAXCHARGESPEED = K_GetSpindashChargeSpeed(player); @@ -8422,6 +8430,13 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->trickdashboost--; } + if (player->trickcharge > 0 && onground == true) + { + player->trickcharge--; + if (player->drift) + player->trickcharge = max(player->trickcharge, 1); + } + if (player->spindashboost) { player->spindashboost--; @@ -8853,6 +8868,14 @@ void K_KartResetPlayerColor(player_t *player) } } + if (player->trickcharge && (leveltime & 1)) + { + player->mo->colorized = true; + player->mo->color = SKINCOLOR_INVINCFLASH; + fullbright = true; + goto finalise; + } + if (player->ringboost && (leveltime & 1)) // ring boosting { player->mo->colorized = true; @@ -9899,6 +9922,15 @@ static void K_KartDrift(player_t *player, boolean onground) K_SpawnDriftBoostExplosion(player, 4); K_SpawnDriftElectricSparks(player, K_DriftSparkColor(player, player->driftcharge), false); } + + if (player->trickcharge) + { + player->driftboost += 20; + player->wavedashboost += 10; + P_Thrust(player->mo, pushdir, player->speed / 2); + S_StartSound(player->mo, sfx_gshba); + player->trickcharge = 0; + } } // Remove charge @@ -10017,6 +10049,9 @@ static void K_KartDrift(player_t *player, boolean onground) driftadditive = 0; } + if (player->trickcharge && driftadditive) + driftadditive += 24; + // This spawns the drift sparks if ((player->driftcharge + driftadditive >= dsone) || (player->driftcharge < 0)) @@ -12412,17 +12447,17 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { S_StartSound(player->mo, sfx_s23c); K_SpawnDashDustRelease(player); - player->trickboost = TICRATE - player->trickboostdecay; - player->wavedash += 150; // bonus for the slow fall - //player->wavedashdelay = TICRATE/2 - 2; - player->wavedashdelay = 0; + + UINT8 award = TICRATE - player->trickboostdecay; + + //player->trickboost = award; + player->trickcharge += award*4; + K_AwardPlayerRings(player, award/2, true); if (player->trickpanel == TRICKSTATE_FORWARD) player->trickboostpower /= 18; else if (player->trickpanel != TRICKSTATE_BACK) player->trickboostpower /= 9; - - player->trickdash = true; } player->trickpanel = TRICKSTATE_NONE; diff --git a/src/k_respawn.c b/src/k_respawn.c index 107e7c7ed..f7873e90a 100644 --- a/src/k_respawn.c +++ b/src/k_respawn.c @@ -157,6 +157,7 @@ void K_DoIngameRespawn(player_t *player) player->driftboost = player->strongdriftboost = 0; player->gateBoost = 0; player->trickdash = 0; + player->trickcharge = 0; player->wavedash = player->wavedashboost = player->wavedashdelay = player->trickdashboost = 0; K_TumbleInterrupt(player); diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 6314665b9..d77880391 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -331,10 +331,12 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->wavedashdelay); else if (fastcmp(field,"wavedashboost")) lua_pushinteger(L, plr->wavedashboost); - else if (fastcmp(field,"trickdashboost")) - lua_pushinteger(L, plr->trickdashboost); - else if (fastcmp(field,"trickdash")) - lua_pushinteger(L, plr->trickdash); + else if (fastcmp(field,"trickcharge")) + lua_pushinteger(L, plr->trickcharge); + //else if (fastcmp(field,"trickdashboost")) + // lua_pushinteger(L, plr->trickdashboost); + //else if (fastcmp(field,"trickdash")) + // lua_pushinteger(L, plr->trickdash); else if (fastcmp(field,"lastsafelap")) lua_pushinteger(L, plr->lastsafelap); else if (fastcmp(field,"instaWhipCharge")) @@ -819,10 +821,12 @@ static int player_set(lua_State *L) plr->wavedashdelay = luaL_checkinteger(L, 3); else if (fastcmp(field,"wavedashboost")) plr->wavedashboost = luaL_checkinteger(L, 3); - else if (fastcmp(field,"trickdashboost")) - plr->trickdashboost = luaL_checkinteger(L, 3); - else if (fastcmp(field,"trickdash")) - plr->trickdash = luaL_checkinteger(L, 3); + else if (fastcmp(field,"trickcharge")) + plr->trickcharge = luaL_checkinteger(L, 3); + //else if (fastcmp(field,"trickdashboost")) + // plr->trickdashboost = luaL_checkinteger(L, 3); + //else if (fastcmp(field,"trickdash")) + // plr->trickdash = luaL_checkinteger(L, 3); else if (fastcmp(field,"lastsafelap")) plr->lastsafelap = luaL_checkinteger(L, 3); else if (fastcmp(field,"instaWhipCharge")) diff --git a/src/p_saveg.c b/src/p_saveg.c index f86cf2c3d..30668eb3f 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -547,6 +547,7 @@ static void P_NetArchivePlayers(savebuffer_t *save) WRITEUINT16(save->p, players[i].wavedashboost); WRITEUINT8(save->p, players[i].trickdash); WRITEUINT16(save->p, players[i].trickdashboost); + WRITEUINT16(save->p, players[i].trickcharge); WRITEUINT8(save->p, players[i].lastsafelap); @@ -1067,6 +1068,7 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) players[i].wavedashboost = READUINT16(save->p); players[i].trickdash = READUINT8(save->p); players[i].trickdashboost = READUINT16(save->p); + players[i].trickcharge = READUINT16(save->p); players[i].lastsafelap = READUINT8(save->p); From 19edcbe9c2333e1863ac33c0d57e06d66f31abd7 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Thu, 9 Nov 2023 02:02:41 -0700 Subject: [PATCH 34/88] WIP: Trickpanel crack IV --- src/d_player.h | 4 +-- src/k_kart.c | 84 ++++++++++++++++++--------------------------- src/k_respawn.c | 4 +-- src/lua_playerlib.c | 12 +++---- src/p_saveg.c | 8 ++--- 5 files changed, 45 insertions(+), 67 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index a021290cf..d31874e76 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -898,11 +898,11 @@ struct player_t UINT16 wavedash; // How long is our chained sliptide? Grant a proportional boost when it's over. UINT8 wavedashdelay; // How long since the last sliptide? Only boost once you've been straightened out for a bit. UINT16 wavedashboost; // The actual boost granted from wavedash. - UINT16 trickdashboost; // Trickdashes grant a snappier boost that permits sliptide. [UNUSED, TOO MUCH CRACK] - boolean trickdash; // Is the wavedash we're charging right now getting upgraded to a trickdash? [UNUSED] UINT16 trickcharge; // Landed normally from a trick panel? Get the benefits package! + UINT16 infinitether; // Generic infinitether time, used for infinitether leniency. + UINT8 lastsafelap; mobj_t *stumbleIndicator; diff --git a/src/k_kart.c b/src/k_kart.c index e212dc6ae..904ed2b56 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1263,10 +1263,10 @@ static boolean K_HasInfiniteTether(player_t *player) if (player->eggmanexplode > 0) return true; - if (player->trickdash) + if (player->trickcharge) return true; - if (player->trickcharge) + if (player->infinitether) return true; return false; @@ -1887,9 +1887,9 @@ static void K_SpawnGenericSpeedLines(player_t *player, boolean top) fast->colorized = true; fast->renderflags |= RF_ADD; } - else if (player->wavedashboost || player->trickdashboost) + else if (player->wavedashboost) { - fast->color = (player->trickdashboost) ? K_RainbowColor(leveltime) : SKINCOLOR_WHITE; + fast->color = SKINCOLOR_WHITE; fast->colorized = true; } else if (player->ringboost) @@ -3243,14 +3243,9 @@ static void K_GetKartBoostPower(player_t *player) ADDBOOST(8*FRACUNIT/10, 4*FRACUNIT, 2*SLIPTIDEHANDLING/5); // + 80% top speed, + 400% acceleration, +20% handling } - if (player->trickdashboost) - { - ADDBOOST(8*FRACUNIT/10, 8*FRACUNIT, 3*SLIPTIDEHANDLING/5); // + 80% top speed, + 800% acceleration, +30% handling - } - if (player->trickcharge) { - ADDBOOST(0, 0, 2*SLIPTIDEHANDLING/10); // 0% speed 0% accel 20% handle + ADDBOOST(0, FRACUNIT, 2*SLIPTIDEHANDLING/10); // 0% speed 100% accel 20% handle } if (player->spindashboost) // Spindash boost @@ -4340,17 +4335,6 @@ void K_UpdateWavedashIndicator(player_t *player) // Storing boost mobj->rollangle += 3*ANG15/4; } - - if (player->trickdash) - { - mobj->sprite = SPR_TRBS; - mobj->renderflags |= RF_ADD; - } - else - { - mobj->sprite = SPR_SLPT; - mobj->renderflags &= ~RF_ADD; - } } static mobj_t *K_TrickCatholocismBlast(mobj_t *trickIndicator, fixed_t destscale, angle_t rollangle) @@ -8134,7 +8118,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->sneakertimer || player->ringboost || player->driftboost || player->startboost || player->eggmanexplode || player->trickboost - || player->gateBoost || player->wavedashboost || player->trickdashboost) + || player->gateBoost || player->wavedashboost) { #if 0 if (player->invincibilitytimer) @@ -8425,11 +8409,6 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->wavedashboost--; } - if (player->trickdashboost > 0 && onground == true) - { - player->trickdashboost--; - } - if (player->trickcharge > 0 && onground == true) { player->trickcharge--; @@ -8437,6 +8416,11 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->trickcharge = max(player->trickcharge, 1); } + if (player->infinitether > 0) + { + player->infinitether--; + } + if (player->spindashboost) { player->spindashboost--; @@ -8549,6 +8533,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->dotrickfx && !player->mo->hitlag) { S_StartSound(player->mo, sfx_trick1); + player->trickcharge = 8*TICRATE; player->dotrickfx = false; } @@ -9845,6 +9830,8 @@ static void K_KartDrift(player_t *player, boolean onground) const UINT16 buttons = K_GetKartButtons(player); + boolean dokicker = false; + // Drifting is actually straffing + automatic turning. // Holding the Jump button will enable drifting. // (This comment is extremely funny) @@ -9907,6 +9894,7 @@ static void K_KartDrift(player_t *player, boolean onground) K_SpawnDriftBoostExplosion(player, 3); K_SpawnDriftElectricSparks(player, K_DriftSparkColor(player, player->driftcharge), false); + dokicker = true; } else if (player->driftcharge >= dsfour) { @@ -9921,15 +9909,17 @@ static void K_KartDrift(player_t *player, boolean onground) K_SpawnDriftBoostExplosion(player, 4); K_SpawnDriftElectricSparks(player, K_DriftSparkColor(player, player->driftcharge), false); + dokicker = true; } - if (player->trickcharge) + if (player->trickcharge && dokicker) { player->driftboost += 20; player->wavedashboost += 10; P_Thrust(player->mo, pushdir, player->speed / 2); S_StartSound(player->mo, sfx_gshba); player->trickcharge = 0; + player->infinitether = TICRATE*2; } } @@ -9983,7 +9973,6 @@ static void K_KartDrift(player_t *player, boolean onground) // And take away wavedash properties: advanced cornering demands advanced finesse player->wavedash = 0; player->wavedashboost = 0; - player->trickdashboost = 0; } else if ((player->pflags & PF_DRIFTINPUT) && player->drift != 0) { @@ -10050,7 +10039,7 @@ static void K_KartDrift(player_t *player, boolean onground) } if (player->trickcharge && driftadditive) - driftadditive += 24; + driftadditive += 16; // This spawns the drift sparks if ((player->driftcharge + driftadditive >= dsone) @@ -10174,20 +10163,10 @@ static void K_KartDrift(player_t *player, boolean onground) fixed_t yourPower = maxZipPower - FixedMul(yourPowerReduction, powerSpread); int yourBoost = FixedInt(FixedMul(yourPower, player->wavedash/10 * FRACUNIT)); - if (player->trickdash) - { - player->trickdashboost += 3*yourBoost/2; - S_StartSoundAtVolume(player->mo, sfx_gshba, 255); - } - else - { - player->wavedashboost += yourBoost; - } + player->wavedashboost += yourBoost; S_StartSoundAtVolume(player->mo, sfx_waved3, 255); // Boost - player->trickdash = 0; - K_SpawnDriftBoostExplosion(player, 0); } S_StopSoundByID(player->mo, sfx_waved1); @@ -10841,7 +10820,7 @@ static void K_KartSpindash(player_t *player) K_KartSpindashWind(player->mo); } - if ((player->wavedashboost > 0 || player->trickdashboost > 0) && (spawnWind == true)) + if ((player->wavedashboost > 0) && (spawnWind == true)) { K_KartSpindashWind(player->mo); } @@ -12284,6 +12263,10 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { S_StartSound(player->mo, sfx_trick0); player->dotrickfx = true; + + // Calculate speed boost decay: + // Base speed boost duration is 35 tics. + // At most, lose 3/4th of your boost. player->trickboostdecay = min(TICRATE*3/4, abs(momz/FRACUNIT)); if (cmd->turning > 0) @@ -12319,10 +12302,15 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { S_StartSound(player->mo, sfx_trick0); player->dotrickfx = true; + + // Calculate speed boost decay: + // Base speed boost duration is 35 tics. + // At most, lose 3/4th of your boost. player->trickboostdecay = min(TICRATE*3/4, abs(momz/FRACUNIT)); if (cmd->throwdir > 0) // forward trick { + if (player->mo->momz * P_MobjFlip(player->mo) > 0) { player->mo->momz = 0; @@ -12348,12 +12336,6 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->mo->momz = 0; // relative = false; } - // Calculate speed boost decay: - // Base speed boost duration is 35 tics. - // At most, lose 3/4th of your boost. - player->trickboostdecay = min(TICRATE*3/4, abs(momz/FRACUNIT)); - //CONS_Printf("decay: %d\n", player->trickboostdecay); - player->mo->momz += P_MobjFlip(player->mo)*48*mapobjectscale; player->trickpanel = TRICKSTATE_BACK; @@ -12442,6 +12424,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->mo->hitlag = 3; S_StartSound(player->mo, sfx_gshac); // TODO player->fastfall = 0; // intentionally skip bounce + player->trickcharge = 0; } else { @@ -12450,9 +12433,8 @@ void K_MoveKartPlayer(player_t *player, boolean onground) UINT8 award = TICRATE - player->trickboostdecay; - //player->trickboost = award; - player->trickcharge += award*4; - K_AwardPlayerRings(player, award/2, true); + player->trickboost = award; + K_AwardPlayerRings(player, award, true); if (player->trickpanel == TRICKSTATE_FORWARD) player->trickboostpower /= 18; diff --git a/src/k_respawn.c b/src/k_respawn.c index f7873e90a..946a62c08 100644 --- a/src/k_respawn.c +++ b/src/k_respawn.c @@ -156,9 +156,9 @@ void K_DoIngameRespawn(player_t *player) player->ringboost = 0; player->driftboost = player->strongdriftboost = 0; player->gateBoost = 0; - player->trickdash = 0; player->trickcharge = 0; - player->wavedash = player->wavedashboost = player->wavedashdelay = player->trickdashboost = 0; + player->infinitether = 0; + player->wavedash = player->wavedashboost = player->wavedashdelay = 0; K_TumbleInterrupt(player); P_ResetPlayer(player); diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index d77880391..48f5739e2 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -333,10 +333,8 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->wavedashboost); else if (fastcmp(field,"trickcharge")) lua_pushinteger(L, plr->trickcharge); - //else if (fastcmp(field,"trickdashboost")) - // lua_pushinteger(L, plr->trickdashboost); - //else if (fastcmp(field,"trickdash")) - // lua_pushinteger(L, plr->trickdash); + else if (fastcmp(field,"infinitether")) + lua_pushinteger(L, plr->infinitether); else if (fastcmp(field,"lastsafelap")) lua_pushinteger(L, plr->lastsafelap); else if (fastcmp(field,"instaWhipCharge")) @@ -823,10 +821,8 @@ static int player_set(lua_State *L) plr->wavedashboost = luaL_checkinteger(L, 3); else if (fastcmp(field,"trickcharge")) plr->trickcharge = luaL_checkinteger(L, 3); - //else if (fastcmp(field,"trickdashboost")) - // plr->trickdashboost = luaL_checkinteger(L, 3); - //else if (fastcmp(field,"trickdash")) - // plr->trickdash = luaL_checkinteger(L, 3); + else if (fastcmp(field,"infinitether")) + plr->infinitether = luaL_checkinteger(L, 3); else if (fastcmp(field,"lastsafelap")) plr->lastsafelap = luaL_checkinteger(L, 3); else if (fastcmp(field,"instaWhipCharge")) diff --git a/src/p_saveg.c b/src/p_saveg.c index 30668eb3f..5f89f86db 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -545,10 +545,10 @@ static void P_NetArchivePlayers(savebuffer_t *save) WRITEUINT16(save->p, players[i].wavedash); WRITEUINT8(save->p, players[i].wavedashdelay); WRITEUINT16(save->p, players[i].wavedashboost); - WRITEUINT8(save->p, players[i].trickdash); - WRITEUINT16(save->p, players[i].trickdashboost); WRITEUINT16(save->p, players[i].trickcharge); + WRITEUINT16(save->p, players[i].infinitether); + WRITEUINT8(save->p, players[i].lastsafelap); WRITEMEM(save->p, players[i].public_key, PUBKEYLENGTH); @@ -1066,10 +1066,10 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) players[i].wavedash = READUINT16(save->p); players[i].wavedashdelay = READUINT8(save->p); players[i].wavedashboost = READUINT16(save->p); - players[i].trickdash = READUINT8(save->p); - players[i].trickdashboost = READUINT16(save->p); players[i].trickcharge = READUINT16(save->p); + players[i].infinitether = READUINT16(save->p); + players[i].lastsafelap = READUINT8(save->p); READMEM(save->p, players[i].public_key, PUBKEYLENGTH); From 06bc06869c7b96970fc2e8165065d960beb31873 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Thu, 9 Nov 2023 17:02:26 -0700 Subject: [PATCH 35/88] Lite Steer profile option, itemstate pflags -> player.itemflags --- src/cvars.cpp | 8 ++ src/d_netcmd.c | 7 ++ src/d_player.h | 18 +++-- src/deh_tables.c | 9 +-- src/g_build_ticcmd.cpp | 2 +- src/g_demo.c | 8 ++ src/g_game.c | 4 +- src/g_game.h | 1 + src/k_botitem.c | 24 +++--- src/k_botsearch.c | 4 +- src/k_collide.cpp | 2 +- src/k_hud.c | 2 +- src/k_kart.c | 90 +++++++++++----------- src/k_menu.h | 1 + src/k_profiles.c | 15 ++++ src/k_profiles.h | 5 +- src/k_roulette.c | 2 +- src/lua_playerlib.c | 4 + src/menus/options-profiles-1.c | 2 + src/menus/options-profiles-edit-controls.c | 5 ++ src/p_inter.c | 10 +-- src/p_mobj.c | 2 +- src/p_saveg.c | 6 ++ 23 files changed, 148 insertions(+), 83 deletions(-) diff --git a/src/cvars.cpp b/src/cvars.cpp index 4b0897dcf..d41c9e61d 100644 --- a/src/cvars.cpp +++ b/src/cvars.cpp @@ -905,6 +905,7 @@ void Dummymenuplayer_OnChange(void); consvar_t cv_dummymenuplayer = MenuDummy("dummymenuplayer", "P1").onchange(Dummymenuplayer_OnChange).values({{0, "NOPE"}, {1, "P1"}, {2, "P2"}, {3, "P3"}, {4, "P4"}}); consvar_t cv_dummyprofileautoroulette = MenuDummy("dummyprofileautoroulette", "Off").on_off(); +consvar_t cv_dummyprofilelitesteer = MenuDummy("dummyprofilelitesteer", "On").on_off(); consvar_t cv_dummyprofilekickstart = MenuDummy("dummyprofilekickstart", "Off").on_off(); consvar_t cv_dummyprofilename = MenuDummy("dummyprofilename", ""); consvar_t cv_dummyprofileplayername = MenuDummy("dummyprofileplayername", ""); @@ -1011,6 +1012,13 @@ consvar_t cv_autoroulette[MAXSPLITSCREENPLAYERS] = { Player("autoroulette4", "Off").on_off().onchange(weaponPrefChange4), }; +consvar_t cv_litesteer[MAXSPLITSCREENPLAYERS] = { + Player("litesteer", "On").on_off().onchange(weaponPrefChange), + Player("litesteer2", "On").on_off().onchange(weaponPrefChange2), + Player("litesteer3", "On").on_off().onchange(weaponPrefChange3), + Player("litesteer4", "On").on_off().onchange(weaponPrefChange4), +}; + consvar_t cv_cam_dist[MAXSPLITSCREENPLAYERS] = { Player("cam_dist", "190").floating_point(), Player("cam2_dist", "190").floating_point(), diff --git a/src/d_netcmd.c b/src/d_netcmd.c index b51f1408a..63a6f37a9 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1229,6 +1229,7 @@ enum { WP_KICKSTARTACCEL = 1<<0, WP_SHRINKME = 1<<1, WP_AUTOROULETTE = 1<<2, + WP_LITESTEER = 1<<3, }; void WeaponPref_Send(UINT8 ssplayer) @@ -1241,6 +1242,9 @@ void WeaponPref_Send(UINT8 ssplayer) if (cv_autoroulette[ssplayer].value) prefs |= WP_AUTOROULETTE; + if (cv_litesteer[ssplayer].value) + prefs |= WP_LITESTEER; + if (cv_shrinkme[ssplayer].value) prefs |= WP_SHRINKME; @@ -1259,6 +1263,9 @@ void WeaponPref_Save(UINT8 **cp, INT32 playernum) if (player->pflags & PF_AUTOROULETTE) prefs |= WP_AUTOROULETTE; + if (player->pflags & PF_LITESTEER) + prefs |= WP_LITESTEER; + if (player->pflags & PF_SHRINKME) prefs |= WP_SHRINKME; diff --git a/src/d_player.h b/src/d_player.h index b9ca4d532..aae92b311 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -64,6 +64,14 @@ typedef enum PST_REBORN } playerstate_t; +typedef enum +{ + IF_USERINGS = 1, // Have to be not holding the item button to change from using rings to using items (or vice versa) - prevents weirdness + IF_ITEMOUT = 1<<1, // Are you holding an item out? + IF_EGGMANOUT = 1<<2, // Eggman mark held, separate from IF_ITEMOUT so it doesn't stop you from getting items + IF_HOLDREADY = 1<<3, // Hold button-style item is ready to activate +} itemflags_t; + // // Player internal flags // @@ -95,11 +103,9 @@ typedef enum PF_RINGLOCK = 1<<13, // Prevent picking up rings while SPB is locked on - // The following four flags are mutually exclusive, although they can also all be off at the same time. If we ever run out of pflags, eventually turn them into a seperate five(+) mode UINT8..? - PF_USERINGS = 1<<14, // Have to be not holding the item button to change from using rings to using items (or vice versa) - prevents weirdness - PF_ITEMOUT = 1<<15, // Are you holding an item out? - PF_EGGMANOUT = 1<<16, // Eggman mark held, separate from PF_ITEMOUT so it doesn't stop you from getting items - PF_HOLDREADY = 1<<17, // Hold button-style item is ready to activate + PF_LITESTEER = 1<<14, // Hold Down to shallow turn (digital only) + + //15-17 free, was previously itemflags stuff PF_DRIFTINPUT = 1<<18, // Drifting! PF_GETSPARKS = 1<<19, // Can get sparks @@ -915,6 +921,8 @@ struct player_t UINT8 ringboxdelay; // Delay until Ring Box auto-activates UINT8 ringboxaward; // Where did we stop? + UINT8 itemflags; // holds IS_flags (see itemstate_t) + fixed_t outrun; // Milky Way road effect uint8_t public_key[PUBKEYLENGTH]; diff --git a/src/deh_tables.c b/src/deh_tables.c index 3023b70eb..3bf8c289b 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -6093,11 +6093,10 @@ const char *const PLAYERFLAG_LIST[] = { "RINGLOCK", // Prevent picking up rings while SPB is locked on - // The following four flags are mutually exclusive, although they can also all be off at the same time. If we ever run out of pflags, eventually turn them into a seperate five(+) mode UINT8..? - "USERINGS", // Have to be not holding the item button to change from using rings to using items (or vice versa) - prevents weirdness - "ITEMOUT", // Are you holding an item out? - "EGGMANOUT", // Eggman mark held, separate from PF_ITEMOUT so it doesn't stop you from getting items - "HOLDREADY", // Hold button-style item is ready to activate + "LITESTEER", // Shallow digital turn with DOWN + "UNUSED", + "UNUSED", + "UNUSED", "DRIFTINPUT", // Drifting! "GETSPARKS", // Can get sparks diff --git a/src/g_build_ticcmd.cpp b/src/g_build_ticcmd.cpp index 81d431a12..6dca175da 100644 --- a/src/g_build_ticcmd.cpp +++ b/src/g_build_ticcmd.cpp @@ -380,7 +380,7 @@ class TiccmdBuilder // ugly with the current abstractions, though, and there's a fortunate trick here: // if you can input full strength turns on both axes, either you're using a fucking // square gate, or you're not on an analog device. - if (joystickvector.yaxis >= JOYAXISRANGE && abs(cmd->turning) == KART_FULLTURN) // >= beacuse some analog devices can go past JOYAXISRANGE (?!) + if (cv_litesteer[ssplayer - 1].value && joystickvector.yaxis >= JOYAXISRANGE && abs(cmd->turning) == KART_FULLTURN) // >= beacuse some analog devices can go past JOYAXISRANGE (?!) cmd->turning /= 2; } diff --git a/src/g_demo.c b/src/g_demo.c index d039ddfdd..26c4e078b 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -127,6 +127,7 @@ demoghost *ghosts = NULL; #define DEMO_SHRINKME 0x04 #define DEMO_BOT 0x08 #define DEMO_AUTOROULETTE 0x10 +#define DEMO_LITESTEER 0x20 // For demos #define ZT_FWD 0x0001 @@ -2480,6 +2481,8 @@ void G_BeginRecording(void) i |= DEMO_KICKSTART; if (player->pflags & PF_AUTOROULETTE) i |= DEMO_AUTOROULETTE; + if (player->pflags & PF_LITESTEER) + i |= DEMO_LITESTEER; if (player->pflags & PF_SHRINKME) i |= DEMO_SHRINKME; if (player->bot == true) @@ -3447,6 +3450,11 @@ void G_DoPlayDemo(const char *defdemoname) else players[p].pflags &= ~PF_AUTOROULETTE; + if (flags & DEMO_LITESTEER) + players[p].pflags |= PF_LITESTEER; + else + players[p].pflags &= ~PF_LITESTEER; + if (flags & DEMO_SHRINKME) players[p].pflags |= PF_SHRINKME; else diff --git a/src/g_game.c b/src/g_game.c index b42085fc9..af58cfb47 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2127,7 +2127,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) totalring = players[player].totalring; xtralife = players[player].xtralife; - pflags = (players[player].pflags & (PF_WANTSTOJOIN|PF_KICKSTARTACCEL|PF_SHRINKME|PF_SHRINKACTIVE|PF_AUTOROULETTE)); + pflags = (players[player].pflags & (PF_WANTSTOJOIN|PF_KICKSTARTACCEL|PF_SHRINKME|PF_SHRINKACTIVE|PF_AUTOROULETTE|PF_LITESTEER)); // SRB2kart memcpy(&itemRoulette, &players[player].itemRoulette, sizeof (itemRoulette)); @@ -2175,7 +2175,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) } else { - if (players[player].pflags & PF_ITEMOUT) + if (players[player].itemflags & IF_ITEMOUT) { itemtype = 0; itemamount = 0; diff --git a/src/g_game.h b/src/g_game.h index fc747ae7b..9464a6e8a 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -99,6 +99,7 @@ extern consvar_t cv_pauseifunfocused; extern consvar_t cv_kickstartaccel[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_autoroulette[MAXSPLITSCREENPLAYERS]; +extern consvar_t cv_litesteer[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_shrinkme[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_deadzone[MAXSPLITSCREENPLAYERS]; diff --git a/src/k_botitem.c b/src/k_botitem.c index c483afdb5..ee9fe577e 100644 --- a/src/k_botitem.c +++ b/src/k_botitem.c @@ -440,7 +440,7 @@ static boolean K_BotRevealsGenericTrap(player_t *player, INT16 turnamt, boolean --------------------------------------------------*/ static void K_BotItemGenericTrapShield(player_t *player, ticcmd_t *cmd, INT16 turnamt, boolean mine) { - if (player->pflags & PF_ITEMOUT) + if (player->itemflags & IF_ITEMOUT) { return; } @@ -465,7 +465,7 @@ static void K_BotItemGenericTrapShield(player_t *player, ticcmd_t *cmd, INT16 tu --------------------------------------------------*/ static void K_BotItemGenericOrbitShield(player_t *player, ticcmd_t *cmd) { - if (player->pflags & PF_ITEMOUT) + if (player->itemflags & IF_ITEMOUT) { return; } @@ -811,7 +811,7 @@ static boolean K_BotRevealsEggbox(player_t *player) --------------------------------------------------*/ static void K_BotItemEggmanShield(player_t *player, ticcmd_t *cmd) { - if (player->pflags & PF_EGGMANOUT) + if (player->itemflags & IF_EGGMANOUT) { return; } @@ -1221,7 +1221,7 @@ static void K_BotItemBubble(player_t *player, ticcmd_t *cmd) hold = true; } - if (hold && (player->pflags & PF_HOLDREADY)) + if (hold && (player->itemflags & IF_HOLDREADY)) { cmd->buttons |= BT_ATTACK; } @@ -1245,7 +1245,7 @@ static void K_BotItemFlame(player_t *player, ticcmd_t *cmd) { player->botvars.itemconfirm--; } - else if (player->pflags & PF_HOLDREADY) + else if (player->itemflags & IF_HOLDREADY) { INT32 flamemax = player->flamelength; @@ -1532,7 +1532,7 @@ static void K_BotItemRouletteMash(player_t *player, ticcmd_t *cmd) --------------------------------------------------*/ void K_BotItemUsage(player_t *player, ticcmd_t *cmd, INT16 turnamt) { - if (player->pflags & PF_USERINGS) + if (player->itemflags & IF_USERINGS) { if (player->rings > 0) { @@ -1567,7 +1567,7 @@ void K_BotItemUsage(player_t *player, ticcmd_t *cmd, INT16 turnamt) { K_BotItemEggmanExplosion(player, cmd); } - else if (player->pflags & PF_EGGMANOUT) + else if (player->itemflags & IF_EGGMANOUT) { K_BotItemEggman(player, cmd); } @@ -1604,7 +1604,7 @@ void K_BotItemUsage(player_t *player, ticcmd_t *cmd, INT16 turnamt) K_BotItemSneaker(player, cmd); break; case KITEM_BANANA: - if (!(player->pflags & PF_ITEMOUT)) + if (!(player->itemflags & IF_ITEMOUT)) { K_BotItemGenericTrapShield(player, cmd, turnamt, false); } @@ -1617,7 +1617,7 @@ void K_BotItemUsage(player_t *player, ticcmd_t *cmd, INT16 turnamt) K_BotItemEggmanShield(player, cmd); break; case KITEM_ORBINAUT: - if (!(player->pflags & PF_ITEMOUT)) + if (!(player->itemflags & IF_ITEMOUT)) { K_BotItemGenericOrbitShield(player, cmd); } @@ -1627,7 +1627,7 @@ void K_BotItemUsage(player_t *player, ticcmd_t *cmd, INT16 turnamt) } break; case KITEM_JAWZ: - if (!(player->pflags & PF_ITEMOUT)) + if (!(player->itemflags & IF_ITEMOUT)) { K_BotItemGenericOrbitShield(player, cmd); } @@ -1637,7 +1637,7 @@ void K_BotItemUsage(player_t *player, ticcmd_t *cmd, INT16 turnamt) } break; case KITEM_MINE: - if (!(player->pflags & PF_ITEMOUT)) + if (!(player->itemflags & IF_ITEMOUT)) { K_BotItemGenericTrapShield(player, cmd, turnamt, true); } @@ -1654,7 +1654,7 @@ void K_BotItemUsage(player_t *player, ticcmd_t *cmd, INT16 turnamt) K_BotItemBallhog(player, cmd); break; case KITEM_DROPTARGET: - if (!(player->pflags & PF_ITEMOUT)) + if (!(player->itemflags & IF_ITEMOUT)) { K_BotItemGenericTrapShield(player, cmd, turnamt, false); } diff --git a/src/k_botsearch.c b/src/k_botsearch.c index bdc7ecf62..8d0fc1bc7 100644 --- a/src/k_botsearch.c +++ b/src/k_botsearch.c @@ -577,8 +577,8 @@ static BlockItReturn_t K_FindObjectsForNudging(mobj_t *thing) } // Has held item shield else if (K_PlayerAttackSteer(thing, side, 20, - (thing->player->pflags & (PF_ITEMOUT|PF_EGGMANOUT)), - (g_nudgeSearch.botmo->player->pflags & (PF_ITEMOUT|PF_EGGMANOUT)) + (thing->player->itemflags & (IF_ITEMOUT|IF_EGGMANOUT)), + (g_nudgeSearch.botmo->player->itemflags & (IF_ITEMOUT|IF_EGGMANOUT)) )) { break; diff --git a/src/k_collide.cpp b/src/k_collide.cpp index 87a4a6862..0b78db526 100644 --- a/src/k_collide.cpp +++ b/src/k_collide.cpp @@ -190,7 +190,7 @@ boolean K_EggItemCollide(mobj_t *t1, mobj_t *t2) if (t1->target->hnext == t1) { P_SetTarget(&t1->target->hnext, NULL); - t1->target->player->pflags &= ~PF_EGGMANOUT; + t1->target->player->itemflags &= ~IF_EGGMANOUT; } } diff --git a/src/k_hud.c b/src/k_hud.c index ab26ae388..4f9d94729 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -1453,7 +1453,7 @@ static void K_drawKartItem(void) break; } - if ((stplyr->pflags & PF_ITEMOUT) && !(leveltime & 1)) + if ((stplyr->itemflags & IF_ITEMOUT) && !(leveltime & 1)) localpatch[1] = kp_nodraw; } diff --git a/src/k_kart.c b/src/k_kart.c index 99483e230..64a2d7472 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -6629,11 +6629,11 @@ void K_DropHnextList(player_t *player) player->bananadrag = 0; - if (player->pflags & PF_EGGMANOUT) + if (player->itemflags & IF_EGGMANOUT) { - player->pflags &= ~PF_EGGMANOUT; + player->itemflags &= ~IF_EGGMANOUT; } - else if ((player->pflags & PF_ITEMOUT) + else if ((player->itemflags & IF_ITEMOUT) && (dropall || (--player->itemamount <= 0))) { player->itemamount = 0; @@ -7026,11 +7026,11 @@ static void K_MoveHeldObjects(player_t *player) { player->bananadrag = 0; - if (player->pflags & PF_EGGMANOUT) + if (player->itemflags & IF_EGGMANOUT) { - player->pflags &= ~PF_EGGMANOUT; + player->itemflags &= ~IF_EGGMANOUT; } - else if (player->pflags & PF_ITEMOUT) + else if (player->itemflags & IF_ITEMOUT) { player->itemamount = 0; K_UnsetItemOut(player); @@ -7045,11 +7045,11 @@ static void K_MoveHeldObjects(player_t *player) P_SetTarget(&player->mo->hnext, NULL); player->bananadrag = 0; - if (player->pflags & PF_EGGMANOUT) + if (player->itemflags & IF_EGGMANOUT) { - player->pflags &= ~PF_EGGMANOUT; + player->itemflags &= ~IF_EGGMANOUT; } - else if (player->pflags & PF_ITEMOUT) + else if (player->itemflags & IF_ITEMOUT) { player->itemamount = 0; K_UnsetItemOut(player); @@ -8033,7 +8033,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) } if (player->itemtype == KITEM_NONE) - player->pflags &= ~PF_HOLDREADY; + player->itemflags &= ~IF_HOLDREADY; // DKR style camera for boosting if (player->karthud[khud_boostcam] != 0 || player->karthud[khud_destboostcam] != 0) @@ -8378,7 +8378,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) S_StopSoundByID(player->mo, sfx_wchrg2); } - if (player->itemamount || player->respawn.state != RESPAWNST_NONE || player->pflags & (PF_ITEMOUT|PF_EGGMANOUT) || player->rocketsneakertimer || player->ringboxdelay) + if (player->itemamount || player->respawn.state != RESPAWNST_NONE || player->itemflags & (IF_ITEMOUT|IF_EGGMANOUT) || player->rocketsneakertimer || player->ringboxdelay) player->instaWhipCharge = 0; if (player->tiregrease) @@ -8707,7 +8707,7 @@ void K_KartPlayerAfterThink(player_t *player) K_MoveHeldObjects(player); // Jawz reticule (seeking) - if (player->itemtype == KITEM_JAWZ && (player->pflags & PF_ITEMOUT)) + if (player->itemtype == KITEM_JAWZ && (player->itemflags & IF_ITEMOUT)) { const INT32 lastTargID = player->lastjawztarget; mobj_t *lastTarg = NULL; @@ -10178,7 +10178,7 @@ void K_StripItems(player_t *player) K_DropKitchenSink(player); player->itemtype = KITEM_NONE; player->itemamount = 0; - player->pflags &= ~(PF_ITEMOUT|PF_EGGMANOUT); + player->itemflags &= ~(IF_ITEMOUT|IF_EGGMANOUT); if (player->itemRoulette.eggman == false) { @@ -11021,7 +11021,7 @@ static void K_trickPanelTimingVisual(player_t *player, fixed_t momz) void K_SetItemOut(player_t *player) { - player->pflags |= PF_ITEMOUT; + player->itemflags |= IF_ITEMOUT; if (player->mo->scale >= FixedMul(GROW_PHYSICS_SCALE, mapobjectscale)) { @@ -11039,7 +11039,7 @@ void K_SetItemOut(player_t *player) void K_UnsetItemOut(player_t *player) { - player->pflags &= ~PF_ITEMOUT; + player->itemflags &= ~IF_ITEMOUT; player->itemscale = ITEMSCALE_NORMAL; player->bananadrag = 0; } @@ -11051,7 +11051,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { ticcmd_t *cmd = &player->cmd; boolean ATTACK_IS_DOWN = ((cmd->buttons & BT_ATTACK) && !(player->oldcmd.buttons & BT_ATTACK) && (player->respawn.state == RESPAWNST_NONE)); - boolean HOLDING_ITEM = (player->pflags & (PF_ITEMOUT|PF_EGGMANOUT)); + boolean HOLDING_ITEM = (player->itemflags & (IF_ITEMOUT|IF_EGGMANOUT)); boolean NO_HYUDORO = (player->stealingtimer == 0); if (!player->exiting) @@ -11077,9 +11077,9 @@ void K_MoveKartPlayer(player_t *player, boolean onground) || player->itemRoulette.active == true || player->rocketsneakertimer || player->eggmanexplode)) - player->pflags |= PF_USERINGS; + player->itemflags |= IF_USERINGS; else - player->pflags &= ~PF_USERINGS; + player->itemflags &= ~IF_USERINGS; } if (player->ringboxdelay) @@ -11120,7 +11120,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->instaWhipCooldown = 0; } - if (leveltime < starttime || player->pflags & (PF_ITEMOUT|PF_EGGMANOUT) || player->rocketsneakertimer || player->instaWhipCooldown) + if (leveltime < starttime || player->itemflags & (IF_ITEMOUT|IF_EGGMANOUT) || player->rocketsneakertimer || player->instaWhipCooldown) { chargingwhip = false; player->instaWhipCharge = 0; @@ -11194,7 +11194,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) // First, the really specific, finicky items that function without the item being directly in your item slot. { // Ring boosting - if (player->pflags & PF_USERINGS) + if (player->itemflags & IF_USERINGS) { if ((cmd->buttons & BT_ATTACK) && !player->ringdelay && player->rings > 0) { @@ -11218,13 +11218,13 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->eggmanexplode = 1; } // Eggman Monitor throwing - else if (player->pflags & PF_EGGMANOUT) + else if (player->itemflags & IF_EGGMANOUT) { if (ATTACK_IS_DOWN) { K_ThrowKartItem(player, false, MT_EGGMANITEM, -1, 0, 0); K_PlayAttackTaunt(player->mo); - player->pflags &= ~PF_EGGMANOUT; + player->itemflags &= ~IF_EGGMANOUT; K_UpdateHnextList(player, true); } } @@ -11328,7 +11328,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) prev = mo; } } - else if (ATTACK_IS_DOWN && (player->pflags & PF_ITEMOUT)) // Banana x3 thrown + else if (ATTACK_IS_DOWN && (player->itemflags & IF_ITEMOUT)) // Banana x3 thrown { K_ThrowKartItem(player, false, MT_BANANA, -1, 0, 0); K_PlayAttackTaunt(player->mo); @@ -11341,7 +11341,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { mobj_t *mo; player->itemamount--; - player->pflags |= PF_EGGMANOUT; + player->itemflags |= IF_EGGMANOUT; S_StartSound(player->mo, sfx_s254); mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_EGGMANITEM_SHIELD); if (mo) @@ -11391,7 +11391,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) prev = mo; } } - else if (ATTACK_IS_DOWN && (player->pflags & PF_ITEMOUT)) // Orbinaut x3 thrown + else if (ATTACK_IS_DOWN && (player->itemflags & IF_ITEMOUT)) // Orbinaut x3 thrown { K_ThrowKartItem(player, true, MT_ORBINAUT, 1, 0, 0); K_PlayAttackTaunt(player->mo); @@ -11432,7 +11432,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) prev = mo; } } - else if (ATTACK_IS_DOWN && HOLDING_ITEM && (player->pflags & PF_ITEMOUT)) // Jawz thrown + else if (ATTACK_IS_DOWN && HOLDING_ITEM && (player->itemflags & IF_ITEMOUT)) // Jawz thrown { K_ThrowKartItem(player, true, MT_JAWZ, 1, 0, 0); K_PlayAttackTaunt(player->mo); @@ -11458,12 +11458,12 @@ void K_MoveKartPlayer(player_t *player, boolean onground) P_SetTarget(&player->mo->hnext, mo); } } - else if (ATTACK_IS_DOWN && (player->pflags & PF_ITEMOUT)) + else if (ATTACK_IS_DOWN && (player->itemflags & IF_ITEMOUT)) { K_ThrowKartItem(player, false, MT_SSMINE, 1, 1, 0); K_PlayAttackTaunt(player->mo); player->itemamount--; - player->pflags &= ~PF_ITEMOUT; + player->itemflags &= ~IF_ITEMOUT; K_UpdateHnextList(player, true); } break; @@ -11493,12 +11493,12 @@ void K_MoveKartPlayer(player_t *player, boolean onground) P_SetTarget(&player->mo->hnext, mo); } } - else if (ATTACK_IS_DOWN && (player->pflags & PF_ITEMOUT)) + else if (ATTACK_IS_DOWN && (player->itemflags & IF_ITEMOUT)) { K_ThrowKartItem(player, (player->throwdir > 0), MT_DROPTARGET, -1, 0, 0); K_PlayAttackTaunt(player->mo); player->itemamount--; - player->pflags &= ~PF_ITEMOUT; + player->itemflags &= ~IF_ITEMOUT; K_UpdateHnextList(player, true); } break; @@ -11518,7 +11518,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (player->ballhogcharge == 0) player->ballhogtap = false; - boolean realcharge = (cmd->buttons & BT_ATTACK) && (player->pflags & PF_HOLDREADY) && (player->ballhogcharge < ballhogmax); + boolean realcharge = (cmd->buttons & BT_ATTACK) && (player->itemflags & IT_HOLDREADY) && (player->ballhogcharge < ballhogmax); if ((realcharge && !player->ballhogtap) || (player->ballhogtap && player->ballhogcharge < BALLHOGINCREMENT)) { player->ballhogcharge++; @@ -11541,11 +11541,11 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { if (cmd->buttons & BT_ATTACK) { - player->pflags &= ~PF_HOLDREADY; + player->itemflags &= ~IF_HOLDREADY; } else { - player->pflags |= PF_HOLDREADY; + player->itemflags |= IF_HOLDREADY; } if (player->ballhogcharge > 0) @@ -11581,7 +11581,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } player->ballhogcharge = 0; - player->pflags &= ~PF_HOLDREADY; + player->itemflags &= ~IF_HOLDREADY; } } } @@ -11715,7 +11715,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (!HOLDING_ITEM && NO_HYUDORO) { - if ((cmd->buttons & BT_ATTACK) && (player->pflags & PF_HOLDREADY)) + if ((cmd->buttons & BT_ATTACK) && (player->itemflags & IF_HOLDREADY)) { if (player->bubbleblowup == 0) S_StartSound(player->mo, sfx_s3k75); @@ -11735,7 +11735,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) K_PlayAttackTaunt(player->mo); player->bubbleblowup = 0; player->bubblecool = 0; - player->pflags &= ~PF_HOLDREADY; + player->itemflags &= ~IF_HOLDREADY; player->itemamount--; } } @@ -11748,9 +11748,9 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->bubbleblowup--; if (player->bubblecool) - player->pflags &= ~PF_HOLDREADY; + player->itemflags &= ~IF_HOLDREADY; else - player->pflags |= PF_HOLDREADY; + player->itemflags |= IF_HOLDREADY; } } break; @@ -11774,7 +11774,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) flamemax = player->flamelength + TICRATE; // TICRATE leniency period, but we block most effects at flamelength 0 down below - if ((cmd->buttons & BT_ATTACK) && (player->pflags & PF_HOLDREADY)) + if ((cmd->buttons & BT_ATTACK) && (player->itemflags & IF_HOLDREADY)) { const INT32 incr = (gametyperules & GTR_CLOSERPLAYERS) ? 4 : 2; player->flamemeter += incr; @@ -11816,13 +11816,13 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->flamemeter = 0; player->flamelength = 0; - player->pflags &= ~PF_HOLDREADY; + player->itemflags &= ~IF_HOLDREADY; player->itemamount--; } } else { - player->pflags |= PF_HOLDREADY; + player->itemflags |= IF_HOLDREADY; if (!(gametyperules & GTR_CLOSERPLAYERS) || leveltime % 6 == 0) { @@ -11892,12 +11892,12 @@ void K_MoveKartPlayer(player_t *player, boolean onground) P_SetTarget(&player->mo->hnext, mo); } } - else if (ATTACK_IS_DOWN && HOLDING_ITEM && (player->pflags & PF_ITEMOUT)) // Sink thrown + else if (ATTACK_IS_DOWN && HOLDING_ITEM && (player->itemflags & IF_ITEMOUT)) // Sink thrown { K_ThrowKartItem(player, false, MT_SINK, 1, 2, 0); K_PlayAttackTaunt(player->mo); player->itemamount--; - player->pflags &= ~PF_ITEMOUT; + player->itemflags &= ~IF_ITEMOUT; K_UpdateHnextList(player, true); } break; @@ -11932,7 +11932,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) // No more! if (!player->itemamount) { - player->pflags &= ~PF_ITEMOUT; + player->itemflags &= ~IF_ITEMOUT; player->itemtype = KITEM_NONE; } @@ -12027,7 +12027,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->trickpanel = 0; K_trickPanelTimingVisual(player, momz); // fail trick visual P_SetPlayerMobjState(player->mo, S_KART_SPINOUT); - if (player->pflags & (PF_ITEMOUT|PF_EGGMANOUT)) + if (player->itemflags & (IF_ITEMOUT|IF_EGGMANOUT)) { //K_PopPlayerShield(player); // shield is just being yeeted, don't pop K_DropHnextList(player); diff --git a/src/k_menu.h b/src/k_menu.h index c02f29d50..f4144ac39 100644 --- a/src/k_menu.h +++ b/src/k_menu.h @@ -979,6 +979,7 @@ extern consvar_t cv_dummyprofilename; extern consvar_t cv_dummyprofileplayername; extern consvar_t cv_dummyprofilekickstart; extern consvar_t cv_dummyprofileautoroulette; +extern consvar_t cv_dummyprofilelitesteer; extern consvar_t cv_dummyprofilerumble; void M_ResetOptions(void); diff --git a/src/k_profiles.c b/src/k_profiles.c index f1ff15210..cd2491731 100644 --- a/src/k_profiles.c +++ b/src/k_profiles.c @@ -72,6 +72,7 @@ profile_t* PR_MakeProfile( new->followercolor = fcol; new->kickstartaccel = false; new->autoroulette = false; + new->litesteer = true; // Copy from gamecontrol directly as we'll be setting controls up directly in the profile. memcpy(new->controls, controlarray, sizeof(new->controls)); @@ -89,6 +90,7 @@ profile_t* PR_MakeProfileFromPlayer(const char *prname, const char *pname, const // Player bound cvars: new->kickstartaccel = cv_kickstartaccel[pnum].value; new->autoroulette = cv_autoroulette[pnum].value; + new->litesteer = cv_litesteer[pnum].value; new->rumble = cv_rumble[pnum].value; return new; @@ -276,6 +278,7 @@ void PR_SaveProfiles(void) // Consvars. WRITEUINT8(save.p, profilesList[i]->kickstartaccel); WRITEUINT8(save.p, profilesList[i]->autoroulette); + WRITEUINT8(save.p, profilesList[i]->litesteer); WRITEUINT8(save.p, profilesList[i]->rumble); // Controls. @@ -425,6 +428,17 @@ void PR_LoadProfiles(void) profilesList[i]->autoroulette = (boolean)READUINT8(save.p); } + // 7->8, add litesteer + if (version < 8) + { + profilesList[i]->litesteer = true; + + } + else + { + profilesList[i]->litesteer = (boolean)READUINT8(save.p); + } + if (version < 4) { profilesList[i]->rumble = true; @@ -478,6 +492,7 @@ static void PR_ApplyProfile_Settings(profile_t *p, UINT8 playernum) // toggles CV_StealthSetValue(&cv_kickstartaccel[playernum], p->kickstartaccel); CV_StealthSetValue(&cv_autoroulette[playernum], p->autoroulette); + CV_StealthSetValue(&cv_litesteer[playernum], p->litesteer); // set controls... memcpy(&gamecontrol[playernum], p->controls, sizeof(gamecontroldefault)); diff --git a/src/k_profiles.h b/src/k_profiles.h index 3b941500f..e920fe9be 100644 --- a/src/k_profiles.h +++ b/src/k_profiles.h @@ -31,7 +31,7 @@ extern "C" { #define SKINNAMESIZE 16 #define PROFILENAMELEN 6 -#define PROFILEVER 7 +#define PROFILEVER 8 #define MAXPROFILES 16 #define PROFILESFILE "ringprofiles.prf" #define PROFILE_GUEST 0 @@ -74,7 +74,8 @@ struct profile_t // Player-specific consvars. // @TODO: List all of those boolean kickstartaccel; // cv_kickstartaccel - boolean autoroulette; // cv_autoroulette + boolean autoroulette; // cv_autoroulette + boolean litesteer; // cv_litesteer boolean rumble; // cv_rumble // Finally, control data itself diff --git a/src/k_roulette.c b/src/k_roulette.c index 1b378aeae..cfc57fdbb 100644 --- a/src/k_roulette.c +++ b/src/k_roulette.c @@ -1622,7 +1622,7 @@ void K_KartItemRoulette(player_t *const player, ticcmd_t *const cmd) // If the roulette finishes or the player presses BT_ATTACK, stop the roulette and calculate the item. // I'm returning via the exact opposite, however, to forgo having another bracket embed. Same result either way, I think. // Finally, if you get past this check, now you can actually start calculating what item you get. - if (confirmItem == true && (player->pflags & (PF_ITEMOUT|PF_EGGMANOUT|PF_USERINGS)) == 0) + if (confirmItem == true && (player->itemflags & (IF_ITEMOUT|IF_EGGMANOUT|IF_USERINGS)) == 0) { if (roulette->eggman == true) { diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 5cba9fa62..0f6b7a485 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -259,6 +259,8 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->ringboxdelay); else if (fastcmp(field,"ringboxaward")) lua_pushinteger(L, plr->ringboxaward); + else if (fastcmp(field,"itemflags")) + lua_pushinteger(L, plr->itemflags); else if (fastcmp(field,"drift")) lua_pushinteger(L, plr->drift); else if (fastcmp(field,"driftcharge")) @@ -745,6 +747,8 @@ static int player_set(lua_State *L) plr->ringboxdelay = luaL_checkinteger(L, 3); else if (fastcmp(field,"ringboxaward")) plr->ringboxaward = luaL_checkinteger(L, 3); + else if (fastcmp(field,"itemflags")) + plr->itemflags = luaL_checkinteger(L, 3); else if (fastcmp(field,"drift")) plr->drift = luaL_checkinteger(L, 3); else if (fastcmp(field,"driftcharge")) diff --git a/src/menus/options-profiles-1.c b/src/menus/options-profiles-1.c index ee9f3a40d..bb194a2ee 100644 --- a/src/menus/options-profiles-1.c +++ b/src/menus/options-profiles-1.c @@ -89,6 +89,7 @@ static void M_StartEditProfile(INT32 c) CV_StealthSet(&cv_dummyprofileplayername, optionsmenu.profile->playername); CV_StealthSetValue(&cv_dummyprofilekickstart, optionsmenu.profile->kickstartaccel); CV_StealthSetValue(&cv_dummyprofileautoroulette, optionsmenu.profile->autoroulette); + CV_StealthSetValue(&cv_dummyprofilelitesteer, optionsmenu.profile->litesteer); CV_StealthSetValue(&cv_dummyprofilerumble, optionsmenu.profile->rumble); } else @@ -97,6 +98,7 @@ static void M_StartEditProfile(INT32 c) CV_StealthSet(&cv_dummyprofileplayername, ""); CV_StealthSetValue(&cv_dummyprofilekickstart, 0); // off CV_StealthSetValue(&cv_dummyprofileautoroulette, 0); // off + CV_StealthSetValue(&cv_dummyprofilelitesteer, 1); // on CV_StealthSetValue(&cv_dummyprofilerumble, 1); // on } diff --git a/src/menus/options-profiles-edit-controls.c b/src/menus/options-profiles-edit-controls.c index dc648abd6..0b7e8dcf6 100644 --- a/src/menus/options-profiles-edit-controls.c +++ b/src/menus/options-profiles-edit-controls.c @@ -94,6 +94,9 @@ menuitem_t OPTIONS_ProfileControls[] = { {IT_CONTROL | IT_CVAR, "AUTO ROULETTE", "Item roulette auto-stops on a random result.", NULL, {.cvar = &cv_dummyprofileautoroulette}, 0, 0}, + {IT_CONTROL | IT_CVAR, "LITE STEER", "Hold DOWN on d-pad/keyboard for shallow turns.", + NULL, {.cvar = &cv_dummyprofilelitesteer}, 0, 0}, + {IT_HEADER, "EXTRA", "", NULL, {NULL}, 0, 0}, @@ -191,6 +194,7 @@ static void M_ProfileControlSaveResponse(INT32 choice) // Save the profile optionsmenu.profile->kickstartaccel = cv_dummyprofilekickstart.value; optionsmenu.profile->autoroulette = cv_dummyprofileautoroulette.value; + optionsmenu.profile->litesteer = cv_dummyprofilelitesteer.value; optionsmenu.profile->rumble = cv_dummyprofilerumble.value; memcpy(&optionsmenu.profile->controls, optionsmenu.tempcontrols, sizeof(gamecontroldefault)); @@ -201,6 +205,7 @@ static void M_ProfileControlSaveResponse(INT32 choice) memcpy(&gamecontrol[belongsto], optionsmenu.tempcontrols, sizeof(gamecontroldefault)); CV_SetValue(&cv_kickstartaccel[belongsto], cv_dummyprofilekickstart.value); CV_SetValue(&cv_autoroulette[belongsto], cv_dummyprofileautoroulette.value); + CV_SetValue(&cv_litesteer[belongsto], cv_dummyprofilelitesteer.value); CV_SetValue(&cv_rumble[belongsto], cv_dummyprofilerumble.value); } diff --git a/src/p_inter.c b/src/p_inter.c index e5feda38a..266cba2e2 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -153,7 +153,7 @@ boolean P_CanPickupItem(player_t *player, UINT8 weapon) if (player->itemRoulette.active == true || player->ringboxdelay > 0 || (weapon != 3 && player->itemamount) - || (player->pflags & PF_ITEMOUT)) + || (player->itemflags & IF_ITEMOUT)) return false; if (weapon == 3 && K_GetShieldFromItem(player->itemtype) != KSHIELD_NONE) @@ -1577,10 +1577,10 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget // I wish I knew a better way to do this if (target->target && target->target->player && target->target->player->mo) { - if ((target->target->player->pflags & PF_EGGMANOUT) && target->type == MT_EGGMANITEM_SHIELD) - target->target->player->pflags &= ~PF_EGGMANOUT; + if ((target->target->player->itemflags & IF_EGGMANOUT) && target->type == MT_EGGMANITEM_SHIELD) + target->target->player->itemflags &= ~IF_EGGMANOUT; - if (target->target->player->pflags & PF_ITEMOUT) + if (target->target->player->itemflags & IF_ITEMOUT) { if ((target->type == MT_BANANA_SHIELD && target->target->player->itemtype == KITEM_BANANA) // trail items || (target->type == MT_SSMINE_SHIELD && target->target->player->itemtype == KITEM_MINE) @@ -1608,7 +1608,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget } if (!target->target->player->itemamount) - target->target->player->pflags &= ~PF_ITEMOUT; + target->target->player->itemflags &= ~IF_ITEMOUT; if (target->target->hnext == target) P_SetTarget(&target->target->hnext, NULL); diff --git a/src/p_mobj.c b/src/p_mobj.c index f0baa74e1..5e74fc9db 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6471,7 +6471,7 @@ static void P_MobjSceneryThink(mobj_t *mobj) break; } - if (mobj->target->player->pflags & PF_ITEMOUT) + if (mobj->target->player->itemflags & IF_ITEMOUT) { if (leveltime & 1) mobj->tracer->renderflags &= ~RF_DONTDRAW; diff --git a/src/p_saveg.c b/src/p_saveg.c index 0b0aeab9b..e36464ad9 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -559,6 +559,9 @@ static void P_NetArchivePlayers(savebuffer_t *save) WRITEUINT8(save->p, players[i].ringboxdelay); WRITEUINT8(save->p, players[i].ringboxaward); + + WRITEUINT8(save->p, players[i].itemflags); + WRITEFIXED(save->p, players[i].outrun); WRITEUINT8(save->p, players[i].rideroid); @@ -1076,6 +1079,9 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) players[i].ringboxdelay = READUINT8(save->p); players[i].ringboxaward = READUINT8(save->p); + + players[i].itemflags = READUINT8(save->p); + players[i].outrun = READFIXED(save->p); players[i].rideroid = (boolean)READUINT8(save->p); From 0b51bc91f949a34573b9c8216aa939703a7dc14b Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Thu, 9 Nov 2023 17:07:04 -0700 Subject: [PATCH 36/88] Fix comment referring to itemflags by wrong name --- src/d_player.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_player.h b/src/d_player.h index aae92b311..ff6dfc23b 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -921,7 +921,7 @@ struct player_t UINT8 ringboxdelay; // Delay until Ring Box auto-activates UINT8 ringboxaward; // Where did we stop? - UINT8 itemflags; // holds IS_flags (see itemstate_t) + UINT8 itemflags; // holds IF_ flags (see itemflags_t) fixed_t outrun; // Milky Way road effect From 81e7ec6aa30675e223059ee5c74192e8a9ea2be7 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Thu, 9 Nov 2023 17:30:19 -0700 Subject: [PATCH 37/88] itemflag tyop --- src/k_kart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index 64a2d7472..a56320b54 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -11518,7 +11518,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (player->ballhogcharge == 0) player->ballhogtap = false; - boolean realcharge = (cmd->buttons & BT_ATTACK) && (player->itemflags & IT_HOLDREADY) && (player->ballhogcharge < ballhogmax); + boolean realcharge = (cmd->buttons & BT_ATTACK) && (player->itemflags & IF_HOLDREADY) && (player->ballhogcharge < ballhogmax); if ((realcharge && !player->ballhogtap) || (player->ballhogtap && player->ballhogcharge < BALLHOGINCREMENT)) { player->ballhogcharge++; From 3313935630e927f6611740411dca987373a86c3e Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Thu, 9 Nov 2023 20:27:18 -0700 Subject: [PATCH 38/88] Don't allow respawn lap reset to increase lap --- src/k_respawn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_respawn.c b/src/k_respawn.c index 21af8253d..144156fc6 100644 --- a/src/k_respawn.c +++ b/src/k_respawn.c @@ -295,7 +295,7 @@ void K_DoIngameRespawn(player_t *player) player->respawn.init = true; player->respawn.fast = true; player->respawn.returnspeed = 0; - player->laps = player->lastsafelap; + player->laps = min(player->laps, player->lastsafelap); player->respawn.airtimer = player->airtime; player->respawn.truedeath = !!(player->pflags & PF_FAULT); From 37f23842295a01631b99f16d85186796d5622aa8 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 9 Nov 2023 22:46:57 -0800 Subject: [PATCH 39/88] Add srb2::math, fixed-point, vector, line and slope formula classes - srb2::math::Fixed - Operator overloads for FixedMul and FixedDiv - Implicit conversion between fixed_t, Fixed and floating-point types - srb2::math::Vec2 - Template to any type - Operator overloads for arithmetic operations - Convertible between different types - srb2::math::LineSegment - Template to any type - Holds two Vec2 instances - Sorting methods and vertical/horizontal test - srb2::math::LineEquation - Slope formula from LineSegment - y method to find y from x - Intersect algorithm - Fixed-point specialization to avoid overflows - srb2::math::LineEquationX - Inherits LineEquation - x method to find x from y --- src/math/fixed.hpp | 107 +++++++++++++++++++++++++++++++++++++ src/math/line_equation.hpp | 102 +++++++++++++++++++++++++++++++++++ src/math/line_segment.hpp | 43 +++++++++++++++ src/math/traits.hpp | 34 ++++++++++++ src/math/vec.hpp | 84 +++++++++++++++++++++++++++++ 5 files changed, 370 insertions(+) create mode 100644 src/math/fixed.hpp create mode 100644 src/math/line_equation.hpp create mode 100644 src/math/line_segment.hpp create mode 100644 src/math/traits.hpp create mode 100644 src/math/vec.hpp diff --git a/src/math/fixed.hpp b/src/math/fixed.hpp new file mode 100644 index 000000000..0e5cae4c1 --- /dev/null +++ b/src/math/fixed.hpp @@ -0,0 +1,107 @@ +// DR. ROBOTNIK'S RING RACERS +//----------------------------------------------------------------------------- +// Copyright (C) 2023 by James Robert Roman +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- + +#ifndef math_fixed_hpp +#define math_fixed_hpp + +#include + +#include "traits.hpp" + +#include "../m_fixed.h" + +namespace srb2::math +{ + +struct Fixed +{ + static Fixed copysign(fixed_t x, fixed_t y) { return (x < 0) != (y < 0) ? -x : x; } + static Fixed hypot(fixed_t x, fixed_t y) { return FixedHypot(x, y); } + + constexpr Fixed() : val_(0) {} + constexpr Fixed(fixed_t val) : val_(val) {} + + template , bool> = true> + Fixed(T val) : val_(FloatToFixed(val)) {} + + Fixed(const Fixed& b) = default; + Fixed& operator=(const Fixed& b) = default; + + fixed_t value() const { return val_; } + int sign() const { return val_ < 0 ? -1 : 1; } + + operator fixed_t() const { return val_; } + explicit operator float() const { return FixedToFloat(val_); } + + Fixed& operator+=(const Fixed& b) + { + val_ += b.val_; + return *this; + } + + Fixed& operator-=(const Fixed& b) + { + val_ -= b.val_; + return *this; + } + + Fixed& operator*=(const Fixed& b) + { + val_ = FixedMul(val_, b.val_); + return *this; + } + + Fixed& operator/=(const Fixed& b) + { + val_ = FixedDiv(val_, b.val_); + return *this; + } + + Fixed operator-() const { return -val_; } + +#define X(op) \ + template \ + Fixed operator op(const T& b) const { return val_ op b; } \ + Fixed operator op(const Fixed& b) const \ + { \ + Fixed f{val_};\ + f op##= b;\ + return f;\ + } \ + template \ + Fixed& operator op##=(const T& b) \ + { \ + val_ op##= b; \ + return *this; \ + } + + X(+) + X(-) + X(*) + X(/) + +#undef X + +private: + fixed_t val_; +}; + +template <> +struct Traits +{ + static constexpr Fixed kZero = 0; + static constexpr Fixed kUnit = FRACUNIT; + + static constexpr auto copysign = Fixed::copysign; + static constexpr auto hypot = Fixed::hypot; +}; + +}; // namespace srb2::math + +#endif/*math_fixed_hpp*/ diff --git a/src/math/line_equation.hpp b/src/math/line_equation.hpp new file mode 100644 index 000000000..ec4b69d52 --- /dev/null +++ b/src/math/line_equation.hpp @@ -0,0 +1,102 @@ +// DR. ROBOTNIK'S RING RACERS +//----------------------------------------------------------------------------- +// Copyright (C) 2023 by James Robert Roman +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- + +#ifndef math_line_equation_hpp +#define math_line_equation_hpp + +#include "fixed.hpp" +#include "line_segment.hpp" +#include "vec.hpp" + +namespace srb2::math +{ + +template +struct LineEquation +{ + using vec2 = Vec2; + using line_segment = LineSegment; + + // Fixed-point: shift value by this amount during + // multiplications and divisions to avoid overflows. + static constexpr std::enable_if_t, fixed_t> kF = 1024; // fixed_t, not Fixed + + LineEquation() {} + LineEquation(const vec2& p, const vec2& d) : d_(d), m_(d.y / d.x), b_(p.y - (p.x * m())) {} + LineEquation(const line_segment& l) : LineEquation(l.a, l.b - l.a) {} + + const vec2& d() const { return d_; } + T m() const { return m_; } + T b() const { return b_; } + T y(T x) const { return (m() * x) + b(); } + + vec2 intersect(const LineEquation& q) const + { + T x = (b() - q.b()) / (q.m() - m()); + return {x, y(x)}; + } + +protected: + vec2 d_{}; + T m_{}, b_{}; +}; + +template <> +inline LineEquation::LineEquation(const vec2& p, const vec2& d) : + d_(d), m_((d.y / d.x) / kF), b_((p.y / kF) - (p.x * m_)) +{ +} + +template <> +inline Fixed LineEquation::m() const +{ + return m_ * kF; +} + +template <> +inline Fixed LineEquation::b() const +{ + return b_ * kF; +} + +template <> +inline Fixed LineEquation::y(Fixed x) const +{ + return ((m_ * x) + b_) * kF; +} + +template <> +inline LineEquation::vec2 LineEquation::intersect(const LineEquation& q) const +{ + Fixed x = ((b_ - q.b_) / ((q.m_ - m_) * kF)) * kF; + return {x, y(x)}; +} + +template +struct LineEquationX : LineEquation +{ + T x(T y) const { return (y - LineEquation::b()) / LineEquation::m(); } +}; + +template <> +struct LineEquationX : LineEquation +{ + LineEquationX() {} + LineEquationX(const vec2& p, const vec2& d) : LineEquation(p, d), w_((d.x / d.y) / kF), a_((p.x / kF) - (p.y * w_)) {} + LineEquationX(const line_segment& l) : LineEquationX(l.a, l.b - l.a) {} + + Fixed x(Fixed y) const { return ((w_ * y) + a_) * kF; } + +protected: + Fixed w_{}, a_{}; +}; + +}; // namespace srb2::math + +#endif/*math_line_equation_hpp*/ diff --git a/src/math/line_segment.hpp b/src/math/line_segment.hpp new file mode 100644 index 000000000..0094acf60 --- /dev/null +++ b/src/math/line_segment.hpp @@ -0,0 +1,43 @@ +// DR. ROBOTNIK'S RING RACERS +//----------------------------------------------------------------------------- +// Copyright (C) 2023 by James Robert Roman +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- + +#ifndef math_line_segment_hpp +#define math_line_segment_hpp + +#include +#include + +#include "vec.hpp" + +namespace srb2::math +{ + +template +struct LineSegment +{ + using vec2 = Vec2; + using view = std::pair; + + vec2 a, b; + + LineSegment(vec2 a_, vec2 b_) : a(a_), b(b_) {} + + template + LineSegment(const LineSegment& b) : LineSegment(b.a, b.b) {} + + bool horizontal() const { return a.y == b.y; } + bool vertical() const { return a.x == b.x; } + + view by_x() const { return std::minmax(a, b, [](auto& a, auto& b) { return a.x < b.x; }); } + view by_y() const { return std::minmax(a, b, [](auto& a, auto& b) { return a.y < b.y; }); } +}; + +}; // namespace srb2 + +#endif/*math_line_segment_hpp*/ diff --git a/src/math/traits.hpp b/src/math/traits.hpp new file mode 100644 index 000000000..fbb6aaa5b --- /dev/null +++ b/src/math/traits.hpp @@ -0,0 +1,34 @@ +// DR. ROBOTNIK'S RING RACERS +//----------------------------------------------------------------------------- +// Copyright (C) 2023 by James Robert Roman +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- + +#ifndef math_traits_hpp +#define math_traits_hpp + +#include +#include + +namespace srb2::math +{ + +template +struct Traits; + +template +struct Traits>> +{ + static constexpr T kZero = 0.0; + static constexpr T kUnit = 1.0; + + static T copysign(T x, T y) { return std::copysign(x, y); } + static T hypot(T x, T y) { return std::hypot(x, y); } +}; + +}; // namespace srb2::math + +#endif/*math_traits_hpp*/ diff --git a/src/math/vec.hpp b/src/math/vec.hpp new file mode 100644 index 000000000..670a3677c --- /dev/null +++ b/src/math/vec.hpp @@ -0,0 +1,84 @@ +// DR. ROBOTNIK'S RING RACERS +//----------------------------------------------------------------------------- +// Copyright (C) 2023 by James Robert Roman +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- + +#ifndef math_vec_hpp +#define math_vec_hpp + +#include + +#include "traits.hpp" + +namespace srb2::math +{ + +template +struct Vec2 +{ + T x, y; + + Vec2() : x{}, y{} {} + Vec2(T x_, T y_) : x(x_), y(y_) {} + Vec2(T z) : x(z), y(z) {} + + template + Vec2(const Vec2& b) : Vec2(b.x, b.y) {} + + T magnitude() const { return Traits::hypot(x, y); } + Vec2 normal() const { return {-y, x}; } + +#define X(op) \ + Vec2& operator op##=(const Vec2& b) \ + { \ + x op##= b.x; \ + y op##= b.y; \ + return *this; \ + } \ + Vec2 operator op(const Vec2& b) const { return Vec2(x op b.x, y op b.y); } \ + + X(+) + X(-) + X(*) + X(/) + +#undef X + + Vec2 operator-() const { return Vec2(-x, -y); } +}; + +template +struct is_vec2 : std::false_type {}; + +template +struct is_vec2> : std::true_type {}; + +template +inline constexpr bool is_vec2_v = is_vec2::value; + +#define X(op) \ + template , bool> = true> \ + Vec2 operator op(const T& a, const Vec2& b) \ + { \ + return Vec2 {a} op Vec2 {b}; \ + } \ + template , bool> = true> \ + Vec2 operator op(const Vec2& a, const U& b) \ + { \ + return Vec2 {a} op Vec2 {b}; \ + } \ + +X(+) +X(-) +X(*) +X(/) + +#undef X + +}; // namespace srb2::math + +#endif/*math_vec_hpp*/ From 5a62a07e54b1838f05f1e45288b525aecffba8fe Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 9 Nov 2023 23:53:42 -0800 Subject: [PATCH 40/88] Add srb2::sweep, AABB line sweep algorithms --- src/CMakeLists.txt | 1 + src/p_sweep.cpp | 271 +++++++++++++++++++++++++++++++++++++++++++++ src/p_sweep.hpp | 131 ++++++++++++++++++++++ 3 files changed, 403 insertions(+) create mode 100644 src/p_sweep.cpp create mode 100644 src/p_sweep.hpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8cfba2d4c..4f088dae7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -64,6 +64,7 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32 p_tick.c p_user.c p_slopes.c + p_sweep.cpp tables.c r_bsp.cpp r_data.c diff --git a/src/p_sweep.cpp b/src/p_sweep.cpp new file mode 100644 index 000000000..d4e9d22ef --- /dev/null +++ b/src/p_sweep.cpp @@ -0,0 +1,271 @@ +// DR. ROBOTNIK'S RING RACERS +//----------------------------------------------------------------------------- +// Copyright (C) 2023 by James Robert Roman +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- + +#include +#include + +#include "p_sweep.hpp" + +using namespace srb2::math; +using namespace srb2::sweep; + +Result SlopeAABBvsLine::vs_slope(const line_segment& l) const +{ + auto [a, b] = l.by_x(); // left, right + LineEquation ql{l}; + unit ls = copysign(kUnit, ql.m()); + + auto hit = [&](const vec2& k, unit xr, unit x, const vec2& n) -> Contact + { + std::optional k2; + + if (l.horizontal()) + { + // Horizontal line: create second contact point on opposite corner. + // TODO: avoid duplicate point + k2 = vec2(std::clamp(x + xr, a.x, b.x), k.y); + } + + return {time(x), n, k, k2}; + }; + + auto slide = [&](const vec2& k, const vec2& s) -> std::optional + { + vec2 kf = k * s; + vec2 r = r_ * s; + vec2 p = k - r; + + // Slide vertically along AABB left/right edge. + unit f = q_.y(p.x) * s.y; + + if (f - r_ > kf.y) + { + // Out of bounds detection. + // This should never slide in front. + // If it does, there was never a hit. + return {}; + } + + if (f + r_ < kf.y) + { + // Slid behind contact point. + // Try sliding horizontally along AABB top/bottom + // edge. + + if (q_.m() == kZero) + { + // Sweep is horizontal. + // It is impossible to slide against a line's + // end by the X axis because the line segment + // lies on that axis. + return {}; + } + + p.x = q_.x(p.y); + f = p.x * s.x; + + if (f - r_ > kf.x) + { + // Slid beyond contact point. + return {}; + } + + if (f + r_ < kf.x) + { + // Out of bounds detection. + // This should never slide behind. + // If it does, there was never a hit. + return {}; + } + + return hit(k, r.x, p.x, {kZero, -s.y}); + } + + return hit(k, r.x, p.x, {-s.x, kZero}); + }; + + // xrs.x = x radius + // xrs.y = x sign + auto bind = [&](const vec2& k, const vec2& xrs, unit ns) -> std::optional + { + if (k.x < a.x) + { + return slide(a, {xrs.y, ls}); + } + + if (k.x > b.x) + { + return slide(b, {xrs.y, -ls}); + } + + return hit(k, xrs.x, k.x + xrs.x, normal(l) * ns); + }; + + if (ql.m() == q_.m()) + { + // Parallel lines can only cross at the ends. + vec2 s{kUnit, ls}; + return order(slide(a, s), slide(b, -s), ds_.x); + } + + vec2 i = ql.intersect(q_); + + // Compare slopes to determine if ray is moving upward or + // downward into line. + // For a positive line, AABB top left corner hits the + // line first if the ray is moving upward. + // Swap diagonal corners to bottom right if moving + // downward. + unit ys = q_.m() * ds_.x < ql.m() * ds_.x ? -kUnit : kUnit; + unit yr = r_ * ys; + + // Swap left/right corners if line is negative. + unit xr = yr * ls; + + // Intersection as if ray were offset -r, +r. + vec2 v = [&] + { + unit y = (q_.m() * xr) + yr; + unit x = y / (ql.m() - q_.m()); + return vec2 {x, (x * q_.m()) + y}; + }(); + + // Find the intersection along diagonally oppposing AABB + // corners. + vec2 xrs{xr, ds_.x}; + return {bind(i + v, xrs, -ys), bind(i - v, -xrs, -ys)}; +} + +// TODO: Comments. Bitch. +Result SlopeAABBvsLine::vs_vertical(const line_segment& l) const +{ + auto [a, b] = l.by_y(); // bottom, top + + auto hit = [&](const vec2& p, std::optional q, unit x, const vec2& n) -> Contact { return {time(x), n, p, q}; }; + + auto bind = [&](const vec2& k, const vec2& a, const vec2& b, const vec2& s, auto limit) -> std::optional + { + vec2 r = r_ * s; + vec2 af = a * s; + unit kyf = k.y * s.y; + + if (kyf + r_ < af.y) + { + if (q_.m() == kZero) + { + return {}; + } + + unit x = q_.x(a.y - r.y); + + if ((x * s.x) - r_ > af.x) + { + return {}; + } + + return hit(a, {}, x, {kZero, -s.y}); + } + + // TODO: avoid duplicate point + vec2 k2{k.x, limit(k.y - r.y, a.y)}; + unit byf = b.y * s.y; + vec2 n{-s.x, kZero}; + + if (kyf + r_ > byf) + { + if (kyf - r_ > byf) + { + return {}; + } + + return hit(b, k2, k.x - r.x, n); + } + + return hit(vec2(k.x, k.y + r.y), k2, k.x - r.x, n); + }; + + vec2 i{a.x, q_.y(a.x)}; + vec2 v{kZero, q_.m() * r_ * ds_.x * ds_.y}; + vec2 s = ds_ * ds_.y; + + // Damn you, template overloads! + auto min = [](unit x, unit y) { return std::min(x, y); }; + auto max = [](unit x, unit y) { return std::max(x, y); }; + + return order(bind(i - v, a, b, s, max), bind(i + v, b, a, -s, min), ds_.y); +} + +Result VerticalAABBvsLine::vs_slope(const line_segment& l) const +{ + auto [a, b] = l.by_x(); // left, right + LineEquation ql{l}; + + auto hit = [&](const vec2& k, unit xr, unit y, const vec2& n) -> Contact + { + std::optional k2; + + if (l.horizontal()) + { + // Horizontal line: create second contact point on opposite corner. + // TODO: avoid duplicate point + k2 = vec2(std::clamp(x_ + xr, a.x, b.x), k.y); + } + + return {time(y), n, k, k2}; + }; + + auto bind = [&](const vec2& a, const vec2& b, const vec2& s) -> std::optional + { + vec2 r = r_ * s; + unit xf = x_ * s.x; + + if (xf - r_ > b.x * s.x) + { + return {}; + } + + unit axf = a.x * s.x; + + if (xf - r_ < axf) + { + if (xf + r_ < axf) + { + return {}; + } + + return hit(a, r.x, a.y - r.y, {kZero, -s.y}); + } + + vec2 i{x_, ql.y(x_)}; + vec2 v{r.x, ql.m() * r.x}; + vec2 k = i - v; + return hit(k, r.x, k.y - r.y, normal(l) * -s.y); + }; + + unit mys = copysign(kUnit, ql.m() * ds_.y); + vec2 s{kUnit, ds_.y * mys}; + return order(bind(a, b, s), bind(b, a, -s), mys); +} + +Result VerticalAABBvsLine::vs_vertical(const line_segment& l) const +{ + // Box does not overlap Y plane. + if (x_ + r_ < l.a.x || x_ - r_ > l.a.x) + { + return {}; + } + + auto [a, b] = l.by_y(); // bottom, top + + auto hit = [&](const vec2& k, unit yr) -> Contact { return {time(k.y + yr), {kZero, -ds_.y}, k}; }; + + // Offset away from line ends. + // Contacts are opposite when swept downward. + return order(hit(a, -r_), hit(b, r_), ds_.y); +} diff --git a/src/p_sweep.hpp b/src/p_sweep.hpp new file mode 100644 index 000000000..68c6ac359 --- /dev/null +++ b/src/p_sweep.hpp @@ -0,0 +1,131 @@ +// DR. ROBOTNIK'S RING RACERS +//----------------------------------------------------------------------------- +// Copyright (C) 2023 by James Robert Roman +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- + +#ifndef p_sweep_hpp +#define p_sweep_hpp + +#include +#include + +#include "math/fixed.hpp" +#include "math/line_equation.hpp" +#include "math/line_segment.hpp" +#include "math/vec.hpp" + +namespace srb2::sweep +{ + +using unit = math::Fixed; +using vec2 = math::Vec2; +using line_segment = math::LineSegment; + +struct Contact +{ + unit z; // time + vec2 n; // normal TODO REMOVE duplicate for each contact + vec2 p; // contact point 1 + std::optional q; // AABBvsLine: contact point 2 +}; + +struct Result +{ + std::optional hit, exit; // TODO result itself should be optional, not each contact +}; + +namespace detail +{ + +template +struct BaseAABBvsLine : protected srb2::math::Traits +{ +public: + Result operator()(const line_segment& l) const + { + auto derived = static_cast(this); + return l.vertical() ? derived->vs_vertical(l) : derived->vs_slope(l); + } + +protected: + unit r_; // AABB radius + vec2 ds_; // sweep direction signs + + BaseAABBvsLine(unit r, const vec2& d, unit pz, unit dz) : + r_(r), ds_(copysign(kUnit, d.x), copysign(kUnit, d.y)), t_(pz, dz) {} + + unit time(unit x) const { return (x - t_.x) / t_.y; } + + static Result order(std::optional&& t1, std::optional&& t2, unit s) + { + return s > kZero ? Result {t1, t2} : Result {t2, t1}; + } + + static vec2 normal(const vec2& v) + { + // Normalize vector so that x is positive -- normal always points up. + return v.normal() * (copysign(kUnit, v.x) / v.magnitude()); + } + + static vec2 normal(const line_segment& l) { return normal(l.b - l.a); } + +private: + vec2 t_; // origin and length for calculating time +}; + +}; // namespace detail + +// Sweep can be represented as y = mx + b +struct SlopeAABBvsLine : detail::BaseAABBvsLine +{ + SlopeAABBvsLine(unit r, const line_segment& l) : SlopeAABBvsLine(r, l.a, l.b - l.a) {} + + Result vs_slope(const line_segment& l) const; + Result vs_vertical(const line_segment& l) const; + +private: + math::LineEquationX q_; + + SlopeAABBvsLine(unit r, const vec2& p, const vec2& d) : BaseAABBvsLine(r, d, p.x, d.x), q_(p, d) {} +}; + +// Sweep is vertical +struct VerticalAABBvsLine : detail::BaseAABBvsLine +{ + VerticalAABBvsLine(unit r, const line_segment& l) : VerticalAABBvsLine(r, l.a, l.b - l.a) {} + + Result vs_slope(const line_segment& l) const; + Result vs_vertical(const line_segment& l) const; + +private: + unit x_; + + VerticalAABBvsLine(unit r, const vec2& p, const vec2& d) : BaseAABBvsLine(r, d, p.y, d.y), x_(p.x) {} +}; + +struct AABBvsLine +{ + AABBvsLine(unit r, const line_segment& l) : + var_(l.vertical() ? var_t {VerticalAABBvsLine(r, l)} : var_t {SlopeAABBvsLine(r, l)}) + { + } + + Result operator()(const line_segment& l) const + { + Result rs; + std::visit([&](auto& sweeper) { rs = sweeper(l); }, var_); + return rs; + } + +private: + using var_t = std::variant; + var_t var_; +}; + +}; // namespace srb2::sweep + +#endif/*p_sweep_hpp*/ From 7861d51a7f39848d9478739cbd396fba4637ae82 Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 10 Nov 2023 00:02:32 -0800 Subject: [PATCH 41/88] P_TryMove: sweep collided lines to find nearest normal --- src/CMakeLists.txt | 1 + src/cvars.cpp | 1 + src/p_local.h | 18 ++++- src/p_map.c | 190 +++++++++++++++++++++++++++++++++------------ src/p_mobj.c | 4 +- src/p_test.cpp | 78 +++++++++++++++++++ 6 files changed, 238 insertions(+), 54 deletions(-) create mode 100644 src/p_test.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4f088dae7..a1f3d29e6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -65,6 +65,7 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32 p_user.c p_slopes.c p_sweep.cpp + p_test.cpp tables.c r_bsp.cpp r_data.c diff --git a/src/cvars.cpp b/src/cvars.cpp index 4b0897dcf..9336becb2 100644 --- a/src/cvars.cpp +++ b/src/cvars.cpp @@ -806,6 +806,7 @@ consvar_t cv_numlaps = OnlineCheat("numlaps", "Map default").values(numlaps_cons consvar_t cv_restrictskinchange = OnlineCheat("restrictskinchange", "Yes").yes_no().description("Don't let players change their skin in the middle of gameplay"); consvar_t cv_spbtest = OnlineCheat("spbtest", "Off").on_off().description("SPB can never target a player"); +consvar_t cv_showgremlins = OnlineCheat("showgremlins", "No").yes_no().description("Show line collision errors"); consvar_t cv_timescale = OnlineCheat(cvlist_timer)("timescale", "1.0").floating_point().min_max(FRACUNIT/20, 20*FRACUNIT).description("Overclock or slow down the game"); consvar_t cv_ufo_follow = OnlineCheat("ufo_follow", "0").min_max(0, MAXPLAYERS).description("Make UFO Catcher folow this player"); consvar_t cv_ufo_health = OnlineCheat("ufo_health", "-1").min_max(-1, 100).description("Override UFO Catcher health -- applied at spawn or when value is changed"); diff --git a/src/p_local.h b/src/p_local.h index 0e0a3fb23..045a59472 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -387,9 +387,16 @@ struct tm_t // so missiles don't explode against sky hack walls line_t *ceilingline; - // set by PIT_CheckLine() for any line that stopped the PIT_CheckLine() - // that is, for any line which is 'solid' - line_t *blockingline; + // P_CheckPosition: this position blocks movement + boolean blocking; + + // P_CheckPosition: set this before each call to + // P_CheckPosition to enable a line sweep on collided + // lines + boolean sweep; + + // sweep: max step up at tm.x, tm.y + fixed_t maxstep; }; extern tm_t tm; @@ -415,6 +422,7 @@ struct TryMoveResult_t boolean success; line_t *line; mobj_t *mo; + vector2_t normal; }; boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y, TryMoveResult_t *result); @@ -422,6 +430,10 @@ boolean P_CheckMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff, T boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff, TryMoveResult_t *result); boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y, TryMoveResult_t *result); +void P_TestLine(line_t *ld); +void P_ClearTestLines(void); +line_t *P_SweepTestLines(fixed_t ax, fixed_t ay, fixed_t bx, fixed_t by, fixed_t r, vector2_t *return_normal); + boolean P_IsLineBlocking(const line_t *ld, const mobj_t *thing); boolean P_IsLineTripWire(const line_t *ld); boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam); diff --git a/src/p_map.c b/src/p_map.c index 79b9ba59e..683dd3c5d 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -1770,7 +1770,6 @@ static BlockItReturn_t PIT_CheckCameraLine(line_t *ld) // could be crossed in either order. // this line is out of the if so upper and lower textures can be hit by a splat - tm.blockingline = ld; if (!ld->backsector) // one sided line { if (P_PointOnLineSide(mapcampointer->x, mapcampointer->y, ld)) @@ -1841,6 +1840,22 @@ boolean P_IsLineTripWire(const line_t *ld) return ld->tripwire; } +static boolean P_UsingStepUp(mobj_t *thing) +{ + if (thing->flags & MF_NOCLIP) + { + return false; + } + + // orbits have no collision + if (thing->player && thing->player->loop.radius) + { + return false; + } + + return true; +} + // // PIT_CheckLine // Adjusts tm.floorz and tm.ceilingz as lines are contacted @@ -1898,14 +1913,20 @@ static BlockItReturn_t PIT_CheckLine(line_t *ld) // could be crossed in either order. // this line is out of the if so upper and lower textures can be hit by a splat - tm.blockingline = ld; { - UINT8 shouldCollide = LUA_HookMobjLineCollide(tm.thing, tm.blockingline); // checks hook for thing's type + UINT8 shouldCollide = LUA_HookMobjLineCollide(tm.thing, ld); // checks hook for thing's type if (P_MobjWasRemoved(tm.thing)) return BMIT_CONTINUE; // one of them was removed??? if (shouldCollide == 1) - return BMIT_ABORT; // force collide + { + if (tm.sweep) + { + P_TestLine(ld); + } + tm.blocking = true; // force collide + return BMIT_CONTINUE; + } else if (shouldCollide == 2) return BMIT_CONTINUE; // force no collide } @@ -1914,15 +1935,55 @@ static BlockItReturn_t PIT_CheckLine(line_t *ld) { if (P_PointOnLineSide(tm.thing->x, tm.thing->y, ld)) return BMIT_CONTINUE; // don't hit the back side - return BMIT_ABORT; + + if (tm.sweep) + { + P_TestLine(ld); + } + tm.blocking = true; + return BMIT_CONTINUE; } if (P_IsLineBlocking(ld, tm.thing)) - return BMIT_ABORT; + { + if (tm.sweep) + { + P_TestLine(ld); + } + tm.blocking = true; + return BMIT_CONTINUE; + } // set openrange, opentop, openbottom P_LineOpening(ld, tm.thing, &open); + if (tm.sweep && P_UsingStepUp(tm.thing)) + { + // copied from P_TryMove + // TODO: refactor this into one place + if (open.range < tm.thing->height) + { + P_TestLine(ld); + } + else if (tm.maxstep > 0) + { + if (tm.thing->z < open.floor) + { + if (open.floorstep > tm.maxstep) + { + P_TestLine(ld); + } + } + else if (open.ceiling < tm.thing->z + tm.thing->height) + { + if (open.ceilingstep > tm.maxstep) + { + P_TestLine(ld); + } + } + } + } + // adjust floor / ceiling heights if (open.ceiling < tm.ceilingz) { @@ -2042,7 +2103,8 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y, TryMoveResult_t *re tm.bbox[BOXLEFT] = x - tm.thing->radius; newsubsec = R_PointInSubsector(x, y); - tm.ceilingline = tm.blockingline = NULL; + tm.ceilingline = NULL; + tm.blocking = false; // The base floor / ceiling is from the subsector // that contains the point. @@ -2314,23 +2376,33 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y, TryMoveResult_t *re validcount++; + P_ClearTestLines(); + // check lines for (bx = xl; bx <= xh; bx++) { for (by = yl; by <= yh; by++) { - if (!P_BlockLinesIterator(bx, by, PIT_CheckLine)) - { - blockval = false; - } + P_BlockLinesIterator(bx, by, PIT_CheckLine); } } + if (tm.blocking) + { + blockval = false; + } + if (result != NULL) { - result->line = tm.blockingline; + result->line = NULL; result->mo = tm.hitthing; } + else + { + P_ClearTestLines(); + } + + tm.sweep = false; return blockval; } @@ -2379,7 +2451,7 @@ boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam) tm.bbox[BOXLEFT] = x - thiscam->radius; newsubsec = R_PointInSubsector(x, y); - tm.ceilingline = tm.blockingline = NULL; + tm.ceilingline = NULL; mapcampointer = thiscam; @@ -2753,22 +2825,6 @@ fixed_t P_GetThingStepUp(mobj_t *thing, fixed_t destX, fixed_t destY) return maxstep; } -static boolean P_UsingStepUp(mobj_t *thing) -{ - if (thing->flags & MF_NOCLIP) - { - return false; - } - - // orbits have no collision - if (thing->player && thing->player->loop.radius) - { - return false; - } - - return true; -} - static boolean increment_move ( mobj_t * thing, @@ -2821,7 +2877,29 @@ increment_move tryy = y; } - if (!P_CheckPosition(thing, tryx, tryy, result)) + if (P_UsingStepUp(thing)) + { + tm.maxstep = P_GetThingStepUp(thing, tryx, tryy); + } + + if (result) + { + tm.sweep = true; + } + + boolean move_ok = P_CheckPosition(thing, tryx, tryy, result); + + if (P_MobjWasRemoved(thing)) + { + return false; + } + + if (result) + { + result->line = P_SweepTestLines(thing->x, thing->y, x, y, thing->radius, &result->normal); + } + + if (!move_ok) { return false; // solid wall or thing } @@ -3466,30 +3544,27 @@ static void P_HitSlideLine(line_t *ld) // // HitBounceLine, for players // -static void P_PlayerHitBounceLine(line_t *ld) +static void P_PlayerHitBounceLine(line_t *ld, vector2_t* normal) { - INT32 side; - angle_t lineangle; fixed_t movelen; fixed_t x, y; - side = P_PointOnLineSide(slidemo->x, slidemo->y, ld); - lineangle = ld->angle - ANGLE_90; - - if (side == 1) - lineangle += ANGLE_180; - - lineangle >>= ANGLETOFINESHIFT; - movelen = P_AproxDistance(tmxmove, tmymove); if (slidemo->player && movelen < (15*mapobjectscale)) movelen = (15*mapobjectscale); - x = FixedMul(movelen, FINECOSINE(lineangle)); - y = FixedMul(movelen, FINESINE(lineangle)); + if (!ld) + { + angle_t th = R_PointToAngle2(0, 0, tmxmove, tmymove); + normal->x = -FCOS(th); + normal->y = -FSIN(th); + } - if (P_IsLineTripWire(ld)) + x = FixedMul(movelen, normal->x); + y = FixedMul(movelen, normal->y); + + if (ld && P_IsLineTripWire(ld)) { tmxmove = x * 4; tmymove = y * 4; @@ -3958,6 +4033,8 @@ papercollision: static void P_BouncePlayerMove(mobj_t *mo, TryMoveResult_t *result) { + extern consvar_t cv_showgremlins; + fixed_t mmomx = 0, mmomy = 0; fixed_t oldmomx = mo->momx, oldmomy = mo->momy; @@ -3982,8 +4059,23 @@ static void P_BouncePlayerMove(mobj_t *mo, TryMoveResult_t *result) slidemo = mo; bestslideline = result->line; - if (bestslideline == NULL) - return; + if (bestslideline == NULL && cv_showgremlins.value) + { + // debug + mobj_t*x = P_SpawnMobj(mo->x, mo->y, mo->z, MT_THOK); + x->frame = FF_FULLBRIGHT | FF_ADD; + x->renderflags = RF_ALWAYSONTOP; + x->color = SKINCOLOR_RED; + + CONS_Printf( + "GREMLIN: leveltime=%u x=%f y=%f z=%f angle=%f\n", + leveltime, + FixedToFloat(mo->x), + FixedToFloat(mo->y), + FixedToFloat(mo->z), + AngleToFloat(R_PointToAngle2(0, 0, oldmomx, oldmomy)) + ); + } if (mo->eflags & MFE_JUSTBOUNCEDWALL) // Stronger push-out { @@ -3996,7 +4088,7 @@ static void P_BouncePlayerMove(mobj_t *mo, TryMoveResult_t *result) tmymove = FixedMul(mmomy, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3))); } - if (P_IsLineTripWire(bestslideline)) + if (bestslideline && P_IsLineTripWire(bestslideline)) { // TRIPWIRE CANNOT BE MADE NONBOUNCY K_ApplyTripWire(mo->player, TRIPSTATE_BLOCKED); @@ -4014,7 +4106,7 @@ static void P_BouncePlayerMove(mobj_t *mo, TryMoveResult_t *result) K_SpawnBumpEffect(mo); } - P_PlayerHitBounceLine(bestslideline); + P_PlayerHitBounceLine(bestslideline, &result->normal); mo->eflags |= MFE_JUSTBOUNCEDWALL; mo->momx = tmxmove; @@ -4022,7 +4114,7 @@ static void P_BouncePlayerMove(mobj_t *mo, TryMoveResult_t *result) mo->player->cmomx = tmxmove; mo->player->cmomy = tmymove; - if (!P_IsLineTripWire(bestslideline)) + if (!bestslideline || !P_IsLineTripWire(bestslideline)) { if (!P_TryMove(mo, mo->x + tmxmove, mo->y + tmymove, true, NULL)) { diff --git a/src/p_mobj.c b/src/p_mobj.c index f0baa74e1..447592037 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1671,7 +1671,7 @@ void P_XYMovement(mobj_t *mo) // blocked move moved = false; - if (LUA_HookMobjMoveBlocked(mo, tm.hitthing, tm.blockingline)) + if (LUA_HookMobjMoveBlocked(mo, tm.hitthing, result.line)) { if (P_MobjWasRemoved(mo)) return; @@ -1679,7 +1679,7 @@ void P_XYMovement(mobj_t *mo) else if (P_MobjWasRemoved(mo)) return; - P_PushSpecialLine(tm.blockingline, mo); + P_PushSpecialLine(result.line, mo); if (mo->flags & MF_MISSILE) { diff --git a/src/p_test.cpp b/src/p_test.cpp new file mode 100644 index 000000000..e362f33a5 --- /dev/null +++ b/src/p_test.cpp @@ -0,0 +1,78 @@ +// DR. ROBOTNIK'S RING RACERS +//----------------------------------------------------------------------------- +// Copyright (C) 2023 by James Robert Roman +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- + +#include +#include + +#include "math/fixed.hpp" +#include "p_sweep.hpp" + +#include "p_local.h" + +namespace +{ + +std::vector g_lines; + +}; + +void P_TestLine(line_t* ld) +{ + g_lines.emplace_back(ld); +} + +line_t* P_SweepTestLines(fixed_t ax, fixed_t ay, fixed_t bx, fixed_t by, fixed_t r, vector2_t* return_normal) +{ + using namespace srb2::math; + using namespace srb2::sweep; + + struct Collision + { + unit z; + vec2 normal; + line_t* ld; + + bool operator<(const Collision& b) const { return z < b.z; } + }; + + std::optional collision; + + LineSegment l{{ax, ay}, {bx, by}}; + AABBvsLine sweep{r, l}; + + for (line_t* ld : g_lines) + { + LineSegment ls{{ld->v1->x, ld->v1->y}, {ld->v2->x, ld->v2->y}}; + Result rs = sweep(ls); + if (rs.hit) + { + if (!collision || rs.hit->z < collision->z) + { + collision = {rs.hit->z, rs.hit->n, ld}; + } + } + } + + g_lines.clear(); + + if (!collision) + { + return nullptr; + } + + return_normal->x = Fixed {collision->normal.x}; + return_normal->y = Fixed {collision->normal.y}; + + return collision->ld; +} + +void P_ClearTestLines(void) +{ + g_lines.clear(); +} From 77af33d182f97df1d27e890ceb96e2b2c80cdd87 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Fri, 10 Nov 2023 02:58:05 -0700 Subject: [PATCH 42/88] More idiomatic unused pflags --- src/deh_tables.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/deh_tables.c b/src/deh_tables.c index 3bf8c289b..72141e85a 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -6094,9 +6094,9 @@ const char *const PLAYERFLAG_LIST[] = { "RINGLOCK", // Prevent picking up rings while SPB is locked on "LITESTEER", // Shallow digital turn with DOWN - "UNUSED", - "UNUSED", - "UNUSED", + "\x01", // Free + "\x01", // Free + "\x01", // Free "DRIFTINPUT", // Drifting! "GETSPARKS", // Can get sparks From 90902997ba3a7026265217ff1d73441f22f35069 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Fri, 10 Nov 2023 16:33:50 -0700 Subject: [PATCH 43/88] Unset RF_DONTDRAW during controllable non-flashing states --- src/p_user.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index 419e78ab6..ced510540 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4329,12 +4329,12 @@ void P_PlayerThink(player_t *player) } } + boolean deathcontrolled = (player->respawn.state != RESPAWNST_NONE && player->respawn.truedeath == true) + || (player->pflags & PF_NOCONTEST) || (player->karmadelay); + boolean powercontrolled = (player->hyudorotimer) || (player->growshrinktimer > 0); + // Flash player after being hit. - if (!(player->hyudorotimer // SRB2kart - fixes Hyudoro not flashing when it should. - || player->growshrinktimer > 0 // Grow doesn't flash either. - || (player->respawn.state != RESPAWNST_NONE && player->respawn.truedeath == true) // Respawn timer (for drop dash effect) - || (player->pflags & PF_NOCONTEST) // NO CONTEST explosion - || player->karmadelay)) + if (!deathcontrolled && !powercontrolled) { if (player->flashing > 1 && player->flashing < K_GetKartFlashing(player) && (leveltime & 1)) @@ -4342,6 +4342,10 @@ void P_PlayerThink(player_t *player) else player->mo->renderflags &= ~RF_DONTDRAW; } + else if (!deathcontrolled) + { + player->mo->renderflags &= ~RF_DONTDRAW; + } if (player->stairjank > 0) { From ff131335d4d1157a42dfd4c55d224196315dc396 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Fri, 10 Nov 2023 16:47:52 -0700 Subject: [PATCH 44/88] Don't force player sounds to full volume when exiting --- src/s_sound.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/s_sound.c b/src/s_sound.c index c0bec85fc..d5ce60424 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -426,6 +426,7 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume) for (i = 0; i <= r_splitscreen; i++) { player_t *player = &players[displayplayers[i]]; + boolean camaway = false; memset(&listener[i], 0, sizeof (listener[i])); listenmobj[i] = NULL; @@ -442,9 +443,11 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume) else { listenmobj[i] = player->mo; + if (player->exiting) + camaway = true; } - if (origin && origin == listenmobj[i] && !camera[i].freecam) + if (origin && origin == listenmobj[i] && !camera[i].freecam && !camaway) { itsUs = true; } From e3fe3ed54ab3dbfa04ad59428fd4ab3f0ed38ed4 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Fri, 10 Nov 2023 17:08:39 -0700 Subject: [PATCH 45/88] Handle sound falloff for exiting player sounds --- src/s_sound.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/s_sound.c b/src/s_sound.c index d5ce60424..f744b1598 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -766,6 +766,9 @@ void S_UpdateSounds(void) if (c->origin != listenmobj[i]) continue; + if (listenmobj[i]->player && listenmobj[i]->player->exiting) + continue; + itsUs = true; } From 4997c4c0ed2ac9ae5be455c3df53c0d7c8bfa129 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Fri, 10 Nov 2023 17:28:54 -0700 Subject: [PATCH 46/88] Add K_IsPlayingDisplayPlayer for HUD sounds --- src/k_kart.c | 6 ++++++ src/k_kart.h | 2 ++ src/k_roulette.c | 6 +++--- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 99483e230..bf6f731d7 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -12630,4 +12630,10 @@ void K_SetTireGrease(player_t *player, tic_t tics) player->tiregrease = tics; } +// somewhat sensible check for HUD sounds in a post-bot-takeover world +boolean K_IsPlayingDisplayPlayer(player_t *player) +{ + return P_IsDisplayPlayer(player) && (!player->exiting); +} + //} diff --git a/src/k_kart.h b/src/k_kart.h index 7a4424f08..4ddd8b1c3 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -243,6 +243,8 @@ boolean K_isPlayerInSpecialState(player_t *p); void K_SetTireGrease(player_t *player, tic_t tics); +boolean K_IsPlayingDisplayPlayer(player_t *player); + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/k_roulette.c b/src/k_roulette.c index 1b378aeae..d01678d9c 100644 --- a/src/k_roulette.c +++ b/src/k_roulette.c @@ -1633,7 +1633,7 @@ void K_KartItemRoulette(player_t *const player, ticcmd_t *const cmd) //player->karthud[khud_itemblinkmode] = 1; //player->karthud[khud_rouletteoffset] = K_GetRouletteOffset(roulette, FRACUNIT); - if (P_IsDisplayPlayer(player)) + if (K_IsPlayingDisplayPlayer(player)) { S_StartSound(NULL, sfx_itrole); } @@ -1680,7 +1680,7 @@ void K_KartItemRoulette(player_t *const player, ticcmd_t *const cmd) player->karthud[khud_itemblinkmode] = 0; player->karthud[khud_rouletteoffset] = K_GetRouletteOffset(roulette, FRACUNIT); - if (P_IsDisplayPlayer(player)) + if (K_IsPlayingDisplayPlayer(player)) { if (roulette->ringbox) { @@ -1714,7 +1714,7 @@ void K_KartItemRoulette(player_t *const player, ticcmd_t *const cmd) // This makes the roulette produce the random noises. roulette->sound = (roulette->sound + 1) % 8; - if (P_IsDisplayPlayer(player)) + if (K_IsPlayingDisplayPlayer(player)) { if (roulette->ringbox) S_StartSound(NULL, sfx_s240); From e20218a9d6722758510b4b97d69ee37bc7cf29ed Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Sun, 12 Nov 2023 03:38:17 -0700 Subject: [PATCH 47/88] Trick Charge VFX WIP --- src/deh_tables.c | 4 ++++ src/info.c | 31 +++++++++++++++++++++++++++++++ src/info.h | 6 ++++++ src/k_kart.c | 15 +++++++++++++++ src/k_objects.h | 2 ++ src/objects/CMakeLists.txt | 1 + src/objects/charge.c | 34 ++++++++++++++++++++++++++++++++++ src/p_mobj.c | 5 +++++ 8 files changed, 98 insertions(+) create mode 100644 src/objects/charge.c diff --git a/src/deh_tables.c b/src/deh_tables.c index c0d35b1b5..4b11f9421 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -3325,6 +3325,8 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_BLOCKRING", "S_BLOCKBODY", + "S_CHARGEAURA", + "S_SERVANTHAND", "S_HORNCODE", @@ -5555,6 +5557,8 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t "MT_BLOCKRING", "MT_BLOCKBODY", + "MT_CHARGEAURA", + "MT_SERVANTHAND", "MT_HORNCODE", diff --git a/src/info.c b/src/info.c index 8e3b38bb9..4e93c7473 100644 --- a/src/info.c +++ b/src/info.c @@ -567,6 +567,8 @@ char sprnames[NUMSPRITES + 1][5] = "GRNG", // Guard ring "GBDY", // Guard body + "TRC1", // Charge aura + "DHND", // Servant Hand "HORN", // Horncode @@ -4138,6 +4140,8 @@ state_t states[NUMSTATES] = {SPR_GRNG, FF_FULLBRIGHT|FF_PAPERSPRITE|0, -1, {NULL}, 0, 0, S_NULL}, // S_BLOCKRING {SPR_GBDY, FF_FULLBRIGHT|FF_ANIMATE|0, -1, {NULL}, 4, 2, S_NULL}, // S_BLOCKBODY + {SPR_TRC1, FF_FULLBRIGHT|FF_ANIMATE|0, -1, {NULL}, 4, 2, S_NULL}, // S_CHARGEAURA + {SPR_DHND, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SERVANTHAND {SPR_HORN, 0, -1, {NULL}, 0, 0, S_NULL}, // S_HORNCODE @@ -23241,6 +23245,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_CHARGEAURA + -1, // doomednum + S_CHARGEAURA, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 67*FRACUNIT, // radius + 67*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags + S_NULL // raisestate + }, + { // MT_SERVANTHAND -1, // doomednum S_SERVANTHAND, // spawnstate diff --git a/src/info.h b/src/info.h index f27c34e85..54cb2ed75 100644 --- a/src/info.h +++ b/src/info.h @@ -1124,6 +1124,8 @@ typedef enum sprite SPR_GRNG, // Guard ring SPR_GBDY, // Guard body + SPR_TRC1, // Charge aura + SPR_DHND, // Servant Hand SPR_HORN, // Horncode @@ -4549,6 +4551,8 @@ typedef enum state S_BLOCKRING, S_BLOCKBODY, + S_CHARGEAURA, + S_SERVANTHAND, S_HORNCODE, @@ -6817,6 +6821,8 @@ typedef enum mobj_type MT_BLOCKRING, MT_BLOCKBODY, + MT_CHARGEAURA, + MT_SERVANTHAND, MT_HORNCODE, diff --git a/src/k_kart.c b/src/k_kart.c index 904ed2b56..da2dbb070 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -8532,8 +8532,23 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->dotrickfx && !player->mo->hitlag) { + int i; S_StartSound(player->mo, sfx_trick1); + + if (!player->trickcharge) + { + for(i = 0;i < 5;i++) + { + mobj_t *aura = P_SpawnMobjFromMobj(player->mo, 0, 0, player->mo->height/2, MT_CHARGEAURA); + aura->angle = player->mo->angle + i*ANG15; + aura->target = player->mo; + if (i != 0) + aura->renderflags |= RF_TRANS50; + } + } + player->trickcharge = 8*TICRATE; + player->dotrickfx = false; } diff --git a/src/k_objects.h b/src/k_objects.h index c88bf3320..baae5e050 100644 --- a/src/k_objects.h +++ b/src/k_objects.h @@ -126,6 +126,8 @@ void Obj_BlockRingThink(mobj_t *ring); void Obj_BlockBodyThink(mobj_t *body); void Obj_GuardBreakThink(mobj_t *fx); +void Obj_ChargeAuraThink(mobj_t *aura); + /* Ring Shooter */ boolean Obj_RingShooterThinker(mobj_t *mo); boolean Obj_PlayerRingShooterFreeze(player_t *const player); diff --git a/src/objects/CMakeLists.txt b/src/objects/CMakeLists.txt index 1e035d52d..8abbd34ee 100644 --- a/src/objects/CMakeLists.txt +++ b/src/objects/CMakeLists.txt @@ -39,6 +39,7 @@ target_sources(SRB2SDL2 PRIVATE wpzothers.c shadow.cpp ball-switch.cpp + charge.c ) add_subdirectory(versus) diff --git a/src/objects/charge.c b/src/objects/charge.c new file mode 100644 index 000000000..6566b69c3 --- /dev/null +++ b/src/objects/charge.c @@ -0,0 +1,34 @@ +#include "../doomdef.h" +#include "../info.h" +#include "../k_objects.h" +#include "../p_local.h" +#include "../k_kart.h" +#include "../k_powerup.h" + +void Obj_ChargeAuraThink (mobj_t *aura) +{ + if (P_MobjWasRemoved(aura->target) || !aura->target->player || !aura->target->player->trickcharge) + { + P_RemoveMobj(aura); + } + else + { + mobj_t *mo = aura->target; + player_t *player = mo->player; + + // Follow player + aura->flags &= ~(MF_NOCLIPTHING); + P_MoveOrigin(aura, mo->x, mo->y, mo->z + mo->height/2); + aura->flags |= MF_NOCLIPTHING; + aura->color = mo->color; + + fixed_t baseScale = 12*mo->scale/10; + P_SetScale(aura, baseScale); + + // Twirl + aura->angle = aura->angle - ANG1*(player->trickcharge/TICRATE + 4); + // Visuals + aura->renderflags |= RF_PAPERSPRITE|RF_ADD; + + } +} \ No newline at end of file diff --git a/src/p_mobj.c b/src/p_mobj.c index 565647cb7..732231631 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8781,6 +8781,11 @@ static boolean P_MobjRegularThink(mobj_t *mobj) Obj_BlockBodyThink(mobj); break; } + case MT_CHARGEAURA: + { + Obj_ChargeAuraThink(mobj); + break; + } case MT_GUARDBREAK: { Obj_GuardBreakThink(mobj); From 1adfc7f2a4272f9748fe39ce12d3864b3455d429 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 12 Nov 2023 17:29:54 +0000 Subject: [PATCH 48/88] TRICKSTATE_FORWARD blast effect Fun and simple papersprite buffoonery Hey remember when the author of this commit thought papersprites would be a one-off side feature Also fixes a potential invalid dereference when getting the color for MT_SIDETRICK --- src/deh_tables.c | 2 ++ src/info.c | 33 ++++++++++++++++++++++-- src/info.h | 3 +++ src/k_kart.c | 34 ++++++++++++++++++++++--- src/p_mobj.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 133 insertions(+), 5 deletions(-) diff --git a/src/deh_tables.c b/src/deh_tables.c index 4b11f9421..f951e365a 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -3902,6 +3902,7 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_SIDETRICK", "S_BACKTRICK", + "S_FORWARDTRICK", // DEZ Ring Shooter "S_TIREGRABBER", @@ -5664,6 +5665,7 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t "MT_SMOOTHLANDING", "MT_TRICKINDICATOR", "MT_SIDETRICK", + "MT_FORWARDTRICK", "MT_TIREGRABBER", "MT_RINGSHOOTER", diff --git a/src/info.c b/src/info.c index 4e93c7473..51cfc2b63 100644 --- a/src/info.c +++ b/src/info.c @@ -641,6 +641,7 @@ char sprnames[NUMSPRITES + 1][5] = "TRK4", "TRK5", "TRK6", + "TRK7", "TIRG", // Tire grabbers "RSHT", // DEZ Ring Shooter @@ -4681,8 +4682,9 @@ state_t states[NUMSTATES] = {SPR_NULL, 0, 1, {NULL}, 12, 1, S_TRICKINDICATOR_UNDERLAY_ARROW2}, // S_TRICKINDICATOR_UNDERLAY_ARROW, {SPR_TRK4, FF_FULLBRIGHT|FF_ANIMATE|FF_PAPERSPRITE, 13, {NULL}, 12, 1, S_INVISIBLE}, // S_TRICKINDICATOR_UNDERLAY_ARROW2, - {SPR_TRK5, FF_FULLBRIGHT|FF_ANIMATE|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_SIDETRICK, - {SPR_TRK6, FF_FULLBRIGHT|FF_ANIMATE|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_BACKTRICK, + {SPR_TRK5, FF_FULLBRIGHT|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_SIDETRICK, + {SPR_TRK6, FF_FULLBRIGHT|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_BACKTRICK, + {SPR_TRK7, FF_FULLBRIGHT|FF_PAPERSPRITE|FF_ANIMATE, -1, {NULL}, 6, 4, S_NULL}, // S_FORWARDTRICK, {SPR_TIRG, FF_ANIMATE, -1, {NULL}, 1, 1, S_NULL}, // S_TIREGRABBER {SPR_RSHT, FF_PAPERSPRITE|0, -1, {NULL}, 0, 0, S_NULL}, // S_RINGSHOOTER_SIDE @@ -25432,6 +25434,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_FORWARDTRICK + -1, // doomednum + S_FORWARDTRICK, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 60*FRACUNIT, // radius + 86*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPTHING|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags + S_NULL // raisestate + }, + { // MT_TIREGRABBER -1, // doomednum S_TIREGRABBER, // spawnstate diff --git a/src/info.h b/src/info.h index 54cb2ed75..1bb5cfdac 100644 --- a/src/info.h +++ b/src/info.h @@ -1198,6 +1198,7 @@ typedef enum sprite SPR_TRK4, SPR_TRK5, SPR_TRK6, + SPR_TRK7, SPR_TIRG, // Tire grabbers SPR_RSHT, // DEZ Ring Shooter @@ -5127,6 +5128,7 @@ typedef enum state S_SIDETRICK, S_BACKTRICK, + S_FORWARDTRICK, // DEZ Ring Shooter S_TIREGRABBER, @@ -6928,6 +6930,7 @@ typedef enum mobj_type MT_SMOOTHLANDING, MT_TRICKINDICATOR, MT_SIDETRICK, + MT_FORWARDTRICK, MT_TIREGRABBER, MT_RINGSHOOTER, diff --git a/src/k_kart.c b/src/k_kart.c index 5831acbde..8162c1520 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -12397,9 +12397,37 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } INT32 j; + skincolornum_t trickcolor = SKINCOLOR_NONE; - if (player->trickpanel == TRICKSTATE_FORWARD) - ; // Not yet sprited + if (P_MobjWasRemoved(player->trickIndicator) == false) + trickcolor = player->trickIndicator->color; + + if (player->trickpanel == TRICKSTATE_FORWARD) + { + for (j = 0; j < 2; j++) + { + mobj_t *fwush = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_FORWARDTRICK); + + P_SetTarget(&fwush->target, player->mo); + fwush->hitlag = TRICKLAG; + fwush->color = trickcolor; + fwush->renderflags |= RF_DONTDRAW; + fwush->flags2 |= MF2_AMBUSH; // don't interp on first think + fwush->threshold = 0; + + fwush->movedir = player->mo->angle; + if (j == 0) + { + fwush->angle = fwush->old_angle = fwush->movedir + ANGLE_135; + fwush->movefactor = 1; + } + else + { + fwush->angle = fwush->old_angle = fwush->movedir - ANGLE_135; + fwush->movefactor = -1; + } + } + } else for (j = 0; j < 8; j++, baseangle += angledelta) { mobj_t *swipe = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_SIDETRICK); @@ -12409,7 +12437,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) P_SetTarget(&swipe->target, player->mo); swipe->hitlag = TRICKLAG; - swipe->color = player->trickIndicator->color; + swipe->color = trickcolor; swipe->angle = baseangle + ANGLE_90; swipe->renderflags |= RF_DONTDRAW; swipe->flags2 |= MF2_AMBUSH; // don't interp on first think diff --git a/src/p_mobj.c b/src/p_mobj.c index 56c94b3ac..a37758add 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8537,6 +8537,72 @@ static boolean P_MobjRegularThink(mobj_t *mobj) } break; } + case MT_FORWARDTRICK: + { + fixed_t destx, desty; + fixed_t zoff = 0; + + if (!mobj->target + || !mobj->target->health + || !mobj->target->player + || mobj->target->player->trickpanel != TRICKSTATE_FORWARD) + { + P_RemoveMobj(mobj); + return false; + } + + // Flicker every other frame from first visibility + if (mobj->flags2 & MF2_BOSSDEAD) + { + mobj->renderflags |= RF_DONTDRAW; + } + else + { + mobj->renderflags &= ~RF_DONTDRAW; + mobj->renderflags |= (mobj->target->renderflags & RF_DONTDRAW); + } + + mobj->eflags = (mobj->eflags & ~MFE_VERTICALFLIP)|(mobj->target->eflags & MFE_VERTICALFLIP); + mobj->flags2 = ((mobj->flags2 & ~MF2_OBJECTFLIP)|(mobj->target->flags2 & MF2_OBJECTFLIP)) ^ MF2_BOSSDEAD; + + // sweeping effect + const fixed_t sweep = FixedMul(FRACUNIT - (mobj->threshold * 2), mobj->radius); + + mobj->threshold += FRACUNIT/(7*4); + if (mobj->threshold > FRACUNIT) + mobj->threshold -= FRACUNIT; + + P_InstaScale(mobj, mobj->target->scale); + + destx = mobj->target->x; + desty = mobj->target->y; + + destx += P_ReturnThrustX(mobj, mobj->movedir, sweep); + desty += P_ReturnThrustY(mobj, mobj->movedir, sweep); + + const fixed_t sideways = P_ReturnThrustY(mobj, mobj->angle - mobj->movedir, mobj->radius); + destx += P_ReturnThrustX(mobj, mobj->movedir + ANGLE_90, sideways); + desty += P_ReturnThrustY(mobj, mobj->movedir + ANGLE_90, sideways); + + if (mobj->eflags & MFE_VERTICALFLIP) + zoff += mobj->target->height - (mobj->height + 18*mobj->scale); + else + zoff += 18*mobj->scale; + + // Necessary to "ride" on Garden Top + zoff += mobj->target->sprzoff; + + if (mobj->flags2 & MF2_AMBUSH) + { + P_SetOrigin(mobj, destx, desty, mobj->target->z + zoff); + mobj->flags2 &= ~MF2_AMBUSH; + } + else + { + P_MoveOrigin(mobj, destx, desty, mobj->target->z + zoff); + } + break; + } case MT_LIGHTNINGSHIELD: { if (!mobj->target || !mobj->target->health || !mobj->target->player From 3ab5da8a3ecd339f74f02a2ff31cdea7c6478bfa Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 12 Nov 2023 17:37:14 +0000 Subject: [PATCH 49/88] MT_CHARGEAURA: Fix target setting to track reference --- src/k_kart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index 8162c1520..c9e7f1657 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -8544,7 +8544,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) { mobj_t *aura = P_SpawnMobjFromMobj(player->mo, 0, 0, player->mo->height/2, MT_CHARGEAURA); aura->angle = player->mo->angle + i*ANG15; - aura->target = player->mo; + P_SetTarget(&aura->target, player->mo); if (i != 0) aura->renderflags |= RF_TRANS50; } From 2082a372dfe054a18df9bc9d94b4892fe33dffb5 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 12 Nov 2023 17:43:48 +0000 Subject: [PATCH 50/88] MT_FORWARDTRICK: Don't interp when your sweep returns you to the front of the player --- src/p_mobj.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/p_mobj.c b/src/p_mobj.c index a37758add..a3ce910e4 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8570,7 +8570,10 @@ static boolean P_MobjRegularThink(mobj_t *mobj) mobj->threshold += FRACUNIT/(7*4); if (mobj->threshold > FRACUNIT) + { mobj->threshold -= FRACUNIT; + mobj->flags2 |= MF2_AMBUSH; + } P_InstaScale(mobj, mobj->target->scale); From 9bb1f56fa6042d10805e3d0c447ed11bda72dd1a Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 12 Nov 2023 22:28:51 +0000 Subject: [PATCH 51/88] MT_FORWARDTRICK: Adjustments based on feedback - Animate 4x as fast without flickering - Fix interp issues - Spawn additive trail of the final frame --- src/info.c | 2 +- src/p_mobj.c | 41 ++++++++++++++++++++--------------------- 2 files changed, 21 insertions(+), 22 deletions(-) diff --git a/src/info.c b/src/info.c index 51cfc2b63..83b6407c0 100644 --- a/src/info.c +++ b/src/info.c @@ -4684,7 +4684,7 @@ state_t states[NUMSTATES] = {SPR_TRK5, FF_FULLBRIGHT|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_SIDETRICK, {SPR_TRK6, FF_FULLBRIGHT|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_BACKTRICK, - {SPR_TRK7, FF_FULLBRIGHT|FF_PAPERSPRITE|FF_ANIMATE, -1, {NULL}, 6, 4, S_NULL}, // S_FORWARDTRICK, + {SPR_TRK7, FF_FULLBRIGHT|FF_PAPERSPRITE|FF_ANIMATE, -1, {NULL}, 6, 1, S_NULL}, // S_FORWARDTRICK, {SPR_TIRG, FF_ANIMATE, -1, {NULL}, 1, 1, S_NULL}, // S_TIREGRABBER {SPR_RSHT, FF_PAPERSPRITE|0, -1, {NULL}, 0, 0, S_NULL}, // S_RINGSHOOTER_SIDE diff --git a/src/p_mobj.c b/src/p_mobj.c index a3ce910e4..c2b98d99e 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8551,32 +8551,17 @@ static boolean P_MobjRegularThink(mobj_t *mobj) return false; } - // Flicker every other frame from first visibility - if (mobj->flags2 & MF2_BOSSDEAD) - { - mobj->renderflags |= RF_DONTDRAW; - } - else - { - mobj->renderflags &= ~RF_DONTDRAW; - mobj->renderflags |= (mobj->target->renderflags & RF_DONTDRAW); - } + mobj->renderflags &= ~RF_DONTDRAW; + mobj->renderflags |= (mobj->target->renderflags & RF_DONTDRAW); mobj->eflags = (mobj->eflags & ~MFE_VERTICALFLIP)|(mobj->target->eflags & MFE_VERTICALFLIP); mobj->flags2 = ((mobj->flags2 & ~MF2_OBJECTFLIP)|(mobj->target->flags2 & MF2_OBJECTFLIP)) ^ MF2_BOSSDEAD; // sweeping effect + P_InstaScale(mobj, (6*mobj->target->scale)/5); + const fixed_t sweep = FixedMul(FRACUNIT - (mobj->threshold * 2), mobj->radius); - mobj->threshold += FRACUNIT/(7*4); - if (mobj->threshold > FRACUNIT) - { - mobj->threshold -= FRACUNIT; - mobj->flags2 |= MF2_AMBUSH; - } - - P_InstaScale(mobj, mobj->target->scale); - destx = mobj->target->x; desty = mobj->target->y; @@ -8588,9 +8573,9 @@ static boolean P_MobjRegularThink(mobj_t *mobj) desty += P_ReturnThrustY(mobj, mobj->movedir + ANGLE_90, sideways); if (mobj->eflags & MFE_VERTICALFLIP) - zoff += mobj->target->height - (mobj->height + 18*mobj->scale); + zoff += mobj->target->height - (mobj->height + 18*mobj->target->scale); else - zoff += 18*mobj->scale; + zoff += 18*mobj->target->scale; // Necessary to "ride" on Garden Top zoff += mobj->target->sprzoff; @@ -8604,6 +8589,20 @@ static boolean P_MobjRegularThink(mobj_t *mobj) { P_MoveOrigin(mobj, destx, desty, mobj->target->z + zoff); } + + mobj->threshold += FRACUNIT/6; + if (mobj->threshold > FRACUNIT) + { + mobj_t *puff = P_SpawnGhostMobj(mobj); + if (puff) + { + puff->renderflags = (puff->renderflags & ~RF_TRANSMASK)|RF_ADD; + } + + mobj->threshold -= FRACUNIT; + mobj->flags2 |= MF2_AMBUSH; + } + break; } case MT_LIGHTNINGSHIELD: From ec4ea384c30ee4bfeb60100953f320d46864530b Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 4 Nov 2023 13:28:21 +0000 Subject: [PATCH 52/88] Obj_AudienceInit: Clean up handling - Don't require a mapthing to select a random Follower from the Audience list - Don't print an error message if the mapheader Audience list is empty. This is probably intentional. --- src/objects/audience.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/objects/audience.c b/src/objects/audience.c index f1c1a0131..b3d844184 100644 --- a/src/objects/audience.c +++ b/src/objects/audience.c @@ -29,6 +29,7 @@ Obj_AudienceInit mapthing_t *mthing, INT32 followerpick) { + const boolean ourchoiceofvisuals = (followerpick < 0 || followerpick > numfollowers); INT16 *reflist = NULL; INT16 tempreflist[MAXHEADERFOLLOWERS]; UINT8 numref = 0; @@ -36,9 +37,9 @@ Obj_AudienceInit audience_mainstate(mobj) = S_NULL; // Pick follower - if (mthing != NULL) + if (ourchoiceofvisuals == true) { - if (mthing->thing_stringargs[0] != NULL) + if (mthing != NULL && mthing->thing_stringargs[0] != NULL) { // From mapthing char *stringcopy = Z_StrDup(mthing->thing_stringargs[0]); @@ -56,11 +57,23 @@ Obj_AudienceInit *c = ' '; } - if ((tempreflist[numref++] = K_FollowerAvailable(tok)) == -1) + if ((tempreflist[numref] = K_FollowerAvailable(tok)) == -1) + { CONS_Alert(CONS_WARNING, "Mapthing %s: Follower \"%s\" is invalid!\n", sizeu1(mthing-mapthings), tok); + } + else + numref++; + tok = strtok(NULL, " ,"); } + if (!numref) + { + // This is the one thing a user should definitely be told about. + CONS_Alert(CONS_WARNING, "Mapthing %s: Follower audience has no valid followers to pick from!\n", sizeu1(mthing-mapthings)); + // DO NOT RETURN HERE + } + Z_Free(stringcopy); reflist = tempreflist; @@ -81,8 +94,8 @@ Obj_AudienceInit if (!numref || !reflist) { - // This is the one thing a user should definitely be told about. - CONS_Alert(CONS_WARNING, "Mapthing %s: Follower audience has no valid followers to pick from!\n", sizeu1(mthing-mapthings)); + // Clean up after ourselves. + P_RemoveMobj(mobj); return; } @@ -137,11 +150,11 @@ Obj_AudienceInit } // Handle colors - if (mthing != NULL) + if (ourchoiceofvisuals == true) { UINT16 colorpick = SKINCOLOR_NONE; - if (mthing->thing_stringargs[1] != NULL) + if (mthing != NULL && mthing->thing_stringargs[1] != NULL) { if (!stricmp("Random", mthing->thing_stringargs[1])) { From 9e49f761b0a6be78348cc89936a72439ca00d08b Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 4 Nov 2023 13:32:08 +0000 Subject: [PATCH 53/88] Prison Egg polish: Spawn three Followers on hit - Selected from the mapheader's Audience list - Since most Prison Break maps don't have Audience lists set, you'll be seeing a lot of Flicky/Motobuddy/Chao for now - Yes, these will disappear in deathpits like in Sky Chase - Intentionally did not do this for the CD Special Stage UFO --- src/k_objects.h | 2 +- src/objects/audience.c | 27 ++++++++++++++------ src/p_inter.c | 56 ++++++++++++++++++++++++++++++++++++++++++ src/p_mobj.c | 6 +++-- 4 files changed, 80 insertions(+), 11 deletions(-) diff --git a/src/k_objects.h b/src/k_objects.h index c88bf3320..bad973f62 100644 --- a/src/k_objects.h +++ b/src/k_objects.h @@ -136,7 +136,7 @@ void Obj_UpdateRingShooterFace(mobj_t *part); /* Follower Audience */ void Obj_AudienceInit(mobj_t * mobj, mapthing_t *mthing, INT32 followerpick); -void Obj_AudienceThink(mobj_t * mobj, boolean focusonplayer); +void Obj_AudienceThink(mobj_t * mobj, boolean focusonplayer, boolean checkdeathpit); /* Random Item Boxes */ void Obj_RandomItemVisuals(mobj_t *mobj); diff --git a/src/objects/audience.c b/src/objects/audience.c index b3d844184..b6d211132 100644 --- a/src/objects/audience.c +++ b/src/objects/audience.c @@ -202,8 +202,11 @@ Obj_AudienceInit void Obj_AudienceThink ( mobj_t * mobj, - boolean focusonplayer) + boolean focusonplayer, + boolean checkdeathpit) { + boolean landed = false; + if (audience_mainstate(mobj) == S_NULL) { // Uninitialised, don't do anything funny. @@ -328,15 +331,23 @@ Obj_AudienceThink } else if (mobj->flags2 & MF2_OBJECTFLIP) { - if (mobj->z + mobj->height >= mobj->ceilingz) - { - mobj->momz = -audience_bobamp(mobj); - P_SetMobjState(mobj, audience_mainstate(mobj)); - } + landed = (mobj->z + mobj->height >= mobj->ceilingz); } - else if (mobj->z <= mobj->floorz) + else { - mobj->momz = audience_bobamp(mobj); + landed = (mobj->z <= mobj->floorz); + } + + if (landed == true) + { + if (checkdeathpit && P_CheckDeathPitCollide(mobj)) + { + P_RemoveMobj(mobj); + return; + } + + mobj->momx = mobj->momy = 0; + mobj->momz = P_MobjFlip(mobj)*audience_bobamp(mobj); P_SetMobjState(mobj, audience_mainstate(mobj)); } } diff --git a/src/p_inter.c b/src/p_inter.c index 266cba2e2..f90848f66 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2103,6 +2103,62 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget cur = cur->hnext; } + // Spawn three Followers (if possible) + if (mapheaderinfo[gamemap-1]->numFollowers) + { + dir = FixedAngle(P_RandomKey(PR_RANDOMAUDIENCE, 360)*FRACUNIT); + + const fixed_t launchmomentum = 11 * mapobjectscale; + const fixed_t jaggedness = 4; + angle_t launchangle; + UINT8 i; + for (i = 0; i < 3; i++, dir += ANGLE_120) + { + cur = P_SpawnMobj( + target->x, target->y, + target->z + target->height/2, + MT_RANDOMAUDIENCE + ); + + // We check if you have some horrible Lua + if (P_MobjWasRemoved(cur)) + break; + + Obj_AudienceInit(cur, NULL, -1); + + // We check again if the list is invalid + if (P_MobjWasRemoved(cur)) + break; + + // For Followers, this makes them + // MF2_AMBUSH - try to always look at the nearest player + // MF2_DONTRESPAWN - Check for death pits + cur->flags2 |= (MF2_AMBUSH|MF2_DONTRESPAWN); + + cur->hitlag = target->hitlag; + + P_SetScale(cur, cur->destscale/TICRATE); + cur->scalespeed = cur->destscale/TICRATE; + cur->z -= cur->height/2; + + // flags are NOT from the target - just in case it's just been placed on the ceiling as a gimmick + cur->flags2 |= (source->flags2 & MF2_OBJECTFLIP); + cur->eflags |= (source->eflags & MFE_VERTICALFLIP); + + launchangle = FixedAngle(P_RandomRange(PR_RANDOMAUDIENCE, 60/jaggedness, 80/jaggedness) * jaggedness*FRACUNIT); + + cur->momz = P_MobjFlip(target) // THIS one uses target! + * P_ReturnThrustY(cur, launchangle, launchmomentum); + + cur->angle = dir; + + P_InstaThrust( + cur, cur->angle, + P_ReturnThrustX(cur, launchangle, launchmomentum) + ); + } + } + S_StartSound(target, sfx_mbs60); P_AddBrokenPrison(target, inflictor, source); diff --git a/src/p_mobj.c b/src/p_mobj.c index f58006a0d..839e37cfc 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7270,7 +7270,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) if (mobj->flags2 & MF2_STRONGBOX) { - Obj_AudienceThink(mobj, true); + Obj_AudienceThink(mobj, true, false); if (P_MobjWasRemoved(mobj)) return false; } @@ -10808,7 +10808,9 @@ void P_SceneryThinker(mobj_t *mobj) if (mobj->type == MT_RANDOMAUDIENCE) { - Obj_AudienceThink(mobj, !!(mobj->flags2 & MF2_AMBUSH)); + Obj_AudienceThink(mobj, !!(mobj->flags2 & MF2_AMBUSH), !!(mobj->flags2 & MF2_DONTRESPAWN)); + if (P_MobjWasRemoved(mobj)) + return; } } From 3805a4d5f0c4425f24c865105a2880cfbf994a7e Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 12 Nov 2023 23:51:44 +0000 Subject: [PATCH 54/88] Adjust Prison followers based on feedback... - Exist for 1.5 seconds before disappearing - Flickers away in the last half second - Twice as many spawned, at half the size - Different arc - Severely reduced gravity - Don't jump if they hypothetically touch the floor --- src/objects/audience.c | 6 ++++++ src/p_inter.c | 21 +++++++++++++-------- src/p_mobj.c | 4 ++++ 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/objects/audience.c b/src/objects/audience.c index b6d211132..b5814ae16 100644 --- a/src/objects/audience.c +++ b/src/objects/audience.c @@ -207,6 +207,12 @@ Obj_AudienceThink { boolean landed = false; + if (mobj->fuse && mobj->fuse < (TICRATE/2)) + { + mobj->renderflags ^= RF_DONTDRAW; + return; // no jumping when you hit the floor, your gravity is weird + } + if (audience_mainstate(mobj) == S_NULL) { // Uninitialised, don't do anything funny. diff --git a/src/p_inter.c b/src/p_inter.c index f90848f66..f510cf2fa 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2108,11 +2108,11 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget { dir = FixedAngle(P_RandomKey(PR_RANDOMAUDIENCE, 360)*FRACUNIT); - const fixed_t launchmomentum = 11 * mapobjectscale; + const fixed_t launchmomentum = 7 * mapobjectscale; const fixed_t jaggedness = 4; angle_t launchangle; UINT8 i; - for (i = 0; i < 3; i++, dir += ANGLE_120) + for (i = 0; i < 6; i++, dir += ANG60) { cur = P_SpawnMobj( target->x, target->y, @@ -2130,13 +2130,9 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget if (P_MobjWasRemoved(cur)) break; - // For Followers, this makes them - // MF2_AMBUSH - try to always look at the nearest player - // MF2_DONTRESPAWN - Check for death pits - cur->flags2 |= (MF2_AMBUSH|MF2_DONTRESPAWN); - cur->hitlag = target->hitlag; + cur->destscale /= 2; P_SetScale(cur, cur->destscale/TICRATE); cur->scalespeed = cur->destscale/TICRATE; cur->z -= cur->height/2; @@ -2145,7 +2141,13 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget cur->flags2 |= (source->flags2 & MF2_OBJECTFLIP); cur->eflags |= (source->eflags & MFE_VERTICALFLIP); - launchangle = FixedAngle(P_RandomRange(PR_RANDOMAUDIENCE, 60/jaggedness, 80/jaggedness) * jaggedness*FRACUNIT); + launchangle = FixedAngle( + ( + ( + P_RandomRange(PR_RANDOMAUDIENCE, 12/jaggedness, 24/jaggedness) * jaggedness + ) + (i & 1)*16 + ) * FRACUNIT + ); cur->momz = P_MobjFlip(target) // THIS one uses target! * P_ReturnThrustY(cur, launchangle, launchmomentum); @@ -2156,6 +2158,9 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget cur, cur->angle, P_ReturnThrustX(cur, launchangle, launchmomentum) ); + + cur->fuse = (3*TICRATE)/2; + cur->flags |= MF_NOCLIPHEIGHT; } } diff --git a/src/p_mobj.c b/src/p_mobj.c index 839e37cfc..da1b58d8e 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1278,6 +1278,10 @@ fixed_t P_GetMobjGravity(mobj_t *mo) } break; } + case MT_RANDOMAUDIENCE: + if (mo->fuse) + gravityadd /= 10; + break; default: break; } From 041d7660ae401b5ab54398af9eae78d7e5a1403d Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Sun, 12 Nov 2023 23:32:59 -0700 Subject: [PATCH 55/88] Charge minimum viable visuals (plus future frame/obj setup) --- src/deh_tables.c | 10 +++ src/info.c | 144 +++++++++++++++++++++++++++++++++++++++++++ src/info.h | 14 +++++ src/k_kart.c | 22 ++++--- src/k_objects.h | 5 ++ src/objects/charge.c | 106 ++++++++++++++++++++++++++++++- src/p_mobj.c | 25 ++++++++ 7 files changed, 315 insertions(+), 11 deletions(-) diff --git a/src/deh_tables.c b/src/deh_tables.c index f951e365a..e80bcb37a 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -3326,6 +3326,11 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_BLOCKBODY", "S_CHARGEAURA", + "S_CHARGEFALL", + "S_CHARGEFLICKER", + "S_CHARGESPARK", + "S_CHARGERELEASE", + "S_CHARGEEXTRA", "S_SERVANTHAND", @@ -5559,6 +5564,11 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t "MT_BLOCKBODY", "MT_CHARGEAURA", + "MT_CHARGEFALL", + "MT_CHARGEFLICKER", + "MT_CHARGESPARK", + "MT_CHARGERELEASE", + "MT_CHARGEEXTRA", "MT_SERVANTHAND", diff --git a/src/info.c b/src/info.c index 83b6407c0..67f1001df 100644 --- a/src/info.c +++ b/src/info.c @@ -568,6 +568,10 @@ char sprnames[NUMSPRITES + 1][5] = "GBDY", // Guard body "TRC1", // Charge aura + "TRC2", // Charge fall + "TRC3", // Charge flicker/sparks + "TRC4", // Charge release + "TRC5", // Charge extra "DHND", // Servant Hand @@ -4142,6 +4146,11 @@ state_t states[NUMSTATES] = {SPR_GBDY, FF_FULLBRIGHT|FF_ANIMATE|0, -1, {NULL}, 4, 2, S_NULL}, // S_BLOCKBODY {SPR_TRC1, FF_FULLBRIGHT|FF_ANIMATE|0, -1, {NULL}, 4, 2, S_NULL}, // S_CHARGEAURA + {SPR_TRC2, FF_FULLBRIGHT|FF_ANIMATE|0, 20, {NULL}, 19, 1, S_NULL}, // S_CHARGEFALL + {SPR_TRC3, FF_FULLBRIGHT|FF_ADD|0, 2, {NULL}, 0, 0, S_NULL}, // S_CHARGEFLICKER + {SPR_TRC3, FF_FULLBRIGHT|FF_ADD|1, 2, {NULL}, 0, 0, S_NULL}, // S_CHARGESPARK + {SPR_TRC4, FF_FULLBRIGHT|FF_ADD|FF_ANIMATE|0, -1, {NULL}, 4, 1, S_NULL}, // S_CHARGERELEASE + {SPR_TRC5, FF_FULLBRIGHT|FF_ADD|FF_ANIMATE|0, -1, {NULL}, 4, 1, S_NULL}, // S_CHARGEEXTRA {SPR_DHND, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SERVANTHAND @@ -23274,6 +23283,141 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_CHARGEFALL + -1, // doomednum + S_CHARGEFALL, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 67*FRACUNIT, // radius + 67*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags + S_NULL // raisestate + }, + + { // MT_CHARGEFLICKER + -1, // doomednum + S_CHARGEFLICKER, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 67*FRACUNIT, // radius + 67*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags + S_NULL // raisestate + }, + + { // MT_CHARGESPARK + -1, // doomednum + S_CHARGESPARK, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 67*FRACUNIT, // radius + 67*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags + S_NULL // raisestate + }, + + { // MT_CHARGERELEASE + -1, // doomednum + S_CHARGERELEASE, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 67*FRACUNIT, // radius + 67*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags + S_NULL // raisestate + }, + + { // MT_CHARGEEXTRA + -1, // doomednum + S_CHARGEEXTRA, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 67*FRACUNIT, // radius + 67*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags + S_NULL // raisestate + }, + { // MT_SERVANTHAND -1, // doomednum S_SERVANTHAND, // spawnstate diff --git a/src/info.h b/src/info.h index 1bb5cfdac..3d83aebed 100644 --- a/src/info.h +++ b/src/info.h @@ -1125,6 +1125,10 @@ typedef enum sprite SPR_GBDY, // Guard body SPR_TRC1, // Charge aura + SPR_TRC2, // Charge fall + SPR_TRC3, // Charge flicker/sparks + SPR_TRC4, // Charge release + SPR_TRC5, // Charge extra SPR_DHND, // Servant Hand @@ -4553,6 +4557,11 @@ typedef enum state S_BLOCKBODY, S_CHARGEAURA, + S_CHARGEFALL, + S_CHARGEFLICKER, + S_CHARGESPARK, + S_CHARGERELEASE, + S_CHARGEEXTRA, S_SERVANTHAND, @@ -6824,6 +6833,11 @@ typedef enum mobj_type MT_BLOCKBODY, MT_CHARGEAURA, + MT_CHARGEFALL, + MT_CHARGEFLICKER, + MT_CHARGESPARK, + MT_CHARGERELEASE, + MT_CHARGEEXTRA, MT_SERVANTHAND, diff --git a/src/k_kart.c b/src/k_kart.c index c9e7f1657..6f970d03a 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -8545,7 +8545,9 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) mobj_t *aura = P_SpawnMobjFromMobj(player->mo, 0, 0, player->mo->height/2, MT_CHARGEAURA); aura->angle = player->mo->angle + i*ANG15; P_SetTarget(&aura->target, player->mo); - if (i != 0) + if (i == 0) + aura->extravalue2 = 1; + else aura->renderflags |= RF_TRANS50; } } @@ -8871,14 +8873,6 @@ void K_KartResetPlayerColor(player_t *player) } } - if (player->trickcharge && (leveltime & 1)) - { - player->mo->colorized = true; - player->mo->color = SKINCOLOR_INVINCFLASH; - fullbright = true; - goto finalise; - } - if (player->ringboost && (leveltime & 1)) // ring boosting { player->mo->colorized = true; @@ -12483,9 +12477,17 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { P_InstaThrust(player->mo, player->mo->angle, 2*abs(player->fastfall)/3 + 15*FRACUNIT); player->mo->hitlag = 3; - S_StartSound(player->mo, sfx_gshac); // TODO + S_StartSound(player->mo, sfx_gshba); // TODO player->fastfall = 0; // intentionally skip bounce player->trickcharge = 0; + + UINT8 i; + for (i = 0; i < 4; i++) + { + mobj_t *arc = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_CHARGEFALL); + P_SetTarget(&arc->target, player->mo); + arc->extravalue1 = i; + } } else { diff --git a/src/k_objects.h b/src/k_objects.h index baae5e050..1dc774f4f 100644 --- a/src/k_objects.h +++ b/src/k_objects.h @@ -127,6 +127,11 @@ void Obj_BlockBodyThink(mobj_t *body); void Obj_GuardBreakThink(mobj_t *fx); void Obj_ChargeAuraThink(mobj_t *aura); +void Obj_ChargeFallThink(mobj_t *charge); +void Obj_ChargeFlickerThink(mobj_t *flicker); +void Obj_ChargeSparkThink(mobj_t *spawk); +void Obj_ChargeReleaseThink(mobj_t *release); +void Obj_ChargeExtraThink(mobj_t *extra); /* Ring Shooter */ boolean Obj_RingShooterThinker(mobj_t *mo); diff --git a/src/objects/charge.c b/src/objects/charge.c index 6566b69c3..bb695ce5a 100644 --- a/src/objects/charge.c +++ b/src/objects/charge.c @@ -4,10 +4,16 @@ #include "../p_local.h" #include "../k_kart.h" #include "../k_powerup.h" +#include "../m_random.h" +#define CHARGEAURA_BURSTTIME (9) +#define CHARGEAURA_SPARKRADIUS (160) + +// xval1: destruction timer +// xval2: master (spawns other visuals) void Obj_ChargeAuraThink (mobj_t *aura) { - if (P_MobjWasRemoved(aura->target) || !aura->target->player || !aura->target->player->trickcharge) + if (P_MobjWasRemoved(aura->target) || !aura->target->player || (aura->extravalue1 >= CHARGEAURA_BURSTTIME)) { P_RemoveMobj(aura); } @@ -22,7 +28,20 @@ void Obj_ChargeAuraThink (mobj_t *aura) aura->flags |= MF_NOCLIPTHING; aura->color = mo->color; + aura->renderflags &= ~RF_DONTDRAW; + fixed_t baseScale = 12*mo->scale/10; + + if (aura->extravalue1 || !player->trickcharge) + { + aura->extravalue1++; + baseScale += (mo->scale / 3) * aura->extravalue1; + aura->renderflags &= ~RF_TRANSMASK; + aura->renderflags |= (aura->extravalue1)<extravalue1 % 2) + aura->renderflags |= RF_DONTDRAW; + } + P_SetScale(aura, baseScale); // Twirl @@ -30,5 +49,90 @@ void Obj_ChargeAuraThink (mobj_t *aura) // Visuals aura->renderflags |= RF_PAPERSPRITE|RF_ADD; + // fuck + boolean forceinvisible = !!!(leveltime % 8); + if (aura->extravalue1 || !(player->driftcharge > K_GetKartDriftSparkValueForStage(player, 3))) + forceinvisible = false; + + if (forceinvisible) + aura->renderflags |= RF_DONTDRAW; + + if (aura->extravalue2) + { + if (player->driftcharge) + { + mobj_t *spark = P_SpawnMobjFromMobj(aura, + mo->scale*P_RandomRange(PR_DECORATION, -1*CHARGEAURA_SPARKRADIUS, CHARGEAURA_SPARKRADIUS), + mo->scale*P_RandomRange(PR_DECORATION, -1*CHARGEAURA_SPARKRADIUS, CHARGEAURA_SPARKRADIUS), + mo->scale*P_RandomRange(PR_DECORATION, -1*CHARGEAURA_SPARKRADIUS, CHARGEAURA_SPARKRADIUS), + MT_CHARGESPARK); + spark->frame = P_RandomRange(PR_DECORATION, 1, 5); + P_SetTarget(&spark->target, aura); + P_SetScale(spark, 15*aura->scale/10); + } + + if (forceinvisible) + { + mobj_t *flicker = P_SpawnMobjFromMobj(aura, 0, 0, 0, MT_CHARGEFLICKER); + P_SetTarget(&flicker->target, aura); + P_SetScale(flicker, aura->scale); + } + } } +} + +void Obj_ChargeFallThink (mobj_t *charge) +{ + if (P_MobjWasRemoved(charge->target) || !charge->target->player) + { + P_RemoveMobj(charge); + } + else + { + mobj_t *mo = charge->target; + player_t *player = mo->player; + + // Follow player + charge->flags &= ~(MF_NOCLIPTHING); + P_MoveOrigin(charge, mo->x, mo->y, mo->z); + charge->flags |= MF_NOCLIPTHING; + charge->color = mo->color; + charge->angle = mo->angle + ANGLE_45 + (ANGLE_90 * charge->extravalue1); + + if (!P_IsObjectOnGround(mo)) + charge->renderflags |= RF_DONTDRAW; + else + charge->renderflags &= ~RF_DONTDRAW; + + fixed_t baseScale = 12*mo->scale/10; + P_SetScale(charge, baseScale); + + charge->renderflags &= ~RF_TRANSMASK; + if (charge->tics < 10) + charge->renderflags |= (9 - charge->tics)<renderflags |= RF_PAPERSPRITE|RF_ADD; + } +} + +void Obj_ChargeFlickerThink (mobj_t *flicker) +{ + // xd +} + +void Obj_ChargeSparkThink (mobj_t *spark) +{ + // xd + spark->renderflags |= RF_FULLBRIGHT|RF_ADD; +} + +void Obj_ChargeReleaseThink (mobj_t *flicker) +{ + // xd +} + +void Obj_ChargeExtraThink (mobj_t *flicker) +{ + // xd } \ No newline at end of file diff --git a/src/p_mobj.c b/src/p_mobj.c index c2b98d99e..4305f6cb7 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8856,6 +8856,31 @@ static boolean P_MobjRegularThink(mobj_t *mobj) Obj_ChargeAuraThink(mobj); break; } + case MT_CHARGEFALL: + { + Obj_ChargeFallThink(mobj); + break; + } + case MT_CHARGEFLICKER: + { + Obj_ChargeFlickerThink(mobj); + break; + } + case MT_CHARGESPARK: + { + Obj_ChargeSparkThink(mobj); + break; + } + case MT_CHARGERELEASE: + { + Obj_ChargeReleaseThink(mobj); + break; + } + case MT_CHARGEEXTRA: + { + Obj_ChargeExtraThink(mobj); + break; + } case MT_GUARDBREAK: { Obj_GuardBreakThink(mobj); From b946a66574fa0abdd60a315a396e7a41a36c2aec Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Mon, 13 Nov 2023 04:35:15 -0700 Subject: [PATCH 56/88] Trick Panel charge release WIP --- src/k_kart.c | 20 +++++++++++++++++++- src/objects/charge.c | 14 ++++++++++---- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 6f970d03a..c50ffd6cd 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -5218,6 +5218,18 @@ void K_SpawnDriftElectricSparks(player_t *player, int color, boolean shockwave) fixed_t sparkspeed = mobjinfo[MT_DRIFTELECTRICSPARK].speed; fixed_t sparkradius = 2 * shockscale * mobjinfo[MT_DRIFTELECTRICSPARK].radius; + if (player->trickcharge) + { + mobj_t *release = P_SpawnMobjFromMobj(mo, 0, 0, 0, MT_CHARGERELEASE); + release->momx = mo->momx/2; + release->momy = mo->momy/2; + release->momz = mo->momz/2; + release->angle = K_MomentumAngleReal(mo); + release->scale /= 5; + release->scalespeed = release->scale; + release->tics = 10; + } + for (hdir = -1; hdir <= 1; hdir += 2) { for (vdir = -1; vdir <= 1; vdir += 2) @@ -5225,12 +5237,16 @@ void K_SpawnDriftElectricSparks(player_t *player, int color, boolean shockwave) fixed_t hspeed = FixedMul(hdir * sparkspeed, mo->scale); // P_InstaThrust treats speed as absolute fixed_t vspeed = vdir * sparkspeed; // P_SetObjectMomZ scales speed with object scale angle_t sparkangle = mo->angle + ANGLE_45; + mobj_t *spark; for (i = 0; i < 4; i++) { fixed_t xoff = P_ReturnThrustX(mo, sparkangle, sparkradius); fixed_t yoff = P_ReturnThrustY(mo, sparkangle, sparkradius); - mobj_t *spark = P_SpawnMobjFromMobj(mo, x + xoff, y + yoff, z, MT_DRIFTELECTRICSPARK); + if (player->trickcharge && !shockwave) + spark = P_SpawnMobjFromMobj(mo, x + xoff, y + yoff, z, MT_CHARGEEXTRA); + else + spark = P_SpawnMobjFromMobj(mo, x + xoff, y + yoff, z, MT_DRIFTELECTRICSPARK); spark->angle = sparkangle; spark->color = color; @@ -5244,6 +5260,8 @@ void K_SpawnDriftElectricSparks(player_t *player, int color, boolean shockwave) if (shockwave) spark->frame |= FF_ADD; + else if (player->trickcharge) + spark->tics = 10; sparkangle += ANGLE_90; K_ReduceVFX(spark, player); diff --git a/src/objects/charge.c b/src/objects/charge.c index bb695ce5a..0ca6acda4 100644 --- a/src/objects/charge.c +++ b/src/objects/charge.c @@ -127,12 +127,18 @@ void Obj_ChargeSparkThink (mobj_t *spark) spark->renderflags |= RF_FULLBRIGHT|RF_ADD; } -void Obj_ChargeReleaseThink (mobj_t *flicker) +void Obj_ChargeReleaseThink (mobj_t *release) { - // xd + release->renderflags &= ~RF_TRANSMASK; + if (release->tics < 10) + release->renderflags |= (9 - release->tics)<rollangle += ANG30; } -void Obj_ChargeExtraThink (mobj_t *flicker) +void Obj_ChargeExtraThink (mobj_t *extra) { - // xd + extra->renderflags &= ~RF_TRANSMASK; + if (extra->tics < 10) + extra->renderflags |= (9 - extra->tics)<rollangle += ANG30; } \ No newline at end of file From aad6795ba7cae8186cfa9bfabfc915451b8a5f65 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Mon, 13 Nov 2023 16:41:09 -0700 Subject: [PATCH 57/88] Trickpanels: I don't even know who I am anymore --- src/d_player.h | 1 + src/info.c | 4 ++-- src/k_kart.c | 46 ++++++++++++++++++++++++++------------------ src/k_objects.h | 2 -- src/lua_playerlib.c | 4 ++++ src/objects/charge.c | 39 ++++++++++++++++++++----------------- src/p_mobj.c | 10 ---------- src/p_saveg.c | 2 ++ src/p_user.c | 1 + 9 files changed, 58 insertions(+), 51 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 8a0b1d9b0..a49ccb8ad 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -648,6 +648,7 @@ struct player_t respawnvars_t respawn; // Respawn info mobj_t *ringShooter; // DEZ respawner object tic_t airtime; // Used to track just air time, but has evolved over time into a general "karted" timer. Rename this variable? + tic_t lastairtime; UINT8 startboost; // (0 to 125) - Boost you get from start of race UINT8 dropdashboost; // Boost you get when holding A while respawning diff --git a/src/info.c b/src/info.c index 67f1001df..e777c2784 100644 --- a/src/info.c +++ b/src/info.c @@ -23333,7 +23333,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags + MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_SCENERY, // flags S_NULL // raisestate }, @@ -23360,7 +23360,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags + MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_SCENERY, // flags S_NULL // raisestate }, diff --git a/src/k_kart.c b/src/k_kart.c index c50ffd6cd..a4a2db32e 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3243,11 +3243,6 @@ static void K_GetKartBoostPower(player_t *player) ADDBOOST(8*FRACUNIT/10, 4*FRACUNIT, 2*SLIPTIDEHANDLING/5); // + 80% top speed, + 400% acceleration, +20% handling } - if (player->trickcharge) - { - ADDBOOST(0, FRACUNIT, 2*SLIPTIDEHANDLING/10); // 0% speed 100% accel 20% handle - } - if (player->spindashboost) // Spindash boost { const fixed_t MAXCHARGESPEED = K_GetSpindashChargeSpeed(player); @@ -3313,6 +3308,13 @@ static void K_GetKartBoostPower(player_t *player) ADDBOOST(6*FRACUNIT/20, FRACUNIT, 0); // + 30% top speed, + 100% acceleration, +0% handling } + if (player->trickcharge) + { + // NB: This is an acceleration-only boost. + // If this is applied earlier in the chain, it will diminish real speed boosts. + ADDBOOST(0, FRACUNIT, 2*SLIPTIDEHANDLING/10); // 0% speed 100% accel 20% handle + } + if (player->draftpower > 0) // Drafting { // 30% - 44%, each point of speed adds 1.75% @@ -5218,16 +5220,14 @@ void K_SpawnDriftElectricSparks(player_t *player, int color, boolean shockwave) fixed_t sparkspeed = mobjinfo[MT_DRIFTELECTRICSPARK].speed; fixed_t sparkradius = 2 * shockscale * mobjinfo[MT_DRIFTELECTRICSPARK].radius; - if (player->trickcharge) + if (player->trickcharge && !shockwave) { mobj_t *release = P_SpawnMobjFromMobj(mo, 0, 0, 0, MT_CHARGERELEASE); - release->momx = mo->momx/2; - release->momy = mo->momy/2; - release->momz = mo->momz/2; - release->angle = K_MomentumAngleReal(mo); + P_SetTarget(&release->target, mo); + release->tics = 40; release->scale /= 5; - release->scalespeed = release->scale; - release->tics = 10; + release->destscale *= 2; + release->scalespeed = release->scale/2; } for (hdir = -1; hdir <= 1; hdir += 2) @@ -5259,9 +5259,14 @@ void K_SpawnDriftElectricSparks(player_t *player, int color, boolean shockwave) P_SetScale(spark, shockscale * spark->scale); if (shockwave) + { spark->frame |= FF_ADD; + } else if (player->trickcharge) - spark->tics = 10; + { + spark->tics = 20; + } + sparkangle += ANGLE_90; K_ReduceVFX(spark, player); @@ -8554,7 +8559,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->dotrickfx && !player->mo->hitlag) { int i; - S_StartSound(player->mo, sfx_trick1); + S_StartSoundAtVolume(player->mo, sfx_trick1, 255/2); if (!player->trickcharge) { @@ -8567,6 +8572,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) aura->extravalue2 = 1; else aura->renderflags |= RF_TRANS50; + aura->cvmem = leveltime; } } @@ -10003,6 +10009,7 @@ static void K_KartDrift(player_t *player, boolean onground) // And take away wavedash properties: advanced cornering demands advanced finesse player->wavedash = 0; player->wavedashboost = 0; + player->trickcharge = 0; } else if ((player->pflags & PF_DRIFTINPUT) && player->drift != 0) { @@ -12306,7 +12313,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) #define TRICKTHRESHOLD (KART_FULLTURN/4) if (aimingcompare < -TRICKTHRESHOLD) // side trick { - S_StartSound(player->mo, sfx_trick0); + S_StartSoundAtVolume(player->mo, sfx_trick0, 255/2); player->dotrickfx = true; // Calculate speed boost decay: @@ -12345,7 +12352,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } else if (aimingcompare > TRICKTHRESHOLD) // forward/back trick { - S_StartSound(player->mo, sfx_trick0); + S_StartSoundAtVolume(player->mo, sfx_trick0, 255/2); player->dotrickfx = true; // Calculate speed boost decay: @@ -12495,7 +12502,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { P_InstaThrust(player->mo, player->mo->angle, 2*abs(player->fastfall)/3 + 15*FRACUNIT); player->mo->hitlag = 3; - S_StartSound(player->mo, sfx_gshba); // TODO + S_StartSound(player->mo, sfx_gshba); player->fastfall = 0; // intentionally skip bounce player->trickcharge = 0; @@ -12510,12 +12517,13 @@ void K_MoveKartPlayer(player_t *player, boolean onground) else { S_StartSound(player->mo, sfx_s23c); - K_SpawnDashDustRelease(player); UINT8 award = TICRATE - player->trickboostdecay; player->trickboost = award; - K_AwardPlayerRings(player, award, true); + K_AwardPlayerRings(player, + (TICRATE-player->trickboostdecay) * player->lastairtime/3 / TICRATE, // Scale ring award by same amount as trickboost + true); if (player->trickpanel == TRICKSTATE_FORWARD) player->trickboostpower /= 18; diff --git a/src/k_objects.h b/src/k_objects.h index 1dc774f4f..4a1dec35c 100644 --- a/src/k_objects.h +++ b/src/k_objects.h @@ -128,8 +128,6 @@ void Obj_GuardBreakThink(mobj_t *fx); void Obj_ChargeAuraThink(mobj_t *aura); void Obj_ChargeFallThink(mobj_t *charge); -void Obj_ChargeFlickerThink(mobj_t *flicker); -void Obj_ChargeSparkThink(mobj_t *spawk); void Obj_ChargeReleaseThink(mobj_t *release); void Obj_ChargeExtraThink(mobj_t *extra); diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index e8e928d63..ec5aeaad4 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -233,6 +233,8 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->lastpickuptype); else if (fastcmp(field,"airtime")) lua_pushinteger(L, plr->airtime); + else if (fastcmp(field,"lastairtime")) + lua_pushinteger(L, plr->lastairtime); else if (fastcmp(field,"flashing")) lua_pushinteger(L, plr->flashing); else if (fastcmp(field,"spinouttimer")) @@ -725,6 +727,8 @@ static int player_set(lua_State *L) plr->airtime = luaL_checkinteger(L, 3); else if (fastcmp(field,"airtime")) plr->airtime = luaL_checkinteger(L, 3); + else if (fastcmp(field,"lastairtime")) + plr->lastairtime = luaL_checkinteger(L, 3); else if (fastcmp(field,"flashing")) plr->flashing = luaL_checkinteger(L, 3); else if (fastcmp(field,"spinouttimer")) diff --git a/src/objects/charge.c b/src/objects/charge.c index 0ca6acda4..b4124343a 100644 --- a/src/objects/charge.c +++ b/src/objects/charge.c @@ -11,6 +11,7 @@ // xval1: destruction timer // xval2: master (spawns other visuals) +// cvmem: spawn time (used to offset flash) void Obj_ChargeAuraThink (mobj_t *aura) { if (P_MobjWasRemoved(aura->target) || !aura->target->player || (aura->extravalue1 >= CHARGEAURA_BURSTTIME)) @@ -50,7 +51,7 @@ void Obj_ChargeAuraThink (mobj_t *aura) aura->renderflags |= RF_PAPERSPRITE|RF_ADD; // fuck - boolean forceinvisible = !!!(leveltime % 8); + boolean forceinvisible = !!!((leveltime - aura->cvmem) % 4); if (aura->extravalue1 || !(player->driftcharge > K_GetKartDriftSparkValueForStage(player, 3))) forceinvisible = false; @@ -67,6 +68,7 @@ void Obj_ChargeAuraThink (mobj_t *aura) mo->scale*P_RandomRange(PR_DECORATION, -1*CHARGEAURA_SPARKRADIUS, CHARGEAURA_SPARKRADIUS), MT_CHARGESPARK); spark->frame = P_RandomRange(PR_DECORATION, 1, 5); + spark->renderflags |= RF_FULLBRIGHT|RF_ADD; P_SetTarget(&spark->target, aura); P_SetScale(spark, 15*aura->scale/10); } @@ -90,7 +92,6 @@ void Obj_ChargeFallThink (mobj_t *charge) else { mobj_t *mo = charge->target; - player_t *player = mo->player; // Follow player charge->flags &= ~(MF_NOCLIPTHING); @@ -116,29 +117,31 @@ void Obj_ChargeFallThink (mobj_t *charge) } } -void Obj_ChargeFlickerThink (mobj_t *flicker) -{ - // xd -} - -void Obj_ChargeSparkThink (mobj_t *spark) -{ - // xd - spark->renderflags |= RF_FULLBRIGHT|RF_ADD; -} - +// xval1: lifetime (used to offset from tracked player) void Obj_ChargeReleaseThink (mobj_t *release) { release->renderflags &= ~RF_TRANSMASK; - if (release->tics < 10) - release->renderflags |= (9 - release->tics)<rollangle += ANG30; + if (release->tics < 36) + release->renderflags |= (9 - release->tics/4)<rollangle += ANG15/2; + + if (P_MobjWasRemoved(release->target) || !release->target->player) + return; + + release->extravalue1++; + + fixed_t off = 8 * release->extravalue1 * release->target->scale; + angle_t ang = K_MomentumAngle(release->target) + ANGLE_180; + fixed_t xoff = FixedMul(off, FINECOSINE(ang >> ANGLETOFINESHIFT)); + fixed_t yoff = FixedMul(off, FINESINE(ang >> ANGLETOFINESHIFT)); + + P_MoveOrigin(release, release->target->x + xoff, release->target->y + yoff, release->target->z + release->target->height/2); } void Obj_ChargeExtraThink (mobj_t *extra) { extra->renderflags &= ~RF_TRANSMASK; - if (extra->tics < 10) - extra->renderflags |= (9 - extra->tics)<tics < 18) + extra->renderflags |= (9 - extra->tics/2)<rollangle += ANG30; } \ No newline at end of file diff --git a/src/p_mobj.c b/src/p_mobj.c index 4305f6cb7..715970404 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8861,16 +8861,6 @@ static boolean P_MobjRegularThink(mobj_t *mobj) Obj_ChargeFallThink(mobj); break; } - case MT_CHARGEFLICKER: - { - Obj_ChargeFlickerThink(mobj); - break; - } - case MT_CHARGESPARK: - { - Obj_ChargeSparkThink(mobj); - break; - } case MT_CHARGERELEASE: { Obj_ChargeReleaseThink(mobj); diff --git a/src/p_saveg.c b/src/p_saveg.c index 3ccab24d5..a733ab159 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -401,6 +401,7 @@ static void P_NetArchivePlayers(savebuffer_t *save) WRITEUINT32(save->p, K_GetWaypointHeapIndex(players[i].currentwaypoint)); WRITEUINT32(save->p, K_GetWaypointHeapIndex(players[i].nextwaypoint)); WRITEUINT32(save->p, players[i].airtime); + WRITEUINT32(save->p, players[i].lastairtime); WRITEUINT8(save->p, players[i].startboost); WRITEUINT8(save->p, players[i].dropdashboost); @@ -936,6 +937,7 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) players[i].currentwaypoint = (waypoint_t *)(size_t)READUINT32(save->p); players[i].nextwaypoint = (waypoint_t *)(size_t)READUINT32(save->p); players[i].airtime = READUINT32(save->p); + players[i].lastairtime = READUINT32(save->p); players[i].startboost = READUINT8(save->p); players[i].dropdashboost = READUINT8(save->p); diff --git a/src/p_user.c b/src/p_user.c index a73a8124a..2c36e7f97 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4084,6 +4084,7 @@ void P_PlayerThink(player_t *player) if (P_IsObjectOnGround(player->mo) && !P_PlayerInPain(player)) // This isn't airtime, but it's control loss all the same. { + player->lastairtime = player->airtime; player->airtime = 0; } else From c7972f27a09ee1f0105abe81d56753d9225f5701 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 13 Nov 2023 17:10:11 -0800 Subject: [PATCH 58/88] Revert "Try to correctly interpolate chase camera viewpoint as angle changes" This reverts commit c758a8ad27aa21946082b69085ee852570f0d67c. --- src/r_fps.c | 10 ++++------ src/r_fps.h | 1 - src/r_main.cpp | 11 ++--------- 3 files changed, 6 insertions(+), 16 deletions(-) diff --git a/src/r_fps.c b/src/r_fps.c index 61c3eb192..1418b2a22 100644 --- a/src/r_fps.c +++ b/src/r_fps.c @@ -140,6 +140,10 @@ void R_InterpolateView(fixed_t frac) prevview = newview; } + viewx = R_LerpFixed(prevview->x, newview->x, frac); + viewy = R_LerpFixed(prevview->y, newview->y, frac); + viewz = R_LerpFixed(prevview->z, newview->z, frac); + viewangle = R_LerpAngle(prevview->angle, newview->angle, frac); aimingangle = R_LerpAngle(prevview->aim, newview->aim, frac); viewroll = R_LerpAngle(prevview->roll, newview->roll, frac); @@ -147,12 +151,6 @@ void R_InterpolateView(fixed_t frac) viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT); viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT); - fixed_t zoom = R_LerpFixed(prevview->zoom, newview->zoom, frac); - - viewx = R_LerpFixed(prevview->x, newview->x, frac) - FixedMul(viewcos, zoom); - viewy = R_LerpFixed(prevview->y, newview->y, frac) - FixedMul(viewsin, zoom); - viewz = R_LerpFixed(prevview->z, newview->z, frac); - viewplayer = newview->player; viewsector = R_PointInSubsector(viewx, viewy)->sector; diff --git a/src/r_fps.h b/src/r_fps.h index f2df84cd9..969c427fa 100644 --- a/src/r_fps.h +++ b/src/r_fps.h @@ -48,7 +48,6 @@ struct viewvars_t { fixed_t x; fixed_t y; fixed_t z; - fixed_t zoom; boolean sky; sector_t *sector; player_t *player; diff --git a/src/r_main.cpp b/src/r_main.cpp index e05c88fe3..7277c2ace 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -1244,7 +1244,6 @@ void R_SetupFrame(int s) newview->x = r_viewmobj->x; newview->y = r_viewmobj->y; newview->z = r_viewmobj->z; - newview->zoom = 0; R_SetupCommonFrame(player, r_viewmobj->subsector); } @@ -1253,13 +1252,9 @@ void R_SetupFrame(int s) { r_viewmobj = NULL; - fixed_t x = player->mo ? player->mo->x : thiscam->x; - fixed_t y = player->mo ? player->mo->y : thiscam->y; - - newview->x = x; - newview->y = y; + newview->x = thiscam->x; + newview->y = thiscam->y; newview->z = thiscam->z + (thiscam->height>>1); - newview->zoom = FixedHypot(thiscam->x - x, thiscam->y - y); R_SetupCommonFrame(player, thiscam->subsector); } @@ -1272,7 +1267,6 @@ void R_SetupFrame(int s) newview->x = r_viewmobj->x; newview->y = r_viewmobj->y; newview->z = player->viewz; - newview->zoom = 0; R_SetupCommonFrame(player, r_viewmobj->subsector); } @@ -1303,7 +1297,6 @@ void R_SkyboxFrame(int s) newview->x = r_viewmobj->x; newview->y = r_viewmobj->y; newview->z = r_viewmobj->z; // 26/04/17: use actual Z position instead of spawnpoint angle! - newview->zoom = 0; if (mapheaderinfo[gamemap-1]) { From 3033c6928b5682b5e0b303c7fa4bdcba98556a3c Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 12 Nov 2023 04:48:12 -0800 Subject: [PATCH 59/88] Remove MF_STICKY --- src/d_clisrv.c | 2 +- src/deh_tables.c | 2 +- src/p_mobj.c | 19 ------------------- src/p_mobj.h | 3 +-- src/r_bbox.c | 2 +- 5 files changed, 4 insertions(+), 24 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 2bfc47f24..d242d4e71 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -5618,7 +5618,7 @@ static INT16 Consistancy(void) if (TypeIsNetSynced(mo->type) == false) continue; - if (mo->flags & (MF_SPECIAL | MF_SOLID | MF_PUSHABLE | MF_BOSS | MF_MISSILE | MF_SPRING | MF_MONITOR | MF_FIRE | MF_ENEMY | MF_PAIN | MF_STICKY)) + if (mo->flags & (MF_SPECIAL | MF_SOLID | MF_PUSHABLE | MF_BOSS | MF_MISSILE | MF_SPRING | MF_MONITOR | MF_FIRE | MF_ENEMY | MF_PAIN)) { ret -= mo->type; ret += mo->x; diff --git a/src/deh_tables.c b/src/deh_tables.c index 72141e85a..f7de4fa57 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -5993,7 +5993,7 @@ const char *const MOBJFLAG_LIST[] = { "ENEMY", "SCENERY", "PAIN", - "STICKY", + "\x01", // free: 1<<23 (name un-matchable) "APPLYTERRAIN", "NOCLIPTHING", "GRENADEBOUNCE", diff --git a/src/p_mobj.c b/src/p_mobj.c index da1b58d8e..51ac3380e 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1725,25 +1725,6 @@ void P_XYMovement(mobj_t *mo) P_ExplodeMissile(mo); return; } - else if (mo->flags & MF_STICKY) - { - S_StartSound(mo, mo->info->activesound); - mo->momx = mo->momy = mo->momz = 0; //Full stop! - mo->flags |= MF_NOGRAVITY; //Stay there! - mo->flags &= ~MF_STICKY; //Don't check again! - - // Check for hit against sky here - if (P_CheckSkyHit(mo)) - { - // Hack to prevent missiles exploding - // against the sky. - // Does not handle sky floors. - // Check frontsector as well. - - P_RemoveMobj(mo); - return; - } - } else { boolean walltransferred = false; diff --git a/src/p_mobj.h b/src/p_mobj.h index 382bfcd9e..d15269bb7 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -149,8 +149,7 @@ typedef enum MF_SCENERY = 1<<21, // Painful (shit hurts). MF_PAIN = 1<<22, - // This mobj will stick to any surface or solid object it touches. - MF_STICKY = 1<<23, + // free: 1<<23 // Object uses terrain effects. (Overlays, footsteps, etc) MF_APPLYTERRAIN = 1<<24, // for chase camera, don't be blocked by things (partial clipping) diff --git a/src/r_bbox.c b/src/r_bbox.c index 3654565a8..2e0b345c2 100644 --- a/src/r_bbox.c +++ b/src/r_bbox.c @@ -240,7 +240,7 @@ static boolean is_tangible (mobj_t *thing) // These objects probably do nothing! :D if ((thing->flags & (MF_SPECIAL|MF_SOLID|MF_SHOOTABLE |MF_PUSHABLE|MF_BOSS|MF_MISSILE|MF_SPRING - |MF_MONITOR|MF_ENEMY|MF_PAIN|MF_STICKY + |MF_MONITOR|MF_ENEMY|MF_PAIN |MF_PICKUPFROMBELOW)) == 0U) { return false; From 39a7c3b3ad52ccd56747d2235a731373df28cbeb Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 13 Nov 2023 18:57:58 -0800 Subject: [PATCH 60/88] Remove MF_MONITOR --- src/d_clisrv.c | 2 +- src/deh_tables.c | 2 +- src/g_demo.c | 2 +- src/info.c | 70 ++++++++++++++++++++++++------------------------ src/p_floor.c | 21 --------------- src/p_inter.c | 4 +-- src/p_map.c | 2 +- src/p_mobj.c | 47 -------------------------------- src/p_mobj.h | 3 +-- src/p_user.c | 3 --- src/r_bbox.c | 2 +- 11 files changed, 43 insertions(+), 115 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index d242d4e71..f030fa7b0 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -5618,7 +5618,7 @@ static INT16 Consistancy(void) if (TypeIsNetSynced(mo->type) == false) continue; - if (mo->flags & (MF_SPECIAL | MF_SOLID | MF_PUSHABLE | MF_BOSS | MF_MISSILE | MF_SPRING | MF_MONITOR | MF_FIRE | MF_ENEMY | MF_PAIN)) + if (mo->flags & (MF_SPECIAL | MF_SOLID | MF_PUSHABLE | MF_BOSS | MF_MISSILE | MF_SPRING | MF_FIRE | MF_ENEMY | MF_PAIN)) { ret -= mo->type; ret += mo->x; diff --git a/src/deh_tables.c b/src/deh_tables.c index f7de4fa57..6c70886a9 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -5987,7 +5987,7 @@ const char *const MOBJFLAG_LIST[] = { "SLOPE", "MISSILE", "SPRING", - "MONITOR", + "\x01", // free: 1<<17 (name un-matchable) "NOTHINK", "NOCLIPHEIGHT", "ENEMY", diff --git a/src/g_demo.c b/src/g_demo.c index 26c4e078b..3a6bd1430 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -1330,7 +1330,7 @@ readghosttic: z = READFIXED(g->p); angle = READANGLE(g->p); if (!(mobjinfo[type].flags & MF_SHOOTABLE) - || !(mobjinfo[type].flags & (MF_ENEMY|MF_MONITOR)) + || !(mobjinfo[type].flags & MF_ENEMY) || health != 0 || i >= 4) // only spawn for the first 4 hits per frame, to prevent ghosts from splode-spamming too bad. continue; poof = P_SpawnMobj(x, y, z, MT_GHOST); diff --git a/src/info.c b/src/info.c index 23c3225ee..933180ec6 100644 --- a/src/info.c +++ b/src/info.c @@ -9548,7 +9548,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_RING_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -9575,7 +9575,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_PITY_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -9602,7 +9602,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_ATTRACT_ICON,// damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -9629,7 +9629,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_FORCE_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -9656,7 +9656,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_ARMAGEDDON_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -9683,7 +9683,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_WHIRLWIND_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -9710,7 +9710,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_ELEMENTAL_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -9737,7 +9737,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_SNEAKERS_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -9764,7 +9764,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_INVULN_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -9791,7 +9791,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_1UP_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -9818,7 +9818,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_EGGMAN_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -9845,7 +9845,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_MIXUP_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -9872,7 +9872,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_UNKNOWN, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -9899,7 +9899,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_GRAVITY_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -9926,7 +9926,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_RECYCLER_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -9953,7 +9953,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_SCORE1K_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -9980,7 +9980,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_SCORE10K_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -10007,7 +10007,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_FLAMEAURA_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -10034,7 +10034,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_BUBBLEWRAP_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -10061,7 +10061,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_THUNDERCOIN_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -10088,7 +10088,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_PITY_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR|MF_GRENADEBOUNCE, // flags + MF_SOLID|MF_SHOOTABLE|MF_GRENADEBOUNCE, // flags S_NULL // raisestate }, @@ -10115,7 +10115,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_ATTRACT_ICON,// damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR|MF_GRENADEBOUNCE, // flags + MF_SOLID|MF_SHOOTABLE|MF_GRENADEBOUNCE, // flags S_NULL // raisestate }, @@ -10142,7 +10142,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_FORCE_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR|MF_GRENADEBOUNCE, // flags + MF_SOLID|MF_SHOOTABLE|MF_GRENADEBOUNCE, // flags S_NULL // raisestate }, @@ -10169,7 +10169,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_ARMAGEDDON_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR|MF_GRENADEBOUNCE, // flags + MF_SOLID|MF_SHOOTABLE|MF_GRENADEBOUNCE, // flags S_NULL // raisestate }, @@ -10196,7 +10196,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_WHIRLWIND_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR|MF_GRENADEBOUNCE, // flags + MF_SOLID|MF_SHOOTABLE|MF_GRENADEBOUNCE, // flags S_NULL // raisestate }, @@ -10223,7 +10223,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_ELEMENTAL_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR|MF_GRENADEBOUNCE, // flags + MF_SOLID|MF_SHOOTABLE|MF_GRENADEBOUNCE, // flags S_NULL // raisestate }, @@ -10250,7 +10250,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_SNEAKERS_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR|MF_GRENADEBOUNCE, // flags + MF_SOLID|MF_SHOOTABLE|MF_GRENADEBOUNCE, // flags S_NULL // raisestate }, @@ -10277,7 +10277,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_INVULN_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR|MF_GRENADEBOUNCE, // flags + MF_SOLID|MF_SHOOTABLE|MF_GRENADEBOUNCE, // flags S_NULL // raisestate }, @@ -10304,7 +10304,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_EGGMAN_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR|MF_GRENADEBOUNCE, // flags + MF_SOLID|MF_SHOOTABLE|MF_GRENADEBOUNCE, // flags S_NULL // raisestate }, @@ -10331,7 +10331,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_GRAVITY_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR|MF_GRENADEBOUNCE, // flags + MF_SOLID|MF_SHOOTABLE|MF_GRENADEBOUNCE, // flags S_NULL // raisestate }, @@ -10358,7 +10358,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_FLAMEAURA_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR|MF_GRENADEBOUNCE, // flags + MF_SOLID|MF_SHOOTABLE|MF_GRENADEBOUNCE, // flags S_NULL // raisestate }, @@ -10385,7 +10385,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_BUBBLEWRAP_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR|MF_GRENADEBOUNCE, // flags + MF_SOLID|MF_SHOOTABLE|MF_GRENADEBOUNCE, // flags S_NULL // raisestate }, @@ -10412,7 +10412,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_THUNDERCOIN_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR|MF_GRENADEBOUNCE, // flags + MF_SOLID|MF_SHOOTABLE|MF_GRENADEBOUNCE, // flags S_NULL // raisestate }, @@ -10439,7 +10439,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_RING_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -10466,7 +10466,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_RING_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, diff --git a/src/p_floor.c b/src/p_floor.c index 4b96192c8..1a7f2285a 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -1017,7 +1017,6 @@ static mobj_t *SearchMarioNode(msecnode_t *node) } // Ignore popped monitors, too. if (node->m_thing->health == 0 // this only really applies for monitors - || (!(node->m_thing->flags & MF_MONITOR) && (mobjinfo[node->m_thing->type].flags & MF_MONITOR)) // gold monitor support || (node->m_thing->type == MT_RANDOMITEM)) continue; // Okay, we found something valid. @@ -2344,7 +2343,6 @@ void EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher) fixed_t topheight = *rover->topheight; mariothink_t *block; mobj_t *thing; - fixed_t oldx = 0, oldy = 0, oldz = 0; I_Assert(puncher != NULL); I_Assert(puncher->player != NULL); @@ -2362,7 +2360,6 @@ void EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher) S_StartSound(puncher, sfx_mario1); // "Thunk!" sound - puncher is "close enough". else // Found something! { - const boolean itsamonitor = (thing->flags & MF_MONITOR) == MF_MONITOR; // create and initialize new elevator thinker block = Z_Calloc(sizeof (*block), PU_LEVSPEC, NULL); @@ -2383,13 +2380,6 @@ void EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher) R_CreateInterpolator_SectorPlane(&block->thinker, roversec, false); R_CreateInterpolator_SectorPlane(&block->thinker, roversec, true); - if (itsamonitor) - { - oldx = thing->x; - oldy = thing->y; - oldz = thing->z; - } - P_UnsetThingPosition(thing); thing->x = thing->old_x = sector->soundorg.x; thing->y = thing->old_y = sector->soundorg.y; @@ -2410,16 +2400,5 @@ void EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher) // "Powerup rise" sound S_StartSound(puncher, sfx_mario9); // Puncher is "close enough" } - - if (itsamonitor && thing) - { - P_UnsetThingPosition(thing); - thing->x = thing->old_x = oldx; - thing->y = thing->old_y = oldy; - thing->z = thing->old_z = oldz; - thing->momx = 1; - thing->momy = 1; - P_SetThingPosition(thing); - } } } diff --git a/src/p_inter.c b/src/p_inter.c index f510cf2fa..cce3bf9c1 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1537,7 +1537,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget target->momx = target->momy = target->momz = 0; // SRB2kart - if (target->type != MT_PLAYER && !(target->flags & MF_MONITOR) + if (target->type != MT_PLAYER && !(target->type == MT_ORBINAUT || target->type == MT_ORBINAUT_SHIELD || target->type == MT_JAWZ || target->type == MT_JAWZ_SHIELD || target->type == MT_BANANA || target->type == MT_BANANA_SHIELD @@ -1630,7 +1630,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget // if killed by a player if (source && source->player) { - if (target->flags & MF_MONITOR || target->type == MT_RANDOMITEM) + if (target->type == MT_RANDOMITEM) { P_SetTarget(&target->target, source); diff --git a/src/p_map.c b/src/p_map.c index 683dd3c5d..884bd5fd7 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -4220,7 +4220,7 @@ static BlockItReturn_t PIT_RadiusAttack(mobj_t *thing) if ((bombdamagetype & DMG_CANTHURTSELF) && bombsource && thing->type == bombsource->type) // ignore the type of guys who dropped the bomb (Jetty-Syn Bomber or Skim can bomb eachother, but not themselves.) return BMIT_CONTINUE; - if ((thing->flags & (MF_MONITOR|MF_SHOOTABLE)) != MF_SHOOTABLE) + if ((thing->flags & MF_SHOOTABLE) != MF_SHOOTABLE) return BMIT_CONTINUE; dx = abs(thing->x - bombspot->x); diff --git a/src/p_mobj.c b/src/p_mobj.c index 51ac3380e..0e2fb4912 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10058,48 +10058,6 @@ static void K_MineExplodeThink(mobj_t *mobj) } } -static void P_MonitorFuseThink(mobj_t *mobj) -{ - mobj_t *newmobj; - - // Special case for ALL monitors. - // If a box's speed is nonzero, it's allowed to respawn as a WRM/SRM. - if (mobj->info->speed != 0 && (mobj->flags2 & (MF2_AMBUSH|MF2_STRONGBOX))) - { - mobjtype_t spawnchance[64]; - INT32 numchoices = 0, i = 0; - - // This define should make it a lot easier to organize and change monitor weights -#define SETMONITORCHANCES(type, strongboxamt, weakboxamt) \ -for (i = ((mobj->flags2 & MF2_STRONGBOX) ? strongboxamt : weakboxamt); i; --i) spawnchance[numchoices++] = type - - // Type SRM WRM - SETMONITORCHANCES(MT_SNEAKERS_BOX, 0, 10); // Super Sneakers - SETMONITORCHANCES(MT_INVULN_BOX, 2, 0); // Invincibility - SETMONITORCHANCES(MT_WHIRLWIND_BOX, 3, 8); // Whirlwind Shield - SETMONITORCHANCES(MT_ELEMENTAL_BOX, 3, 8); // Elemental Shield - SETMONITORCHANCES(MT_ATTRACT_BOX, 2, 0); // Attraction Shield - SETMONITORCHANCES(MT_FORCE_BOX, 3, 3); // Force Shield - SETMONITORCHANCES(MT_ARMAGEDDON_BOX, 2, 0); // Armageddon Shield - SETMONITORCHANCES(MT_MIXUP_BOX, 0, 1); // Teleporters - SETMONITORCHANCES(MT_RECYCLER_BOX, 0, 1); // Recycler - SETMONITORCHANCES(MT_1UP_BOX, 1, 1); // 1-Up - // ======================================= - // Total 16 32 - -#undef SETMONITORCHANCES - - i = P_RandomKey(PR_UNDEFINED, numchoices); // Gotta love those random numbers! - newmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, spawnchance[i]); - } - else - newmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobj->type); - - // Transfer flags2 (ambush, strongbox, objectflip) - newmobj->flags2 = mobj->flags2; - P_RemoveMobj(mobj); // make sure they disappear -} - static boolean P_CanFlickerFuse(mobj_t *mobj) { switch (mobj->type) @@ -10148,11 +10106,6 @@ static boolean P_FuseThink(mobj_t *mobj) if (LUA_HookMobj(mobj, MOBJ_HOOK(MobjFuse)) || P_MobjWasRemoved(mobj)) ; - else if (mobj->info->flags & MF_MONITOR) - { - P_MonitorFuseThink(mobj); - return false; - } else switch (mobj->type) { // gargoyle and snowman handled in P_PushableThinker, not here diff --git a/src/p_mobj.h b/src/p_mobj.h index d15269bb7..435bc9235 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -137,8 +137,7 @@ typedef enum MF_MISSILE = 1<<15, // Item is a spring. MF_SPRING = 1<<16, - // Item box - MF_MONITOR = 1<<17, + // free: 1<<17 // Don't run the thinker for this object. MF_NOTHINK = 1<<18, // Don't adjust z if below or above floorz/ceilingz diff --git a/src/p_user.c b/src/p_user.c index acf119d35..cab3659dd 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2709,9 +2709,6 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius) if (!(mo->flags & MF_SHOOTABLE) && (mo->type != MT_SPB)) // Don't want to give SPB MF_SHOOTABLE, to ensure it's undamagable through other means continue; - if (mo->flags & MF_MONITOR) - continue; // Monitors cannot be 'nuked'. - if (abs(inflictor->x - mo->x) > radius || abs(inflictor->y - mo->y) > radius || abs(inflictor->z - mo->z) > radius) continue; // Workaround for possible integer overflow in the below -Red diff --git a/src/r_bbox.c b/src/r_bbox.c index 2e0b345c2..ed6c54988 100644 --- a/src/r_bbox.c +++ b/src/r_bbox.c @@ -240,7 +240,7 @@ static boolean is_tangible (mobj_t *thing) // These objects probably do nothing! :D if ((thing->flags & (MF_SPECIAL|MF_SOLID|MF_SHOOTABLE |MF_PUSHABLE|MF_BOSS|MF_MISSILE|MF_SPRING - |MF_MONITOR|MF_ENEMY|MF_PAIN + |MF_ENEMY|MF_PAIN |MF_PICKUPFROMBELOW)) == 0U) { return false; From b4d7740dab08066102e27124d456a05281935b8c Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 13 Nov 2023 00:46:08 -0800 Subject: [PATCH 61/88] MT_ITEMCLASH: additive and 2x scale --- src/info.c | 12 ++++++------ src/p_mobj.c | 2 ++ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/info.c b/src/info.c index 933180ec6..449798758 100644 --- a/src/info.c +++ b/src/info.c @@ -4815,12 +4815,12 @@ state_t states[NUMSTATES] = {SPR_FLEN, FF_FULLBRIGHT|1, 3, {NULL}, 0, 0, S_FLINGENERGY3}, // S_FLINGENERGY2, {SPR_FLEN, FF_FULLBRIGHT|2, 3, {NULL}, 0, 0, S_NULL}, // S_FLINGENERGY3, - {SPR_CLAS, FF_FULLBRIGHT|FF_TRANS30, 2, {A_PlayActiveSound}, 0, 0, S_CLASH2}, // S_CLASH1 - {SPR_CLAS, FF_FULLBRIGHT|FF_TRANS30|1, 2, {NULL}, 0, 0, S_CLASH3}, // S_CLASH2 - {SPR_CLAS, FF_FULLBRIGHT|FF_TRANS30|2, 2, {NULL}, 0, 0, S_CLASH4}, // S_CLASH3 - {SPR_CLAS, FF_FULLBRIGHT|FF_TRANS30|3, 2, {NULL}, 0, 0, S_CLASH5}, // S_CLASH4 - {SPR_CLAS, FF_FULLBRIGHT|FF_TRANS30|4, 2, {NULL}, 0, 0, S_CLASH6}, // S_CLASH5 - {SPR_CLAS, FF_FULLBRIGHT|FF_TRANS30|5, 2, {NULL}, 0, 0, S_NULL}, // S_CLASH6 + {SPR_CLAS, FF_FULLBRIGHT|FF_ADD, 2, {A_PlayActiveSound}, 0, 0, S_CLASH2}, // S_CLASH1 + {SPR_CLAS, FF_FULLBRIGHT|FF_ADD|1, 2, {NULL}, 0, 0, S_CLASH3}, // S_CLASH2 + {SPR_CLAS, FF_FULLBRIGHT|FF_ADD|2, 2, {NULL}, 0, 0, S_CLASH4}, // S_CLASH3 + {SPR_CLAS, FF_FULLBRIGHT|FF_ADD|3, 2, {NULL}, 0, 0, S_CLASH5}, // S_CLASH4 + {SPR_CLAS, FF_FULLBRIGHT|FF_ADD|4, 2, {NULL}, 0, 0, S_CLASH6}, // S_CLASH5 + {SPR_CLAS, FF_FULLBRIGHT|FF_ADD|5, 2, {NULL}, 0, 0, S_NULL}, // S_CLASH6 {SPR_PSHW, FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_FIREDITEM2}, // S_FIREDITEM1 {SPR_PSHW, FF_FULLBRIGHT|1, 3, {NULL}, 0, 0, S_FIREDITEM3}, // S_FIREDITEM2 diff --git a/src/p_mobj.c b/src/p_mobj.c index 0e2fb4912..e4ac1f209 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10760,6 +10760,8 @@ fixed_t P_GetMobjDefaultScale(mobj_t *mobj) { switch(mobj->type) { + case MT_ITEMCLASH: + return 2*FRACUNIT; case MT_SPECIALSTAGEARCH: return 5*FRACUNIT; case MT_SPECIALSTAGEBOMB: From e1e5c304bcee78984d8aa8c579cf3745780b5f3c Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 13 Nov 2023 00:50:44 -0800 Subject: [PATCH 62/88] Flame jets: scale momentum to map scale --- src/p_mobj.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index e4ac1f209..5db1ca1ef 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -5679,12 +5679,12 @@ static void P_FlameJetSceneryThink(mobj_t *mobj) flame->angle = mobj->angle; if (mobj->flags2 & MF2_AMBUSH) // Wave up and down instead of side-to-side - flame->momz = mobj->fuse << (FRACBITS - 2); + flame->momz = (mobj->fuse * mapobjectscale) / 4; else flame->angle += FixedAngle(mobj->fuse<movedir; + strength = 20*mapobjectscale; + strength -= ((20*mapobjectscale)/16)*mobj->movedir; P_InstaThrust(flame, flame->angle, strength); S_StartSound(flame, sfx_fire); @@ -5714,8 +5714,8 @@ static void P_VerticalFlameJetSceneryThink(mobj_t *mobj) flame = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_FLAMEJETFLAME); - strength = 20*FRACUNIT; - strength -= ((20*FRACUNIT)/16)*mobj->movedir; + strength = 20*mapobjectscale; + strength -= ((20*mapobjectscale)/16)*mobj->movedir; // If deaf'd, the object spawns on the ceiling. if (mobj->flags2 & MF2_AMBUSH) @@ -5729,7 +5729,7 @@ static void P_VerticalFlameJetSceneryThink(mobj_t *mobj) P_SetMobjState(flame, S_FLAMEJETFLAME7); } - P_InstaThrust(flame, mobj->angle, FixedDiv(mobj->fuse*FRACUNIT, 3*FRACUNIT)); + P_InstaThrust(flame, mobj->angle, (mobj->fuse * mapobjectscale) / 3); S_StartSound(flame, sfx_fire); } From 9783c6760df590759f51f357fe9f892587c7ca4b Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 13 Nov 2023 00:53:06 -0800 Subject: [PATCH 63/88] Flame jets: bigger hitbox, do not squash and stretch, 3x scale --- src/info.c | 6 +++--- src/p_mobj.c | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/info.c b/src/info.c index 449798758..43efba091 100644 --- a/src/info.c +++ b/src/info.c @@ -14618,13 +14618,13 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_None, // deathsound 5*FRACUNIT, // speed - 8*FRACUNIT, // radius - 8*FRACUNIT, // height + 16*FRACUNIT, // radius + 32*FRACUNIT, // height 0, // display offset DMG_NORMAL, // mass 0, // damage sfx_None, // activesound - MF_NOGRAVITY|MF_MISSILE|MF_PAIN, // flags + MF_NOGRAVITY|MF_MISSILE|MF_PAIN|MF_NOSQUISH, // flags S_NULL // raisestate }, diff --git a/src/p_mobj.c b/src/p_mobj.c index 5db1ca1ef..0bdba2deb 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10760,6 +10760,8 @@ fixed_t P_GetMobjDefaultScale(mobj_t *mobj) { switch(mobj->type) { + case MT_FLAMEJETFLAME: + return 3*FRACUNIT; case MT_ITEMCLASH: return 2*FRACUNIT; case MT_SPECIALSTAGEARCH: From 21e870726d10437507a11cfe32c60402b9b5fedc Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 13 Nov 2023 03:13:01 -0800 Subject: [PATCH 64/88] Flame jets: do not receive hitlag --- src/info.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/info.c b/src/info.c index 43efba091..c22f351cd 100644 --- a/src/info.c +++ b/src/info.c @@ -14624,7 +14624,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = DMG_NORMAL, // mass 0, // damage sfx_None, // activesound - MF_NOGRAVITY|MF_MISSILE|MF_PAIN|MF_NOSQUISH, // flags + MF_NOGRAVITY|MF_MISSILE|MF_PAIN|MF_NOSQUISH|MF_NOHITLAGFORME, // flags S_NULL // raisestate }, From b81b932ba971a0e88904172caada2ea8449a4e9e Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 13 Nov 2023 03:14:00 -0800 Subject: [PATCH 65/88] MF_MISSILE: do not run collision against other object, if MF_PAIN was evaluated --- src/p_map.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index 884bd5fd7..3b50ee1fd 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -538,6 +538,7 @@ static void P_DoFanAndGasJet(mobj_t *spring, mobj_t *object) static BlockItReturn_t PIT_CheckThing(mobj_t *thing) { fixed_t blockdist; + boolean damage = false; if (tm.thing == NULL || P_MobjWasRemoved(tm.thing) == true) return BMIT_STOP; // func just popped our tm.thing, cannot continue. @@ -694,10 +695,12 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) if (P_DamageMobj(tm.thing, thing, thing, 1, damagetype) && (damagetype = (thing->info->mass>>8))) S_StartSound(thing, damagetype); - } - if (P_MobjWasRemoved(tm.thing) || P_MobjWasRemoved(thing)) - return BMIT_CONTINUE; + if (P_MobjWasRemoved(tm.thing) || P_MobjWasRemoved(thing)) + return BMIT_CONTINUE; + + damage = true; + } } else if (tm.thing->flags & MF_PAIN && thing->player) { // Painful thing splats player in the face @@ -712,10 +715,12 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) if (P_DamageMobj(thing, tm.thing, tm.thing, 1, damagetype) && (damagetype = (tm.thing->info->mass>>8))) S_StartSound(tm.thing, damagetype); - } - if (P_MobjWasRemoved(tm.thing) || P_MobjWasRemoved(thing)) - return BMIT_CONTINUE; + if (P_MobjWasRemoved(tm.thing) || P_MobjWasRemoved(thing)) + return BMIT_CONTINUE; + + damage = true; + } } // check for skulls slamming into things @@ -1216,7 +1221,7 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) } // missiles can hit other things - if (tm.thing->flags & MF_MISSILE) + if ((tm.thing->flags & MF_MISSILE) && !damage) // if something was already damaged, don't run this { UINT8 damagetype = (tm.thing->info->mass ^ DMG_WOMBO); From 74d1f1bfb7d5dc3d9fd0bde9d02d23e89f8777ab Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 13 Nov 2023 00:54:35 -0800 Subject: [PATCH 66/88] Add MF_DONTPUNT --- src/d_clisrv.c | 2 +- src/deh_tables.c | 2 +- src/p_mobj.h | 3 ++- src/r_bbox.c | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index f030fa7b0..dc6b93bc8 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -5618,7 +5618,7 @@ static INT16 Consistancy(void) if (TypeIsNetSynced(mo->type) == false) continue; - if (mo->flags & (MF_SPECIAL | MF_SOLID | MF_PUSHABLE | MF_BOSS | MF_MISSILE | MF_SPRING | MF_FIRE | MF_ENEMY | MF_PAIN)) + if (mo->flags & (MF_SPECIAL | MF_SOLID | MF_PUSHABLE | MF_BOSS | MF_MISSILE | MF_SPRING | MF_FIRE | MF_ENEMY | MF_PAIN | MF_DONTPUNT)) { ret -= mo->type; ret += mo->x; diff --git a/src/deh_tables.c b/src/deh_tables.c index 6c70886a9..d521a63de 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -5993,7 +5993,7 @@ const char *const MOBJFLAG_LIST[] = { "ENEMY", "SCENERY", "PAIN", - "\x01", // free: 1<<23 (name un-matchable) + "DONTPUNT", "APPLYTERRAIN", "NOCLIPTHING", "GRENADEBOUNCE", diff --git a/src/p_mobj.h b/src/p_mobj.h index 435bc9235..d469552cb 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -148,7 +148,8 @@ typedef enum MF_SCENERY = 1<<21, // Painful (shit hurts). MF_PAIN = 1<<22, - // free: 1<<23 + // Object cannot be punted by invincible players. (Default CAN be punted, if it deals damage or is solid.) + MF_DONTPUNT = 1<<23, // Object uses terrain effects. (Overlays, footsteps, etc) MF_APPLYTERRAIN = 1<<24, // for chase camera, don't be blocked by things (partial clipping) diff --git a/src/r_bbox.c b/src/r_bbox.c index ed6c54988..b828e989d 100644 --- a/src/r_bbox.c +++ b/src/r_bbox.c @@ -240,7 +240,7 @@ static boolean is_tangible (mobj_t *thing) // These objects probably do nothing! :D if ((thing->flags & (MF_SPECIAL|MF_SOLID|MF_SHOOTABLE |MF_PUSHABLE|MF_BOSS|MF_MISSILE|MF_SPRING - |MF_ENEMY|MF_PAIN + |MF_ENEMY|MF_PAIN|MF_DONTPUNT |MF_PICKUPFROMBELOW)) == 0U) { return false; From b11f340dab163e2fd007bb70a431d663f1e715c2 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 13 Nov 2023 19:20:29 -0800 Subject: [PATCH 67/88] Add MF_ELEMENTAL --- src/d_clisrv.c | 2 +- src/deh_tables.c | 2 +- src/p_mobj.h | 3 ++- src/r_bbox.c | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index dc6b93bc8..f1cacc833 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -5618,7 +5618,7 @@ static INT16 Consistancy(void) if (TypeIsNetSynced(mo->type) == false) continue; - if (mo->flags & (MF_SPECIAL | MF_SOLID | MF_PUSHABLE | MF_BOSS | MF_MISSILE | MF_SPRING | MF_FIRE | MF_ENEMY | MF_PAIN | MF_DONTPUNT)) + if (mo->flags & (MF_SPECIAL | MF_SOLID | MF_PUSHABLE | MF_BOSS | MF_MISSILE | MF_SPRING | MF_ELEMENTAL | MF_FIRE | MF_ENEMY | MF_PAIN | MF_DONTPUNT)) { ret -= mo->type; ret += mo->x; diff --git a/src/deh_tables.c b/src/deh_tables.c index d521a63de..daaa3ec59 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -5987,7 +5987,7 @@ const char *const MOBJFLAG_LIST[] = { "SLOPE", "MISSILE", "SPRING", - "\x01", // free: 1<<17 (name un-matchable) + "ELEMENTAL", "NOTHINK", "NOCLIPHEIGHT", "ENEMY", diff --git a/src/p_mobj.h b/src/p_mobj.h index d469552cb..61780c004 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -137,7 +137,8 @@ typedef enum MF_MISSILE = 1<<15, // Item is a spring. MF_SPRING = 1<<16, - // free: 1<<17 + // Object is elemental. If it is punted, it will evaporate. + MF_ELEMENTAL = 1<<17, // Don't run the thinker for this object. MF_NOTHINK = 1<<18, // Don't adjust z if below or above floorz/ceilingz diff --git a/src/r_bbox.c b/src/r_bbox.c index b828e989d..ce4f3d758 100644 --- a/src/r_bbox.c +++ b/src/r_bbox.c @@ -240,7 +240,7 @@ static boolean is_tangible (mobj_t *thing) // These objects probably do nothing! :D if ((thing->flags & (MF_SPECIAL|MF_SOLID|MF_SHOOTABLE |MF_PUSHABLE|MF_BOSS|MF_MISSILE|MF_SPRING - |MF_ENEMY|MF_PAIN|MF_DONTPUNT + |MF_ELEMENTAL|MF_ENEMY|MF_PAIN|MF_DONTPUNT |MF_PICKUPFROMBELOW)) == 0U) { return false; From a8a1c14580ee735672de5235ce4a9e27b79d0703 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 13 Nov 2023 00:56:19 -0800 Subject: [PATCH 68/88] mobj_t: add reappear and punt_ref members, add to savegame and Lua --- src/lua_mobjlib.c | 29 ++++++++++++++++++- src/p_mobj.c | 3 ++ src/p_mobj.h | 3 ++ src/p_saveg.c | 72 +++++++++++++++++++++++++++++++++++++++-------- 4 files changed, 95 insertions(+), 12 deletions(-) diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index ce4668038..51751f996 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -106,7 +106,9 @@ enum mobj_e { mobj_tid, mobj_special, mobj_args, - mobj_stringargs + mobj_stringargs, + mobj_reappear, + mobj_punt_ref, }; static const char *const mobj_opt[] = { @@ -194,6 +196,8 @@ static const char *const mobj_opt[] = { "special", "args", "stringargs", + "reappear", + "punt_ref", NULL}; #define UNIMPLEMENTED luaL_error(L, LUA_QL("mobj_t") " field " LUA_QS " is not implemented for Lua and cannot be accessed.", mobj_opt[field]) @@ -493,6 +497,17 @@ static int mobj_get(lua_State *L) case mobj_stringargs: LUA_PushUserdata(L, mo->thing_stringargs, META_THINGSTRINGARGS); break; + case mobj_reappear: + lua_pushinteger(L, mo->reappear); + break; + case mobj_punt_ref: + if (mo->punt_ref && P_MobjWasRemoved(mo->punt_ref)) + { // don't put invalid mobj back into Lua. + P_SetTarget(&mo->punt_ref, NULL); + return 0; + } + LUA_PushUserdata(L, mo->punt_ref, META_MOBJ); + break; default: // extra custom variables in Lua memory lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS); I_Assert(lua_istable(L, -1)); @@ -883,6 +898,18 @@ static int mobj_set(lua_State *L) return NOSET; case mobj_stringargs: return NOSET; + case mobj_reappear: + mo->reappear = luaL_checkinteger(L, 3); + break; + case mobj_punt_ref: + if (lua_isnil(L, 3)) + P_SetTarget(&mo->punt_ref, NULL); + else + { + mobj_t *punt_ref = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); + P_SetTarget(&mo->punt_ref, punt_ref); + } + break; default: lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS); I_Assert(lua_istable(L, -1)); diff --git a/src/p_mobj.c b/src/p_mobj.c index 0bdba2deb..e781107f0 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10250,6 +10250,8 @@ void P_MobjThinker(mobj_t *mobj) P_SetTarget(&mobj->hprev, NULL); if (mobj->itnext && P_MobjWasRemoved(mobj->itnext)) P_SetTarget(&mobj->itnext, NULL); + if (mobj->punt_ref && P_MobjWasRemoved(mobj->punt_ref)) + P_SetTarget(&mobj->punt_ref, NULL); if (mobj->flags & MF_NOTHINK) return; @@ -11803,6 +11805,7 @@ void P_RemoveMobj(mobj_t *mobj) } P_SetTarget(&mobj->itnext, NULL); + P_SetTarget(&mobj->punt_ref, NULL); P_RemoveThingTID(mobj); P_DeleteMobjStringArgs(mobj); diff --git a/src/p_mobj.h b/src/p_mobj.h index 61780c004..96f6aa5bb 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -437,6 +437,9 @@ struct mobj_t boolean frozen; + tic_t reappear; + mobj_t *punt_ref; + // WARNING: New fields must be added separately to savegame and Lua. }; diff --git a/src/p_saveg.c b/src/p_saveg.c index fad0ce24c..ef09120d7 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2668,9 +2668,16 @@ typedef enum MD2_FROZEN = 1<<28, MD2_TERRAIN = 1<<29, MD2_WATERSKIP = 1<<30, - MD2_LIGHTLEVEL = (INT32)(1U<<31), + MD2_MORE = (INT32)(1U<<31), } mobj_diff2_t; +typedef enum +{ + MD3_LIGHTLEVEL = 1, + MD3_REAPPEAR = 1<<1, + MD3_PUNT_REF = 1<<2, +} mobj_diff3_t; + typedef enum { tc_mobj, @@ -2781,12 +2788,14 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8 const mobj_t *mobj = (const mobj_t *)th; UINT32 diff; UINT32 diff2; + UINT32 diff3; size_t j; if (TypeIsNetSynced(mobj->type) == false) return; diff2 = 0; + diff3 = 0; if (mobj->spawnpoint) { @@ -2968,8 +2977,6 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8 || (slope->normal.z != FRACUNIT)) diff2 |= MD2_FLOORSPRITESLOPE; } - if (mobj->lightlevel) - diff2 |= MD2_LIGHTLEVEL; if (mobj->hitlag) diff2 |= MD2_HITLAG; if (mobj->waterskip) @@ -2987,6 +2994,16 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8 if (mobj->terrain != NULL || mobj->terrainOverlay != NULL) diff2 |= MD2_TERRAIN; + if (mobj->lightlevel) + diff3 |= MD3_LIGHTLEVEL; + if (mobj->reappear) + diff3 |= MD3_REAPPEAR; + if (mobj->punt_ref) + diff3 |= MD3_PUNT_REF; + + if (diff3 != 0) + diff2 |= MD2_MORE; + if (diff2 != 0) diff |= MD_MORE; @@ -2998,6 +3015,8 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8 WRITEUINT32(save->p, diff); if (diff & MD_MORE) WRITEUINT32(save->p, diff2); + if (diff2 & MD2_MORE) + WRITEUINT32(save->p, diff3); WRITEFIXED(save->p, mobj->z); // Force this so 3dfloor problems don't arise. WRITEFIXED(save->p, mobj->floorz); @@ -3235,10 +3254,6 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8 WRITEFIXED(save->p, slope->normal.y); WRITEFIXED(save->p, slope->normal.z); } - if (diff2 & MD2_LIGHTLEVEL) - { - WRITEINT16(save->p, mobj->lightlevel); - } if (diff2 & MD2_HITLAG) { WRITEINT32(save->p, mobj->hitlag); @@ -3261,6 +3276,19 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8 WRITEUINT32(save->p, SaveMobjnum(mobj->terrainOverlay)); } + if (diff3 & MD3_LIGHTLEVEL) + { + WRITEINT16(save->p, mobj->lightlevel); + } + if (diff3 & MD3_REAPPEAR) + { + WRITEUINT32(save->p, mobj->reappear); + } + if (diff3 & MD3_PUNT_REF) + { + WRITEUINT32(save->p, mobj->punt_ref->mobjnum); + } + WRITEUINT32(save->p, mobj->mobjnum); } @@ -4134,6 +4162,7 @@ static thinker_t* LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker) mobj_t *mobj; UINT32 diff; UINT32 diff2; + UINT32 diff3; INT32 i; fixed_t z, floorz, ceilingz; ffloor_t *floorrover = NULL, *ceilingrover = NULL; @@ -4145,6 +4174,11 @@ static thinker_t* LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker) else diff2 = 0; + if (diff2 & MD2_MORE) + diff3 = READUINT32(save->p); + else + diff3 = 0; + z = READFIXED(save->p); // Force this so 3dfloor problems don't arise. floorz = READFIXED(save->p); ceilingz = READFIXED(save->p); @@ -4470,10 +4504,6 @@ static thinker_t* LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker) P_UpdateSlopeLightOffset(slope); } - if (diff2 & MD2_LIGHTLEVEL) - { - mobj->lightlevel = READINT16(save->p); - } if (diff2 & MD2_HITLAG) { mobj->hitlag = READINT32(save->p); @@ -4500,6 +4530,19 @@ static thinker_t* LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker) mobj->terrain = NULL; } + if (diff3 & MD3_LIGHTLEVEL) + { + mobj->lightlevel = READINT16(save->p); + } + if (diff3 & MD3_REAPPEAR) + { + mobj->reappear = READUINT32(save->p); + } + if (diff3 & MD3_PUNT_REF) + { + mobj->punt_ref = (mobj_t *)(size_t)READUINT32(save->p); + } + // set sprev, snext, bprev, bnext, subsector P_SetThingPosition(mobj); @@ -5539,6 +5582,13 @@ static void P_RelinkPointers(void) if (!P_SetTarget(&mobj->terrainOverlay, P_FindNewPosition(temp))) CONS_Debug(DBG_GAMELOGIC, "terrainOverlay not found on %d\n", mobj->type); } + if (mobj->punt_ref) + { + temp = (UINT32)(size_t)mobj->punt_ref; + mobj->punt_ref = NULL; + if (!P_SetTarget(&mobj->punt_ref, P_FindNewPosition(temp))) + CONS_Debug(DBG_GAMELOGIC, "punt_ref not found on %d\n", mobj->type); + } } for (i = 0; i < MAXPLAYERS; i++) From 61cad641bb8b11ab90efd2a5eb231455d8672bc3 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 13 Nov 2023 01:04:55 -0800 Subject: [PATCH 69/88] Invincible player punts hazardous/solid things, unless MF_ELEMENTAL If player is in one of these states: - Invincibility - Grow (K_IsBigger) - Flame Shield dash - Over 200% speed And the other object: - Does not have MF_DONTPUNT Then, touching a solid object: - Punts the object, unless the object has MF_ELEMENTAL - Fizzles the object, if the object has MF_ELEMENTAL Or, when an object damages the player: - That object is punted, unless it has MF_ELEMENTAL - The object fizzles, if it has MF_ELEMENTAL Punting means: - A copy of the object is made - Both the player and copy receive 5 tics of hitlag - The copy is thrust away from the player at a minimum of 60 FU, or 2x either the player's or object's momentum, whichever is ultimately greater - The copy despawns after 2 seconds - The copy flickers constantly, while thrust away Fizzling means: - The object disappears completely - A puff of smoke is spawned in place of the object - No hitlag is applied to the player Both punting and fizzling: - Hide the original object (intangible and invisible) - The original object reppears after 30 seconds - For 2 seconds before reappearing, the object flickers back in, but is still intangible --- src/k_collide.cpp | 112 ++++++++++++++++++++++++++++++++++++++++++++++ src/k_collide.h | 3 ++ src/k_kart.c | 30 +++++++++++++ src/k_kart.h | 3 ++ src/p_inter.c | 9 ++++ src/p_local.h | 2 + src/p_map.c | 12 ++++- src/p_mobj.c | 6 +++ src/p_mobj.h | 5 +++ src/p_user.c | 3 ++ src/r_things.cpp | 6 +++ src/s_sound.c | 3 ++ 12 files changed, 192 insertions(+), 2 deletions(-) diff --git a/src/k_collide.cpp b/src/k_collide.cpp index 0b78db526..76917d2b5 100644 --- a/src/k_collide.cpp +++ b/src/k_collide.cpp @@ -18,6 +18,7 @@ #include "k_podium.h" #include "k_powerup.h" #include "k_hitlag.h" +#include "m_random.h" angle_t K_GetCollideAngle(mobj_t *t1, mobj_t *t2) { @@ -1170,3 +1171,114 @@ boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2) return false; } + +void K_PuntHazard(mobj_t *t1, mobj_t *t2) +{ + // TODO: spawn a unique mobjtype other than MT_GHOST + mobj_t *img = P_SpawnGhostMobj(t1); + + K_MakeObjectReappear(t1); + + img->flags &= ~MF_NOGRAVITY; + img->renderflags = t1->renderflags & ~RF_DONTDRAW; + img->extravalue1 = 1; + img->extravalue2 = 2; + img->fuse = 2*TICRATE; + + struct Vector + { + fixed_t x_, y_, z_; + fixed_t h_ = FixedHypot(x_, y_); + fixed_t speed_ = std::max(60 * mapobjectscale, FixedHypot(h_, z_) * 2); + + explicit Vector(fixed_t x, fixed_t y, fixed_t z) : x_(x), y_(y), z_(z) {} + explicit Vector(const mobj_t* mo) : + Vector(std::max( + Vector(mo->x - mo->old_x, mo->y - mo->old_y, mo->z - mo->old_z), + Vector(mo->momx, mo->momy, mo->momz) + )) + { + } + explicit Vector(const Vector&) = default; + + bool operator<(const Vector& b) const { return speed_ < b.speed_; } + + void invert() + { + x_ = -x_; + y_ = -y_; + z_ = -z_; + } + + void thrust(mobj_t* mo) const + { + angle_t yaw = R_PointToAngle2(0, 0, h_, z_); + yaw = std::max(AbsAngle(yaw), static_cast(ANGLE_11hh)) + (yaw & ANGLE_180); + + P_InstaThrust(mo, R_PointToAngle2(0, 0, x_, y_), FixedMul(speed_, FCOS(yaw))); + mo->momz = FixedMul(speed_, FSIN(yaw)); + } + }; + + Vector h_vector(t1); + Vector p_vector(t2); + + h_vector.invert(); + + std::max(h_vector, p_vector).thrust(img); + + K_DoPowerClash(img, t2); // applies hitlag + P_SpawnMobj(t2->x/2 + t1->x/2, t2->y/2 + t1->y/2, t2->z/2 + t1->z/2, MT_ITEMCLASH); +} + +boolean K_PuntCollide(mobj_t *t1, mobj_t *t2) +{ + if (t1->flags & MF_DONTPUNT) + { + return false; + } + + if (!t2->player) + { + return false; + } + + if (!K_PlayerCanPunt(t2->player)) + { + return false; + } + + if (t1->flags & MF_ELEMENTAL) + { + K_MakeObjectReappear(t1); + + // copied from MT_ITEMCAPSULE + UINT8 i; + INT16 spacing = (t1->radius >> 1) / t1->scale; + // dust effects + for (i = 0; i < 10; i++) + { + mobj_t *puff = P_SpawnMobjFromMobj( + t1, + P_RandomRange(PR_ITEM_DEBRIS, -spacing, spacing) * FRACUNIT, + P_RandomRange(PR_ITEM_DEBRIS, -spacing, spacing) * FRACUNIT, + P_RandomRange(PR_ITEM_DEBRIS, 0, 4*spacing) * FRACUNIT, + MT_SPINDASHDUST + ); + + puff->momz = puff->scale * P_MobjFlip(puff); + + P_Thrust(puff, R_PointToAngle2(t2->x, t2->y, puff->x, puff->y), 3*puff->scale); + + puff->momx += t2->momx / 2; + puff->momy += t2->momy / 2; + puff->momz += t2->momz / 2; + } + } + else + { + K_PuntHazard(t1, t2); + } + + return true; +} diff --git a/src/k_collide.h b/src/k_collide.h index 84d9a324e..525e5b9c3 100644 --- a/src/k_collide.h +++ b/src/k_collide.h @@ -33,6 +33,9 @@ boolean K_SMKIceBlockCollide(mobj_t *t1, mobj_t *t2); boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2); +void K_PuntHazard(mobj_t *t1, mobj_t *t2); +boolean K_PuntCollide(mobj_t *t1, mobj_t *t2); + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/k_kart.c b/src/k_kart.c index e5e07eae8..cc6137a2b 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -12636,4 +12636,34 @@ boolean K_IsPlayingDisplayPlayer(player_t *player) return P_IsDisplayPlayer(player) && (!player->exiting); } +boolean K_PlayerCanPunt(player_t *player) +{ + if (player->invincibilitytimer > 0) + { + return true; + } + + if (player->flamedash > 0 && player->itemtype == KITEM_FLAMESHIELD) + { + return true; + } + + if (player->growshrinktimer > 0) + { + return true; + } + + if (player->tripwirePass >= TRIPWIRE_BLASTER && player->speed >= 2 * K_GetKartSpeed(player, false, false)) + { + return true; + } + + return false; +} + +void K_MakeObjectReappear(mobj_t *mo) +{ + (!P_MobjWasRemoved(mo->punt_ref) ? mo->punt_ref : mo)->reappear = leveltime + (30*TICRATE); +} + //} diff --git a/src/k_kart.h b/src/k_kart.h index 4ddd8b1c3..7b3d6d62c 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -245,6 +245,9 @@ void K_SetTireGrease(player_t *player, tic_t tics); boolean K_IsPlayingDisplayPlayer(player_t *player); +boolean K_PlayerCanPunt(player_t *player); +void K_MakeObjectReappear(mobj_t *mo); + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/p_inter.c b/src/p_inter.c index cce3bf9c1..69d0c2a17 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -43,6 +43,7 @@ #include "k_hitlag.h" #include "acs/interface.h" #include "k_powerup.h" +#include "k_collide.h" // CTF player names #define CTFTEAMCODE(pl) pl->ctfteam ? (pl->ctfteam == 1 ? "\x85" : "\x84") : "" @@ -2929,6 +2930,14 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da invincible = false; } + // TODO: doing this from P_DamageMobj limits punting to objects that damage the player. + // And it may be kind of yucky. + // But this is easier than accounting for every condition in PIT_CheckThing! + if (inflictor && K_PuntCollide(inflictor, target)) + { + return false; + } + if (invincible && type != DMG_STUMBLE && type != DMG_WHUMBLE) { const INT32 oldHitlag = target->hitlag; diff --git a/src/p_local.h b/src/p_local.h index 045a59472..4cd26c9fd 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -595,6 +595,8 @@ mobj_t *P_FindMobjFromTID(mtag_t tid, mobj_t *i, mobj_t *activator); void P_DeleteMobjStringArgs(mobj_t *mobj); +tic_t P_MobjIsReappearing(const mobj_t *mobj); + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/p_map.c b/src/p_map.c index 3b50ee1fd..9888c23c3 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -563,6 +563,10 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) if ((thing->flags & MF_NOCLIPTHING) || !(thing->flags & (MF_SOLID|MF_SPECIAL|MF_PAIN|MF_SHOOTABLE|MF_SPRING))) return BMIT_CONTINUE; + // Thing is respawning + if (P_MobjIsReappearing(thing)) + return BMIT_CONTINUE; + blockdist = thing->radius + tm.thing->radius; if (abs(thing->x - tm.x) >= blockdist || abs(thing->y - tm.y) >= blockdist) @@ -1631,7 +1635,10 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) if (tm.thing->z + tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - K_KartSolidBounce(tm.thing, thing); + if (!K_PuntCollide(thing, tm.thing)) + { + K_KartSolidBounce(tm.thing, thing); + } return BMIT_CONTINUE; } } @@ -2346,7 +2353,8 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y, TryMoveResult_t *re // Check things first, possibly picking things up. // MF_NOCLIPTHING: used by camera to not be blocked by things - if (!(thing->flags & MF_NOCLIPTHING)) + // Respawning things should also be intangible to other things + if (!(thing->flags & MF_NOCLIPTHING) && !P_MobjIsReappearing(thing)) { for (bx = xl; bx <= xh; bx++) { diff --git a/src/p_mobj.c b/src/p_mobj.c index e781107f0..fdb6e0f24 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -15381,3 +15381,9 @@ void P_DeleteMobjStringArgs(mobj_t *mobj) mobj->script_stringargs[i] = NULL; } } + +tic_t P_MobjIsReappearing(const mobj_t *mobj) +{ + tic_t t = (!P_MobjWasRemoved(mobj->punt_ref) ? mobj->punt_ref : mobj)->reappear; + return t - min(leveltime, t); +} diff --git a/src/p_mobj.h b/src/p_mobj.h index 96f6aa5bb..1fbb676bf 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -437,7 +437,12 @@ struct mobj_t boolean frozen; + // Object was punted and is temporarily invisible and + // intangible. This is the leveltime that it will + // reappear. tic_t reappear; + + // If punt_ref, set punt_ref->reappear, treat as if this->reappear mobj_t *punt_ref; // WARNING: New fields must be added separately to savegame and Lua. diff --git a/src/p_user.c b/src/p_user.c index cab3659dd..516bc168a 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1166,6 +1166,9 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj) K_ReduceVFX(ghost, mobj->player); + ghost->reappear = mobj->reappear; + P_SetTarget(&ghost->punt_ref, mobj->punt_ref); + return ghost; } diff --git a/src/r_things.cpp b/src/r_things.cpp index 0ecf02c12..deacfce92 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -3746,6 +3746,12 @@ boolean R_ThingVisible (mobj_t *thing) if (r_viewmobj && (thing == r_viewmobj || (r_viewmobj->player && r_viewmobj->player->followmobj == thing))) return false; + if (tic_t t = P_MobjIsReappearing(thing)) + { + // Flicker back in + return t <= 2*TICRATE && (leveltime & 1); + } + if ((viewssnum == 0 && (thing->renderflags & RF_DONTDRAWP1)) || (viewssnum == 1 && (thing->renderflags & RF_DONTDRAWP2)) || (viewssnum == 2 && (thing->renderflags & RF_DONTDRAWP3)) diff --git a/src/s_sound.c b/src/s_sound.c index f744b1598..33cf4c3be 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -948,6 +948,9 @@ boolean S_AdjustSoundParams(const mobj_t *listener, const mobj_t *source, INT32 if (!listener) return false; + if (source->thinker.function.acp1 == (actionf_p1)P_MobjThinker && P_MobjIsReappearing(source)) + return false; + // Init listensource with default listener listensource.x = listener->x; listensource.y = listener->y; From a0c791706e1be2d6258eae66ca60efd1f4b5ee6a Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 13 Nov 2023 01:14:22 -0800 Subject: [PATCH 70/88] MT_FLAMEJETFLAME: apply MF_ELEMENTAL --- src/info.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/info.c b/src/info.c index c22f351cd..5f4a711ff 100644 --- a/src/info.c +++ b/src/info.c @@ -14624,7 +14624,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = DMG_NORMAL, // mass 0, // damage sfx_None, // activesound - MF_NOGRAVITY|MF_MISSILE|MF_PAIN|MF_NOSQUISH|MF_NOHITLAGFORME, // flags + MF_NOGRAVITY|MF_MISSILE|MF_PAIN|MF_NOSQUISH|MF_NOHITLAGFORME|MF_ELEMENTAL, // flags S_NULL // raisestate }, From 9b86dbf8e049f74f8667a72b9294f563bb102ad6 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 13 Nov 2023 01:15:05 -0800 Subject: [PATCH 71/88] MT_DAYTONAPINETREE_SIDE: set punt_ref to center object --- src/p_mobj.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/p_mobj.c b/src/p_mobj.c index fdb6e0f24..3f4ec495a 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11321,6 +11321,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) mobj->y + FINESINE((ang>>ANGLETOFINESHIFT) & FINEMASK), mobj->z, MT_DAYTONAPINETREE_SIDE); side->angle = ang; P_SetTarget(&side->target, mobj); + P_SetTarget(&side->punt_ref, mobj); side->threshold = i; } break; From 97ea2eadc542d5c92c8a49f45305e48755e23dce Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 13 Nov 2023 19:35:20 -0800 Subject: [PATCH 72/88] Apply MF_DONTPUNT to MT_PLAYER, MT_INSTAWHIP and all items - MT_PLAYER - MT_INSTAWHIP - MT_BANANA - MT_BANANA_SHIELD - MT_ORBINAUT - MT_ORBINAUT_SHIELD - MT_JAWZ - MT_JAWZ_SHIELD - MT_SSMINE - MT_SSMINE_SHIELD - MT_LANDMINE - MT_DROPTARGET - MT_DROPTARGET_SHIELD - MT_BALLHOG - MT_SPB - MT_GARDENTOP - MT_SINK - MT_SINK_SHIELD - MT_GACHABOM - MT_DUELBOMB --- src/info.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/info.c b/src/info.c index 5f4a711ff..d0781ae7a 100644 --- a/src/info.c +++ b/src/info.c @@ -5742,7 +5742,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 1000, // mass MT_THOK, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE, // flags + MF_SOLID|MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE|MF_DONTPUNT, // flags (statenum_t)MT_THOK // raisestate }, @@ -23111,7 +23111,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags + MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP|MF_DONTPUNT, // flags S_NULL // raisestate }, @@ -24002,7 +24002,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_peel, // activesound - MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE, // flags + MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE|MF_DONTPUNT, // flags S_NULL // raisestate }, @@ -24029,7 +24029,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_None, // activesound - MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE, // flags + MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE|MF_DONTPUNT, // flags S_NULL // raisestate }, @@ -24083,7 +24083,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_s3k96, // activesound - MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE, // flags + MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE|MF_DONTPUNT, // flags S_NULL // raisestate }, @@ -24110,7 +24110,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_None, // activesound - MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE, // flags + MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE|MF_DONTPUNT, // flags S_NULL // raisestate }, @@ -24137,7 +24137,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_s3kc0s, // activesound - MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE, // flags + MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE|MF_DONTPUNT, // flags S_NULL // raisestate }, @@ -24164,7 +24164,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_None, // activesound - MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE, // flags + MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE|MF_DONTPUNT, // flags S_NULL // raisestate }, @@ -24218,7 +24218,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_s3k5c, // activesound - MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE, // flags + MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE|MF_DONTPUNT, // flags S_NULL // raisestate }, @@ -24245,7 +24245,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_None, // activesound - MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE, // flags + MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE|MF_DONTPUNT, // flags S_NULL // raisestate }, @@ -24353,7 +24353,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // mass 0, // damage sfx_s3k5c, // activesound - MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE, // flags + MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE|MF_DONTPUNT, // flags S_NULL // raisestate }, @@ -24380,7 +24380,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_s3k96, // activesound - MF_SPECIAL|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE, // flags + MF_SPECIAL|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE|MF_DONTPUNT, // flags S_NULL // raisestate }, @@ -24407,7 +24407,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_None, // activesound - MF_SPECIAL|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE, // flags + MF_SPECIAL|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE|MF_DONTPUNT, // flags S_NULL // raisestate }, @@ -24461,7 +24461,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_None, // activesound - MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN, // flags + MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_DONTPUNT, // flags S_NULL // raisestate }, @@ -24515,7 +24515,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_kc64, // activesound - MF_SOLID|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags + MF_SOLID|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP|MF_DONTPUNT, // flags S_NULL // raisestate }, @@ -24758,7 +24758,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_NOCLIPTHING|MF_DONTENCOREMAP, // flags + MF_NOCLIPTHING|MF_DONTENCOREMAP|MF_DONTPUNT, // flags S_NULL // raisestate }, @@ -25055,7 +25055,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_s3k5c, // activesound - MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN, // flags + MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_DONTPUNT, // flags S_NULL // raisestate }, @@ -25082,7 +25082,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_None, // activesound - MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE, // flags + MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE|MF_DONTPUNT, // flags S_NULL // raisestate }, @@ -25136,7 +25136,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_s3k96, // activesound - MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE, // flags + MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE|MF_DONTPUNT, // flags S_NULL // raisestate }, @@ -25190,7 +25190,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // mass 0, // damage sfx_None, // activesound - MF_SPECIAL|MF_DONTENCOREMAP|MF_APPLYTERRAIN, // flags + MF_SPECIAL|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_DONTPUNT, // flags S_NULL // raisestate }, From ed13705ff81a29fa6c350a73bfe2f2b4eab5c1b3 Mon Sep 17 00:00:00 2001 From: VelocitOni Date: Tue, 14 Nov 2023 02:11:22 -0500 Subject: [PATCH 73/88] Don't punt super flicky Don't punt the Super Flicky --- src/info.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/info.c b/src/info.c index d0781ae7a..f82551b92 100644 --- a/src/info.c +++ b/src/info.c @@ -30433,7 +30433,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // mass 0, // damage sfx_None, // activesound - MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT, // flags + MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_DONTPUNT, // flags S_NULL // raisestate }, From cbe42f969b4cbbf2de75325b588f304e519c76c3 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 14 Nov 2023 01:05:04 -0800 Subject: [PATCH 74/88] Obj_SuperFlickyOwner: check valid before returning source - Flicky::source() dereferences a pointer --- src/objects/super-flicky.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/objects/super-flicky.cpp b/src/objects/super-flicky.cpp index d78de32fd..601ccdf7e 100644 --- a/src/objects/super-flicky.cpp +++ b/src/objects/super-flicky.cpp @@ -765,7 +765,7 @@ mobj_t *Obj_SuperFlickyOwner(const mobj_t* mobj) { const Flicky* x = static_cast(mobj); - return x->source(); + return x->valid() ? x->source() : nullptr; } boolean Obj_IsSuperFlickyWhippable(const mobj_t* mobj) @@ -780,4 +780,4 @@ boolean Obj_IsSuperFlickyTargettingYou(const mobj_t* mobj, mobj_t *player) const Flicky* x = static_cast(mobj); return player == x->chasing(); -} \ No newline at end of file +} From b08ae70559c4d6c12b05b9456eb1ab7a4313fc60 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 14 Nov 2023 20:00:19 -0800 Subject: [PATCH 75/88] ArchiveSectors: send diff5 --- src/p_saveg.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/p_saveg.c b/src/p_saveg.c index ef09120d7..ea59a1ccd 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2029,6 +2029,8 @@ static void ArchiveSectors(savebuffer_t *save) WRITEUINT8(save->p, diff3); if (diff3 & SD_DIFF4) WRITEUINT8(save->p, diff4); + if (diff4 & SD_DIFF5) + WRITEUINT8(save->p, diff5); if (diff & SD_FLOORHT) WRITEFIXED(save->p, ss->floorheight); if (diff & SD_CEILHT) From cd2219f605e2f3ae29be2c27ae17d303b55395ba Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 14 Nov 2023 20:32:22 -0800 Subject: [PATCH 76/88] P_PlayerRingBurst: check player->curshield directly, handles Garden Top correctly --- src/p_inter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_inter.c b/src/p_inter.c index 69d0c2a17..1357af345 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3360,7 +3360,7 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings) return; // Have a shield? You get hit, but don't lose your rings! - if (K_GetShieldFromItem(player->itemtype) != KSHIELD_NONE) + if (player->curshield != KSHIELD_NONE) return; // 20 is the maximum number of rings that can be taken from you at once - half the span of your counter From 19cd35a10faec19776b5f6d918856def8bf83860 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 14 Nov 2023 20:33:09 -0800 Subject: [PATCH 77/88] P_DamageMobj: do not spill rings if player has shield --- src/p_inter.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/p_inter.c b/src/p_inter.c index 1357af345..8ceee836f 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3173,6 +3173,12 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da break; } + // Have a shield? You get hit, but don't lose your rings! + if (player->curshield != KSHIELD_NONE) + { + ringburst = 0; + } + if (type != DMG_STUMBLE && type != DMG_WHUMBLE) { if (type != DMG_STING) From a7e6ed7607e462e8cabeab820bc13060d58ee86a Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 14 Nov 2023 20:33:33 -0800 Subject: [PATCH 78/88] K_PopPlayerShield: do not destroy Garden Top before it is deployed --- src/k_kart.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index cc6137a2b..79d214388 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -6414,7 +6414,10 @@ void K_PopPlayerShield(player_t *player) return; case KSHIELD_TOP: - Obj_GardenTopDestroy(player); + if (player->curshield == KSHIELD_TOP) + { + Obj_GardenTopDestroy(player); + } return; // everything is handled by Obj_GardenTopDestroy case KSHIELD_LIGHTNING: From b1c0f6647e1b1ea8a61793ae4886bd6b91c52be6 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 14 Nov 2023 21:01:40 -0800 Subject: [PATCH 79/88] Obj_IsSuperFlickyWhippable: pass target - Old behavior: if flicky is chasing itself. What? Why did I write this?? --- src/k_collide.cpp | 2 +- src/k_objects.h | 2 +- src/objects/super-flicky.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/k_collide.cpp b/src/k_collide.cpp index 76917d2b5..568f87338 100644 --- a/src/k_collide.cpp +++ b/src/k_collide.cpp @@ -925,7 +925,7 @@ boolean K_InstaWhipCollide(mobj_t *shield, mobj_t *victim) } else if (victim->type == MT_SUPER_FLICKY) { - if (Obj_IsSuperFlickyWhippable(victim)) + if (Obj_IsSuperFlickyWhippable(victim, attacker)) { K_AddHitLag(victim, victimHitlag, true); K_AddHitLag(attacker, attackerHitlag, false); diff --git a/src/k_objects.h b/src/k_objects.h index bad973f62..186ba9b48 100644 --- a/src/k_objects.h +++ b/src/k_objects.h @@ -168,7 +168,7 @@ void Obj_BlockSuperFlicky(mobj_t *flicky); void Obj_SuperFlickyPlayerCollide(mobj_t *flicky, mobj_t *player); void Obj_SuperFlickyLanding(mobj_t *flicky); mobj_t *Obj_SuperFlickyOwner(const mobj_t *flicky); -boolean Obj_IsSuperFlickyWhippable(const mobj_t *flicky); +boolean Obj_IsSuperFlickyWhippable(const mobj_t *flicky, const mobj_t *target); boolean Obj_IsSuperFlickyTargettingYou(const mobj_t *flicky, mobj_t *player); /* Battle/Power-UP UFO */ diff --git a/src/objects/super-flicky.cpp b/src/objects/super-flicky.cpp index 601ccdf7e..344cbd46c 100644 --- a/src/objects/super-flicky.cpp +++ b/src/objects/super-flicky.cpp @@ -768,11 +768,11 @@ mobj_t *Obj_SuperFlickyOwner(const mobj_t* mobj) return x->valid() ? x->source() : nullptr; } -boolean Obj_IsSuperFlickyWhippable(const mobj_t* mobj) +boolean Obj_IsSuperFlickyWhippable(const mobj_t* mobj, const mobj_t* target) { const Flicky* x = static_cast(mobj); - return mobj == x->chasing() && !x->stunned(); + return target == x->chasing() && !x->stunned(); } boolean Obj_IsSuperFlickyTargettingYou(const mobj_t* mobj, mobj_t *player) From 0301847339293b6ea0e4be14ae851c4ecc4488b7 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Wed, 15 Nov 2023 00:54:01 -0700 Subject: [PATCH 80/88] Fix double offset scale on charge sparks --- src/objects/charge.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/objects/charge.c b/src/objects/charge.c index b4124343a..7623b6ece 100644 --- a/src/objects/charge.c +++ b/src/objects/charge.c @@ -7,7 +7,7 @@ #include "../m_random.h" #define CHARGEAURA_BURSTTIME (9) -#define CHARGEAURA_SPARKRADIUS (160) +#define CHARGEAURA_SPARKRADIUS (40) // xval1: destruction timer // xval2: master (spawns other visuals) @@ -63,9 +63,9 @@ void Obj_ChargeAuraThink (mobj_t *aura) if (player->driftcharge) { mobj_t *spark = P_SpawnMobjFromMobj(aura, - mo->scale*P_RandomRange(PR_DECORATION, -1*CHARGEAURA_SPARKRADIUS, CHARGEAURA_SPARKRADIUS), - mo->scale*P_RandomRange(PR_DECORATION, -1*CHARGEAURA_SPARKRADIUS, CHARGEAURA_SPARKRADIUS), - mo->scale*P_RandomRange(PR_DECORATION, -1*CHARGEAURA_SPARKRADIUS, CHARGEAURA_SPARKRADIUS), + FRACUNIT*P_RandomRange(PR_DECORATION, -1*CHARGEAURA_SPARKRADIUS, CHARGEAURA_SPARKRADIUS), + FRACUNIT*P_RandomRange(PR_DECORATION, -1*CHARGEAURA_SPARKRADIUS, CHARGEAURA_SPARKRADIUS), + FRACUNIT*P_RandomRange(PR_DECORATION, -1*CHARGEAURA_SPARKRADIUS, CHARGEAURA_SPARKRADIUS), MT_CHARGESPARK); spark->frame = P_RandomRange(PR_DECORATION, 1, 5); spark->renderflags |= RF_FULLBRIGHT|RF_ADD; From f0ddb79156658399b38daae77b00e95bb98229b4 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Wed, 15 Nov 2023 01:03:55 -0700 Subject: [PATCH 81/88] Allow bubblebounce from trick, but disable trick handling --- src/k_kart.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index ddfc36387..021e71158 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -12500,18 +12500,21 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (player->fastfall) { - P_InstaThrust(player->mo, player->mo->angle, 2*abs(player->fastfall)/3 + 15*FRACUNIT); - player->mo->hitlag = 3; - S_StartSound(player->mo, sfx_gshba); - player->fastfall = 0; // intentionally skip bounce - player->trickcharge = 0; - - UINT8 i; - for (i = 0; i < 4; i++) + if (player->curshield != KSHIELD_BUBBLE) // Allow bubblebounce (it's cute) but don't give standard trick rewards { - mobj_t *arc = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_CHARGEFALL); - P_SetTarget(&arc->target, player->mo); - arc->extravalue1 = i; + P_InstaThrust(player->mo, player->mo->angle, 2*abs(player->fastfall)/3 + 15*FRACUNIT); + player->mo->hitlag = 3; + S_StartSound(player->mo, sfx_gshba); + player->fastfall = 0; // intentionally skip bounce + player->trickcharge = 0; + + UINT8 i; + for (i = 0; i < 4; i++) + { + mobj_t *arc = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_CHARGEFALL); + P_SetTarget(&arc->target, player->mo); + arc->extravalue1 = i; + } } } else From eb394ec5f89541a20504afb59a503852bead027c Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Wed, 15 Nov 2023 15:41:33 -0700 Subject: [PATCH 82/88] Use more realistic practice conditions for SPB Attack --- src/k_roulette.c | 4 ++-- src/objects/random-item.c | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/k_roulette.c b/src/k_roulette.c index 70d00893e..107908fd7 100644 --- a/src/k_roulette.c +++ b/src/k_roulette.c @@ -192,7 +192,7 @@ static kartitems_t K_KartItemReelTimeAttack[] = static kartitems_t K_KartItemReelSPBAttack[] = { - KITEM_GACHABOM, + KITEM_DROPTARGET, KITEM_SUPERRING, KITEM_NONE }; @@ -1242,7 +1242,7 @@ static void K_CalculateRouletteSpeed(itemroulette_t *const roulette) return; } - if (K_TimeAttackRules() == true) + if (K_TimeAttackRules() == true && !(modeattacking & ATTACKING_SPB)) { // Time Attack rules; use a consistent speed. roulette->tics = roulette->speed = ROULETTE_SPEED_TIMEATTACK; diff --git a/src/objects/random-item.c b/src/objects/random-item.c index 8df3fb937..fcdbe6b4b 100644 --- a/src/objects/random-item.c +++ b/src/objects/random-item.c @@ -121,10 +121,14 @@ void Obj_RandomItemVisuals(mobj_t *mobj) // // Then extraval1 starts ticking up and triggers the transformation from Ringbox to Random Item. if (mobj->fuse == 0 && !(mobj->flags & MF_NOCLIPTHING) && !(mobj->flags2 & MF2_BOSSDEAD) && !cv_thunderdome.value - && (modeattacking == 0 || specialstageinfo.valid)) // Time Attacking in Special is a fucked-looking exception + && (modeattacking == ATTACKING_NONE || !!(modeattacking & ATTACKING_SPB) || specialstageinfo.valid)) // Time Attacking in Special is a fucked-looking exception { mobj->extravalue1++; + // Dumb, but in Attack starts (or POSITION from hell) you can reach early boxes before they transform. + if (leveltime == 0) + mobj->extravalue1 = RINGBOX_TIME; + // Don't transform stuff that isn't a Ring Box, idiot statenum_t boxstate = mobj->state - states; if (boxstate < S_RINGBOX1 || boxstate > S_RINGBOX12) From 600aec3449c7cc8aaaa19f1502c7549e97dc1023 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 15 Nov 2023 14:48:53 -0800 Subject: [PATCH 83/88] renderhitbox: shown MF_PAPERCOLLISION correctly --- src/r_bbox.c | 43 +++++++++++++++++++++++++++---------------- src/r_things.cpp | 35 ++++++++++++++++++++++++++--------- 2 files changed, 53 insertions(+), 25 deletions(-) diff --git a/src/r_bbox.c b/src/r_bbox.c index ce4f3d758..d484c3b51 100644 --- a/src/r_bbox.c +++ b/src/r_bbox.c @@ -204,29 +204,40 @@ void R_DrawThingBoundingBox(vissprite_t *vis) .color = R_GetBoundingBoxColor(vis->mobj), }; - // 1--3 - // | | - // 0--2 + if (vis->mobjflags & MF_PAPERCOLLISION) + { + // 0--1 - // left + draw_bbox_col(&bb, 0, tx - rc, ty - rs); // left + draw_bbox_col(&bb, 1, tx + rc, ty + rs); // right + draw_bbox_row(&bb, 0, 1); // connect both + } + else + { + // 1--3 + // | | + // 0--2 - draw_bbox_col(&bb, 0, tx, ty); // bottom - draw_bbox_col(&bb, 1, tx - rc, ty + rs); // top + // left - // right + draw_bbox_col(&bb, 0, tx, ty); // bottom + draw_bbox_col(&bb, 1, tx - rc, ty + rs); // top - tx += rs; - ty += rc; + // right - draw_bbox_col(&bb, 2, tx, ty); // bottom - draw_bbox_col(&bb, 3, tx - rc, ty + rs); // top + tx += rs; + ty += rc; - // connect all four columns + draw_bbox_col(&bb, 2, tx, ty); // bottom + draw_bbox_col(&bb, 3, tx - rc, ty + rs); // top - draw_bbox_row(&bb, 0, 1); - draw_bbox_row(&bb, 1, 3); - draw_bbox_row(&bb, 3, 2); - draw_bbox_row(&bb, 2, 0); + // connect all four columns + + draw_bbox_row(&bb, 0, 1); + draw_bbox_row(&bb, 1, 3); + draw_bbox_row(&bb, 3, 2); + draw_bbox_row(&bb, 2, 0); + } } static boolean is_tangible (mobj_t *thing) diff --git a/src/r_things.cpp b/src/r_things.cpp index deacfce92..37dcc3bf4 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -1586,13 +1586,22 @@ static void R_ProjectBoundingBox(mobj_t *thing, vissprite_t *vis) R_InterpolateMobjState(thing, FRACUNIT, &interp); } - // 1--3 - // | | - // 0--2 - - // start in the (0) corner - gx = interp.x - thing->radius - viewx; - gy = interp.y - thing->radius - viewy; + if (thing->flags & MF_PAPERCOLLISION) + { + // 0--1 + // start in the middle + gx = interp.x - viewx; + gy = interp.y - viewy; + } + else + { + // 1--3 + // | | + // 0--2 + // start in the (0) corner + gx = interp.x - thing->radius - viewx; + gy = interp.y - thing->radius - viewy; + } tz = FixedMul(gx, viewcos) + FixedMul(gy, viewsin); @@ -1620,8 +1629,16 @@ static void R_ProjectBoundingBox(mobj_t *thing, vissprite_t *vis) box->gx = tx; box->gy = tz; - box->scale = 2 * FixedMul(thing->radius, viewsin); - box->xscale = 2 * FixedMul(thing->radius, viewcos); + if (thing->flags & MF_PAPERCOLLISION) + { + box->scale = FixedMul(thing->radius, FCOS(viewangle - interp.angle)); + box->xscale = FixedMul(thing->radius, FSIN(viewangle - interp.angle)); + } + else + { + box->scale = 2 * FixedMul(thing->radius, viewsin); + box->xscale = 2 * FixedMul(thing->radius, viewcos); + } box->pz = interp.z; box->pzt = box->pz + box->thingheight; From 2ebbfe3e7a3553fe72d7757347efd0fc340268d3 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 15 Nov 2023 14:51:16 -0800 Subject: [PATCH 84/88] MT_WALLSPIKE: let radius be increased without requiring map/HVR adjustment --- src/p_mobj.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/p_mobj.c b/src/p_mobj.c index 54d62622e..26265c21d 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -13867,7 +13867,16 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj) // Use per-thing collision for spikes unless the intangible flag is checked. if (!(mthing->thing_args[2] & TMSF_INTANGIBLE) && !metalrecording) { + const fixed_t kSpriteRadius = 16 * mobj->scale; + fixed_t x = FixedMul(mobj->radius - kSpriteRadius, FCOS(mobj->angle)); + fixed_t y = FixedMul(mobj->radius - kSpriteRadius, FSIN(mobj->angle)); + + mobj->sprxoff -= x; + mobj->spryoff -= y; + P_UnsetThingPosition(mobj); + mobj->x += x; + mobj->y += y; mobj->flags &= ~(MF_NOBLOCKMAP | MF_NOCLIPHEIGHT); mobj->flags |= MF_SOLID; P_SetThingPosition(mobj); From d9bf6119a3452e287e2f3c664c24c8da9cc1038d Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 15 Nov 2023 14:51:46 -0800 Subject: [PATCH 85/88] MT_WALLSPIKE: increase hitbox size to match sprite --- src/info.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/info.c b/src/info.c index 546cd2b68..dc460763a 100644 --- a/src/info.c +++ b/src/info.c @@ -9386,7 +9386,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_WALLSPIKED2, // xdeathstate sfx_mspogo, // deathsound 2*TICRATE, // speed - 16*FRACUNIT, // radius + 48*FRACUNIT, // radius 14*FRACUNIT, // height 0, // display offset 4, // mass From 4065f56b98dd4038df4e521e44957db2a7f9f0f7 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 15 Nov 2023 15:36:49 -0800 Subject: [PATCH 86/88] MT_WALLSPIKE: always bounce toward tip --- src/k_kart.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 021e71158..4bf2c73a7 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -998,7 +998,7 @@ boolean K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2) boolean K_KartSolidBounce(mobj_t *bounceMobj, mobj_t *solidMobj) { const fixed_t minBump = 25*mapobjectscale; - fixed_t distx, disty, dist; + fixed_t distx, disty; fixed_t force; if ((!bounceMobj || P_MobjWasRemoved(bounceMobj)) @@ -1034,17 +1034,30 @@ boolean K_KartSolidBounce(mobj_t *bounceMobj, mobj_t *solidMobj) return false; } - // Multiply by force - distx = FixedMul(force, distx); - disty = FixedMul(force, disty); - dist = FixedHypot(distx, disty); - { // Normalize to the desired push value. - fixed_t normalisedx = FixedDiv(distx, dist); - fixed_t normalisedy = FixedDiv(disty, dist); + fixed_t normalisedx; + fixed_t normalisedy; fixed_t bounceSpeed; + // Multiply by force + distx = FixedMul(force, distx); + disty = FixedMul(force, disty); + fixed_t dist = FixedHypot(distx, disty); + + normalisedx = FixedDiv(distx, dist); + normalisedy = FixedDiv(disty, dist); + + if (solidMobj->type == MT_WALLSPIKE) + { + fixed_t co = FCOS(solidMobj->angle); + fixed_t si = FSIN(solidMobj->angle); + + // Always thrust out toward the tip + normalisedx = FixedMul(normalisedx, abs(si)) - co; + normalisedy = FixedMul(normalisedy, abs(co)) - si; + } + bounceSpeed = FixedHypot(bounceMobj->momx, bounceMobj->momy); bounceSpeed = FixedMul(bounceSpeed, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3))); bounceSpeed += minBump; From c4e4c9e9b0d11176a76fba8ac8f19f0055876396 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 15 Nov 2023 15:41:52 -0800 Subject: [PATCH 87/88] MT_SPIKE, MT_WALLSPIKE: entire hitbox hurts, hurt all objects, tumbles objects that fall onto spikes --- src/p_map.c | 128 ++++++++++++++++++++-------------------------------- 1 file changed, 49 insertions(+), 79 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index 69ff25357..7f1b3bf84 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -659,23 +659,6 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) && (tm.thing->type == MT_BLENDEYE_MAIN || tm.thing->type == MT_BLENDEYE_EYE || tm.thing->type == MT_BLENDEYE_PUYO)) return BMIT_CONTINUE; - // When solid spikes move, assume they just popped up and teleport things on top of them to hurt. - if (tm.thing->type == MT_SPIKE && tm.thing->flags & MF_SOLID) - { - if (thing->z > tm.thing->z + tm.thing->height) - return BMIT_CONTINUE; // overhead - if (thing->z + thing->height < tm.thing->z) - return BMIT_CONTINUE; // underneath - - if (tm.thing->eflags & MFE_VERTICALFLIP) - P_SetOrigin(thing, thing->x, thing->y, tm.thing->z - thing->height - FixedMul(FRACUNIT, tm.thing->scale)); - else - P_SetOrigin(thing, thing->x, thing->y, tm.thing->z + tm.thing->height + FixedMul(FRACUNIT, tm.thing->scale)); - if (thing->flags & MF_SHOOTABLE) - P_DamageMobj(thing, tm.thing, tm.thing, 1, 0); - return BMIT_CONTINUE; - } - if (thing->flags & MF_PAIN) { // Player touches painful thing sitting on the floor // see if it went over / under @@ -1326,78 +1309,65 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) } // Sprite Spikes! - // Do not return because solidity code comes below. - if (tm.thing->type == MT_SPIKE && tm.thing->flags & MF_SOLID && thing->player) // moving spike rams into player?! + if ((tm.thing->type == MT_SPIKE || tm.thing->type == MT_WALLSPIKE) && (tm.thing->flags & MF_SOLID)) // spike pops up { - if (tm.thing->eflags & MFE_VERTICALFLIP) + // see if it went over / under + if (tm.thing->z > thing->z + thing->height) + return BMIT_CONTINUE; // overhead + if (tm.thing->z + tm.thing->height < thing->z) + return BMIT_CONTINUE; // underneath + + if (thing->flags & MF_SHOOTABLE) { - if (thing->z + thing->height <= tm.thing->z + FixedMul(FRACUNIT, tm.thing->scale) - && thing->z + thing->height + thing->momz >= tm.thing->z + FixedMul(FRACUNIT, tm.thing->scale) + tm.thing->momz) - P_DamageMobj(thing, tm.thing, tm.thing, 1, DMG_TUMBLE); + if (P_MobjFlip(thing) == P_MobjFlip(tm.thing)) + { + if (P_DamageMobj(thing, tm.thing, tm.thing, 1, DMG_TUMBLE)) + { + // FIXME: None of this is correct for wall spikes, + // but I don't feel like testing that right now. + + // Increase vertical momentum for a strong effect + thing->momz += (tm.thing->height / 2) * P_MobjFlip(tm.thing); + + // Teleport on top of the spikes + P_MoveOrigin( + thing, + thing->x, + thing->y, + tm.thing->z + (P_MobjFlip(thing) > 0 ? tm.thing->height : -thing->height) + ); + } + } + else + { + P_DamageMobj(thing, tm.thing, tm.thing, 1, DMG_NORMAL); + } } - else if (thing->z >= tm.thing->z + tm.thing->height - FixedMul(FRACUNIT, tm.thing->scale) - && thing->z + thing->momz <= tm.thing->z + tm.thing->height - FixedMul(FRACUNIT, tm.thing->scale) + tm.thing->momz) - P_DamageMobj(thing, tm.thing, tm.thing, 1, DMG_TUMBLE); + return BMIT_CONTINUE; } - else if (thing->type == MT_SPIKE && thing->flags & MF_SOLID && tm.thing->player) // unfortunate player falls into spike?! + else if ((thing->type == MT_SPIKE || thing->type == MT_WALLSPIKE) && + (thing->flags & MF_SOLID) && (tm.thing->flags & MF_SHOOTABLE)) // stationary spike { - if (thing->eflags & MFE_VERTICALFLIP) + // see if it went over / under + if (tm.thing->z > thing->z + thing->height) + return BMIT_CONTINUE; // overhead + if (tm.thing->z + tm.thing->height < thing->z) + return BMIT_CONTINUE; // underneath + + if (tm.thing->player && tm.thing->player && tm.thing->player->tumbleBounces > 0) { - if (tm.thing->z + tm.thing->height <= thing->z - FixedMul(FRACUNIT, thing->scale) - && tm.thing->z + tm.thing->height + tm.thing->momz >= thing->z - FixedMul(FRACUNIT, thing->scale)) - P_DamageMobj(tm.thing, thing, thing, 1, DMG_TUMBLE); + return BMIT_CONTINUE; } - else if (tm.thing->z >= thing->z + thing->height + FixedMul(FRACUNIT, thing->scale) - && tm.thing->z + tm.thing->momz <= thing->z + thing->height + FixedMul(FRACUNIT, thing->scale)) + + if (!P_IsObjectOnGround(tm.thing) && tm.thing->momz * P_MobjFlip(tm.thing) < 0) // fell into it + { P_DamageMobj(tm.thing, thing, thing, 1, DMG_TUMBLE); - } - - if (tm.thing->type == MT_WALLSPIKE && tm.thing->flags & MF_SOLID && thing->player) // wall spike impales player - { - fixed_t bottomz, topz; - bottomz = tm.thing->z; - topz = tm.thing->z + tm.thing->height; - if (tm.thing->eflags & MFE_VERTICALFLIP) - bottomz -= FixedMul(FRACUNIT, tm.thing->scale); - else - topz += FixedMul(FRACUNIT, tm.thing->scale); - - if (thing->z + thing->height > bottomz // above bottom - && thing->z < topz) // below top - // don't check angle, the player was clearly in the way in this case - P_DamageMobj(thing, tm.thing, tm.thing, 1, DMG_NORMAL); - } - else if (thing->type == MT_WALLSPIKE && thing->flags & MF_SOLID && tm.thing->player) - { - fixed_t bottomz, topz; - angle_t touchangle = R_PointToAngle2(thing->tracer->x, thing->tracer->y, tm.thing->x, tm.thing->y); - - if (P_PlayerInPain(tm.thing->player) && (tm.thing->momx || tm.thing->momy)) - { - angle_t playerangle = R_PointToAngle2(0, 0, tm.thing->momx, tm.thing->momy) - touchangle; - if (playerangle > ANGLE_180) - playerangle = InvAngle(playerangle); - if (playerangle < ANGLE_90) - return BMIT_CONTINUE; // Yes, this is intentionally outside the z-height check. No standing on spikes whilst moving away from them. + return BMIT_CONTINUE; } - - bottomz = thing->z; - topz = thing->z + thing->height; - - if (thing->eflags & MFE_VERTICALFLIP) - bottomz -= FixedMul(FRACUNIT, thing->scale); else - topz += FixedMul(FRACUNIT, thing->scale); - - if (tm.thing->z + tm.thing->height > bottomz // above bottom - && tm.thing->z < topz // below top - && !P_MobjWasRemoved(thing->tracer)) // this probably wouldn't work if we didn't have a tracer - { // use base as a reference point to determine what angle you touched the spike at - touchangle = thing->angle - touchangle; - if (touchangle > ANGLE_180) - touchangle = InvAngle(touchangle); - if (touchangle <= ANGLE_22h) // if you touched it at this close an angle, you get poked! - P_DamageMobj(tm.thing, thing, thing, 1, DMG_NORMAL); + { + // Do not return because solidity code comes below. + P_DamageMobj(tm.thing, thing, thing, 1, DMG_NORMAL); } } From d6fb8eb03656d670085bf1569a3628a90b3ba167 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 15 Nov 2023 17:53:34 -0800 Subject: [PATCH 88/88] MT_SPIKE: taller hitbox, matches sprite --- src/info.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/info.c b/src/info.c index dc460763a..71644da80 100644 --- a/src/info.c +++ b/src/info.c @@ -9360,7 +9360,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_mspogo, // deathsound 2*TICRATE, // speed 14*FRACUNIT, // radius - 64*FRACUNIT, // height + 90*FRACUNIT, // height 0, // display offset 4, // mass 0, // damage