Merge pull request 'Follower horns' (#214) from universally-hated-in-dev into next
Reviewed-on: https://codeberg.org/NepDisk/blankart/pulls/214
This commit is contained in:
commit
16d2789a15
19 changed files with 342 additions and 3 deletions
|
|
@ -437,6 +437,7 @@ static CV_PossibleValue_t kartspeedometer_cons_t[] = {{0, "Off"}, {1, "Kilometer
|
|||
consvar_t cv_kartspeedometer = CVAR_INIT ("kartdisplayspeed", "Percentage", CV_SAVE, kartspeedometer_cons_t, NULL); // use tics in display
|
||||
static CV_PossibleValue_t kartvoices_cons_t[] = {{0, "Never"}, {1, "Tasteful"}, {2, "Meme"}, {0, NULL}};
|
||||
consvar_t cv_kartvoices = CVAR_INIT ("kartvoices", "Tasteful", CV_SAVE, kartvoices_cons_t, NULL);
|
||||
consvar_t cv_karthorns = CVAR_INIT ("taunthorns", "Tasteful", CV_SAVE, kartvoices_cons_t, NULL);
|
||||
|
||||
static CV_PossibleValue_t kartbot_cons_t[] = {
|
||||
{0, "Off"},
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ extern consvar_t cv_kartvoterulechanges;
|
|||
extern consvar_t cv_kartgametypepreference;
|
||||
extern consvar_t cv_kartspeedometer;
|
||||
extern consvar_t cv_kartvoices;
|
||||
extern consvar_t cv_karthorns;
|
||||
extern consvar_t cv_kartbot;
|
||||
extern consvar_t cv_kartbot_cap;
|
||||
extern consvar_t cv_kartbot_modifiermax;
|
||||
|
|
|
|||
|
|
@ -206,6 +206,7 @@ typedef enum
|
|||
khud_tauntvoices, // Used to specifically stop taunt voice spam
|
||||
khud_confirmvictim, // Player ID that you dealt damage to
|
||||
khud_confirmvictimdelay, // Delay before playing the sound
|
||||
khud_taunthorns, // Used to specifically stop taunt horn spam
|
||||
|
||||
// Battle
|
||||
khud_cardanimation, // Used to determine the position of some full-screen Battle Mode graphics
|
||||
|
|
|
|||
|
|
@ -33,8 +33,9 @@ typedef enum
|
|||
BT_FORWARD = 1<<5, // Aim Item Forward
|
||||
BT_BACKWARD = 1<<6, // Aim Item Backward
|
||||
BT_LOOKBACK = 1<<7, // Look Backward
|
||||
BT_HORN = 1<<8, // Honk your (follower's) horn
|
||||
|
||||
// free: 1<<8 to 1<<12
|
||||
// free: 1<<9 to 1<<12
|
||||
|
||||
// Lua garbage
|
||||
BT_CUSTOM1 = 1<<13,
|
||||
|
|
|
|||
|
|
@ -3762,7 +3762,9 @@ void readfollower(MYFILE *f)
|
|||
followers[numfollowers].bobspeed = TICRATE*2;
|
||||
followers[numfollowers].bobamp = 4*FRACUNIT;
|
||||
followers[numfollowers].hitconfirmtime = TICRATE;
|
||||
followers[numfollowers].horntime = TICRATE;
|
||||
followers[numfollowers].defaultcolor = FOLLOWERCOLOR_MATCH;
|
||||
followers[numfollowers].hornsound = sfx_horn00;
|
||||
strcpy(followers[numfollowers].icon, "MISSING");
|
||||
|
||||
do
|
||||
|
|
@ -3829,6 +3831,10 @@ void readfollower(MYFILE *f)
|
|||
followers[numfollowers].defaultcolor = color == MAXSKINCOLORS ? SKINCOLOR_GREEN : color;
|
||||
}
|
||||
}
|
||||
else if (fastcmp(word, "HORNSOUND"))
|
||||
{
|
||||
followers[numfollowers].hornsound = get_number(word2);
|
||||
}
|
||||
else if (fastcmp(word, "SCALE"))
|
||||
{
|
||||
followers[numfollowers].scale = (fixed_t)get_number(word2);
|
||||
|
|
@ -3914,6 +3920,16 @@ void readfollower(MYFILE *f)
|
|||
{
|
||||
followers[numfollowers].hitconfirmtime = (tic_t)get_number(word2);
|
||||
}
|
||||
else if (fastcmp(word, "HORNSTATE"))
|
||||
{
|
||||
if (word2)
|
||||
strupr(word2);
|
||||
followers[numfollowers].hornstate = get_number(word2);
|
||||
}
|
||||
else if (fastcmp(word, "HORNTIME"))
|
||||
{
|
||||
followers[numfollowers].horntime = (tic_t)get_number(word2);
|
||||
}
|
||||
else
|
||||
{
|
||||
deh_warning("Follower %d: unknown word '%s'", numfollowers, word);
|
||||
|
|
@ -3980,6 +3996,7 @@ if ((signed)followers[numfollowers].field < threshold) \
|
|||
FALLBACK(bobamp, "BOBAMP", 0, 0);
|
||||
FALLBACK(bobspeed, "BOBSPEED", 0, 0);
|
||||
FALLBACK(hitconfirmtime, "HITCONFIRMTIME", 1, 1);
|
||||
FALLBACK(horntime, "HORNTIME", 1, 1);
|
||||
FALLBACK(scale, "SCALE", 1, 1); // No null/negative scale
|
||||
FALLBACK(bubblescale, "BUBBLESCALE", 0, 0); // No negative scale
|
||||
|
||||
|
|
@ -4011,6 +4028,7 @@ if (!followers[numfollowers].field) \
|
|||
NOSTATE(losestate, "LOSESTATE");
|
||||
NOSTATE(winstate, "WINSTATE");
|
||||
NOSTATE(hitconfirmstate, "HITCONFIRMSTATE");
|
||||
NOSTATE(hornstate, "HORNSTATE");
|
||||
#undef NOSTATE
|
||||
|
||||
CONS_Printf("Added follower '%s'\n", dname);
|
||||
|
|
|
|||
|
|
@ -1370,6 +1370,7 @@ struct int_const_s const INT_CONST[] = {
|
|||
{"BT_FORWARD",BT_FORWARD},
|
||||
{"BT_BACKWARD",BT_BACKWARD},
|
||||
{"BT_LOOKBACK",BT_LOOKBACK},
|
||||
{"BT_HORN",BT_HORN},
|
||||
{"BT_CUSTOM1",BT_CUSTOM1}, // Lua customizable
|
||||
{"BT_CUSTOM2",BT_CUSTOM2}, // Lua customizable
|
||||
{"BT_CUSTOM3",BT_CUSTOM3}, // Lua customizable
|
||||
|
|
@ -1545,6 +1546,7 @@ struct int_const_s const INT_CONST[] = {
|
|||
{"GC_CUSTOM3",gc_custom3},
|
||||
{"GC_RESPAWN",gc_respawn},
|
||||
{"GC_DIRECTOR",gc_director},
|
||||
{"GC_HORNCODE",gc_horncode},
|
||||
{"NUM_GAMECONTROLS",num_gamecontrols},
|
||||
|
||||
// screen.h constants
|
||||
|
|
|
|||
|
|
@ -924,6 +924,10 @@ const char *blancredits[] = {
|
|||
"\"Chearii\"",
|
||||
"\"hayaunderscore\" aka \"DeltaKanyx\"",
|
||||
"\"Guilmon35249vr\"",
|
||||
"Vivian \"toaster\" Grannell", // Horncode
|
||||
"AJ \"Tyron\" Martinez", // Horncode
|
||||
"\"Superstarxalien\"", // Horncode
|
||||
"\"Freaky Mutant Man\"", // Color profiles menu
|
||||
"",
|
||||
"\1Item Design",
|
||||
"\"NepDisk\"",
|
||||
|
|
@ -937,6 +941,9 @@ const char *blancredits[] = {
|
|||
"\"luna\"",
|
||||
"\"White Mage (guy who picked up controller)\"",
|
||||
"\"minenice\"",
|
||||
"\"StarrydustNova\"",
|
||||
"\"merritt\"",
|
||||
"\"Sunflower\" aka \"AnimeSonic\"",
|
||||
"",
|
||||
"\1New Item Art",
|
||||
"\"Spee\"",
|
||||
|
|
@ -957,9 +964,13 @@ const char *blancredits[] = {
|
|||
"\"Miguelius256\"",
|
||||
"\"Toddoesstuff\"",
|
||||
"\"RetroStation\"",
|
||||
"\"StarrydustNova\"",
|
||||
"\"joshyflip\"",
|
||||
"",
|
||||
"\1New Misc Art",
|
||||
"\"scizor300\"",
|
||||
"\"StarrydustNova\"", // Per some indev talks. Can't reveal the secrets yet!
|
||||
"\"joshyflip\"", // Per some indev talks. Can't reveal the secrets yet!
|
||||
"",
|
||||
"\1Additional Assets",
|
||||
"Sonic Team Jr.",
|
||||
|
|
@ -1030,11 +1041,14 @@ const char *blancredits[] = {
|
|||
"\"PX8916\"",
|
||||
"\"Tom\"",
|
||||
"\"Phoenix\"",
|
||||
"\"StarrydustNova\"",
|
||||
"\"Prada\"",
|
||||
"",
|
||||
"\1Special Thanks",
|
||||
"\"merritt\"",
|
||||
"\"luna\"",
|
||||
"\"Sunflower\" aka \"AnimeSonic\"",
|
||||
"\"StarrydustNova\"",
|
||||
"Sunflower's Garden",
|
||||
"The Moe Mansion and Birdhouse Team",
|
||||
"SRB2Kart Saturn Contributors",
|
||||
|
|
|
|||
|
|
@ -1579,6 +1579,12 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
|||
cmd->buttons |= BT_LOOKBACK;
|
||||
}
|
||||
|
||||
// horn with any button/key
|
||||
if (G_PlayerInputDown(forplayer, gc_horncode, false, DEADZONE_BUTTON))
|
||||
{
|
||||
cmd->buttons |= BT_HORN;
|
||||
}
|
||||
|
||||
// Lua scriptable buttons
|
||||
if (G_PlayerInputDown(forplayer, gc_custom1, false, DEADZONE_BUTTON))
|
||||
cmd->buttons |= BT_CUSTOM1;
|
||||
|
|
|
|||
|
|
@ -154,6 +154,7 @@ INT32 gamecontroldefault[num_gamecontrols][MAXINPUTMAPPING] = {
|
|||
[gc_brake ] = {'d', KEY_JOY1+1 }, // B
|
||||
[gc_fire ] = {KEY_SPACE, KEY_JOY1+9, KEY_AXIS1+8}, // LB, LT
|
||||
[gc_lookback ] = {KEY_LSHIFT, KEY_JOY1+2 }, // X
|
||||
[gc_horncode ] = {'r', KEY_JOY1+8 }, // R-Stick Click
|
||||
|
||||
[gc_pause ] = {KEY_PAUSE, KEY_JOY1+4 }, // Back
|
||||
[gc_systemmenu ] = { KEY_JOY1+6 }, // Start
|
||||
|
|
@ -509,6 +510,7 @@ static const char *gamecontrolname[num_gamecontrols] =
|
|||
"custom3",
|
||||
"respawn",
|
||||
"director",
|
||||
"horncode",
|
||||
};
|
||||
|
||||
#define NUMKEYNAMES (sizeof (keynames)/sizeof (keyname_t))
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ typedef enum
|
|||
gc_custom3, // Lua scriptable
|
||||
gc_respawn,
|
||||
gc_director,
|
||||
gc_horncode,
|
||||
num_gamecontrols
|
||||
} gamecontrols_e;
|
||||
|
||||
|
|
|
|||
|
|
@ -874,3 +874,6 @@ _(RAINBOWDASHRING)
|
|||
// Sneaker Panels
|
||||
_(SNEAKERPANEL)
|
||||
_(SNEAKERPANELSPAWNER)
|
||||
|
||||
// Horncode
|
||||
_(FOLLOWERHORN)
|
||||
|
|
|
|||
|
|
@ -1017,3 +1017,6 @@ _(sysmsg)
|
|||
// Dash Rings
|
||||
_(dashr)
|
||||
_(rainbr)
|
||||
|
||||
// Horncode
|
||||
_(horn00)
|
||||
|
|
|
|||
|
|
@ -656,5 +656,8 @@ _(AWBT)
|
|||
// Recovery Spin Skid
|
||||
_(RCSP)
|
||||
|
||||
// Horncode
|
||||
_(FHRN)
|
||||
|
||||
// First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw later
|
||||
_(VIEW)
|
||||
|
|
|
|||
|
|
@ -3624,3 +3624,7 @@ _(ALTSHRINK_ARROWBULLET)
|
|||
// Recovery Spin Skid
|
||||
_(RECSPIN_SKID)
|
||||
|
||||
// Horncode
|
||||
_(HORNCODE)
|
||||
_(HORNCODE_ANGRY)
|
||||
_(HORNCODE_HAPPY)
|
||||
|
|
|
|||
186
src/k_follower.c
186
src/k_follower.c
|
|
@ -11,6 +11,8 @@
|
|||
#include "r_skins.h"
|
||||
#include "p_local.h"
|
||||
#include "p_mobj.h"
|
||||
#include "s_sound.h"
|
||||
#include "m_cond.h"
|
||||
|
||||
INT32 numfollowers = 0;
|
||||
follower_t followers[MAXSKINS];
|
||||
|
|
@ -243,6 +245,32 @@ static void K_UpdateFollowerState(mobj_t *f, statenum_t state, followerstate_t t
|
|||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static void K_UpdateFollowerMood(mobj_t *f, followermood_t mood, tic_t time)
|
||||
|
||||
Sets a follower object's mood and time before returning to a normal mood.
|
||||
|
||||
Input Arguments:-
|
||||
f - The follower's mobj_t.
|
||||
mood - The mood to set.
|
||||
time - The mood's duration.
|
||||
|
||||
Return:-
|
||||
None
|
||||
--------------------------------------------------*/
|
||||
static void K_UpdateFollowerMood(mobj_t *f, followermood_t mood, tic_t time)
|
||||
{
|
||||
if (f == NULL || P_MobjWasRemoved(f) == true)
|
||||
{
|
||||
// safety net
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
f->extravalue3 = mood;
|
||||
f->cvmem = (INT32)(time);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_HandleFollower(player_t *player)
|
||||
|
||||
|
|
@ -565,12 +593,27 @@ void K_HandleFollower(player_t *player)
|
|||
|
||||
// However with how the code is factored, this is just a special case of S_INVISBLE to avoid having to add other player variables.
|
||||
|
||||
// Mood system
|
||||
// For now, all this does is change the VFX generated when you honk your horn.
|
||||
if (player->follower->cvmem && (player->follower->extravalue3 != FOLLOWERMOOD_NORMAL))
|
||||
{
|
||||
// Tick down the mood timer
|
||||
player->follower->cvmem--;
|
||||
|
||||
// Return to our normal mood
|
||||
if (player->follower->cvmem == 0)
|
||||
{
|
||||
player->follower->extravalue3 = FOLLOWERMOOD_NORMAL;
|
||||
}
|
||||
}
|
||||
|
||||
// handle follower animations. Could probably be better...
|
||||
// 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 / horn
|
||||
player->follower->movecount = 0;
|
||||
player->follower->reactiontime = 0;
|
||||
|
||||
// spin out
|
||||
player->follower->angle = player->drawangle;
|
||||
|
|
@ -582,6 +625,11 @@ void K_HandleFollower(player_t *player)
|
|||
// if dead, follow the player's z momentum exactly so they both look like they die at the same speed.
|
||||
player->follower->momz = player->mo->momz;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not dead; get mad on the player's behalf.
|
||||
K_UpdateFollowerMood(player->follower, FOLLOWERMOOD_ANGRY, (3 * TICRATE / 2));
|
||||
}
|
||||
}
|
||||
else if (player->exiting)
|
||||
{
|
||||
|
|
@ -600,8 +648,14 @@ void K_HandleFollower(player_t *player)
|
|||
else if (player->follower->movecount)
|
||||
{
|
||||
K_UpdateFollowerState(player->follower, fl.hitconfirmstate, FOLLOWERSTATE_HITCONFIRM);
|
||||
K_UpdateFollowerMood(player->follower, FOLLOWERMOOD_HAPPY, (3 * TICRATE / 2));
|
||||
player->follower->movecount--;
|
||||
}
|
||||
else if (player->follower->reactiontime)
|
||||
{
|
||||
K_UpdateFollowerState(player->follower, fl.hornstate, FOLLOWERSTATE_HORN);
|
||||
player->follower->reactiontime--;
|
||||
}
|
||||
else if (player->speed > 10*player->mo->scale) // animation for moving fast enough
|
||||
{
|
||||
K_UpdateFollowerState(player->follower, fl.followstate, FOLLOWERSTATE_FOLLOW);
|
||||
|
|
@ -610,5 +664,135 @@ void K_HandleFollower(player_t *player)
|
|||
{
|
||||
K_UpdateFollowerState(player->follower, fl.idlestate, FOLLOWERSTATE_IDLE);
|
||||
}
|
||||
|
||||
// Horncode
|
||||
if (P_MobjWasRemoved(player->follower->hprev) == false)
|
||||
{
|
||||
mobj_t *honk = player->follower->hprev;
|
||||
|
||||
honk->flags2 &= ~MF2_AMBUSH;
|
||||
|
||||
honk->color = player->skincolor;
|
||||
|
||||
P_MoveOrigin(
|
||||
honk,
|
||||
player->follower->x,
|
||||
player->follower->y,
|
||||
player->follower->z + player->follower->height
|
||||
);
|
||||
|
||||
K_FlipFromObject(honk, player->follower);
|
||||
|
||||
honk->angle = R_PointToAngle2(
|
||||
player->mo->x,
|
||||
player->mo->y,
|
||||
player->follower->x,
|
||||
player->follower->y
|
||||
);
|
||||
|
||||
honk->destscale = (2*player->mo->scale)/3;
|
||||
|
||||
fixed_t offsetamount = 0;
|
||||
if (honk->fuse > 1)
|
||||
{
|
||||
offsetamount = (honk->fuse-1)*honk->destscale/2;
|
||||
if (leveltime & 1)
|
||||
offsetamount = -offsetamount;
|
||||
}
|
||||
else if (S_SoundPlaying(honk, fl.hornsound))
|
||||
{
|
||||
honk->fuse++;
|
||||
}
|
||||
|
||||
honk->sprxoff = P_ReturnThrustX(honk, honk->angle, offsetamount);
|
||||
honk->spryoff = P_ReturnThrustY(honk, honk->angle, offsetamount);
|
||||
honk->sprzoff = -honk->sprxoff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_FollowerHornTaunt(player_t *taunter, player_t *victim)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
void K_FollowerHornTaunt(player_t *taunter, player_t *victim)
|
||||
{
|
||||
if (
|
||||
(cv_karthorns.value == 0)
|
||||
|| taunter == NULL
|
||||
|| victim == NULL
|
||||
|| taunter->followerskin < 0
|
||||
|| taunter->followerskin >= numfollowers
|
||||
|| (P_IsLocalPlayer(victim) == false && cv_karthorns.value != 2)
|
||||
|| P_MobjWasRemoved(taunter->mo) == true
|
||||
|| P_MobjWasRemoved(taunter->follower) == true
|
||||
)
|
||||
return;
|
||||
|
||||
const follower_t *fl = &followers[taunter->followerskin];
|
||||
|
||||
const boolean tasteful = (taunter->karthud[khud_taunthorns] == 0);
|
||||
|
||||
if (tasteful || cv_karthorns.value == 2)
|
||||
{
|
||||
mobj_t *honk = taunter->follower->hprev;
|
||||
const fixed_t desiredscale = (2*taunter->mo->scale)/3;
|
||||
|
||||
if (P_MobjWasRemoved(honk) == true)
|
||||
{
|
||||
honk = P_SpawnMobj(
|
||||
taunter->follower->x,
|
||||
taunter->follower->y,
|
||||
taunter->follower->z + taunter->follower->height,
|
||||
MT_FOLLOWERHORN
|
||||
);
|
||||
|
||||
if (P_MobjWasRemoved(honk) == true)
|
||||
return; // Permit lua override of horn production
|
||||
|
||||
// Set the horn icon based on the follower's mood.
|
||||
switch (taunter->follower->extravalue3)
|
||||
{
|
||||
case FOLLOWERMOOD_ANGRY:
|
||||
P_SetMobjState(honk, S_HORNCODE_ANGRY);
|
||||
break;
|
||||
case FOLLOWERMOOD_HAPPY:
|
||||
P_SetMobjState(honk, S_HORNCODE_HAPPY);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
P_SetTarget(&taunter->follower->hprev, honk);
|
||||
P_SetTarget(&honk->target, taunter->follower);
|
||||
|
||||
K_FlipFromObject(honk, taunter->follower);
|
||||
|
||||
honk->color = taunter->skincolor;
|
||||
|
||||
honk->angle = honk->old_angle = R_PointToAngle2(
|
||||
taunter->mo->x,
|
||||
taunter->mo->y,
|
||||
taunter->follower->x,
|
||||
taunter->follower->y
|
||||
);
|
||||
}
|
||||
|
||||
// Only do for the first activation this tic.
|
||||
if (!(honk->flags2 & MF2_AMBUSH))
|
||||
{
|
||||
honk->destscale = desiredscale;
|
||||
|
||||
P_SetScale(honk, (11*desiredscale)/10);
|
||||
honk->fuse = TICRATE/2;
|
||||
honk->renderflags |= RF_DONTDRAW;
|
||||
taunter->follower->reactiontime = fl->horntime; // reactiontime is used to play the horn animation for followers.
|
||||
|
||||
S_StartSound(taunter->follower, fl->hornsound);
|
||||
|
||||
honk->flags2 |= MF2_AMBUSH;
|
||||
}
|
||||
|
||||
honk->renderflags &= ~K_GetPlayerDontDrawFlag(victim);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,9 +45,18 @@ typedef enum
|
|||
FOLLOWERSTATE_WIN,
|
||||
FOLLOWERSTATE_LOSE,
|
||||
FOLLOWERSTATE_HITCONFIRM, // Uses movecount as a timer for how long to play this state.
|
||||
FOLLOWERSTATE_HORN, // Uses reactiontime as a timer for how long to play this state.
|
||||
FOLLOWERSTATE__MAX
|
||||
} followerstate_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
FOLLOWERMOOD_NORMAL, // Default mood, produces a ++ symbol when you honk.
|
||||
FOLLOWERMOOD_HAPPY, // Happy mood (recent hitconfirm, won race), produces a ♪ symbol when you honk.
|
||||
FOLLOWERMOOD_ANGRY, // Angry/upset mood (taking damage, recently took damage), produces a 💢 symbol when you honk.
|
||||
FOLLOWERMOOD__MAX
|
||||
} followermood_t;
|
||||
|
||||
//
|
||||
// We'll define these here because they're really just a mobj that'll follow some rules behind a player
|
||||
//
|
||||
|
|
@ -89,6 +98,10 @@ 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 hornstate; // state for pressing horn
|
||||
tic_t horntime; // time to keep the above playing for
|
||||
|
||||
sfxenum_t hornsound; // Press (B) to announce you are pressing (B)
|
||||
};
|
||||
|
||||
extern INT32 numfollowers;
|
||||
|
|
@ -179,6 +192,21 @@ UINT16 K_GetEffectiveFollowerColor(UINT16 followercolor, follower_t *follower, U
|
|||
|
||||
void K_HandleFollower(player_t *player);
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_FollowerHornTaunt(player_t *taunter, player_t *victim)
|
||||
|
||||
Plays horn and spawns object (MOSTLY non-netsynced)
|
||||
|
||||
Input Arguments:-
|
||||
taunter - Source player with a follower
|
||||
victim - Player that hears and sees the honk
|
||||
|
||||
Return:-
|
||||
None
|
||||
--------------------------------------------------*/
|
||||
|
||||
void K_FollowerHornTaunt(player_t *taunter, player_t *victim);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
|
|
|||
50
src/k_kart.c
50
src/k_kart.c
|
|
@ -246,6 +246,7 @@ void K_RegisterKartStuff(void)
|
|||
CV_RegisterVar(&cv_kartspeedometer);
|
||||
CV_RegisterVar(&cv_kartvoices);
|
||||
CV_RegisterVar(&cv_karthitemdialog);
|
||||
CV_RegisterVar(&cv_karthorns);
|
||||
CV_RegisterVar(&cv_kartbot);
|
||||
CV_RegisterVar(&cv_kartbot_cap);
|
||||
CV_RegisterVar(&cv_kartbot_modifiermax);
|
||||
|
|
@ -1541,6 +1542,44 @@ void K_SpawnBumpEffect(mobj_t *mo)
|
|||
S_StartSound(mo, sfx_s3k49);
|
||||
}
|
||||
|
||||
static void K_HonkFollowerHorn(player_t *honkPlayer)
|
||||
{
|
||||
const boolean tasteful = (honkPlayer->karthud[khud_taunthorns] == 0);
|
||||
|
||||
UINT8 i;
|
||||
|
||||
// Loop through all players and make them hear your honking!
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
player_t *p;
|
||||
|
||||
if (!playeringame[i])
|
||||
{
|
||||
// Invalid player
|
||||
continue;
|
||||
}
|
||||
|
||||
p = &players[i];
|
||||
|
||||
if (!p->mo || P_MobjWasRemoved(p->mo))
|
||||
{
|
||||
// Invalid mobj
|
||||
continue;
|
||||
}
|
||||
|
||||
if (p->spectator)
|
||||
{
|
||||
// Not playing
|
||||
continue;
|
||||
}
|
||||
|
||||
K_FollowerHornTaunt(honkPlayer, p);
|
||||
}
|
||||
|
||||
if (tasteful && honkPlayer->karthud[khud_taunthorns] < 2*TICRATE)
|
||||
honkPlayer->karthud[khud_taunthorns] = 2*TICRATE;
|
||||
}
|
||||
|
||||
static SINT8 K_GlanceAtPlayers(player_t *glancePlayer)
|
||||
{
|
||||
const fixed_t maxdistance = FixedMul(1280 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed));
|
||||
|
|
@ -6400,6 +6439,9 @@ void K_KartPlayerHUDUpdate(player_t *player)
|
|||
if (player->karthud[khud_tauntvoices])
|
||||
player->karthud[khud_tauntvoices]--;
|
||||
|
||||
if (player->karthud[khud_taunthorns])
|
||||
player->karthud[khud_taunthorns]--;
|
||||
|
||||
if (gametyperules & GTR_RINGS)
|
||||
{
|
||||
if ((K_RingsActive() == true))
|
||||
|
|
@ -7689,6 +7731,14 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
|
|||
// Do a funny hop!
|
||||
K_QuiteSaltyHop(player);
|
||||
|
||||
// Honk your horn. Beep beep!
|
||||
const boolean honking = ((cmd->buttons & BT_HORN) == BT_HORN);
|
||||
|
||||
if (honking)
|
||||
{
|
||||
K_HonkFollowerHorn(player);
|
||||
}
|
||||
|
||||
player->prevonground = P_IsObjectOnGround(player->mo);
|
||||
|
||||
// Update SPB timer...
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ enum follower {
|
|||
follower_anglelag,
|
||||
follower_bobamp,
|
||||
follower_bobspeed,
|
||||
follower_hornsound,
|
||||
// states
|
||||
follower_idlestate,
|
||||
follower_followstate,
|
||||
|
|
@ -43,6 +44,8 @@ enum follower {
|
|||
follower_losestate,
|
||||
follower_hitconfirmstate,
|
||||
follower_hitconfirmtime,
|
||||
follower_hornstate,
|
||||
follower_horntime,
|
||||
//
|
||||
};
|
||||
static const char *const follower_opt[] = {
|
||||
|
|
@ -61,6 +64,7 @@ static const char *const follower_opt[] = {
|
|||
"anglelag",
|
||||
"bobamp",
|
||||
"bobspeed",
|
||||
"hornsound",
|
||||
// states
|
||||
"idlestate",
|
||||
"followstate",
|
||||
|
|
@ -69,6 +73,8 @@ static const char *const follower_opt[] = {
|
|||
"losestate",
|
||||
"hitconfirmstate",
|
||||
"hitconfirmtime",
|
||||
"hornstate",
|
||||
"horntime",
|
||||
//
|
||||
NULL
|
||||
};
|
||||
|
|
@ -130,6 +136,9 @@ static int follower_get(lua_State *L)
|
|||
case follower_bobspeed:
|
||||
lua_pushinteger(L, follower->bobspeed);
|
||||
break;
|
||||
case follower_hornsound:
|
||||
lua_pushinteger(L, follower->hornsound);
|
||||
break;
|
||||
case follower_idlestate:
|
||||
lua_pushinteger(L, follower->idlestate);
|
||||
break;
|
||||
|
|
@ -151,6 +160,12 @@ static int follower_get(lua_State *L)
|
|||
case follower_hitconfirmtime:
|
||||
lua_pushinteger(L, follower->hitconfirmtime);
|
||||
break;
|
||||
case follower_hornstate:
|
||||
lua_pushinteger(L, follower->hornstate);
|
||||
break;
|
||||
case follower_horntime:
|
||||
lua_pushinteger(L, follower->horntime);
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4499,7 +4499,9 @@ void P_SaveNetGame(savebuffer_t *save, boolean resending)
|
|||
mobj = (mobj_t *)th;
|
||||
if (UNLIKELY(mobj->type == MT_HOOP || mobj->type == MT_HOOPCOLLIDE || mobj->type == MT_HOOPCENTER
|
||||
// MT_SPARK: used for debug stuff
|
||||
|| mobj->type == MT_SPARK || mobj->flags2 & MF2_DONTSYNC))
|
||||
|| mobj->type == MT_SPARK
|
||||
// MT_FOLLOWERHORN: So it turns out hornmod is fundamentally incompatible with netsync
|
||||
|| mobj->type == MT_FOLLOWERHORN || mobj->flags2 & MF2_DONTSYNC))
|
||||
continue;
|
||||
mobj->mobjnum = i++;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue