Horncode
A much more focused replacement for Hornmod, specc'd out by Tyron and Oni working together and implemented by the author of this commit because it's pretty funny.
- Followers have `hornsound` in their SOC configuration.
- The default sound for all followers without a provided one is sfx_horn00.
- They'll play this sound if you use lookback with one following you, and there's nearby players to get the player looking all the way around.
- Only the players who are successfully considered for lookback will hear it.
- Has a v1-like visual with less randomisation, but still netsynced.
- Also controlled by the cvar `taunthorns`, which, like `tauntvoices`, takes "Tasteful" (default), "Meme", and "Off".
TODO: make the condition for horn a little delayed, so you have to hold lookback for a little bit.
This commit is contained in:
parent
2c08cf3301
commit
21849ef1ce
12 changed files with 184 additions and 4 deletions
|
|
@ -436,7 +436,8 @@ consvar_t cv_kartgametypepreference = CVAR_INIT ("kartgametypepreference", "None
|
|||
static CV_PossibleValue_t kartspeedometer_cons_t[] = {{0, "Off"}, {1, "Kilometers"}, {2, "Miles"}, {3, "Fracunits"}, {4, "Percentage"}, {0, NULL}};
|
||||
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_kartvoices = CVAR_INIT ("tauntvoices", "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
|
||||
|
|
|
|||
|
|
@ -3763,6 +3763,7 @@ void readfollower(MYFILE *f)
|
|||
followers[numfollowers].bobamp = 4*FRACUNIT;
|
||||
followers[numfollowers].hitconfirmtime = TICRATE;
|
||||
followers[numfollowers].defaultcolor = FOLLOWERCOLOR_MATCH;
|
||||
followers[numfollowers].hornsound = sfx_horn00;
|
||||
strcpy(followers[numfollowers].icon, "MISSING");
|
||||
|
||||
do
|
||||
|
|
@ -3829,6 +3830,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);
|
||||
|
|
|
|||
|
|
@ -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,5 @@ _(ALTSHRINK_ARROWBULLET)
|
|||
// Recovery Spin Skid
|
||||
_(RECSPIN_SKID)
|
||||
|
||||
// Horncode
|
||||
_(HORNCODE)
|
||||
|
|
|
|||
122
src/k_follower.c
122
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];
|
||||
|
|
@ -610,5 +612,125 @@ 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
|
||||
);
|
||||
|
||||
// TODO (yama): Honk icons based on a follower's "emotion"
|
||||
// (♪ for hitconfirm honks, 💢 for mid-damage honks)
|
||||
|
||||
if (P_MobjWasRemoved(honk) == true)
|
||||
return; // Permit lua override of horn production
|
||||
|
||||
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;
|
||||
|
||||
S_StartSound(taunter->follower, fl->hornsound);
|
||||
|
||||
honk->flags2 |= MF2_AMBUSH;
|
||||
}
|
||||
|
||||
honk->renderflags &= ~K_GetPlayerDontDrawFlag(victim);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,6 +89,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
|
||||
|
||||
sfxenum_t hornsound; // Press (B) to announce you are pressing (B)
|
||||
};
|
||||
|
||||
extern INT32 numfollowers;
|
||||
|
|
@ -179,6 +181,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
|
||||
|
|
|
|||
24
src/k_kart.c
24
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,7 +1542,7 @@ void K_SpawnBumpEffect(mobj_t *mo)
|
|||
S_StartSound(mo, sfx_s3k49);
|
||||
}
|
||||
|
||||
static SINT8 K_GlanceAtPlayers(player_t *glancePlayer)
|
||||
static SINT8 K_GlanceAtPlayers(player_t *glancePlayer, boolean horn)
|
||||
{
|
||||
const fixed_t maxdistance = FixedMul(1280 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed));
|
||||
const angle_t blindSpotSize = ANG10; // ANG5
|
||||
|
|
@ -1623,9 +1624,24 @@ static SINT8 K_GlanceAtPlayers(player_t *glancePlayer)
|
|||
// That poses a limitation if there's an equal number of targets on both sides...
|
||||
// In that case, we'll pick the last chosen glance direction.
|
||||
lastValidGlance = dir;
|
||||
|
||||
if (horn == true)
|
||||
{
|
||||
K_FollowerHornTaunt(glancePlayer, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (horn == true && lastValidGlance != 0)
|
||||
{
|
||||
const boolean tasteful = (glancePlayer->karthud[khud_taunthorns] == 0);
|
||||
|
||||
K_FollowerHornTaunt(glancePlayer, glancePlayer);
|
||||
|
||||
if (tasteful && glancePlayer->karthud[khud_taunthorns] < 2*TICRATE)
|
||||
glancePlayer->karthud[khud_taunthorns] = 2*TICRATE;
|
||||
}
|
||||
|
||||
if (glanceDir > 0)
|
||||
{
|
||||
return 1;
|
||||
|
|
@ -1783,7 +1799,8 @@ void K_KartMoveAnimation(player_t *player)
|
|||
{
|
||||
// Only try glancing if you're driving straight.
|
||||
// This avoids all-players loops when we don't need it.
|
||||
destGlanceDir = K_GlanceAtPlayers(player);
|
||||
const boolean horn = lookback && !(player->pflags & PF_GAINAX);
|
||||
destGlanceDir = K_GlanceAtPlayers(player, horn);
|
||||
|
||||
if (lookback == true)
|
||||
{
|
||||
|
|
@ -6400,6 +6417,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))
|
||||
|
|
|
|||
|
|
@ -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