Merge branch 'master' into net-screen

This commit is contained in:
TehRealSalt 2018-10-05 16:13:25 -04:00
commit cc2af8a329
21 changed files with 183 additions and 130 deletions

View file

@ -2938,7 +2938,9 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
} }
consvar_t cv_allownewplayer = {"allowjoin", "On", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL }; consvar_t cv_allownewplayer = {"allowjoin", "On", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL };
#ifdef VANILLAJOINNEXTROUND
consvar_t cv_joinnextround = {"joinnextround", "Off", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; /// \todo not done consvar_t cv_joinnextround = {"joinnextround", "Off", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; /// \todo not done
#endif
static CV_PossibleValue_t maxplayers_cons_t[] = {{2, "MIN"}, {MAXPLAYERS, "MAX"}, {0, NULL}}; static CV_PossibleValue_t maxplayers_cons_t[] = {{2, "MIN"}, {MAXPLAYERS, "MAX"}, {0, NULL}};
consvar_t cv_maxplayers = {"maxplayers", "8", CV_SAVE, maxplayers_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_maxplayers = {"maxplayers", "8", CV_SAVE, maxplayers_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t resynchattempts_cons_t[] = {{0, "MIN"}, {20, "MAX"}, {0, NULL}}; static CV_PossibleValue_t resynchattempts_cons_t[] = {{0, "MIN"}, {20, "MAX"}, {0, NULL}};
@ -2986,7 +2988,9 @@ void D_ClientServerInit(void)
RegisterNetXCmd(XD_REMOVEPLAYER, Got_RemovePlayer); RegisterNetXCmd(XD_REMOVEPLAYER, Got_RemovePlayer);
#ifndef NONET #ifndef NONET
CV_RegisterVar(&cv_allownewplayer); CV_RegisterVar(&cv_allownewplayer);
#ifdef VANILLAJOINNEXTROUND
CV_RegisterVar(&cv_joinnextround); CV_RegisterVar(&cv_joinnextround);
#endif
CV_RegisterVar(&cv_showjoinaddress); CV_RegisterVar(&cv_showjoinaddress);
CV_RegisterVar(&cv_resynchattempts); CV_RegisterVar(&cv_resynchattempts);
CV_RegisterVar(&cv_blamecfail); CV_RegisterVar(&cv_blamecfail);
@ -3507,8 +3511,10 @@ static void HandleConnect(SINT8 node)
// you get a free second before desynch checks. use it wisely. // you get a free second before desynch checks. use it wisely.
SV_InitResynchVars(node); SV_InitResynchVars(node);
#ifdef VANILLAJOINNEXTROUND
if (cv_joinnextround.value && gameaction == ga_nothing) if (cv_joinnextround.value && gameaction == ga_nothing)
G_SetGamestate(GS_WAITINGPLAYERS); G_SetGamestate(GS_WAITINGPLAYERS);
#endif
if (!SV_SendServerConfig(node)) if (!SV_SendServerConfig(node))
{ {
G_SetGamestate(backupstate); G_SetGamestate(backupstate);

View file

@ -497,7 +497,11 @@ extern UINT32 realpingtable[MAXPLAYERS];
extern UINT32 playerpingtable[MAXPLAYERS]; extern UINT32 playerpingtable[MAXPLAYERS];
#endif #endif
extern consvar_t cv_joinnextround, cv_allownewplayer, cv_maxplayers, cv_resynchattempts, cv_blamecfail, cv_maxsend, cv_noticedownload, cv_downloadspeed; extern consvar_t
#ifdef VANILLAJOINNEXTROUND
cv_joinnextround,
#endif
cv_allownewplayer, cv_maxplayers, cv_resynchattempts, cv_blamecfail, cv_maxsend, cv_noticedownload, cv_downloadspeed;
// Used in d_net, the only dependence // Used in d_net, the only dependence
tic_t ExpandTics(INT32 low); tic_t ExpandTics(INT32 low);

View file

@ -1308,6 +1308,13 @@ static void readlevelheader(MYFILE *f, INT32 num)
else else
mapheaderinfo[num-1]->levelflags &= ~LF_NOZONE; mapheaderinfo[num-1]->levelflags &= ~LF_NOZONE;
} }
else if (fastcmp(word, "SECTIONRACE"))
{
if (i || word2[0] == 'T' || word2[0] == 'Y')
mapheaderinfo[num-1]->levelflags |= LF_SECTIONRACE;
else
mapheaderinfo[num-1]->levelflags &= ~LF_SECTIONRACE;
}
// Individual triggers for menu flags // Individual triggers for menu flags
else if (fastcmp(word, "HIDDEN")) else if (fastcmp(word, "HIDDEN"))
@ -7943,6 +7950,7 @@ struct {
{"LF_NOSSMUSIC",LF_NOSSMUSIC}, {"LF_NOSSMUSIC",LF_NOSSMUSIC},
{"LF_NORELOAD",LF_NORELOAD}, {"LF_NORELOAD",LF_NORELOAD},
{"LF_NOZONE",LF_NOZONE}, {"LF_NOZONE",LF_NOZONE},
{"LF_SECTIONRACE",LF_SECTIONRACE},
// And map flags // And map flags
{"LF2_HIDEINMENU",LF2_HIDEINMENU}, {"LF2_HIDEINMENU",LF2_HIDEINMENU},
{"LF2_HIDEINSTATS",LF2_HIDEINSTATS}, {"LF2_HIDEINSTATS",LF2_HIDEINSTATS},

View file

@ -272,6 +272,7 @@ typedef struct
#define LF_NOSSMUSIC 4 ///< Disable Super Sonic music #define LF_NOSSMUSIC 4 ///< Disable Super Sonic music
#define LF_NORELOAD 8 ///< Don't reload level on death #define LF_NORELOAD 8 ///< Don't reload level on death
#define LF_NOZONE 16 ///< Don't include "ZONE" on level title #define LF_NOZONE 16 ///< Don't include "ZONE" on level title
#define LF_SECTIONRACE 32 ///< Section race level
#define LF2_HIDEINMENU 1 ///< Hide in the multiplayer menu #define LF2_HIDEINMENU 1 ///< Hide in the multiplayer menu
#define LF2_HIDEINSTATS 2 ///< Hide in the statistics screen #define LF2_HIDEINSTATS 2 ///< Hide in the statistics screen

View file

@ -523,12 +523,15 @@ static const char *credits[] = {
"\"VirtAnderson\"", "\"VirtAnderson\"",
"", "",
"\1Special Thanks", "\1Special Thanks",
"Sonic Team Jr. & SRB2", "Sonic Team Jr. & SRB2 (www.srb2.org)",
"Bandit \"Bobby\" Cochenour", // i <3 my dog "Bandit \"Bobby\" Cochenour", // i <3 my dog
"Bear", // i <3 MY dog too
"\"Chrispy\"",
"\"DirkTheHusky\"",
"\"fickle\"", // and my sharki
"\"Nev3r\"", "\"Nev3r\"",
"\"Ritz\"", "\"Ritz\"",
"\"Spherallic\"", "\"Spherallic\"",
"\"DirkTheHusky\"",
"", "",
"\1Produced By", "\1Produced By",
"Kart Krew", "Kart Krew",
@ -554,7 +557,7 @@ static struct {
{112, 80+200* 7, "CREDIT10"}, {112, 80+200* 7, "CREDIT10"},
{240, 80+200* 8, "CREDIT05"}, {240, 80+200* 8, "CREDIT05"},
{120, 80+200* 9, "CREDIT06"},*/ {120, 80+200* 9, "CREDIT06"},*/
{112, 80+200*10, "TYLER52"}, {112, 80+100+200*10, "TYLER52"},
{0, 0, NULL} {0, 0, NULL}
}; };

View file

@ -643,13 +643,13 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
{ {
scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatsize; scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatsize;
scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatsize; scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatsize;
angle = FOFsector->floorpic_angle>>ANGLETOFINESHIFT; angle = FOFsector->floorpic_angle;
} }
else // it's a ceiling else // it's a ceiling
{ {
scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatsize; scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatsize;
scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatsize; scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatsize;
angle = FOFsector->ceilingpic_angle>>ANGLETOFINESHIFT; angle = FOFsector->ceilingpic_angle;
} }
} }
else if (gr_frontsector) else if (gr_frontsector)
@ -658,24 +658,26 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
{ {
scrollx = FIXED_TO_FLOAT(gr_frontsector->floor_xoffs)/fflatsize; scrollx = FIXED_TO_FLOAT(gr_frontsector->floor_xoffs)/fflatsize;
scrolly = FIXED_TO_FLOAT(gr_frontsector->floor_yoffs)/fflatsize; scrolly = FIXED_TO_FLOAT(gr_frontsector->floor_yoffs)/fflatsize;
angle = gr_frontsector->floorpic_angle>>ANGLETOFINESHIFT; angle = gr_frontsector->floorpic_angle;
} }
else // it's a ceiling else // it's a ceiling
{ {
scrollx = FIXED_TO_FLOAT(gr_frontsector->ceiling_xoffs)/fflatsize; scrollx = FIXED_TO_FLOAT(gr_frontsector->ceiling_xoffs)/fflatsize;
scrolly = FIXED_TO_FLOAT(gr_frontsector->ceiling_yoffs)/fflatsize; scrolly = FIXED_TO_FLOAT(gr_frontsector->ceiling_yoffs)/fflatsize;
angle = gr_frontsector->ceilingpic_angle>>ANGLETOFINESHIFT; angle = gr_frontsector->ceilingpic_angle;
} }
} }
if (angle) // Only needs to be done if there's an altered angle if (angle) // Only needs to be done if there's an altered angle
{ {
angle = InvAngle(angle)>>ANGLETOFINESHIFT;
// This needs to be done so that it scrolls in a different direction after rotation like software // This needs to be done so that it scrolls in a different direction after rotation like software
tempxsow = FLOAT_TO_FIXED(scrollx); /*tempxsow = FLOAT_TO_FIXED(scrollx);
tempytow = FLOAT_TO_FIXED(scrolly); tempytow = FLOAT_TO_FIXED(scrolly);
scrollx = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle)))); scrollx = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle))));
scrolly = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle)))); scrolly = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle))));*/
// This needs to be done so everything aligns after rotation // This needs to be done so everything aligns after rotation
// It would be done so that rotation is done, THEN the translation, but I couldn't get it to rotate AND scroll like software does // It would be done so that rotation is done, THEN the translation, but I couldn't get it to rotate AND scroll like software does
@ -689,7 +691,7 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
{ {
// Hurdler: add scrolling texture on floor/ceiling // Hurdler: add scrolling texture on floor/ceiling
v3d->sow = (float)((pv->x / fflatsize) - flatxref + scrollx); v3d->sow = (float)((pv->x / fflatsize) - flatxref + scrollx);
v3d->tow = (float)(flatyref - (pv->y / fflatsize) + scrolly); v3d->tow = (float)(-(pv->y / fflatsize) + flatyref + scrolly);
//v3d->sow = (float)(pv->x / fflatsize); //v3d->sow = (float)(pv->x / fflatsize);
//v3d->tow = (float)(pv->y / fflatsize); //v3d->tow = (float)(pv->y / fflatsize);
@ -700,7 +702,7 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
tempxsow = FLOAT_TO_FIXED(v3d->sow); tempxsow = FLOAT_TO_FIXED(v3d->sow);
tempytow = FLOAT_TO_FIXED(v3d->tow); tempytow = FLOAT_TO_FIXED(v3d->tow);
v3d->sow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle)))); v3d->sow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle))));
v3d->tow = (FIXED_TO_FLOAT(-FixedMul(tempxsow, FINESINE(angle)) - FixedMul(tempytow, FINECOSINE(angle)))); v3d->tow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle))));
} }
//v3d->sow = (float)(v3d->sow - flatxref + scrollx); //v3d->sow = (float)(v3d->sow - flatxref + scrollx);

View file

@ -2226,22 +2226,13 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I
if (G_RaceGametype()) if (G_RaceGametype())
{ {
#define timestring(time) va("%i:%02i.%02i", G_TicsToMinutes(time, true), G_TicsToSeconds(time), G_TicsToCentiseconds(time)) #define timestring(time) va("%i'%02i\"%02i", G_TicsToMinutes(time, true), G_TicsToSeconds(time), G_TicsToCentiseconds(time))
if (players[tab[i].num].exiting) if (players[tab[i].num].exiting)
{
V_DrawRightAlignedString(x, y-4, hilicol, "FIN");
V_DrawRightAlignedString(x+rightoffset, y, hilicol, timestring(players[tab[i].num].realtime)); V_DrawRightAlignedString(x+rightoffset, y, hilicol, timestring(players[tab[i].num].realtime));
}
else if (players[tab[i].num].pflags & PF_TIMEOVER) else if (players[tab[i].num].pflags & PF_TIMEOVER)
V_DrawRightAlignedThinString(x+rightoffset, y-1, 0, "TIME OVER..."); V_DrawRightAlignedThinString(x+rightoffset, y-1, 0, "NO CONTEST.");
else if (circuitmap) else if (circuitmap)
{ V_DrawRightAlignedString(x+rightoffset, y, 0, va("Lap %d", tab[i].count));
V_DrawRightAlignedString(x, y-4, 0, "Lap");
V_DrawRightAlignedString(x, y+4, 0, va("%d", tab[i].count));
V_DrawRightAlignedString(x+rightoffset, y, 0, timestring(players[tab[i].num].starposttime));
}
else
V_DrawRightAlignedString(x+rightoffset, y, 0, timestring(tab[i].count));
#undef timestring #undef timestring
} }
else else

View file

@ -1306,7 +1306,7 @@ static void K_SpawnDashDustRelease(player_t *player)
if (!P_IsObjectOnGround(player->mo)) if (!P_IsObjectOnGround(player->mo))
return; return;
if (player->speed == 0) if (!player->speed && !player->kartstuff[k_startboost])
return; return;
travelangle = player->mo->angle; travelangle = player->mo->angle;
@ -3045,7 +3045,7 @@ static void K_DoShrink(player_t *player)
} }
} }
static void K_DoSPB(player_t *victim, player_t *source) static void K_DoSPB(player_t *victim)
{ {
//INT32 i; //INT32 i;
S_StartSound(victim->mo, sfx_bkpoof); // Sound the BANG! S_StartSound(victim->mo, sfx_bkpoof); // Sound the BANG!
@ -3056,11 +3056,28 @@ static void K_DoSPB(player_t *victim, player_t *source)
P_FlashPal(&players[i], PAL_NUKE, 10); P_FlashPal(&players[i], PAL_NUKE, 10);
}*/ }*/
if (victim->mo && !victim->spectator) if (!victim->mo || !victim->mo->health || victim->spectator)
P_DamageMobj(victim->mo, source->mo, source->mo, 65); return;
{
mobj_t *spbexplode;
if (!victim->kartstuff[k_invincibilitytimer] && !victim->kartstuff[k_growshrinktimer])
{
K_DropHnextList(victim);
K_StripItems(victim);
victim->powers[pw_flashing] = 0;
}
spbexplode = P_SpawnMobj(victim->mo->x, victim->mo->y, victim->mo->z, MT_BLUEEXPLOSION);
if (playeringame[spbplayer] && !players[spbplayer].spectator && players[spbplayer].mo)
P_SetTarget(&spbexplode->target, players[spbplayer].mo);
}
} }
void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, boolean mute) void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, UINT8 sound)
{ {
const fixed_t vscale = mapheaderinfo[gamemap-1]->mobj_scale + (mo->scale - mapheaderinfo[gamemap-1]->mobj_scale); const fixed_t vscale = mapheaderinfo[gamemap-1]->mobj_scale + (mo->scale - mapheaderinfo[gamemap-1]->mobj_scale);
@ -3112,8 +3129,8 @@ void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, boolean mute)
else else
mo->momz = FixedMul(vertispeed, vscale); mo->momz = FixedMul(vertispeed, vscale);
if (!mute) if (sound)
S_StartSound(mo, sfx_kpogos); S_StartSound(mo, (sound == 1 ? sfx_kc2f : sfx_kpogos));
} }
void K_KillBananaChain(mobj_t *banana, mobj_t *inflictor, mobj_t *source) void K_KillBananaChain(mobj_t *banana, mobj_t *inflictor, mobj_t *source)
@ -3849,7 +3866,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
if (player->kartstuff[k_deathsentence]) if (player->kartstuff[k_deathsentence])
{ {
if (player->kartstuff[k_deathsentence] == 1) if (player->kartstuff[k_deathsentence] == 1)
K_DoSPB(player, &players[spbplayer]); K_DoSPB(player);
player->kartstuff[k_deathsentence]--; player->kartstuff[k_deathsentence]--;
} }
@ -4142,7 +4159,8 @@ static void K_KartDrift(player_t *player, boolean onground)
&& (player->kartstuff[k_driftcharge] >= dsone && player->kartstuff[k_driftcharge] < dstwo) && (player->kartstuff[k_driftcharge] >= dsone && player->kartstuff[k_driftcharge] < dstwo)
&& onground) && onground)
{ {
player->kartstuff[k_driftboost] = 20; if (player->kartstuff[k_driftboost] < 20)
player->kartstuff[k_driftboost] = 20;
S_StartSound(player->mo, sfx_s23c); S_StartSound(player->mo, sfx_s23c);
//K_SpawnDashDustRelease(player); //K_SpawnDashDustRelease(player);
player->kartstuff[k_driftcharge] = 0; player->kartstuff[k_driftcharge] = 0;
@ -4152,7 +4170,8 @@ static void K_KartDrift(player_t *player, boolean onground)
&& player->kartstuff[k_driftcharge] < dsthree && player->kartstuff[k_driftcharge] < dsthree
&& onground) && onground)
{ {
player->kartstuff[k_driftboost] = 50; if (player->kartstuff[k_driftboost] < 50)
player->kartstuff[k_driftboost] = 50;
S_StartSound(player->mo, sfx_s23c); S_StartSound(player->mo, sfx_s23c);
//K_SpawnDashDustRelease(player); //K_SpawnDashDustRelease(player);
player->kartstuff[k_driftcharge] = 0; player->kartstuff[k_driftcharge] = 0;
@ -4162,7 +4181,8 @@ static void K_KartDrift(player_t *player, boolean onground)
&& player->kartstuff[k_driftcharge] >= dsthree && player->kartstuff[k_driftcharge] >= dsthree
&& onground) && onground)
{ {
player->kartstuff[k_driftboost] = 125; if (player->kartstuff[k_driftboost] < 125)
player->kartstuff[k_driftboost] = 125;
S_StartSound(player->mo, sfx_s23c); S_StartSound(player->mo, sfx_s23c);
//K_SpawnDashDustRelease(player); //K_SpawnDashDustRelease(player);
player->kartstuff[k_driftcharge] = 0; player->kartstuff[k_driftcharge] = 0;
@ -4795,7 +4815,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
&& !player->kartstuff[k_pogospring]) && !player->kartstuff[k_pogospring])
{ {
K_PlayBoostTaunt(player->mo); K_PlayBoostTaunt(player->mo);
K_DoPogoSpring(player->mo, 32<<FRACBITS, false); K_DoPogoSpring(player->mo, 32<<FRACBITS, 2);
player->kartstuff[k_pogospring] = 1; player->kartstuff[k_pogospring] = 1;
player->kartstuff[k_itemamount]--; player->kartstuff[k_itemamount]--;
} }
@ -5948,7 +5968,7 @@ static void K_drawKartItem(void)
// Quick Eggman numbers // Quick Eggman numbers
if (stplyr->kartstuff[k_eggmanexplode] > 1 /*&& stplyr->kartstuff[k_eggmanexplode] <= 3*TICRATE*/) if (stplyr->kartstuff[k_eggmanexplode] > 1 /*&& stplyr->kartstuff[k_eggmanexplode] <= 3*TICRATE*/)
V_DrawScaledPatch(ITEM_X+17, ITEM_Y+13, V_HUDTRANS|splitflags, kp_eggnum[min(3, G_TicsToSeconds(stplyr->kartstuff[k_eggmanexplode]))]); V_DrawScaledPatch(ITEM_X+17-offset, ITEM_Y+13-offset, V_HUDTRANS|splitflags, kp_eggnum[min(3, G_TicsToSeconds(stplyr->kartstuff[k_eggmanexplode]))]);
} }
void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT16 emblemmap, boolean playing) void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT16 emblemmap, boolean playing)

View file

@ -38,7 +38,7 @@ void K_SpawnSparkleTrail(mobj_t *mo);
void K_SpawnWipeoutTrail(mobj_t *mo, boolean translucent); void K_SpawnWipeoutTrail(mobj_t *mo, boolean translucent);
void K_DriftDustHandling(mobj_t *spawner); void K_DriftDustHandling(mobj_t *spawner);
void K_DoSneaker(player_t *player, boolean doPFlag); void K_DoSneaker(player_t *player, boolean doPFlag);
void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, boolean mute); void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, UINT8 sound);
void K_KillBananaChain(mobj_t *banana, mobj_t *inflictor, mobj_t *source); void K_KillBananaChain(mobj_t *banana, mobj_t *inflictor, mobj_t *source);
void K_UpdateHnextList(player_t *player, boolean clean); void K_UpdateHnextList(player_t *player, boolean clean);
void K_DropHnextList(player_t *player); void K_DropHnextList(player_t *player);

View file

@ -2244,11 +2244,11 @@ static int lib_kDoPogoSpring(lua_State *L)
{ {
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
fixed_t vertispeed = luaL_checkfixed(L, 2); fixed_t vertispeed = luaL_checkfixed(L, 2);
boolean mute = luaL_checkboolean(L, 3); UINT8 sound = luaL_checkinteger(L, 3);
NOHUD NOHUD
if (!mo) if (!mo)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
K_DoPogoSpring(mo, vertispeed, mute); K_DoPogoSpring(mo, vertispeed, sound);
return 0; return 0;
} }

View file

@ -659,7 +659,8 @@ static menuitem_t MISC_HelpMenu[] =
{IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL09", M_HandleImageDef, 1}, {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL09", M_HandleImageDef, 1},
{IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL10", M_HandleImageDef, 1}, {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL10", M_HandleImageDef, 1},
{IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL11", M_HandleImageDef, 1}, {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL11", M_HandleImageDef, 1},
{IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL12", M_HandleImageDef, 0}, {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL12", M_HandleImageDef, 1},
{IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL99", M_HandleImageDef, 0},
}; };
// -------------------------------- // --------------------------------
@ -1539,7 +1540,9 @@ static menuitem_t OP_ServerOptionsMenu[] =
#ifndef NONET #ifndef NONET
{IT_STRING | IT_CVAR, NULL, "Max. Player Count", &cv_maxplayers, 90}, {IT_STRING | IT_CVAR, NULL, "Max. Player Count", &cv_maxplayers, 90},
{IT_STRING | IT_CVAR, NULL, "Allow Players to Join", &cv_allownewplayer, 100}, {IT_STRING | IT_CVAR, NULL, "Allow Players to Join", &cv_allownewplayer, 100},
//{IT_STRING | IT_CVAR, NULL, "Join on Map Change", &cv_joinnextround, 110}, #ifdef VANILLAJOINNEXTROUND
{IT_STRING | IT_CVAR, NULL, "Join on Map Change", &cv_joinnextround, 110},
#endif
{IT_STRING | IT_CVAR, NULL, "Allow WAD Downloading", &cv_downloading, 110}, {IT_STRING | IT_CVAR, NULL, "Allow WAD Downloading", &cv_downloading, 110},
{IT_STRING | IT_CVAR, NULL, "Attempts to resynchronise", &cv_resynchattempts, 120}, {IT_STRING | IT_CVAR, NULL, "Attempts to resynchronise", &cv_resynchattempts, 120},
@ -4269,7 +4272,7 @@ static void M_DrawImageDef(void)
else else
{ {
patch_t *patch = W_CachePatchName(currentMenu->menuitems[itemOn].text,PU_CACHE); patch_t *patch = W_CachePatchName(currentMenu->menuitems[itemOn].text,PU_CACHE);
if (patch->width <= BASEVIDWIDTH) if (patch->height <= BASEVIDHEIGHT)
V_DrawScaledPatch(0,0,0,patch); V_DrawScaledPatch(0,0,0,patch);
else else
V_DrawSmallScaledPatch(0,0,0,patch); V_DrawSmallScaledPatch(0,0,0,patch);

View file

@ -3385,19 +3385,6 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
S_StartSound(player->mo, sfx_kc59); S_StartSound(player->mo, sfx_kc59);
return true; return true;
} }
// Self-Propelled Bomb
if (damage == 65)
{
mobj_t *spbexplode;
if (player == source->player)
return false;
// Just need to do this now! Being thrown upwards is done by the explosion.
//P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_BLUELIGHTNING);
spbexplode = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_BLUEEXPLOSION);
P_SetTarget(&spbexplode->target, source);
return true;
}
//} //}
// Sudden-Death mode // Sudden-Death mode

View file

@ -316,7 +316,7 @@ static void P_DoFanAndGasJet(mobj_t *spring, mobj_t *object)
break; break;
if (object->player) if (object->player)
object->player->kartstuff[k_pogospring] = 1; object->player->kartstuff[k_pogospring] = 1;
K_DoPogoSpring(object, 0, true); K_DoPogoSpring(object, 0, 0);
return; return;
} }
else else

View file

@ -8037,7 +8037,7 @@ void P_MobjThinker(mobj_t *mobj)
if ((sec2 && GETSECSPECIAL(sec2->special, 3) == 1) if ((sec2 && GETSECSPECIAL(sec2->special, 3) == 1)
|| (P_IsObjectOnRealGround(mobj, mobj->subsector->sector) || (P_IsObjectOnRealGround(mobj, mobj->subsector->sector)
&& GETSECSPECIAL(mobj->subsector->sector->special, 3) == 1)) && GETSECSPECIAL(mobj->subsector->sector->special, 3) == 1))
K_DoPogoSpring(mobj, 0, false); K_DoPogoSpring(mobj, 0, 1);
} }
if (mobj->threshold > 0) if (mobj->threshold > 0)
@ -8112,7 +8112,7 @@ void P_MobjThinker(mobj_t *mobj)
if ((sec2 && GETSECSPECIAL(sec2->special, 3) == 1) if ((sec2 && GETSECSPECIAL(sec2->special, 3) == 1)
|| (P_IsObjectOnRealGround(mobj, mobj->subsector->sector) || (P_IsObjectOnRealGround(mobj, mobj->subsector->sector)
&& GETSECSPECIAL(mobj->subsector->sector->special, 3) == 1)) && GETSECSPECIAL(mobj->subsector->sector->special, 3) == 1))
K_DoPogoSpring(mobj, 0, false); K_DoPogoSpring(mobj, 0, 1);
break; break;
} }
@ -8141,7 +8141,7 @@ void P_MobjThinker(mobj_t *mobj)
if ((sec2 && GETSECSPECIAL(sec2->special, 3) == 1) if ((sec2 && GETSECSPECIAL(sec2->special, 3) == 1)
|| (P_IsObjectOnRealGround(mobj, mobj->subsector->sector) || (P_IsObjectOnRealGround(mobj, mobj->subsector->sector)
&& GETSECSPECIAL(mobj->subsector->sector->special, 3) == 1)) && GETSECSPECIAL(mobj->subsector->sector->special, 3) == 1))
K_DoPogoSpring(mobj, 0, false); K_DoPogoSpring(mobj, 0, 1);
} }
if (mobj->threshold > 0) if (mobj->threshold > 0)

View file

@ -2916,7 +2916,9 @@ boolean P_SetupLevel(boolean skipprecip)
} }
else if (G_RaceGametype() && server) else if (G_RaceGametype() && server)
CV_StealthSetValue(&cv_numlaps, CV_StealthSetValue(&cv_numlaps,
((netgame || multiplayer) && cv_basenumlaps.value) ((netgame || multiplayer) && cv_basenumlaps.value
&& (!(mapheaderinfo[gamemap - 1]->levelflags & LF_SECTIONRACE)
|| (mapheaderinfo[gamemap - 1]->numlaps > cv_basenumlaps.value)))
? cv_basenumlaps.value ? cv_basenumlaps.value
: mapheaderinfo[gamemap - 1]->numlaps); : mapheaderinfo[gamemap - 1]->numlaps);

View file

@ -3790,7 +3790,7 @@ DoneSection2:
P_InstaThrust(player->mo, player->mo->angle, minspeed); P_InstaThrust(player->mo, player->mo->angle, minspeed);
player->kartstuff[k_pogospring] = 1; player->kartstuff[k_pogospring] = 1;
K_DoPogoSpring(player->mo, 0, false); K_DoPogoSpring(player->mo, 0, 1);
} }
break; break;
@ -3813,7 +3813,7 @@ DoneSection2:
P_InstaThrust(player->mo, player->mo->angle, minspeed); P_InstaThrust(player->mo, player->mo->angle, minspeed);
player->kartstuff[k_pogospring] = 2; player->kartstuff[k_pogospring] = 2;
K_DoPogoSpring(player->mo, 0, false); K_DoPogoSpring(player->mo, 0, 1);
} }
break; break;
@ -5821,10 +5821,8 @@ void P_SpawnSpecials(INT32 fromnetsave)
} }
else // Otherwise, set calculated offsets such that line's v1 is the apparent origin else // Otherwise, set calculated offsets such that line's v1 is the apparent origin
{ {
fixed_t cosinecomponent = FINECOSINE(flatangle>>ANGLETOFINESHIFT); xoffs = -lines[i].v1->x;
fixed_t sinecomponent = FINESINE(flatangle>>ANGLETOFINESHIFT); yoffs = lines[i].v1->y;
xoffs = (-FixedMul(lines[i].v1->x, cosinecomponent) % MAXFLATSIZE) + (FixedMul(lines[i].v1->y, sinecomponent) % MAXFLATSIZE); // No danger of overflow thanks to the strategically placed modulo operations.
yoffs = (FixedMul(lines[i].v1->x, sinecomponent) % MAXFLATSIZE) + (FixedMul(lines[i].v1->y, cosinecomponent) % MAXFLATSIZE); // Ditto.
} }
for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)

View file

@ -7938,7 +7938,7 @@ static void P_DeathThink(player_t *player)
/*if (player->deadtimer > 30*TICRATE && !G_RaceGametype()) /*if (player->deadtimer > 30*TICRATE && !G_RaceGametype())
player->playerstate = PST_REBORN; player->playerstate = PST_REBORN;
else if (player->lives > 0 && !G_IsSpecialStage(gamemap)*/ else if (player->lives > 0 && !G_IsSpecialStage(gamemap)*/
if (player->lives > 0 && leveltime >= starttime) // *could* you respawn? if (player->lives > 0 /*&& leveltime >= starttime*/) // *could* you respawn?
{ {
// SRB2kart - spawn automatically after 1 second // SRB2kart - spawn automatically after 1 second
if (player->deadtimer > ((netgame || multiplayer) if (player->deadtimer > ((netgame || multiplayer)
@ -8211,7 +8211,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
|| (leveltime < introtime)); // Kart intro cam || (leveltime < introtime)); // Kart intro cam
#endif #endif
if (!(player->climbing || (player->pflags & PF_NIGHTSMODE) || player->playerstate == PST_DEAD)) if (!(player->playerstate == PST_DEAD || player->exiting))
{ {
if (player->spectator) // force cam off for spectators if (player->spectator) // force cam off for spectators
return true; return true;
@ -8704,9 +8704,10 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
{ {
// Don't let the camera match your movement. // Don't let the camera match your movement.
thiscam->momz = 0; thiscam->momz = 0;
if (player->spectator)
thiscam->aiming = 0;
// Only let the camera go a little bit downwards. // Only let the camera go a little bit downwards.
if (!(mo->eflags & MFE_VERTICALFLIP) && thiscam->aiming < ANGLE_337h && thiscam->aiming > ANGLE_180) else if (!(mo->eflags & MFE_VERTICALFLIP) && thiscam->aiming < ANGLE_337h && thiscam->aiming > ANGLE_180)
thiscam->aiming = ANGLE_337h; thiscam->aiming = ANGLE_337h;
else if (mo->eflags & MFE_VERTICALFLIP && thiscam->aiming > ANGLE_22h && thiscam->aiming < ANGLE_180) else if (mo->eflags & MFE_VERTICALFLIP && thiscam->aiming > ANGLE_22h && thiscam->aiming < ANGLE_180)
thiscam->aiming = ANGLE_22h; thiscam->aiming = ANGLE_22h;

View file

@ -1126,30 +1126,12 @@ static void R_Subsector(size_t num, UINT8 viewnumber)
&& polysec->floorheight >= floorcenterz && polysec->floorheight >= floorcenterz
&& (viewz < polysec->floorheight)) && (viewz < polysec->floorheight))
{ {
fixed_t xoff, yoff;
xoff = polysec->floor_xoffs;
yoff = polysec->floor_yoffs;
if (po->angle != 0) {
angle_t fineshift = po->angle >> ANGLETOFINESHIFT;
xoff -= FixedMul(FINECOSINE(fineshift), po->centerPt.x)+FixedMul(FINESINE(fineshift), po->centerPt.y);
yoff -= FixedMul(FINESINE(fineshift), po->centerPt.x)-FixedMul(FINECOSINE(fineshift), po->centerPt.y);
} else {
xoff -= po->centerPt.x;
yoff += po->centerPt.y;
}
light = R_GetPlaneLight(frontsector, polysec->floorheight, viewz < polysec->floorheight); light = R_GetPlaneLight(frontsector, polysec->floorheight, viewz < polysec->floorheight);
light = 0; light = 0;
ffloor[numffloors].plane = R_FindPlane(polysec->floorheight, polysec->floorpic, ffloor[numffloors].plane = R_FindPlane(polysec->floorheight, polysec->floorpic,
polysec->lightlevel, xoff, yoff, polysec->lightlevel, polysec->floor_xoffs, polysec->floor_yoffs,
polysec->floorpic_angle-po->angle, polysec->floorpic_angle-po->angle,
NULL, NULL, NULL, po
NULL
#ifdef POLYOBJECTS_PLANES
, po
#endif
#ifdef ESLOPE #ifdef ESLOPE
, NULL // will ffloors be slopable eventually? , NULL // will ffloors be slopable eventually?
#endif #endif
@ -1174,28 +1156,12 @@ static void R_Subsector(size_t num, UINT8 viewnumber)
&& polysec->ceilingheight <= ceilingcenterz && polysec->ceilingheight <= ceilingcenterz
&& (viewz > polysec->ceilingheight)) && (viewz > polysec->ceilingheight))
{ {
fixed_t xoff, yoff;
xoff = polysec->ceiling_xoffs;
yoff = polysec->ceiling_yoffs;
if (po->angle != 0) {
angle_t fineshift = po->angle >> ANGLETOFINESHIFT;
xoff -= FixedMul(FINECOSINE(fineshift), po->centerPt.x)+FixedMul(FINESINE(fineshift), po->centerPt.y);
yoff -= FixedMul(FINESINE(fineshift), po->centerPt.x)-FixedMul(FINECOSINE(fineshift), po->centerPt.y);
} else {
xoff -= po->centerPt.x;
yoff += po->centerPt.y;
}
light = R_GetPlaneLight(frontsector, polysec->ceilingheight, viewz < polysec->ceilingheight); light = R_GetPlaneLight(frontsector, polysec->ceilingheight, viewz < polysec->ceilingheight);
light = 0; light = 0;
ffloor[numffloors].plane = R_FindPlane(polysec->ceilingheight, polysec->ceilingpic, ffloor[numffloors].plane = R_FindPlane(polysec->ceilingheight, polysec->ceilingpic,
polysec->lightlevel, xoff, yoff, polysec->ceilingpic_angle-po->angle, polysec->lightlevel, polysec->ceiling_xoffs, polysec->ceiling_yoffs,
NULL, NULL polysec->ceilingpic_angle-po->angle,
#ifdef POLYOBJECTS_PLANES NULL, NULL, po
, po
#endif
#ifdef ESLOPE #ifdef ESLOPE
, NULL // will ffloors be slopable eventually? , NULL // will ffloors be slopable eventually?
#endif #endif

View file

@ -1084,10 +1084,10 @@ void R_SetupFrame(player_t *player, boolean skybox)
chasecam = (cv_chasecam.value != 0); chasecam = (cv_chasecam.value != 0);
} }
if (player->climbing || (player->pflags & PF_NIGHTSMODE) || player->playerstate == PST_DEAD) if (player->spectator) // no spectator chasecam
chasecam = true; // force chasecam on
else if (player->spectator) // no spectator chasecam
chasecam = false; // force chasecam off chasecam = false; // force chasecam off
else if (player->playerstate == PST_DEAD || player->exiting)
chasecam = true; // force chasecam on
if (chasecam && !thiscam->chase) if (chasecam && !thiscam->chase)
{ {

View file

@ -450,19 +450,37 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel,
#ifdef ESLOPE #ifdef ESLOPE
if (slope); else // Don't mess with this right now if a slope is involved if (slope); else // Don't mess with this right now if a slope is involved
#endif #endif
if (plangle != 0)
{
// Add the view offset, rotated by the plane angle.
angle_t angle = plangle>>ANGLETOFINESHIFT;
xoff += FixedMul(viewx,FINECOSINE(angle))-FixedMul(viewy,FINESINE(angle));
yoff += -FixedMul(viewx,FINESINE(angle))-FixedMul(viewy,FINECOSINE(angle));
}
else
{ {
xoff += viewx; xoff += viewx;
yoff -= viewy; yoff -= viewy;
if (plangle != 0)
{
// Add the view offset, rotated by the plane angle.
fixed_t cosinecomponent = FINECOSINE(plangle>>ANGLETOFINESHIFT);
fixed_t sinecomponent = FINESINE(plangle>>ANGLETOFINESHIFT);
fixed_t oldxoff = xoff;
xoff = FixedMul(xoff,cosinecomponent)+FixedMul(yoff,sinecomponent);
yoff = -FixedMul(oldxoff,sinecomponent)+FixedMul(yoff,cosinecomponent);
}
} }
#ifdef POLYOBJECTS_PLANES
if (polyobj)
{
if (polyobj->angle != 0)
{
angle_t fineshift = polyobj->angle >> ANGLETOFINESHIFT;
xoff -= FixedMul(FINECOSINE(fineshift), polyobj->centerPt.x)+FixedMul(FINESINE(fineshift), polyobj->centerPt.y);
yoff -= FixedMul(FINESINE(fineshift), polyobj->centerPt.x)-FixedMul(FINECOSINE(fineshift), polyobj->centerPt.y);
}
else
{
xoff -= polyobj->centerPt.x;
yoff += polyobj->centerPt.y;
}
}
#endif
// This appears to fix the Nimbus Ruins sky bug. // This appears to fix the Nimbus Ruins sky bug.
if (picnum == skyflatnum && pfloor) if (picnum == skyflatnum && pfloor)
{ {
@ -488,6 +506,7 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel,
&& !pfloor && !check->ffloor && !pfloor && !check->ffloor
&& check->viewx == viewx && check->viewy == viewy && check->viewz == viewz && check->viewx == viewx && check->viewy == viewy && check->viewz == viewz
&& check->viewangle == viewangle && check->viewangle == viewangle
&& check->plangle == plangle
#ifdef ESLOPE #ifdef ESLOPE
&& check->slope == slope && check->slope == slope
#endif #endif
@ -974,23 +993,65 @@ void R_DrawSinglePlane(visplane_t *pl)
#ifdef ESLOPE #ifdef ESLOPE
if (pl->slope) { if (pl->slope) {
// Potentially override other stuff for now cus we're mean. :< But draw a slope plane! // Potentially override other stuff for now cus we're mean. :< But draw a slope plane!
// I copied ZDoom's code and adapted it to SRB2... -Red // I copied ZDoom's code and adapted it to SRB2... -fickle
floatv3_t p, m, n; floatv3_t p, m, n;
float ang; float ang;
float vx, vy, vz; float vx, vy, vz;
float fudge;
// compiler complains when P_GetZAt is used in FLOAT_TO_FIXED directly // compiler complains when P_GetZAt is used in FLOAT_TO_FIXED directly
// use this as a temp var to store P_GetZAt's return value each time // use this as a temp var to store P_GetZAt's return value each time
fixed_t temp; fixed_t temp;
// Okay, look, don't ask me why this works, but without this setup there's a disgusting-looking misalignment with the textures. -fickle
const float fudge = ((1<<nflatshiftup)+1.0f)/(1<<nflatshiftup);
xoffs &= ((1 << (32-nflatshiftup))-1); angle_t hack = (pl->plangle & (ANGLE_90-1));
yoffs &= ((1 << (32-nflatshiftup))-1);
xoffs -= (pl->slope->o.x + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1); if (hack)
yoffs += (pl->slope->o.y + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1); {
/*
Essentially: We can't & the components along the regular axes when the plane is rotated.
This is because the distance on each regular axis in order to loop is different.
We rotate them, & the components, add them together, & them again, and then rotate them back.
These three seperate & operations are done per axis in order to prevent overflows.
toast 10/04/17
---
...of coooourse, this still isn't perfect. but it looks... merely kind of grody, rather than
completely wrong? idk. i'm just backporting this to kart right now. if anyone else wants to
ever try dig around: it's drifting towards 0,0, and no, multiplying by fudge doesn't fix it.
toast 27/09/18
*/
// Okay, look, don't ask me why this works, but without this setup there's a disgusting-looking misalignment with the textures. -Red const fixed_t cosinecomponent = FINECOSINE(hack>>ANGLETOFINESHIFT);
fudge = ((1<<nflatshiftup)+1.0f)/(1<<nflatshiftup); const fixed_t sinecomponent = FINESINE(hack>>ANGLETOFINESHIFT);
const fixed_t modmask = ((1 << (32-nflatshiftup)) - 1);
fixed_t ox = (FixedMul(pl->slope->o.x,cosinecomponent) & modmask) - (FixedMul(pl->slope->o.y,sinecomponent) & modmask);
fixed_t oy = (-FixedMul(pl->slope->o.x,sinecomponent) & modmask) - (FixedMul(pl->slope->o.y,cosinecomponent) & modmask);
temp = ox & modmask;
oy &= modmask;
ox = FixedMul(temp,cosinecomponent)+FixedMul(oy,-sinecomponent); // negative sine for opposite direction
oy = -FixedMul(temp,-sinecomponent)+FixedMul(oy,cosinecomponent);
temp = xoffs;
xoffs = (FixedMul(temp,cosinecomponent) & modmask) + (FixedMul(yoffs,sinecomponent) & modmask);
yoffs = (-FixedMul(temp,sinecomponent) & modmask) + (FixedMul(yoffs,cosinecomponent) & modmask);
temp = xoffs & modmask;
yoffs &= modmask;
xoffs = FixedMul(temp,cosinecomponent)+FixedMul(yoffs,-sinecomponent); // ditto
yoffs = -FixedMul(temp,-sinecomponent)+FixedMul(yoffs,cosinecomponent);
xoffs -= (pl->slope->o.x - ox);
yoffs += (pl->slope->o.y + oy);
}
else
{
xoffs &= ((1 << (32-nflatshiftup))-1);
yoffs &= ((1 << (32-nflatshiftup))-1);
xoffs -= (pl->slope->o.x + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1);
yoffs += (pl->slope->o.y + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1);
}
xoffs = (fixed_t)(xoffs*fudge); xoffs = (fixed_t)(xoffs*fudge);
yoffs = (fixed_t)(yoffs/fudge); yoffs = (fixed_t)(yoffs/fudge);

View file

@ -1137,7 +1137,7 @@ void Y_VoteDrawer(void)
else else
{ {
V_DrawFixedPatch((x+40)<<FRACBITS, (y)<<FRACBITS, FRACUNIT/4, V_SNAPTOLEFT|V_FLIP, pic, 0); V_DrawFixedPatch((x+40)<<FRACBITS, (y)<<FRACBITS, FRACUNIT/4, V_SNAPTOLEFT|V_FLIP, pic, 0);
V_DrawFixedPatch((x+20)<<FRACBITS, (y<<FRACBITS) + (25<<(FRACBITS-1)) - rubyheight, FRACUNIT/2, V_SNAPTORIGHT, rubyicon, NULL); V_DrawFixedPatch((x+20)<<FRACBITS, (y<<FRACBITS) + (25<<(FRACBITS-1)) - rubyheight, FRACUNIT/2, V_SNAPTOLEFT, rubyicon, NULL);
} }
if (levelinfo[votes[i]].gts) if (levelinfo[votes[i]].gts)