Improve quake effects

- Quake epicenter + radius now work.
- Since quake epicenter works, removed the display player check on all of the quakes, so other players can feel them.
- Multiple quake effects are stored in a linked list and dynamically created/freed, so they can stack together.
- Made in china
- Made the quake effects only work on the z axis.
- Quakes now alternate their intensity and dampen it over time, instead of randomly picking values.
- Added quake effects for offroad and stair-jank
- Disabled quakes in reducevfx
- Removed actionmovie and windowquake (sorry jartha)
This commit is contained in:
Sally Coolatta 2023-05-01 14:10:28 -04:00
parent a08a23101c
commit 60e80d876d
16 changed files with 305 additions and 153 deletions

View file

@ -331,16 +331,22 @@ struct mappoint_t
fixed_t x, y, z;
};
extern struct quake
struct quake_t
{
// camera offsets and duration
fixed_t x,y,z;
UINT16 time;
tic_t time, startTime;
fixed_t intensity;
// location, radius, and intensity...
// optional intensity modulation based on position
fixed_t radius;
mappoint_t *epicenter;
fixed_t radius, intensity;
} quake;
mobj_t *mobj;
// linked list
quake_t *next;
quake_t *prev;
};
extern quake_t *g_quakes;
// Custom Lua values
struct customoption_t

View file

@ -193,7 +193,7 @@ mobj_t *blueflag;
mapthing_t *rflagpoint;
mapthing_t *bflagpoint;
struct quake quake;
quake_t *g_quakes = NULL;
// Map Header Information
mapheader_t** mapheaderinfo = {NULL};

View file

@ -3781,9 +3781,7 @@ void K_TumblePlayer(player_t *player, mobj_t *inflictor, mobj_t *source)
player->mo->momz = K_TumbleZ(player->mo, player->tumbleHeight * FRACUNIT);
P_SetPlayerMobjState(player->mo, S_KART_SPINOUT);
if (P_IsDisplayPlayer(player))
P_StartQuake(64<<FRACBITS, 10);
P_StartQuakeFromMobj(10, 64 * player->mo->scale, 512 * player->mo->scale, player->mo);
}
angle_t K_StumbleSlope(angle_t angle, angle_t pitch, angle_t roll)
@ -3822,9 +3820,7 @@ void K_StumblePlayer(player_t *player)
player->mo->momz = K_TumbleZ(player->mo, player->tumbleHeight * FRACUNIT);
P_SetPlayerMobjState(player->mo, S_KART_SPINOUT);
if (P_IsDisplayPlayer(player))
P_StartQuake(64<<FRACBITS, 10);
P_StartQuakeFromMobj(10, 64 * player->mo->scale, 512 * player->mo->scale, player->mo);
// Reset slope.
player->mo->pitch = player->mo->roll = 0;
@ -4158,8 +4154,11 @@ static void K_HandleTumbleBounce(player_t *player)
// This gives a window for DI!!
K_AddHitLag(player->mo, 3, true);
if (P_IsDisplayPlayer(player) && player->tumbleHeight >= 40)
P_StartQuake((player->tumbleHeight*3/2)<<FRACBITS, 6); // funny earthquakes for the FEEL
if (player->tumbleHeight >= 40)
{
// funny earthquakes for the FEEL
P_StartQuakeFromMobj(6, (player->tumbleHeight * 3 * player->mo->scale) / 2, 512 * player->mo->scale, player->mo);
}
S_StartSound(player->mo, (player->tumbleHeight < 40) ? sfx_s3k5d : sfx_s3k5f); // s3k5d is bounce < 50, s3k5f otherwise!
@ -4288,9 +4287,7 @@ INT32 K_ExplodePlayer(player_t *player, mobj_t *inflictor, mobj_t *source) // A
player->mo->momz = (117 * player->mo->momz) / 200;
P_SetPlayerMobjState(player->mo, S_KART_SPINOUT);
if (P_IsDisplayPlayer(player))
P_StartQuake(64<<FRACBITS, 5);
P_StartQuakeFromMobj(5, 64 * player->mo->scale, 512 * player->mo->scale, player->mo);
return ringburst;
}
@ -4388,24 +4385,25 @@ void K_MineFlashScreen(mobj_t *source)
player_t *p;
S_StartSound(source, sfx_s3k4e);
P_StartQuakeFromMobj(12, 55 * source->scale, MINEQUAKEDIST * source->scale, source);
// check for potential display players near the source so we can have a sick earthquake / flashpal.
// check for potential display players near the source so we can have a sick flashpal.
for (pnum = 0; pnum < MAXPLAYERS; pnum++)
{
p = &players[pnum];
if (!playeringame[pnum] || !P_IsDisplayPlayer(p))
continue;
if (R_PointToDist2(p->mo->x, p->mo->y, source->x, source->y) < mapobjectscale*MINEQUAKEDIST)
{
P_StartQuake(55<<FRACBITS, 12);
continue;
}
if (R_PointToDist2(p->mo->x, p->mo->y, source->x, source->y) < source->scale * MINEQUAKEDIST)
{
if (!bombflashtimer && P_CheckSight(p->mo, source))
{
bombflashtimer = TICRATE*2;
P_FlashPal(p, PAL_WHITE, 1);
}
break; // we can break right now because quakes are global to all split players somehow.
}
}
}

View file

@ -2084,64 +2084,72 @@ static int lib_pSetSkyboxMobj(lua_State *L)
// Shhh, neither does P_StartQuake.
static int lib_pStartQuake(lua_State *L)
{
fixed_t q_intensity = luaL_checkinteger(L, 1);
UINT16 q_time = (UINT16)luaL_checkinteger(L, 2);
tic_t q_time = (tic_t)luaL_checkinteger(L, 1);
fixed_t q_intensity = luaL_checkfixed(L, 2);
fixed_t q_radius = luaL_optinteger(L, 3, 512*FRACUNIT);
static mappoint_t q_epicenter = {0,0,0};
boolean q_epicenter_set = false;
NOHUD
INLEVEL
// While technically we don't support epicenter and radius,
// we get their values anyway if they exist.
// This way when support is added we won't have to change anything.
if (!lua_isnoneornil(L, 3))
if (!lua_isnoneornil(L, 4))
{
luaL_checktype(L, 3, LUA_TTABLE);
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 4, META_MOBJ));
lua_getfield(L, 3, "x");
if (lua_isnil(L, -1))
if (mobj != NULL)
{
lua_pop(L, 1);
lua_rawgeti(L, 3, 1);
q_epicenter.x = mobj->x;
q_epicenter.y = mobj->y;
q_epicenter.z = mobj->z;
q_epicenter_set = true;
}
if (!lua_isnil(L, -1))
q_epicenter.x = luaL_checkinteger(L, -1);
else
q_epicenter.x = 0;
lua_pop(L, 1);
lua_getfield(L, 3, "y");
if (lua_isnil(L, -1))
{
lua_pop(L, 1);
lua_rawgeti(L, 3, 2);
}
if (!lua_isnil(L, -1))
q_epicenter.y = luaL_checkinteger(L, -1);
else
q_epicenter.y = 0;
lua_pop(L, 1);
luaL_checktype(L, 4, LUA_TTABLE);
lua_getfield(L, 3, "z");
if (lua_isnil(L, -1))
{
lua_getfield(L, 4, "x");
if (lua_isnil(L, -1))
{
lua_pop(L, 1);
lua_rawgeti(L, 4, 1);
}
if (!lua_isnil(L, -1))
q_epicenter.x = luaL_checkinteger(L, -1);
else
q_epicenter.x = 0;
lua_pop(L, 1);
lua_rawgeti(L, 3, 3);
}
if (!lua_isnil(L, -1))
q_epicenter.z = luaL_checkinteger(L, -1);
else
q_epicenter.z = 0;
lua_pop(L, 1);
quake.epicenter = &q_epicenter;
lua_getfield(L, 4, "y");
if (lua_isnil(L, -1))
{
lua_pop(L, 1);
lua_rawgeti(L, 4, 2);
}
if (!lua_isnil(L, -1))
q_epicenter.y = luaL_checkinteger(L, -1);
else
q_epicenter.y = 0;
lua_pop(L, 1);
lua_getfield(L, 4, "z");
if (lua_isnil(L, -1))
{
lua_pop(L, 1);
lua_rawgeti(L, 4, 3);
}
if (!lua_isnil(L, -1))
q_epicenter.z = luaL_checkinteger(L, -1);
else
q_epicenter.z = 0;
lua_pop(L, 1);
q_epicenter_set = true;
}
}
else
quake.epicenter = NULL;
quake.radius = luaL_optinteger(L, 4, 512*FRACUNIT);
// These things are actually used in 2.1.
P_StartQuake(q_intensity, q_time);
P_StartQuake(q_time, q_intensity, q_radius, q_epicenter_set ? &q_epicenter : NULL);
return 0;
}

View file

@ -149,10 +149,7 @@ static void Obj_MantaCollide(mobj_t *manta, mobj_t *other)
S_StartSound(other, sfx_gate01 + snd);
other->player->gateBoost += addBoost/2;
if (P_IsDisplayPlayer(other->player) == true)
{
P_StartQuake(12 << FRACBITS, 6);
}
P_StartQuakeFromMobj(6, 12 * other->scale, 512 * other->scale, other);
}
if (touchFlag > 0)

View file

@ -798,7 +798,7 @@ boolean Obj_SpecialUFODamage(mobj_t *ufo, mobj_t *inflictor, mobj_t *source, UIN
S_StopSound(ufo);
S_StartSound(ufo, sfx_clawk2);
P_StartQuake(64<<FRACBITS, 20);
P_StartQuake(20, 64 * ufo->scale, 0, NULL);
ufo_speed(ufo) += addSpeed; // Even more speed!
return true;
@ -806,7 +806,7 @@ boolean Obj_SpecialUFODamage(mobj_t *ufo, mobj_t *inflictor, mobj_t *source, UIN
S_StartSound(ufo, sfx_clawht);
S_StopSoundByID(ufo, sfx_clawzm);
P_StartQuake(64<<FRACBITS, 10);
P_StartQuake(10, 64 * ufo->scale, 0, NULL);
return true;
}

View file

@ -10992,13 +10992,7 @@ void A_MineExplode(mobj_t *actor)
A_Scream(actor);
actor->flags = MF_NOGRAVITY|MF_NOCLIP;
/*
quake.epicenter = NULL;
quake.radius = 512*FRACUNIT;
quake.intensity = 8*FRACUNIT;
quake.time = TICRATE/3;
*/
P_StartQuake(8<<FRACBITS, TICRATE/3);
P_StartQuakeFromMobj(TICRATE/3, 8 * actor->scale, 512 * actor->scale, actor);
P_RadiusAttack(actor, actor->tracer, 192*FRACUNIT, 0, true);
P_MobjCheckWater(actor);
@ -11977,16 +11971,8 @@ void A_Boss5BombExplode(mobj_t *actor)
P_DustRing(locvar1, 4, actor->x, actor->y, actor->z+actor->height, 2*actor->radius, 0, FRACUNIT, actor->scale);
P_DustRing(locvar1, 6, actor->x, actor->y, actor->z+actor->height/2, 3*actor->radius, FRACUNIT, FRACUNIT, actor->scale);
//P_StartQuake(9*FRACUNIT, TICRATE/6, {actor->x, actor->y, actor->z}, 20*actor->radius);
// the above does not exist, so we set the quake values directly instead
quake.intensity = 9*FRACUNIT;
quake.time = TICRATE/6;
// the following quake values have no effect atm? ah well, may as well set them anyway
{
mappoint_t q_epicenter = {actor->x, actor->y, actor->z};
quake.epicenter = &q_epicenter;
}
quake.radius = 20*actor->radius;
P_StartQuakeFromMobj(TICRATE/6, 9 * actor->scale, 20 * actor->radius, actor);
}
// stuff used by A_TNTExplode
@ -12064,7 +12050,6 @@ void A_TNTExplode(mobj_t *actor)
INT32 locvar1 = var1;
INT32 x, y;
INT32 xl, xh, yl, yh;
static mappoint_t epicenter = {0,0,0};
if (LUA_CallAction(A_TNTEXPLODE, actor))
return;
@ -12103,14 +12088,8 @@ void A_TNTExplode(mobj_t *actor)
for (y = yl; y <= yh; y++)
P_BlockThingsIterator(x, y, PIT_TNTExplode);
// cause a quake -- P_StartQuake does not exist yet
epicenter.x = actor->x;
epicenter.y = actor->y;
epicenter.z = actor->z;
quake.intensity = 9*FRACUNIT;
quake.time = TICRATE/6;
quake.epicenter = &epicenter;
quake.radius = 512*FRACUNIT;
// cause a quake
P_StartQuakeFromMobj(TICRATE/6, 9 * actor->scale, 512 * actor->scale, actor);
if (locvar1)
{

View file

@ -2432,8 +2432,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
ringburst = K_ExplodePlayer(player, inflictor, source);
break;
case DMG_WIPEOUT:
if (P_IsDisplayPlayer(player))
P_StartQuake(32<<FRACBITS, 5);
P_StartQuakeFromMobj(5, 32 * player->mo->scale, 512 * player->mo->scale, player->mo);
K_SpinPlayer(player, inflictor, source, KSPIN_WIPEOUT);
K_KartPainEnergyFling(player);
break;

View file

@ -150,8 +150,6 @@ extern consvar_t cv_cam_dist[MAXSPLITSCREENPLAYERS], cv_cam_still[MAXSPLITSCREEN
extern consvar_t cv_cam_speed[MAXSPLITSCREENPLAYERS], cv_cam_rotate[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_tilting;
extern consvar_t cv_actionmovie;
extern consvar_t cv_windowquake;
extern fixed_t t_cam_dist[MAXSPLITSCREENPLAYERS], t_cam_height[MAXSPLITSCREENPLAYERS], t_cam_rotate[MAXSPLITSCREENPLAYERS];

View file

@ -7146,7 +7146,7 @@ static void P_InitLevelSettings(void)
//memset(&ntemprecords, 0, sizeof(nightsdata_t));
// earthquake camera
memset(&quake,0,sizeof(struct quake));
g_quakes = NULL;
// song credit init
Z_Free(cursongcredit.text);

View file

@ -3507,17 +3507,23 @@ boolean P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, cha
case 444: // Earthquake camera
{
quake.intensity = args[1] << FRACBITS;
quake.radius = args[2] << FRACBITS;
quake.time = args[0];
quake.epicenter = NULL; /// \todo
tic_t q_time = args[0];
fixed_t q_intensity = args[1] * mapobjectscale;
fixed_t q_radius = args[2] * mapobjectscale;
// TODO: epicenter
// reasonable defaults.
if (!quake.intensity)
quake.intensity = 8*mapobjectscale;
if (!quake.radius)
quake.radius = 512*mapobjectscale;
if (q_intensity <= 0)
{
q_intensity = 8 * mapobjectscale;
}
if (q_radius <= 0)
{
q_radius = 512 * mapobjectscale;
}
P_StartQuake(q_time, q_intensity, q_radius, NULL);
break;
}
@ -9347,10 +9353,167 @@ static void P_SpawnPushers(void)
}
}
// Rudimentary function to start a earthquake.
// epicenter and radius are not yet used.
void P_StartQuake(fixed_t intensity, tic_t time)
// Add an earthquake effect to the list.
static quake_t *PushQuake(void)
{
quake.intensity = FixedMul(intensity, mapobjectscale);
quake.time = time;
quake_t *quake = Z_Calloc(sizeof(quake_t), PU_LEVEL, NULL);
quake->next = g_quakes;
if (g_quakes != NULL)
{
g_quakes->prev = quake;
}
g_quakes = quake;
return quake;
}
void P_StartQuake(tic_t time, fixed_t intensity, fixed_t radius, mappoint_t *epicenter)
{
quake_t *quake = NULL;
if (time <= 0 || intensity <= 0)
{
// Invalid parameters
return;
}
quake = Z_Calloc(sizeof(quake_t), PU_LEVEL, NULL);
quake->next = g_quakes;
g_quakes->prev = quake;
g_quakes = quake;
quake->time = quake->startTime = time;
quake->intensity = intensity;
if (radius > 0)
{
quake->radius = radius;
if (epicenter != NULL)
{
quake->epicenter = (mappoint_t *)Z_Malloc(sizeof(mappoint_t), PU_LEVEL, NULL);
quake->epicenter->x = epicenter->x;
quake->epicenter->y = epicenter->y;
quake->epicenter->z = epicenter->z;
}
}
}
void P_StartQuakeFromMobj(tic_t time, fixed_t intensity, fixed_t radius, mobj_t *mobj)
{
quake_t *quake = NULL;
if (time <= 0 || intensity <= 0 || radius <= 0 || P_MobjWasRemoved(mobj) == true)
{
// Invalid parameters
return;
}
quake = PushQuake();
quake->time = quake->startTime = time;
quake->intensity = intensity;
quake->radius = radius;
quake->mobj = mobj; // Update epicenter with mobj position every tic
quake->epicenter = (mappoint_t *)Z_Malloc(sizeof(mappoint_t), PU_LEVEL, NULL);
quake->epicenter->x = mobj->x;
quake->epicenter->y = mobj->y;
quake->epicenter->z = mobj->z;
}
void P_DoQuakeOffset(UINT8 view, mappoint_t *viewPos, mappoint_t *offset)
{
player_t *viewer = &players[ displayplayers[view] ];
quake_t *quake = NULL;
fixed_t ir = 0;
fixed_t addZ = 0;
if (cv_reducevfx.value == 1)
{
return;
}
// Add the main quake effects.
quake = g_quakes;
while (quake != NULL)
{
ir = quake->intensity;
// Modulate with time remaining.
ir = FixedMul(ir, 2 * FRACUNIT * (quake->time + 1) / quake->startTime);
// Modulate with distance from epicenter, if it exists.
if (quake->radius > 0 && quake->epicenter != NULL)
{
fixed_t epidist = P_AproxDistance(
viewPos->x - quake->epicenter->x,
viewPos->y - quake->epicenter->y
);
ir = FixedMul(ir, FixedDiv(max(0, quake->radius - epidist), quake->radius));
}
addZ += ir;
quake = quake->next;
}
// Add level-based effects.
if (P_MobjWasRemoved(viewer->mo) == false
&& viewer->speed > viewer->mo->scale
&& P_IsObjectOnGround(viewer->mo) == true)
{
// Add offroad effects.
if (viewer->boostpower < FRACUNIT)
{
ir = FixedMul((FRACUNIT - viewer->boostpower) << 2, mapobjectscale);
addZ += ir;
}
// Add stair jank effects.
if (viewer->stairjank > 0)
{
ir = FixedMul((viewer->stairjank * FRACUNIT * 5) / 17, mapobjectscale);
addZ += ir;
}
}
// Reverse every tic.
if ((leveltime + view) & 1)
{
addZ = -addZ;
}
// Finalize the effects.
offset->z += addZ;
}
void P_FreeQuake(quake_t *remove)
{
if (remove->prev != NULL)
{
remove->prev->next = remove->next;
}
if (remove->next != NULL)
{
remove->next->prev = remove->prev;
}
if (remove == g_quakes)
{
g_quakes = remove->next;
}
if (remove->epicenter != NULL)
{
Z_Free(remove->epicenter);
remove->epicenter = NULL;
}
Z_Free(remove);
}

View file

@ -536,9 +536,11 @@ typedef enum
// This must be updated whenever we up the max flat size - quicker to assume rather than figuring out the sqrt of the specific flat's filesize.
#define MAXFLATSIZE (2048<<FRACBITS)
// Something that should've been done long ago???
// We won't be using epicenter or radius anytime soon so I don't think it's worth it yet.
void P_StartQuake(fixed_t intensity, tic_t time);
// create earthquakes
void P_StartQuake(tic_t time, fixed_t intensity, fixed_t radius, mappoint_t *epicenter);
void P_StartQuakeFromMobj(tic_t time, fixed_t intensity, fixed_t radius, mobj_t *mobj);
void P_DoQuakeOffset(UINT8 view, mappoint_t *viewPos, mappoint_t *offset);
void P_FreeQuake(quake_t *remove);
// at game start
void P_InitPicAnims(void);

View file

@ -666,6 +666,7 @@ void P_RunChaseCameras(void)
//
void P_Ticker(boolean run)
{
quake_t *quake = NULL;
INT32 i;
// Increment jointime and quittime even if paused
@ -962,19 +963,30 @@ void P_Ticker(boolean run)
if (bombflashtimer)
bombflashtimer--; // Bomb seizure prevention
if (quake.time)
// Tick quake effects
quake = g_quakes;
while (quake != NULL)
{
fixed_t ir = quake.intensity>>1;
/// \todo Calculate distance from epicenter if set and modulate the intensity accordingly based on radius.
quake.x = M_RandomRange(-ir,ir);
quake.y = M_RandomRange(-ir,ir);
quake.z = M_RandomRange(-ir,ir);
if (cv_windowquake.value)
I_CursedWindowMovement(FixedInt(quake.x), FixedInt(quake.y));
--quake.time;
if (quake->time <= 0)
{
// Time out, remove this effect
quake_t *remove = quake;
quake = quake->next;
P_FreeQuake(remove);
continue;
}
quake->time--;
if (quake->epicenter != NULL && quake->mobj != NULL && P_MobjWasRemoved(quake->mobj) == false)
{
quake->epicenter->x = quake->mobj->x;
quake->epicenter->y = quake->mobj->y;
quake->epicenter->z = quake->mobj->z;
}
quake = quake->next;
}
else
quake.x = quake.y = quake.z = 0;
if (metalplayback)
G_ReadMetalTic(metalplayback);

View file

@ -2899,9 +2899,6 @@ consvar_t cv_cam_rotate[MAXSPLITSCREENPLAYERS] = {
consvar_t cv_tilting = CVAR_INIT ("tilting", "On", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_actionmovie = CVAR_INIT ("actionmovie", "On", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_windowquake = CVAR_INIT ("windowquake", "Off", CV_SAVE, CV_OnOff, NULL);
fixed_t t_cam_dist[MAXSPLITSCREENPLAYERS] = {-42,-42,-42,-42};
fixed_t t_cam_height[MAXSPLITSCREENPLAYERS] = {-42,-42,-42,-42};
fixed_t t_cam_rotate[MAXSPLITSCREENPLAYERS] = {-42,-42,-42,-42};

View file

@ -982,14 +982,6 @@ angle_t R_ViewRollAngle(const player_t *player)
{
roll += player->tilt;
}
if (cv_actionmovie.value)
{
int xs = intsign(quake.x),
ys = intsign(quake.y),
zs = intsign(quake.z);
roll += (xs ^ ys ^ zs) * ANG1;
}
}
return roll;
@ -1217,11 +1209,16 @@ R_SetupCommonFrame
( player_t * player,
subsector_t * subsector)
{
const UINT8 viewnum = R_GetViewNumber();
mappoint_t viewPos = { newview->x, newview->y, newview->z };
mappoint_t offset = { 0, 0, 0 };
newview->player = player;
newview->x += quake.x;
newview->y += quake.y;
newview->z += quake.z;
P_DoQuakeOffset(viewnum, &viewPos, &offset);
newview->x += offset.x;
newview->y += offset.y;
newview->z += offset.z;
newview->roll = R_ViewRollAngle(player);
@ -1349,7 +1346,7 @@ void R_SkyboxFrame(int s)
if (mapheaderinfo[gamemap-1])
{
mapheader_t *mh = mapheaderinfo[gamemap-1];
vector3_t campos = {0,0,0}; // Position of player's actual view point
mappoint_t campos = { 0, 0, 0 }; // Position of player's actual view point
mobj_t *center = player->skybox.centerpoint;
if (player->awayview.tics) {
@ -1368,9 +1365,7 @@ void R_SkyboxFrame(int s)
// Earthquake effects should be scaled in the skybox
// (if an axis isn't used, the skybox won't shake in that direction)
campos.x += quake.x;
campos.y += quake.y;
campos.z += quake.z;
P_DoQuakeOffset(s, &campos, &campos);
if (center) // Is there a viewpoint?
{
@ -1418,7 +1413,6 @@ void R_SkyboxFrame(int s)
newview->z += campos.z * -mh->skybox_scalez;
}
R_SetupCommonFrame(player, r_viewmobj->subsector);
}
@ -1726,8 +1720,6 @@ void R_RegisterEngineStuff(void)
}
CV_RegisterVar(&cv_tilting);
CV_RegisterVar(&cv_actionmovie);
CV_RegisterVar(&cv_windowquake);
CV_RegisterVar(&cv_showhud);
CV_RegisterVar(&cv_translucenthud);

View file

@ -119,6 +119,7 @@ TYPEDEF (cutscene_t);
TYPEDEF (textpage_t);
TYPEDEF (textprompt_t);
TYPEDEF (mappoint_t);
TYPEDEF (quake_t);
TYPEDEF (customoption_t);
TYPEDEF (gametype_t);
TYPEDEF (staffbrief_t);