diff --git a/src/cvars.cpp b/src/cvars.cpp index 5eb4c6a0be1d6d7cb6837b9e65af172877a91ba2..85085e14739497919ddf91870cdda9b2e2906da0 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 5853e7936beecb3f530ba9aaafd5a0d63914a265..d887aaf733d57ac627f50411e4de11668b300eaa 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 c17b8d48d62a662b32494117e77fa65c84f130bd..8932313776f4578afa8bc8edcfc1d91461eeef99 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/deh_soc.c b/src/deh_soc.c index b7ccb9187ca86c1c94487c88850b501ca2717331..b0e7a473a9181fab7b712459bbf82c989d34fc5c 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 = 10; 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/deh_tables.c b/src/deh_tables.c index 3122a1387164220fab70e8e5b5ea402342ec12a9..df818c09456301efb412c9a7aebc7fbc2cd73a8c 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 diff --git a/src/g_demo.cpp b/src/g_demo.cpp index 13eba5aa308a4b5e8569597ec04fa6ca839ed09d..2e21a7d7ed5839d7f5d96c057fef29ffc922be98 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 diff --git a/src/g_game.c b/src/g_game.c index c9fdfc91f5767564ac466f869ce2f643c083cd93..04daab555d5563e888d71b2cd930e3f93861c9fc 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 335294950c7459944d96887b5343389094691217..ff49c49b47628eb2363b885a9914a270665dfbea 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_follower.c b/src/k_follower.c index 1617c8d456a792a2877784ae7caff8c1f9cb5bed..dc02685b6f7b109855f25fa31e690ee337e1f402 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; + INT32 followerskin; + if (player->followerready == false) { // we aren't ready to perform anything follower related yet. @@ -351,9 +353,11 @@ void K_HandleFollower(player_t *player) player->followerskin = -1; } + 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 + if (player->spectator || followerskin < 0 || player->mo == NULL || P_MobjWasRemoved(player->mo)) { if (player->follower) @@ -364,7 +368,7 @@ 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]; + fl = &followers[followerskin]; an = player->mo->angle + fl->atangle; zoffs = fl->zoffs; @@ -417,7 +421,10 @@ void K_HandleFollower(player_t *player) } // Set follower colour - color = K_GetEffectiveFollowerColor(player->followercolor, fl, player->skincolor, &skins[player->skin]); + if (player->followerskin < 0) // using a fallback follower + 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 { @@ -519,6 +526,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) @@ -537,6 +551,12 @@ 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 = player->mo->angle + ANGLE_180; + } + // Sal: Smoothly rotate angle to the destination value. angleDiff = AngleDeltaSigned(destAngle, player->follower->angle); @@ -628,8 +648,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 +682,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); @@ -730,18 +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 < 0 - || taunter->followerskin >= numfollowers + || followerskin < 0 + || followerskin >= numfollowers ) { return; } - const follower_t *fl = &followers[taunter->followerskin]; + const follower_t *fl = &followers[followerskin]; // Restrict mystic melody special status if (mysticmelodyspecial == true) @@ -866,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 dc3c6cb8b8ab936b7d07c52605b13009a31f145d..edab92f8ef4d680296021120365db685fa651366 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) }; @@ -243,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_hud.cpp b/src/k_hud.cpp index 4aa19ac05746bd18ac28c3d557812da9e33adf7a..cc03a30e7a4b76b78032c764a31a5080a9276f6d 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 a4e92c728258aa0ef21eac12d045a61226bbc174..07cea47742a470d84e60462f85f285a3022a607b 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 9c71770bab3ab03575e09471d26f184326cc66d3..bfd837f240fddbf49826f65fbc558cce30c153b2 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2865,11 +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 >= 0 - && attacker->player->followerskin < numfollowers) + && followerskin >= 0 + && followerskin < numfollowers) { - const follower_t *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. } } @@ -12599,14 +12600,45 @@ 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. { // Ring boosting if (player->itemflags & IF_USERINGS) { - if ((cmd->buttons & BT_ATTACK) && !player->ringdelay && player->rings > 0) + // Auto-Ring + UINT8 tiereddelay = 5; + player->autoring = false; + if ( + player->pflags & PF_AUTORING + && leveltime > starttime + && K_GetForwardMove(player) > 0 + && P_IsObjectOnGround(player->mo) + ) + { + 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) { mobj_t *ring = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_RING); P_SetMobjState(ring, S_FASTRING1); @@ -12628,9 +12660,41 @@ 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 + + const INT32 followerskin = K_GetEffectiveFollowerSkin(player); + if (player->autoring + && player->follower != NULL + && P_MobjWasRemoved(player->follower) == false + && followerskin >= 0 + && followerskin < numfollowers) + { + const follower_t *fl = &followers[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 + { + 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--; - player->ringdelay = 3; + if (player->autoring && !(cmd->buttons & BT_ATTACK)) + player->ringdelay = tiereddelay; + else + player->ringdelay = 3; } + } // Other items else @@ -14416,4 +14480,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 6556138e16969aa88d669b7d17d823ac5b64888b..4c67b23df53206d4d22498b90f094b19e79ee06c 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 diff --git a/src/k_menu.h b/src/k_menu.h index feb465404d7fb0db16dca8957b4e98b91feb6da3..643170b627c7447347fd0c49d9e7ae767bb463e5 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 1076cfc7814c8443eec00c0f8768bd5cede1bbea..3491d70fc2256da62b53fd1e7edf8d52cea44518 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 70d3abd6899016a52a88acff02e2c2089f1ac45c..247a08e9ffe440f6531b31bed5eb7f84561d81ea 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 be2584e63f7acdfc93bf9b40057134f090ab0428..e7c31449c8e5f337de30c7f26091e2b97a6fcd55 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 9599ae456da90c7f6f290315c195933446ad13cb..93d44049a8eb27da002626442632194e218d47f4 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 9a236dae8bc614896ba7dd51c8a775aa64f3a618..14dd0643d1d4bfd8fb68cc1ef7bf1ab26fb917a8 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_enemy.c b/src/p_enemy.c index f2f50e8c5083346d9d8d5dc4f7ecb4ebbcae10b6..0cfc0d5e57a8c8e51b20cca0cee178f6ca786001 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++; } } diff --git a/src/p_saveg.c b/src/p_saveg.c index bef745fdbdb696ea41341e140b6338e6bc20a383..6a54dfb58a2a2de081be9a1d2ac39813f7f43c06 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);