diff --git a/src/doomstat.h b/src/doomstat.h index baa39a873..77317fd0a 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -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 diff --git a/src/g_game.c b/src/g_game.c index 91d150155..d74bd1a4f 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -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}; diff --git a/src/k_kart.c b/src/k_kart.c index c1e29adc2..ccd006e83 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -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<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<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)<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<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<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. } } } diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 214b1518c..e2283c8b0 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -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; } diff --git a/src/objects/manta-ring.c b/src/objects/manta-ring.c index 69f98fc06..793e8ab31 100644 --- a/src/objects/manta-ring.c +++ b/src/objects/manta-ring.c @@ -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) diff --git a/src/objects/ufo.c b/src/objects/ufo.c index 3e85b59e1..29badf611 100644 --- a/src/objects/ufo.c +++ b/src/objects/ufo.c @@ -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<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<scale, 0, NULL); return true; } diff --git a/src/p_enemy.c b/src/p_enemy.c index 152ced8f3..f5c2539b1 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -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<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) { diff --git a/src/p_inter.c b/src/p_inter.c index 844063c35..aa8c08aa4 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -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<mo->scale, 512 * player->mo->scale, player->mo); K_SpinPlayer(player, inflictor, source, KSPIN_WIPEOUT); K_KartPainEnergyFling(player); break; diff --git a/src/p_local.h b/src/p_local.h index 0c7b3bcb8..71a2989e3 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -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]; diff --git a/src/p_setup.c b/src/p_setup.c index 9ad523563..27f523e25 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -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); diff --git a/src/p_spec.c b/src/p_spec.c index 5adad0c23..6ff65a00a 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -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); } diff --git a/src/p_spec.h b/src/p_spec.h index b7a48f992..a4644dbdf 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -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<>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); diff --git a/src/p_user.c b/src/p_user.c index 3ec4683f0..49ee31f5d 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -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}; diff --git a/src/r_main.c b/src/r_main.c index 2dfd3b107..107e6684b 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -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); diff --git a/src/typedef.h b/src/typedef.h index 6b9649ca3..25e2910e1 100644 --- a/src/typedef.h +++ b/src/typedef.h @@ -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);