From 71cc9c08007e9e8bf8e38676b19a0b48b9665e6b Mon Sep 17 00:00:00 2001 From: Ashnal Date: Mon, 29 Apr 2024 23:19:12 -0400 Subject: [PATCH 01/16] Auto-Ring Accessibility Option Lacking animation at this commit --- src/cvars.cpp | 8 +++++ src/d_netcmd.c | 12 +++++++- src/d_player.h | 3 +- src/g_game.c | 2 +- src/g_game.h | 1 + src/k_hud.cpp | 15 ++++++++++ src/k_hud.h | 1 + src/k_kart.c | 29 +++++++++++++++++-- src/k_menu.h | 1 + src/k_profiles.cpp | 5 ++++ src/k_profiles.h | 3 ++ src/menus/options-profiles-1.c | 2 ++ src/menus/options-profiles-edit-1.c | 2 ++ .../options-profiles-edit-accessibility.cpp | 3 ++ src/p_saveg.c | 2 ++ 15 files changed, 84 insertions(+), 5 deletions(-) diff --git a/src/cvars.cpp b/src/cvars.cpp index 5eb4c6a0b..85085e147 100644 --- a/src/cvars.cpp +++ b/src/cvars.cpp @@ -975,6 +975,7 @@ consvar_t cv_dummymenuplayer = MenuDummy("dummymenuplayer", "P1").onchange(Dummy consvar_t cv_dummyprofileautoroulette = MenuDummy("dummyprofileautoroulette", "Off").on_off(); consvar_t cv_dummyprofilefov = MenuDummy("dummyprofilefov", "100").min_max(70, 110); consvar_t cv_dummyprofilelitesteer = MenuDummy("dummyprofilelitesteer", "Off").on_off(); +consvar_t cv_dummyprofileautoring = MenuDummy("dummyprofileautoring", "Off").on_off(); consvar_t cv_dummyprofilekickstart = MenuDummy("dummyprofilekickstart", "Off").on_off(); consvar_t cv_dummyprofilename = MenuDummy("dummyprofilename", ""); consvar_t cv_dummyprofileplayername = MenuDummy("dummyprofileplayername", ""); @@ -1087,6 +1088,13 @@ consvar_t cv_litesteer[MAXSPLITSCREENPLAYERS] = { Player("litesteer4", "Off").on_off().onchange(weaponPrefChange4), }; +consvar_t cv_autoring[MAXSPLITSCREENPLAYERS] = { + Player("autoring", "Off").on_off().onchange(weaponPrefChange), + Player("autoring2", "Off").on_off().onchange(weaponPrefChange2), + Player("autoring3", "Off").on_off().onchange(weaponPrefChange3), + Player("autoring4", "Off").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 5853e7936..d887aaf73 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1258,6 +1258,7 @@ enum { WP_SHRINKME = 1<<1, WP_AUTOROULETTE = 1<<2, WP_ANALOGSTICK = 1<<3, + WP_AUTORING = 1<<4, }; void WeaponPref_Send(UINT8 ssplayer) @@ -1276,6 +1277,9 @@ void WeaponPref_Send(UINT8 ssplayer) if (gamecontrolflags[ssplayer] & GCF_ANALOGSTICK) prefs |= WP_ANALOGSTICK; + if (cv_autoring[ssplayer].value) + prefs |= WP_AUTORING; + UINT8 buf[2]; buf[0] = prefs; buf[1] = cv_mindelay.value; @@ -1301,6 +1305,9 @@ void WeaponPref_Save(UINT8 **cp, INT32 playernum) if (player->pflags & PF_ANALOGSTICK) prefs |= WP_ANALOGSTICK; + if (player->pflags & PF_AUTORING) + prefs |= WP_AUTORING; + WRITEUINT8(*cp, prefs); } @@ -1311,7 +1318,7 @@ size_t WeaponPref_Parse(const UINT8 *bufstart, INT32 playernum) UINT8 prefs = READUINT8(p); - player->pflags &= ~(PF_KICKSTARTACCEL|PF_SHRINKME|PF_AUTOROULETTE); + player->pflags &= ~(PF_KICKSTARTACCEL|PF_SHRINKME|PF_AUTOROULETTE|PF_AUTORING); if (prefs & WP_KICKSTARTACCEL) player->pflags |= PF_KICKSTARTACCEL; @@ -1327,6 +1334,9 @@ size_t WeaponPref_Parse(const UINT8 *bufstart, INT32 playernum) else player->pflags &= ~PF_ANALOGSTICK; + if (prefs & WP_AUTORING) + player->pflags |= PF_AUTORING; + if (leveltime < 2) { // BAD HACK: No other place I tried to slot this in diff --git a/src/d_player.h b/src/d_player.h index c17b8d48d..be2e07ee1 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -109,7 +109,7 @@ typedef enum PF_TRUSTWAYPOINTS = 1<<15, // Do not activate lap cheat prevention next time finish line distance is updated PF_FREEZEWAYPOINTS = 1<<16, // Skip the next waypoint/finish line distance update - //1<<17 free, was previously itemflags stuff + PF_AUTORING = 1<<17, // Accessibility: Non-deterministic item box, no manual stop. PF_DRIFTINPUT = 1<<18, // Drifting! PF_GETSPARKS = 1<<19, // Can get sparks @@ -955,6 +955,7 @@ struct player_t UINT8 typing_duration; // How long since resumed timer UINT8 kickstartaccel; + boolean autoring; // did we autoring this tic? UINT8 stairjank; UINT8 topdriftheld; diff --git a/src/g_game.c b/src/g_game.c index c9fdfc91f..04daab555 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2251,7 +2251,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|PF_ANALOGSTICK)); + pflags = (players[player].pflags & (PF_WANTSTOJOIN|PF_KICKSTARTACCEL|PF_SHRINKME|PF_SHRINKACTIVE|PF_AUTOROULETTE|PF_ANALOGSTICK|PF_AUTORING)); // SRB2kart memcpy(&itemRoulette, &players[player].itemRoulette, sizeof (itemRoulette)); diff --git a/src/g_game.h b/src/g_game.h index 335294950..ff49c49b4 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_autoring[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_shrinkme[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_deadzone[MAXSPLITSCREENPLAYERS]; diff --git a/src/k_hud.cpp b/src/k_hud.cpp index 4aa19ac05..cc03a30e7 100644 --- a/src/k_hud.cpp +++ b/src/k_hud.cpp @@ -212,6 +212,7 @@ static patch_t *kp_bossret[4]; static patch_t *kp_trickcool[2]; patch_t *kp_autoroulette; +patch_t *kp_autoring; patch_t *kp_capsuletarget_arrow[2][2]; patch_t *kp_capsuletarget_icon[2]; @@ -781,6 +782,7 @@ void K_LoadKartHUDGraphics(void) HU_UpdatePatch(&kp_trickcool[1], "K_COOL2"); HU_UpdatePatch(&kp_autoroulette, "A11YITEM"); + HU_UpdatePatch(&kp_autoring, "A11YRING"); sprintf(buffer, "K_BOSB0x"); for (i = 0; i < 8; i++) @@ -3250,6 +3252,19 @@ static void K_drawKartAccessibilityIcons(boolean gametypeinfoshown, INT32 fx) else fx += 12 + 1; } + + if (stplyr->pflags & PF_AUTORING) + { + if (mirror) + fx -= 14; + + V_DrawScaledPatch(fx, fy-1, V_SLIDEIN|splitflags, kp_autoring); + + if (mirror) + fx--; + else + fx += 14 + 1; + } } static void K_drawKartSpeedometer(boolean gametypeinfoshown) diff --git a/src/k_hud.h b/src/k_hud.h index a4e92c728..07cea4774 100644 --- a/src/k_hud.h +++ b/src/k_hud.h @@ -78,6 +78,7 @@ extern patch_t *kp_spraycantarget_far[2][6]; extern patch_t *kp_spraycantarget_near[2][6]; extern patch_t *kp_autoroulette; +extern patch_t *kp_autoring; extern patch_t *kp_button_a[2][2]; extern patch_t *kp_button_b[2][2]; diff --git a/src/k_kart.c b/src/k_kart.c index 9c71770ba..33fc20003 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -12606,7 +12606,28 @@ void K_MoveKartPlayer(player_t *player, boolean onground) // Ring boosting if (player->itemflags & IF_USERINGS) { - if ((cmd->buttons & BT_ATTACK) && !player->ringdelay && player->rings > 0) + // Auto-Ring + boolean autoring; + if ( + player->pflags & PF_AUTORING + && leveltime > starttime + && !(cmd->buttons & BT_BRAKE) + && K_GetKartButtons(player) + && P_IsObjectOnGround(player->mo) + && ( + player->rings > 18 + && FixedDiv(player->speed * 100, K_GetKartSpeed(player, false, true)) < 100*FRACUNIT + || player->rings > 9 + && FixedDiv(player->speed * 100, K_GetKartSpeed(player, false, true)) < 85*FRACUNIT + ||player->rings > 3 + && FixedDiv(player->speed * 100, K_GetKartSpeed(player, false, true)) < 35*FRACUNIT + ) + ) + player->autoring = true; + else + player->autoring = false; + + if (((cmd->buttons & BT_ATTACK) || player->autoring) && !player->ringdelay && player->rings > 0) { mobj_t *ring = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_RING); P_SetMobjState(ring, S_FASTRING1); @@ -12629,8 +12650,12 @@ void K_MoveKartPlayer(player_t *player, boolean onground) ring->shadowscale = 0; P_SetTarget(&ring->target, player->mo); // user player->rings--; - player->ringdelay = 3; + if (player->autoring && !(cmd->buttons & BT_ATTACK)) + player->ringdelay = 6; + else + player->ringdelay = 3; } + } // Other items else diff --git a/src/k_menu.h b/src/k_menu.h index feb465404..643170b62 100644 --- a/src/k_menu.h +++ b/src/k_menu.h @@ -1124,6 +1124,7 @@ extern consvar_t cv_dummyprofileplayername; extern consvar_t cv_dummyprofilekickstart; extern consvar_t cv_dummyprofileautoroulette; extern consvar_t cv_dummyprofilelitesteer; +extern consvar_t cv_dummyprofileautoring; extern consvar_t cv_dummyprofilerumble; extern consvar_t cv_dummyprofilefov; diff --git a/src/k_profiles.cpp b/src/k_profiles.cpp index 1076cfc78..3491d70fc 100644 --- a/src/k_profiles.cpp +++ b/src/k_profiles.cpp @@ -82,6 +82,7 @@ profile_t* PR_MakeProfile( newprofile->kickstartaccel = false; newprofile->autoroulette = false; newprofile->litesteer = false; + newprofile->autoring = false; newprofile->rumble = true; newprofile->fov = atoi(cv_dummyprofilefov.defaultvalue); @@ -103,6 +104,7 @@ profile_t* PR_MakeProfileFromPlayer(const char *prname, const char *pname, const newprofile->kickstartaccel = cv_kickstartaccel[pnum].value; newprofile->autoroulette = cv_autoroulette[pnum].value; newprofile->litesteer = cv_litesteer[pnum].value; + newprofile->autoring = cv_autoring[pnum].value; newprofile->rumble = cv_rumble[pnum].value; newprofile->fov = cv_fov[pnum].value / FRACUNIT; @@ -299,6 +301,7 @@ void PR_SaveProfiles(void) jsonprof.preferences.kickstartaccel = cprof->kickstartaccel; jsonprof.preferences.autoroulette = cprof->autoroulette; jsonprof.preferences.litesteer = cprof->litesteer; + jsonprof.preferences.autoring = cprof->autoring; jsonprof.preferences.rumble = cprof->rumble; jsonprof.preferences.fov = cprof->fov; @@ -473,6 +476,7 @@ void PR_LoadProfiles(void) newprof->kickstartaccel = jsprof.preferences.kickstartaccel; newprof->autoroulette = jsprof.preferences.autoroulette; newprof->litesteer = jsprof.preferences.litesteer; + newprof->autoring = jsprof.preferences.autoring; newprof->rumble = jsprof.preferences.rumble; newprof->fov = jsprof.preferences.fov; @@ -554,6 +558,7 @@ static void PR_ApplyProfile_Settings(profile_t *p, UINT8 playernum) CV_StealthSetValue(&cv_kickstartaccel[playernum], p->kickstartaccel); CV_StealthSetValue(&cv_autoroulette[playernum], p->autoroulette); CV_StealthSetValue(&cv_litesteer[playernum], p->litesteer); + CV_StealthSetValue(&cv_autoring[playernum], p->autoring); CV_StealthSetValue(&cv_rumble[playernum], p->rumble); CV_StealthSetValue(&cv_fov[playernum], p->fov); diff --git a/src/k_profiles.h b/src/k_profiles.h index 70d3abd68..247a08e9f 100644 --- a/src/k_profiles.h +++ b/src/k_profiles.h @@ -46,6 +46,7 @@ struct ProfilePreferencesJson bool kickstartaccel; bool autoroulette; bool litesteer; + bool autoring; bool rumble; uint8_t fov; tm test; @@ -55,6 +56,7 @@ struct ProfilePreferencesJson kickstartaccel, autoroulette, litesteer, + autoring, rumble, fov ) @@ -160,6 +162,7 @@ struct profile_t boolean kickstartaccel; // cv_kickstartaccel boolean autoroulette; // cv_autoroulette boolean litesteer; // cv_litesteer + boolean autoring; // cv_autoring boolean rumble; // cv_rumble UINT8 fov; // cv_fov diff --git a/src/menus/options-profiles-1.c b/src/menus/options-profiles-1.c index be2584e63..e7c31449c 100644 --- a/src/menus/options-profiles-1.c +++ b/src/menus/options-profiles-1.c @@ -102,6 +102,7 @@ void M_StartEditProfile(INT32 c) CV_StealthSetValue(&cv_dummyprofilekickstart, optionsmenu.profile->kickstartaccel); CV_StealthSetValue(&cv_dummyprofileautoroulette, optionsmenu.profile->autoroulette); CV_StealthSetValue(&cv_dummyprofilelitesteer, optionsmenu.profile->litesteer); + CV_StealthSetValue(&cv_dummyprofileautoring, optionsmenu.profile->autoring); CV_StealthSetValue(&cv_dummyprofilerumble, optionsmenu.profile->rumble); CV_StealthSetValue(&cv_dummyprofilefov, optionsmenu.profile->fov); } @@ -112,6 +113,7 @@ void M_StartEditProfile(INT32 c) CV_StealthSetValue(&cv_dummyprofilekickstart, 0); // off CV_StealthSetValue(&cv_dummyprofileautoroulette, 0); // off CV_StealthSetValue(&cv_dummyprofilelitesteer, 1); // on + CV_StealthSetValue(&cv_dummyprofileautoring, 0); // on CV_StealthSetValue(&cv_dummyprofilerumble, 1); // on CV_StealthSetValue(&cv_dummyprofilefov, 90); } diff --git a/src/menus/options-profiles-edit-1.c b/src/menus/options-profiles-edit-1.c index 9599ae456..93d44049a 100644 --- a/src/menus/options-profiles-edit-1.c +++ b/src/menus/options-profiles-edit-1.c @@ -98,6 +98,7 @@ static void M_ProfileEditApply(void) optionsmenu.profile->kickstartaccel = cv_dummyprofilekickstart.value; optionsmenu.profile->autoroulette = cv_dummyprofileautoroulette.value; optionsmenu.profile->litesteer = cv_dummyprofilelitesteer.value; + optionsmenu.profile->autoring = cv_dummyprofileautoring.value; optionsmenu.profile->rumble = cv_dummyprofilerumble.value; optionsmenu.profile->fov = cv_dummyprofilefov.value; @@ -109,6 +110,7 @@ static void M_ProfileEditApply(void) 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_autoring[belongsto], cv_dummyprofileautoring.value); CV_SetValue(&cv_rumble[belongsto], cv_dummyprofilerumble.value); CV_SetValue(&cv_fov[belongsto], cv_dummyprofilefov.value); } diff --git a/src/menus/options-profiles-edit-accessibility.cpp b/src/menus/options-profiles-edit-accessibility.cpp index 9a236dae8..14dd0643d 100644 --- a/src/menus/options-profiles-edit-accessibility.cpp +++ b/src/menus/options-profiles-edit-accessibility.cpp @@ -105,6 +105,9 @@ menuitem_t OPTIONS_ProfileAccessibility[] = { {IT_STRING | IT_CVAR, "Auto Roulette", "Item roulette auto-stops on a random result.", NULL, {.cvar = &cv_dummyprofileautoroulette}, 0, 0}, + {IT_STRING | IT_CVAR, "Auto Ring", "Auto-use rings to maintain momentum.", + NULL, {.cvar = &cv_dummyprofileautoring}, 0, 0}, + {IT_STRING | IT_CVAR, "Kickstart Accel", "Hold A to auto-accel. Tap it to cancel.", NULL, {.cvar = &cv_dummyprofilekickstart}, 0, 0}, diff --git a/src/p_saveg.c b/src/p_saveg.c index bef745fdb..6a54dfb58 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -565,6 +565,7 @@ static void P_NetArchivePlayers(savebuffer_t *save) WRITEUINT8(save->p, players[i].typing_duration); WRITEUINT8(save->p, players[i].kickstartaccel); + WRITEUINT8(save->p, players[i].autoring); WRITEUINT8(save->p, players[i].stairjank); WRITEUINT8(save->p, players[i].topdriftheld); @@ -1166,6 +1167,7 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) players[i].typing_duration = READUINT8(save->p); players[i].kickstartaccel = READUINT8(save->p); + players[i].autoring = READUINT8(save->p); players[i].stairjank = READUINT8(save->p); players[i].topdriftheld = READUINT8(save->p); From a557039ce39ea537038a8706acc615b5d6608924 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 29 Apr 2024 09:57:02 -0400 Subject: [PATCH 02/16] Implement auto-ring use animation Your current follower spits out the rings. Auto ring is in another branch, so it's just always using this currently. --- src/k_kart.c | 19 +++++++++++++++++++ src/p_enemy.c | 23 ++++++++++++++++++----- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 33fc20003..54119254b 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -12649,6 +12649,25 @@ void K_MoveKartPlayer(player_t *player, boolean onground) ring->extravalue2 = 1; // Ring use animation flag ring->shadowscale = 0; P_SetTarget(&ring->target, player->mo); // user + + if (player->follower && !P_MobjWasRemoved(player->follower)) + { + // TODO: only do when using an auto-ring + ring->cusval = player->follower->x - player->mo->x; + ring->cvmem = player->follower->y - player->mo->y; + ring->movefactor = P_GetMobjHead(player->follower) - P_GetMobjHead(player->mo); + } + else + { + ring->cusval = ring->cvmem = ring->movefactor = 0; + } + + // really silly stupid dumb HACK to fix interp + // without needing to duplicate any code + A_AttractChase(ring); + P_SetOrigin(ring, ring->x, ring->y, ring->z); + ring->extravalue1 = 1; + player->rings--; if (player->autoring && !(cmd->buttons & BT_ATTACK)) player->ringdelay = 6; diff --git a/src/p_enemy.c b/src/p_enemy.c index f2f50e8c5..0cfc0d5e5 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3547,13 +3547,26 @@ void A_AttractChase(mobj_t *actor) } else { - fixed_t offz = FixedMul(80*actor->target->scale, FINESINE(FixedAngle((90 - (9 * abs(10 - actor->extravalue1))) << FRACBITS) >> ANGLETOFINESHIFT)); + fixed_t hop = FixedMul( + 80 * actor->target->scale, + FINESINE(FixedAngle((90 - (9 * abs(10 - actor->extravalue1))) << FRACBITS) >> ANGLETOFINESHIFT) + ); + + fixed_t offsFrac = (20 - (actor->extravalue1 - 1)) * FRACUNIT / 20; + fixed_t offsX = FixedMul(actor->cusval, offsFrac); + fixed_t offsY = FixedMul(actor->cvmem, offsFrac); + fixed_t offsZ = FixedMul(actor->movefactor, offsFrac); + //P_SetScale(actor, (actor->destscale = actor->target->scale)); - actor->z = actor->target->z; K_MatchGenericExtraFlags(actor, actor->target); - P_MoveOrigin(actor, actor->target->x, actor->target->y, - actor->z + - ( actor->target->height + offz )* P_MobjFlip(actor)); + + P_MoveOrigin( + actor, + actor->target->x + offsX, + actor->target->y + offsY, + actor->target->z + offsZ + ( actor->target->height + hop ) * P_MobjFlip(actor) + ); + actor->extravalue1++; } } From b610353699decaad09d24583656e33ec6e1c4608 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 29 Apr 2024 10:22:24 -0400 Subject: [PATCH 03/16] Add follower ring animation Add "RingState" and "RingTime" to followers. RingState is the state to use while they're giving you an auto-ring. The animation plays for RingTime tics per-ring, so it can extend to however long they need to use rings. --- src/deh_soc.c | 13 +++++++++++++ src/k_follower.c | 17 ++++++++++++++++- src/k_follower.h | 3 +++ src/k_kart.c | 10 +++++++++- 4 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/deh_soc.c b/src/deh_soc.c index b7ccb9187..d0889e911 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -4152,6 +4152,7 @@ void readfollower(MYFILE *f) followers[numfollowers].bobspeed = TICRATE*2; followers[numfollowers].bobamp = 4*FRACUNIT; followers[numfollowers].hitconfirmtime = TICRATE; + followers[numfollowers].ringtime = 6; followers[numfollowers].defaultcolor = FOLLOWERCOLOR_MATCH; followers[numfollowers].category = UINT8_MAX; followers[numfollowers].hornsound = sfx_horn00; @@ -4329,6 +4330,16 @@ void readfollower(MYFILE *f) { followers[numfollowers].hitconfirmtime = (tic_t)get_number(word2); } + else if (fastcmp(word, "RINGSTATE")) + { + if (word2) + strupr(word2); + followers[numfollowers].ringstate = get_number(word2); + } + else if (fastcmp(word, "RINGTIME")) + { + followers[numfollowers].ringtime = (tic_t)get_number(word2); + } else { deh_warning("Follower %d: unknown word '%s'", numfollowers, word); @@ -4386,6 +4397,7 @@ if ((signed)followers[numfollowers].field < threshold) \ FALLBACK(bobamp, "BOBAMP", 0, 0); FALLBACK(bobspeed, "BOBSPEED", 0, 0); FALLBACK(hitconfirmtime, "HITCONFIRMTIME", 1, 1); + FALLBACK(ringtime, "RINGTIME", 1, 1); FALLBACK(scale, "SCALE", 1, 1); // No null/negative scale FALLBACK(bubblescale, "BUBBLESCALE", 0, 0); // No negative scale @@ -4408,6 +4420,7 @@ if (!followers[numfollowers].field) \ NOSTATE(losestate, "LOSESTATE"); NOSTATE(winstate, "WINSTATE"); NOSTATE(hitconfirmstate, "HITCONFIRMSTATE"); + NOSTATE(ringstate, "RINGSTATE"); #undef NOSTATE if (!followers[numfollowers].hornsound) diff --git a/src/k_follower.c b/src/k_follower.c index 1617c8d45..715c44956 100644 --- a/src/k_follower.c +++ b/src/k_follower.c @@ -537,6 +537,15 @@ void K_HandleFollower(player_t *player) destAngle += ANGLE_180; } + // Using auto-ring, face towards the player while throwing your rings. + if (player->follower->cvmem) + { + destAngle = R_PointToAngle2( + player->follower->x, player->follower->y, + player->mo->x, player->mo->y + ); + } + // Sal: Smoothly rotate angle to the destination value. angleDiff = AngleDeltaSigned(destAngle, player->follower->angle); @@ -628,8 +637,9 @@ void K_HandleFollower(player_t *player) // hurt or dead if (P_PlayerInPain(player) == true || player->mo->state == &states[S_KART_SPINOUT] || player->mo->health <= 0) { - // cancel hit confirm. + // cancel hit confirm / rings player->follower->movecount = 0; + player->follower->cvmem = 0; // spin out player->follower->angle = player->drawangle; @@ -661,6 +671,11 @@ void K_HandleFollower(player_t *player) K_UpdateFollowerState(player->follower, fl->hitconfirmstate, FOLLOWERSTATE_HITCONFIRM); player->follower->movecount--; } + else if (player->follower->cvmem) + { + K_UpdateFollowerState(player->follower, fl->ringstate, FOLLOWERSTATE_RING); + player->follower->cvmem--; + } else if (player->speed > 10*player->mo->scale) // animation for moving fast enough { K_UpdateFollowerState(player->follower, fl->followstate, FOLLOWERSTATE_FOLLOW); diff --git a/src/k_follower.h b/src/k_follower.h index dc3c6cb8b..579532d4a 100644 --- a/src/k_follower.h +++ b/src/k_follower.h @@ -49,6 +49,7 @@ typedef enum FOLLOWERSTATE_WIN, FOLLOWERSTATE_LOSE, FOLLOWERSTATE_HITCONFIRM, // Uses movecount as a timer for how long to play this state. + FOLLOWERSTATE_RING, // Uses cvmem as a timer for how long to play this state. FOLLOWERSTATE__MAX } followerstate_t; @@ -93,6 +94,8 @@ struct follower_t statenum_t losestate; // state when the player has lost statenum_t hitconfirmstate; // state for hit confirm tic_t hitconfirmtime; // time to keep the above playing for + statenum_t ringstate; // state for giving an auto-ring + tic_t ringtime; // time to keep the above playing for sfxenum_t hornsound; // Press (B) to announce you are pressing (B) }; diff --git a/src/k_kart.c b/src/k_kart.c index 54119254b..b57ad6707 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -12650,12 +12650,20 @@ void K_MoveKartPlayer(player_t *player, boolean onground) ring->shadowscale = 0; P_SetTarget(&ring->target, player->mo); // user - if (player->follower && !P_MobjWasRemoved(player->follower)) + if (player->follower != NULL + && P_MobjWasRemoved(player->follower) == false + && player->followerskin >= 0 + && player->followerskin < numfollowers) { // TODO: only do when using an auto-ring + const follower_t *fl = &followers[player->followerskin]; + ring->cusval = player->follower->x - player->mo->x; ring->cvmem = player->follower->y - player->mo->y; ring->movefactor = P_GetMobjHead(player->follower) - P_GetMobjHead(player->mo); + + // cvmem is used to play the ring animation for followers + player->follower->cvmem = fl->ringtime; } else { From 633ffb619530a344d4e86be78ad3c8d4a90f1e1a Mon Sep 17 00:00:00 2001 From: Ashnal Date: Tue, 30 Apr 2024 01:11:45 -0400 Subject: [PATCH 04/16] The one line hookup --- src/k_kart.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index b57ad6707..151a3f16d 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -12650,12 +12650,12 @@ void K_MoveKartPlayer(player_t *player, boolean onground) ring->shadowscale = 0; P_SetTarget(&ring->target, player->mo); // user - if (player->follower != NULL + if (player->autoring + && player->follower != NULL && P_MobjWasRemoved(player->follower) == false && player->followerskin >= 0 && player->followerskin < numfollowers) { - // TODO: only do when using an auto-ring const follower_t *fl = &followers[player->followerskin]; ring->cusval = player->follower->x - player->mo->x; From 500cfa74de299684b7723c9e465399e60d2b6e5a Mon Sep 17 00:00:00 2001 From: Ashnal Date: Tue, 30 Apr 2024 19:54:38 -0400 Subject: [PATCH 05/16] tiered ringdelay for autoring --- src/k_kart.c | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 151a3f16d..b701aec2e 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -12607,25 +12607,36 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (player->itemflags & IF_USERINGS) { // Auto-Ring - boolean autoring; + UINT8 tiereddelay = 5; + player->autoring = false; if ( player->pflags & PF_AUTORING && leveltime > starttime && !(cmd->buttons & BT_BRAKE) && K_GetKartButtons(player) && P_IsObjectOnGround(player->mo) - && ( - player->rings > 18 - && FixedDiv(player->speed * 100, K_GetKartSpeed(player, false, true)) < 100*FRACUNIT - || player->rings > 9 - && FixedDiv(player->speed * 100, K_GetKartSpeed(player, false, true)) < 85*FRACUNIT - ||player->rings > 3 - && FixedDiv(player->speed * 100, K_GetKartSpeed(player, false, true)) < 35*FRACUNIT - ) ) - player->autoring = true; - else - player->autoring = false; + { + fixed_t pspeed = FixedDiv(player->speed * 100, K_GetKartSpeed(player, false, true)); + + if (player->rings >= 18 && pspeed < 100*FRACUNIT) + { + player->autoring = true; + tiereddelay = 3; + } + else if (player->rings >= 10 && pspeed < 85*FRACUNIT) + { + player->autoring = true; + tiereddelay = 4; + } + else if (player->rings >= 4 && pspeed < 35*FRACUNIT) + { + player->autoring = true; + tiereddelay = 5; + } + else + player->autoring = false; + } if (((cmd->buttons & BT_ATTACK) || player->autoring) && !player->ringdelay && player->rings > 0) { @@ -12678,7 +12689,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->rings--; if (player->autoring && !(cmd->buttons & BT_ATTACK)) - player->ringdelay = 6; + player->ringdelay = tiereddelay; else player->ringdelay = 3; } From 947b918c839f4e7c4b0318306a702be726d28209 Mon Sep 17 00:00:00 2001 From: Ashnal Date: Tue, 30 Apr 2024 20:22:15 -0400 Subject: [PATCH 06/16] swap follower angle facing when autoring --- src/k_follower.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/k_follower.c b/src/k_follower.c index 715c44956..09a052025 100644 --- a/src/k_follower.c +++ b/src/k_follower.c @@ -541,8 +541,8 @@ void K_HandleFollower(player_t *player) if (player->follower->cvmem) { destAngle = R_PointToAngle2( - player->follower->x, player->follower->y, - player->mo->x, player->mo->y + player->mo->x, player->mo->y, + player->follower->x, player->follower->y ); } From f85cb8c4005d4e5c7a37af614a25607224620120 Mon Sep 17 00:00:00 2001 From: Ashnal Date: Tue, 30 Apr 2024 21:56:07 -0400 Subject: [PATCH 07/16] Instead 180 from player facing angle --- src/k_follower.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/k_follower.c b/src/k_follower.c index 09a052025..8bdea0d72 100644 --- a/src/k_follower.c +++ b/src/k_follower.c @@ -540,10 +540,7 @@ void K_HandleFollower(player_t *player) // Using auto-ring, face towards the player while throwing your rings. if (player->follower->cvmem) { - destAngle = R_PointToAngle2( - player->mo->x, player->mo->y, - player->follower->x, player->follower->y - ); + destAngle = player->mo->angle + ANGLE_180; } // Sal: Smoothly rotate angle to the destination value. From 3b27feb5330aac6038fecc21591be1827f9413a0 Mon Sep 17 00:00:00 2001 From: Ashnal Date: Thu, 2 May 2024 22:25:54 -0400 Subject: [PATCH 08/16] Fallback follower Ring use animation broken atm --- src/k_follower.c | 19 ++++++++++++++++--- src/k_kart.c | 4 +--- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/k_follower.c b/src/k_follower.c index 8bdea0d72..55f68fba3 100644 --- a/src/k_follower.c +++ b/src/k_follower.c @@ -338,6 +338,8 @@ void K_HandleFollower(player_t *player) angle_t destAngle; INT32 angleDiff; + boolean fallbackfollower; + if (player->followerready == false) { // we aren't ready to perform anything follower related yet. @@ -351,9 +353,14 @@ void K_HandleFollower(player_t *player) player->followerskin = -1; } + if (player->pflags & PF_AUTORING && player->followerskin == -1) + fallbackfollower = true; + else + fallbackfollower = false; + // don't do anything if we can't have a follower to begin with. // (It gets removed under those conditions) - if (player->spectator || player->followerskin < 0 + if (player->spectator || player->followerskin < 0 && !fallbackfollower || player->mo == NULL || P_MobjWasRemoved(player->mo)) { if (player->follower) @@ -364,7 +371,10 @@ void K_HandleFollower(player_t *player) } // Before we do anything, let's be sure of where we're supposed to be - fl = &followers[player->followerskin]; + if (fallbackfollower) + fl = &followers[K_FollowerAvailable("Goddess")]; + else + fl = &followers[player->followerskin]; an = player->mo->angle + fl->atangle; zoffs = fl->zoffs; @@ -417,7 +427,10 @@ void K_HandleFollower(player_t *player) } // Set follower colour - color = K_GetEffectiveFollowerColor(player->followercolor, fl, player->skincolor, &skins[player->skin]); + if (fallbackfollower) + color = fl->defaultcolor; + else + color = K_GetEffectiveFollowerColor(player->followercolor, fl, player->skincolor, &skins[player->skin]); if (player->follower == NULL || P_MobjWasRemoved(player->follower)) // follower doesn't exist / isn't valid { diff --git a/src/k_kart.c b/src/k_kart.c index b701aec2e..595498822 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -12663,9 +12663,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (player->autoring && player->follower != NULL - && P_MobjWasRemoved(player->follower) == false - && player->followerskin >= 0 - && player->followerskin < numfollowers) + && P_MobjWasRemoved(player->follower) == false) { const follower_t *fl = &followers[player->followerskin]; From 4a239e024c555900c79fe167c5d1805ff74c3276 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 2 May 2024 19:53:50 -0700 Subject: [PATCH 09/16] Fix fallback follower --- src/k_follower.c | 2 +- src/k_kart.c | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/k_follower.c b/src/k_follower.c index 55f68fba3..8e5fb1832 100644 --- a/src/k_follower.c +++ b/src/k_follower.c @@ -360,7 +360,7 @@ void K_HandleFollower(player_t *player) // don't do anything if we can't have a follower to begin with. // (It gets removed under those conditions) - if (player->spectator || player->followerskin < 0 && !fallbackfollower + if (player->spectator || (player->followerskin < 0 && !fallbackfollower) || player->mo == NULL || P_MobjWasRemoved(player->mo)) { if (player->follower) diff --git a/src/k_kart.c b/src/k_kart.c index 595498822..db6e35cb1 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -12665,7 +12665,11 @@ void K_MoveKartPlayer(player_t *player, boolean onground) && player->follower != NULL && P_MobjWasRemoved(player->follower) == false) { - const follower_t *fl = &followers[player->followerskin]; + const follower_t *fl = &followers[ + player->followerskin == -1 + ? K_FollowerAvailable("Goddess") + : player->followerskin + ]; ring->cusval = player->follower->x - player->mo->x; ring->cvmem = player->follower->y - player->mo->y; From 489bc151614f74408fc3eae4519584b2a0d18e84 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 2 May 2024 20:18:26 -0700 Subject: [PATCH 10/16] Autoring: set follower to 50% transparency if player cannot use rings --- src/k_follower.c | 7 +++++++ src/k_kart.c | 7 ++++++- src/k_kart.h | 2 ++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/k_follower.c b/src/k_follower.c index 8e5fb1832..618efeedf 100644 --- a/src/k_follower.c +++ b/src/k_follower.c @@ -532,6 +532,13 @@ void K_HandleFollower(player_t *player) { player->follower->renderflags |= RF_DONTDRAW; } + else + { + if ((player->pflags & PF_AUTORING) && !(K_PlayerCanUseItem(player) && (player->itemflags & IF_USERINGS))) + { + player->follower->renderflags |= RF_TRANS50; + } + } // if we're moving let's make the angle the direction we're moving towards. This is to avoid drifting / reverse looking awkward. if (FixedHypot(player->follower->momx, player->follower->momy) >= player->mo->scale) diff --git a/src/k_kart.c b/src/k_kart.c index db6e35cb1..2bd89a293 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -12599,7 +12599,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->instaWhipCharge = min(player->instaWhipCharge, INSTAWHIP_CHARGETIME - 2); } - if (player && player->mo && player->mo->health > 0 && !player->spectator && !P_PlayerInPain(player) && !mapreset && leveltime > introtime) + if (player && player->mo && K_PlayerCanUseItem(player)) { // First, the really specific, finicky items that function without the item being directly in your item slot. { @@ -14481,4 +14481,9 @@ void K_MakeObjectReappear(mobj_t *mo) (!P_MobjWasRemoved(mo->punt_ref) ? mo->punt_ref : mo)->reappear = leveltime + (30*TICRATE); } +boolean K_PlayerCanUseItem(player_t *player) +{ + return (player->mo->health > 0 && !player->spectator && !P_PlayerInPain(player) && !mapreset && leveltime > introtime); +} + //} diff --git a/src/k_kart.h b/src/k_kart.h index 6556138e1..4c67b23df 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -277,6 +277,8 @@ void K_BumperInflate(player_t *player); boolean K_ThunderDome(void); +boolean K_PlayerCanUseItem(player_t *player); + #ifdef __cplusplus } // extern "C" #endif From 009034e848887b51bbb6294bc5c21fcb9df7d458 Mon Sep 17 00:00:00 2001 From: Ashnal Date: Fri, 3 May 2024 20:52:00 -0400 Subject: [PATCH 11/16] Default anim time from 6 to 10 --- src/deh_soc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/deh_soc.c b/src/deh_soc.c index d0889e911..b0e7a473a 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -4152,7 +4152,7 @@ void readfollower(MYFILE *f) followers[numfollowers].bobspeed = TICRATE*2; followers[numfollowers].bobamp = 4*FRACUNIT; followers[numfollowers].hitconfirmtime = TICRATE; - followers[numfollowers].ringtime = 6; + followers[numfollowers].ringtime = 10; followers[numfollowers].defaultcolor = FOLLOWERCOLOR_MATCH; followers[numfollowers].category = UINT8_MAX; followers[numfollowers].hornsound = sfx_horn00; From d1ec829d5fc94e0ad7c739ae2d78a4f232ee75fb Mon Sep 17 00:00:00 2001 From: Ashnal Date: Fri, 3 May 2024 20:52:43 -0400 Subject: [PATCH 12/16] Fix horn and and hitconfirm anim for fallback follower --- src/k_follower.c | 8 ++++++-- src/k_kart.c | 12 ++++++++---- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/k_follower.c b/src/k_follower.c index 618efeedf..1052ec019 100644 --- a/src/k_follower.c +++ b/src/k_follower.c @@ -766,14 +766,18 @@ void K_FollowerHornTaunt(player_t *taunter, player_t *victim, boolean mysticmelo if ( taunter == NULL || victim == NULL - || taunter->followerskin < 0 + || taunter->followerskin < -1 || taunter->followerskin >= numfollowers ) { return; } - const follower_t *fl = &followers[taunter->followerskin]; + follower_t *fl; + if (taunter->followerskin == -1) /// mmm spaghetti + fl = &followers[K_FollowerAvailable("Goddess")]; // special case for checking for fallback follower for autoring + else + fl = &followers[taunter->followerskin]; // Restrict mystic melody special status if (mysticmelodyspecial == true) diff --git a/src/k_kart.c b/src/k_kart.c index 2bd89a293..4f8401935 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2866,10 +2866,15 @@ void K_TryHurtSoundExchange(mobj_t *victim, mobj_t *attacker) attacker->player->confirmVictimDelay = TICRATE/2; if (attacker->player->follower != NULL - && attacker->player->followerskin >= 0 + && attacker->player->followerskin >= -1 && attacker->player->followerskin < numfollowers) { - const follower_t *fl = &followers[attacker->player->followerskin]; + follower_t *fl; + if (attacker->player->followerskin == -1) /// mmm spaghetti + fl = &followers[K_FollowerAvailable("Goddess")]; // special case for checking for fallback follower for autoring + else + fl = &followers[attacker->player->followerskin]; + attacker->player->follower->movecount = fl->hitconfirmtime; // movecount is used to play the hitconfirm animation for followers. } } @@ -12612,8 +12617,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if ( player->pflags & PF_AUTORING && leveltime > starttime - && !(cmd->buttons & BT_BRAKE) - && K_GetKartButtons(player) + && K_GetForwardMove(player) && P_IsObjectOnGround(player->mo) ) { From f1210cec1746f4337ed8521bc7a2c105f2cbb9da Mon Sep 17 00:00:00 2001 From: Ashnal Date: Sat, 4 May 2024 22:50:37 -0400 Subject: [PATCH 13/16] Forwardmove also returns negative values, Oops --- 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 4f8401935..dfc23d61f 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -12617,7 +12617,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if ( player->pflags & PF_AUTORING && leveltime > starttime - && K_GetForwardMove(player) + && K_GetForwardMove(player) > 0 && P_IsObjectOnGround(player->mo) ) { From b79918cee8a543fba0bde5f9edefdd254043a323 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 5 May 2024 01:39:42 -0700 Subject: [PATCH 14/16] jartha review, autoring: fix PF_AUTORING at start of replays --- src/g_demo.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/g_demo.cpp b/src/g_demo.cpp index 13eba5aa3..2e21a7d7e 100644 --- a/src/g_demo.cpp +++ b/src/g_demo.cpp @@ -205,6 +205,7 @@ boolean G_CompatLevel(UINT16 level) #define DEMO_SHRINKME 0x04 #define DEMO_BOT 0x08 #define DEMO_AUTOROULETTE 0x10 +#define DEMO_AUTORING 0x20 // For demos #define ZT_FWD 0x0001 @@ -2310,6 +2311,8 @@ void G_BeginRecording(void) i |= DEMO_KICKSTART; if (player->pflags & PF_AUTOROULETTE) i |= DEMO_AUTOROULETTE; + if (player->pflags & PF_AUTORING) + i |= DEMO_AUTORING; if (player->pflags & PF_SHRINKME) i |= DEMO_SHRINKME; if (player->bot == true) @@ -3383,6 +3386,11 @@ void G_DoPlayDemoEx(const char *defdemoname, lumpnum_t deflumpnum) else players[p].pflags &= ~PF_AUTOROULETTE; + if (flags & DEMO_AUTORING) + players[p].pflags |= PF_AUTORING; + else + players[p].pflags &= ~PF_AUTORING; + if (flags & DEMO_SHRINKME) players[p].pflags |= PF_SHRINKME; else From 78411a25eedac1f863e54aa03e9d60bb9995ae6a Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 5 May 2024 01:44:16 -0700 Subject: [PATCH 15/16] jartha review, autoring: add PF_AUTORING to dehacked table (Lua) --- src/d_player.h | 2 +- src/deh_tables.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index be2e07ee1..893231377 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -109,7 +109,7 @@ typedef enum PF_TRUSTWAYPOINTS = 1<<15, // Do not activate lap cheat prevention next time finish line distance is updated PF_FREEZEWAYPOINTS = 1<<16, // Skip the next waypoint/finish line distance update - PF_AUTORING = 1<<17, // Accessibility: Non-deterministic item box, no manual stop. + PF_AUTORING = 1<<17, // Accessibility: Non-deterministic item box, no manual stop. PF_DRIFTINPUT = 1<<18, // Drifting! PF_GETSPARKS = 1<<19, // Can get sparks diff --git a/src/deh_tables.c b/src/deh_tables.c index 3122a1387..df818c094 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -4066,7 +4066,7 @@ const char *const PLAYERFLAG_LIST[] = { "ANALOGSTICK", // This player is using an analog joystick "TRUSTWAYPOINTS", // Do not activate lap cheat prevention next time finish line distance is updated "FREEZEWAYPOINTS", // Skip the next waypoint/finish line distance update - "\x01", // Free + "AUTORING", // Accessibility: Non-deterministic item box, no manual stop. "DRIFTINPUT", // Drifting! "GETSPARKS", // Can get sparks From 11fce987c00d22085955e01b887b18514dbd0c18 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 5 May 2024 03:02:53 -0700 Subject: [PATCH 16/16] autoring: replace followerskin Goddess cases with K_GetEffectiveFollowerSkin function --- src/k_follower.c | 42 ++++++++++++++++++++++++------------------ src/k_follower.h | 15 +++++++++++++++ src/k_kart.c | 23 +++++++++-------------- 3 files changed, 48 insertions(+), 32 deletions(-) diff --git a/src/k_follower.c b/src/k_follower.c index 1052ec019..dc02685b6 100644 --- a/src/k_follower.c +++ b/src/k_follower.c @@ -338,7 +338,7 @@ void K_HandleFollower(player_t *player) angle_t destAngle; INT32 angleDiff; - boolean fallbackfollower; + INT32 followerskin; if (player->followerready == false) { @@ -353,14 +353,11 @@ void K_HandleFollower(player_t *player) player->followerskin = -1; } - if (player->pflags & PF_AUTORING && player->followerskin == -1) - fallbackfollower = true; - else - fallbackfollower = false; + followerskin = K_GetEffectiveFollowerSkin(player); // don't do anything if we can't have a follower to begin with. // (It gets removed under those conditions) - if (player->spectator || (player->followerskin < 0 && !fallbackfollower) + if (player->spectator || followerskin < 0 || player->mo == NULL || P_MobjWasRemoved(player->mo)) { if (player->follower) @@ -371,10 +368,7 @@ void K_HandleFollower(player_t *player) } // Before we do anything, let's be sure of where we're supposed to be - if (fallbackfollower) - fl = &followers[K_FollowerAvailable("Goddess")]; - else - fl = &followers[player->followerskin]; + fl = &followers[followerskin]; an = player->mo->angle + fl->atangle; zoffs = fl->zoffs; @@ -427,7 +421,7 @@ void K_HandleFollower(player_t *player) } // Set follower colour - if (fallbackfollower) + if (player->followerskin < 0) // using a fallback follower color = fl->defaultcolor; else color = K_GetEffectiveFollowerColor(player->followercolor, fl, player->skincolor, &skins[player->skin]); @@ -762,22 +756,21 @@ void K_HandleFollower(player_t *player) --------------------------------------------------*/ void K_FollowerHornTaunt(player_t *taunter, player_t *victim, boolean mysticmelodyspecial) { + // special case for checking for fallback follower for autoring + const INT32 followerskin = K_GetEffectiveFollowerSkin(taunter); + // Basic checks if ( taunter == NULL || victim == NULL - || taunter->followerskin < -1 - || taunter->followerskin >= numfollowers + || followerskin < 0 + || followerskin >= numfollowers ) { return; } - follower_t *fl; - if (taunter->followerskin == -1) /// mmm spaghetti - fl = &followers[K_FollowerAvailable("Goddess")]; // special case for checking for fallback follower for autoring - else - fl = &followers[taunter->followerskin]; + const follower_t *fl = &followers[followerskin]; // Restrict mystic melody special status if (mysticmelodyspecial == true) @@ -902,3 +895,16 @@ void K_FollowerHornTaunt(player_t *taunter, player_t *victim, boolean mysticmelo } } } + +/*-------------------------------------------------- + INT32 K_GetEffectiveFollowerSkin(const player_t *player); + + See header file for description. +--------------------------------------------------*/ +INT32 K_GetEffectiveFollowerSkin(const player_t *player) +{ + if ((player->pflags & PF_AUTORING) && player->followerskin == -1) + return K_FollowerAvailable("Goddess"); + else + return player->followerskin; +} diff --git a/src/k_follower.h b/src/k_follower.h index 579532d4a..edab92f8e 100644 --- a/src/k_follower.h +++ b/src/k_follower.h @@ -246,6 +246,21 @@ void K_RemoveFollower(player_t *player); void K_FollowerHornTaunt(player_t *taunter, player_t *victim, boolean mysticmelodyspecial); +/*-------------------------------------------------- + INT32 K_GetEffectiveFollowerSkin(const player_t *player) + + Returns the player's follower, set by profile or as + a fallback. + + Input Arguments:- + player - The player. + + Return:- + The resultant skin id for the follower, or -1 for None +--------------------------------------------------*/ + +INT32 K_GetEffectiveFollowerSkin(const player_t *player); + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/k_kart.c b/src/k_kart.c index dfc23d61f..bfd837f24 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2865,16 +2865,12 @@ void K_TryHurtSoundExchange(mobj_t *victim, mobj_t *attacker) attacker->player->confirmVictim = (victim->player - players); attacker->player->confirmVictimDelay = TICRATE/2; + const INT32 followerskin = K_GetEffectiveFollowerSkin(attacker->player); if (attacker->player->follower != NULL - && attacker->player->followerskin >= -1 - && attacker->player->followerskin < numfollowers) + && followerskin >= 0 + && followerskin < numfollowers) { - follower_t *fl; - if (attacker->player->followerskin == -1) /// mmm spaghetti - fl = &followers[K_FollowerAvailable("Goddess")]; // special case for checking for fallback follower for autoring - else - fl = &followers[attacker->player->followerskin]; - + const follower_t *fl = &followers[followerskin]; attacker->player->follower->movecount = fl->hitconfirmtime; // movecount is used to play the hitconfirm animation for followers. } } @@ -12665,15 +12661,14 @@ void K_MoveKartPlayer(player_t *player, boolean onground) ring->shadowscale = 0; P_SetTarget(&ring->target, player->mo); // user + const INT32 followerskin = K_GetEffectiveFollowerSkin(player); if (player->autoring && player->follower != NULL - && P_MobjWasRemoved(player->follower) == false) + && P_MobjWasRemoved(player->follower) == false + && followerskin >= 0 + && followerskin < numfollowers) { - const follower_t *fl = &followers[ - player->followerskin == -1 - ? K_FollowerAvailable("Goddess") - : player->followerskin - ]; + const follower_t *fl = &followers[followerskin]; ring->cusval = player->follower->x - player->mo->x; ring->cvmem = player->follower->y - player->mo->y;