Merge branch 'autoring' into 'master'

Auto-Ring

See merge request KartKrew/Kart!2351
This commit is contained in:
Oni 2024-05-05 12:35:50 +00:00
commit 873d16e6c0
22 changed files with 241 additions and 22 deletions

View file

@ -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(),

View file

@ -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

View file

@ -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;

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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));

View file

@ -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];

View file

@ -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;
}

View file

@ -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

View file

@ -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)

View file

@ -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];

View file

@ -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);
}
//}

View file

@ -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

View file

@ -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;

View file

@ -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);

View file

@ -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

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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},

View file

@ -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++;
}
}

View file

@ -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);