This is a doozy...

HUD:
* Miniaturised Spheres and Emeralds HUD for 3P/4P.
* Repair 3P minimap.
* Move accessibility icons in 3P/4P to next to the lap/bumper sticker (currently only kickstartaccel exists)
* Change language on menu retry to be more generalised.
* Adjust HUD code structuring a bit.

MECHANICAL:
* Now correctly set number of bumpers in Break the Capsules to 1 (from 3).
* The above required reworking K_SpawnBattleCapsules into K_BattleInit, which is a good staging ground to handle more battle-specific setup in future.
* Do not spawn Emeralds or Sphereboxes in Break the Capsules.
* If everyone is WANTED... nobody is.
* Try to handle exceptions to timelimits a little more thoroughly (still not perfect).
* Disable pointlimits in bosses.
This commit is contained in:
toaster 2022-03-05 22:31:43 +00:00
parent 9ac9abbb6e
commit bf43784d22
9 changed files with 350 additions and 180 deletions

View file

@ -54,6 +54,7 @@
// SRB2Kart // SRB2Kart
#include "s_sound.h" // song credits #include "s_sound.h" // song credits
#include "k_kart.h" #include "k_kart.h"
#include "k_boss.h"
#include "k_color.h" #include "k_color.h"
#include "k_hud.h" #include "k_hud.h"
#include "r_fps.h" #include "r_fps.h"
@ -2365,13 +2366,13 @@ static void HU_DrawRankings(void)
else else
V_DrawString(4, 188, hilicol|V_SNAPTOBOTTOM|V_SNAPTOLEFT, gametype_cons_t[gametype].strvalue); V_DrawString(4, 188, hilicol|V_SNAPTOBOTTOM|V_SNAPTOLEFT, gametype_cons_t[gametype].strvalue);
if (gametyperules & (GTR_TIMELIMIT|GTR_POINTLIMIT)) if ((gametyperules & (GTR_TIMELIMIT|GTR_POINTLIMIT)) && !bossinfo.boss)
{ {
if ((gametyperules & GTR_TIMELIMIT) && cv_timelimit.value && timelimitintics > 0) if ((gametyperules & GTR_TIMELIMIT) && cv_timelimit.value && timelimitintics > 0)
{ {
UINT32 timeval = (timelimitintics + starttime + 1 - leveltime); UINT32 timeval = (timelimitintics + starttime + 1 - leveltime);
if (timeval > timelimitintics+1) if (timeval > timelimitintics+1)
timeval = timelimitintics; timeval = timelimitintics+1;
timeval /= TICRATE; timeval /= TICRATE;
if (leveltime <= (timelimitintics + starttime)) if (leveltime <= (timelimitintics + starttime))

View file

@ -42,7 +42,17 @@ INT32 K_StartingBumperCount(void)
boolean K_IsPlayerWanted(player_t *player) boolean K_IsPlayerWanted(player_t *player)
{ {
return (player->position == 1); UINT8 i = 0, nump = 0, numfirst = 0;
for (; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator)
continue;
nump++;
if (players[i].position > 1)
continue;
numfirst++;
}
return ((numfirst < nump) && !player->spectator && (player->position == 1));
} }
void K_SpawnBattlePoints(player_t *source, player_t *victim, UINT8 amount) void K_SpawnBattlePoints(player_t *source, player_t *victim, UINT8 amount)
@ -307,6 +317,8 @@ void K_RunPaperItemSpawners(void)
const boolean overtime = (battleovertime.enabled >= 10*TICRATE); const boolean overtime = (battleovertime.enabled >= 10*TICRATE);
tic_t interval = 8*TICRATE; tic_t interval = 8*TICRATE;
const boolean canmakeemeralds = true; //(!(battlecapsules || bossinfo.boss));
UINT32 emeraldsSpawned = 0; UINT32 emeraldsSpawned = 0;
UINT32 firstUnspawnedEmerald = 0; UINT32 firstUnspawnedEmerald = 0;
@ -316,6 +328,12 @@ void K_RunPaperItemSpawners(void)
UINT8 pcount = 0; UINT8 pcount = 0;
INT16 i; INT16 i;
if (battlecapsules || bossinfo.boss)
{
// Gametype uses paper items, but this specific expression doesn't
return;
}
if (leveltime < starttime) if (leveltime < starttime)
{ {
// Round hasn't started yet! // Round hasn't started yet!
@ -369,14 +387,17 @@ void K_RunPaperItemSpawners(void)
} }
} }
for (i = 0; i < 7; i++) if (canmakeemeralds)
{ {
UINT32 emeraldFlag = (1 << i); for (i = 0; i < 7; i++)
if (!(emeraldsSpawned & emeraldFlag))
{ {
firstUnspawnedEmerald = emeraldFlag; UINT32 emeraldFlag = (1 << i);
break;
if (!(emeraldsSpawned & emeraldFlag))
{
firstUnspawnedEmerald = emeraldFlag;
break;
}
} }
} }
@ -396,11 +417,14 @@ void K_RunPaperItemSpawners(void)
0, 0 0, 0
); );
K_SpawnSphereBox( if (gametyperules & GTR_SPHERES)
battleovertime.x, battleovertime.y, battleovertime.z + (128 * mapobjectscale * flip), {
FixedAngle(P_RandomRange(0, 359) * FRACUNIT), flip, K_SpawnSphereBox(
10 battleovertime.x, battleovertime.y, battleovertime.z + (128 * mapobjectscale * flip),
); FixedAngle(P_RandomRange(0, 359) * FRACUNIT), flip,
10
);
}
} }
} }
else else
@ -442,15 +466,18 @@ void K_RunPaperItemSpawners(void)
return; return;
} }
for (i = 0; i < 7; i++) if (canmakeemeralds)
{ {
UINT32 emeraldFlag = (1 << i); for (i = 0; i < 7; i++)
if (!(emeraldsSpawned & emeraldFlag))
{ {
firstUnspawnedEmerald = emeraldFlag; UINT32 emeraldFlag = (1 << i);
starti = -1;
break; if (!(emeraldsSpawned & emeraldFlag))
{
firstUnspawnedEmerald = emeraldFlag;
starti = -1;
break;
}
} }
} }
@ -485,12 +512,15 @@ void K_RunPaperItemSpawners(void)
} }
else else
{ {
drop = K_SpawnSphereBox( if (gametyperules & GTR_SPHERES)
spotList[r]->x, spotList[r]->y, spotList[r]->z + (128 * mapobjectscale * flip), {
FixedAngle(P_RandomRange(0, 359) * FRACUNIT), flip, drop = K_SpawnSphereBox(
10 spotList[r]->x, spotList[r]->y, spotList[r]->z + (128 * mapobjectscale * flip),
); FixedAngle(P_RandomRange(0, 359) * FRACUNIT), flip,
K_FlipFromObject(drop, spotList[r]); 10
);
K_FlipFromObject(drop, spotList[r]);
}
drop = K_CreatePaperItem( drop = K_CreatePaperItem(
spotList[r]->x, spotList[r]->y, spotList[r]->z + (128 * mapobjectscale * flip), spotList[r]->x, spotList[r]->y, spotList[r]->z + (128 * mapobjectscale * flip),
@ -703,44 +733,79 @@ void K_SetupMovingCapsule(mapthing_t *mt, mobj_t *mobj)
} }
} }
void K_SpawnBattleCapsules(void) void K_SpawnPlayerBattleBumpers(player_t *p)
{
if (!p->mo || p->bumpers <= 0)
return;
{
INT32 i;
angle_t diff = FixedAngle(360*FRACUNIT/p->bumpers);
angle_t newangle = p->mo->angle;
mobj_t *bump;
for (i = 0; i < p->bumpers; i++)
{
bump = P_SpawnMobjFromMobj(p->mo,
P_ReturnThrustX(p->mo, newangle + ANGLE_180, 64*FRACUNIT),
P_ReturnThrustY(p->mo, newangle + ANGLE_180, 64*FRACUNIT),
0, MT_BATTLEBUMPER);
bump->threshold = i;
P_SetTarget(&bump->target, p->mo);
bump->angle = newangle;
bump->color = p->mo->color;
if (p->mo->renderflags & RF_DONTDRAW)
bump->renderflags |= RF_DONTDRAW;
else
bump->renderflags &= ~RF_DONTDRAW;
newangle += diff;
}
}
}
void K_BattleInit(void)
{ {
mapthing_t *mt;
size_t i; size_t i;
if (battlecapsules) if ((gametyperules & GTR_CAPSULES) && !battlecapsules && !bossinfo.boss)
return;
if (bossinfo.boss)
return;
if (!(gametyperules & GTR_CAPSULES))
return;
if (modeattacking != ATTACKING_CAPSULES)
{ {
UINT8 n = 0; mapthing_t *mt;
if (modeattacking != ATTACKING_CAPSULES)
{
UINT8 n = 0;
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator)
continue;
n++;
}
if (n > 1)
goto aftercapsules;
}
mt = mapthings;
for (i = 0; i < nummapthings; i++, mt++)
{
if (mt->type == mobjinfo[MT_BATTLECAPSULE].doomednum)
P_SpawnMapThing(mt);
}
battlecapsules = true;
}
aftercapsules:
if (gametyperules & GTR_BUMPERS)
{
INT32 maxbumpers = K_StartingBumperCount();
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
if (playeringame[i] && !players[i].spectator) if (!playeringame[i] || players[i].spectator)
n++; continue;
if (players[i].exiting) players[i].bumpers = maxbumpers;
return; K_SpawnPlayerBattleBumpers(players+i);
if (n > 1)
break;
} }
if (n > 1)
return;
} }
mt = mapthings;
for (i = 0; i < nummapthings; i++, mt++)
{
if (mt->type == mobjinfo[MT_BATTLECAPSULE].doomednum)
P_SpawnMapThing(mt);
}
battlecapsules = true;
} }

View file

@ -28,6 +28,7 @@ UINT8 K_NumEmeralds(player_t *player);
void K_RunPaperItemSpawners(void); void K_RunPaperItemSpawners(void);
void K_RunBattleOvertime(void); void K_RunBattleOvertime(void);
void K_SetupMovingCapsule(mapthing_t *mt, mobj_t *mobj); void K_SetupMovingCapsule(mapthing_t *mt, mobj_t *mobj);
void K_SpawnBattleCapsules(void); void K_SpawnPlayerBattleBumpers(player_t *p);
void K_BattleInit(void);
#endif #endif

View file

@ -55,6 +55,7 @@ static patch_t *kp_capsulesticker;
static patch_t *kp_capsulestickerwide; static patch_t *kp_capsulestickerwide;
static patch_t *kp_karmasticker; static patch_t *kp_karmasticker;
static patch_t *kp_spheresticker; static patch_t *kp_spheresticker;
static patch_t *kp_splitspheresticker;
static patch_t *kp_splitkarmabomb; static patch_t *kp_splitkarmabomb;
static patch_t *kp_timeoutsticker; static patch_t *kp_timeoutsticker;
@ -192,6 +193,7 @@ void K_LoadKartHUDGraphics(void)
kp_capsulestickerwide = W_CachePatchName("K_STCAPW", PU_HUDGFX); kp_capsulestickerwide = W_CachePatchName("K_STCAPW", PU_HUDGFX);
kp_karmasticker = W_CachePatchName("K_STKARM", PU_HUDGFX); kp_karmasticker = W_CachePatchName("K_STKARM", PU_HUDGFX);
kp_spheresticker = W_CachePatchName("K_STBSMT", PU_HUDGFX); kp_spheresticker = W_CachePatchName("K_STBSMT", PU_HUDGFX);
kp_splitspheresticker = W_CachePatchName("K_SPBSMT", PU_HUDGFX);
kp_splitkarmabomb = W_CachePatchName("K_SPTKRM", PU_HUDGFX); kp_splitkarmabomb = W_CachePatchName("K_SPTKRM", PU_HUDGFX);
kp_timeoutsticker = W_CachePatchName("K_STTOUT", PU_HUDGFX); kp_timeoutsticker = W_CachePatchName("K_STTOUT", PU_HUDGFX);
@ -1456,17 +1458,34 @@ void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT16 emblemmap, UI
// TIME_Y = 6; // 6 // TIME_Y = 6; // 6
tic_t worktime; tic_t worktime;
boolean dontdraw = false;
INT32 splitflags = 0; INT32 splitflags = 0;
if (!mode) if (!mode)
{ {
splitflags = V_HUDTRANS|V_SLIDEIN|V_SNAPTOTOP|V_SNAPTORIGHT|V_SPLITSCREEN; splitflags = V_HUDTRANS|V_SLIDEIN|V_SNAPTOTOP|V_SNAPTORIGHT|V_SPLITSCREEN;
if (cv_timelimit.value && timelimitintics > 0 && !bossinfo.boss) // TODO
#ifndef TESTOVERTIMEINFREEPLAY
if (battlecapsules) // capsules override any time limit settings
;
else
#endif
if (bossinfo.boss == true)
;
else if (timelimitintics > 0 && (gametyperules & GTR_TIMELIMIT)) // TODO
{ {
if (drawtime >= timelimitintics) if (drawtime >= timelimitintics)
{
if (((drawtime-timelimitintics)/TICRATE) & 1)
{
dontdraw = true;
}
drawtime = 0; drawtime = 0;
}
else else
{
drawtime = timelimitintics - drawtime; drawtime = timelimitintics - drawtime;
}
} }
} }
@ -1478,6 +1497,8 @@ void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT16 emblemmap, UI
if (mode && !drawtime) if (mode && !drawtime)
V_DrawKartString(TX, TY+3, splitflags, va("--'--\"--")); V_DrawKartString(TX, TY+3, splitflags, va("--'--\"--"));
else if (dontdraw) // overtime flash
;
else if (worktime < 100) // 99:99:99 only else if (worktime < 100) // 99:99:99 only
{ {
// zero minute // zero minute
@ -1581,13 +1602,13 @@ void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT16 emblemmap, UI
goto bademblem; goto bademblem;
} }
V_DrawRightAlignedString(workx, worky, splitflags, targettext); V_DrawRightAlignedString(workx, worky, splitflags|V_6WIDTHSPACE, targettext);
workx -= 67; workx -= 67;
V_DrawSmallScaledPatch(workx + 4, worky, splitflags, W_CachePatchName("NEEDIT", PU_CACHE)); V_DrawSmallScaledPatch(workx + 4, worky, splitflags, W_CachePatchName("NEEDIT", PU_CACHE));
break; break;
bademblem: bademblem:
emblem = M_GetLevelEmblems(-1); emblem = M_GetLevelEmblems(-1);
} }
@ -2020,22 +2041,49 @@ static void K_drawBossHealthBar(void)
static void K_drawKartEmeralds(void) static void K_drawKartEmeralds(void)
{ {
static const INT32 emeraldOffsets[7][2] = { static const INT32 emeraldOffsets[7][3] = {
{34, 0}, {34, 0, 15},
{25, 8}, {25, 8, 11},
{43, 8}, {43, 8, 19},
{16, 0}, {16, 0, 7},
{52, 0}, {52, 0, 23},
{7, 8}, { 7, 8, 3},
{61, 8} {61, 8, 27}
}; };
const INT32 startx = BASEVIDWIDTH - 77 - 8; INT32 splitflags = V_SLIDEIN|V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_SPLITSCREEN;
const INT32 starty = BASEVIDHEIGHT - 29 - 8; INT32 startx = BASEVIDWIDTH - 77;
INT32 starty = BASEVIDHEIGHT - 29;
INT32 i = 0, xindex = 0;
INT32 i; {
if (r_splitscreen)
{
starty = (starty/2) - 8;
}
starty -= 8;
V_DrawScaledPatch(startx, starty, V_HUDTRANS|V_SLIDEIN|V_SNAPTOBOTTOM|V_SNAPTORIGHT, kp_rankemeraldback); if (r_splitscreen < 2)
{
startx -= 8;
V_DrawScaledPatch(startx, starty, V_HUDTRANS|splitflags, kp_rankemeraldback);
}
else
{
xindex = 2;
starty -= 15;
if (stplyr == &players[displayplayers[0]] || stplyr == &players[displayplayers[2]]) // If we are P1 or P3...
{
startx = LAPS_X;
splitflags = V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_SPLITSCREEN;
}
else // else, that means we're P2 or P4.
{
startx = LAPS2_X + 1;
splitflags = V_SNAPTORIGHT|V_SNAPTOBOTTOM|V_SPLITSCREEN;
}
}
}
for (i = 0; i < 7; i++) for (i = 0; i < 7; i++)
{ {
@ -2054,16 +2102,16 @@ static void K_drawKartEmeralds(void)
colormap = R_GetTranslationColormap(TC_DEFAULT, emeraldColor, GTC_CACHE); colormap = R_GetTranslationColormap(TC_DEFAULT, emeraldColor, GTC_CACHE);
V_DrawMappedPatch( V_DrawMappedPatch(
startx + emeraldOffsets[i][0], starty + emeraldOffsets[i][1], startx + emeraldOffsets[i][xindex], starty + emeraldOffsets[i][1],
V_HUDTRANS|V_SLIDEIN|V_SNAPTOBOTTOM|V_SNAPTORIGHT, V_HUDTRANS|splitflags,
kp_rankemerald, colormap kp_rankemerald, colormap
); );
if (whiteFlash == true) if (whiteFlash == true)
{ {
V_DrawScaledPatch( V_DrawScaledPatch(
startx + emeraldOffsets[i][0], starty + emeraldOffsets[i][1], startx + emeraldOffsets[i][xindex], starty + emeraldOffsets[i][1],
V_HUDTRANSHALF|V_SLIDEIN|V_SNAPTOBOTTOM|V_SNAPTORIGHT, V_HUDTRANSHALF|splitflags,
kp_rankemeraldflash kp_rankemeraldflash
); );
} }
@ -2328,7 +2376,8 @@ static void K_drawKartLapsAndRings(void)
{ {
UINT8 *colormap = R_GetTranslationColormap(stplyr->skin, stplyr->skincolor, GTC_CACHE); UINT8 *colormap = R_GetTranslationColormap(stplyr->skin, stplyr->skincolor, GTC_CACHE);
V_DrawMappedPatch(fr+21, fy-13, V_HUDTRANS|V_SLIDEIN|splitflags, faceprefix[stplyr->skin][FACE_MINIMAP], colormap); V_DrawMappedPatch(fr+21, fy-13, V_HUDTRANS|V_SLIDEIN|splitflags, faceprefix[stplyr->skin][FACE_MINIMAP], colormap);
V_DrawScaledPatch(fr+34, fy-10, V_HUDTRANS|V_SLIDEIN|splitflags, fontv[PINGNUM_FONT].font[(stplyr->lives % 10)]); // make sure this doesn't overflow if (stplyr->lives >= 0)
V_DrawScaledPatch(fr+34, fy-10, V_HUDTRANS|V_SLIDEIN|splitflags, fontv[PINGNUM_FONT].font[(stplyr->lives % 10)]); // make sure this doesn't overflow OR underflow
} }
} }
else else
@ -2366,7 +2415,8 @@ static void K_drawKartLapsAndRings(void)
{ {
UINT8 *colormap = R_GetTranslationColormap(stplyr->skin, stplyr->skincolor, GTC_CACHE); UINT8 *colormap = R_GetTranslationColormap(stplyr->skin, stplyr->skincolor, GTC_CACHE);
V_DrawMappedPatch(LAPS_X+46, LAPS_Y-16, V_HUDTRANS|V_SLIDEIN|splitflags, faceprefix[stplyr->skin][FACE_RANK], colormap); V_DrawMappedPatch(LAPS_X+46, LAPS_Y-16, V_HUDTRANS|V_SLIDEIN|splitflags, faceprefix[stplyr->skin][FACE_RANK], colormap);
V_DrawScaledPatch(LAPS_X+63, LAPS_Y-11, V_HUDTRANS|V_SLIDEIN|splitflags, kp_facenum[(stplyr->lives % 10)]); // make sure this doesn't overflow if (stplyr->lives >= 0)
V_DrawScaledPatch(LAPS_X+63, LAPS_Y-11, V_HUDTRANS|V_SLIDEIN|splitflags, kp_facenum[(stplyr->lives % 10)]); // make sure this doesn't overflow OR underflow
} }
} }
} }
@ -2388,7 +2438,8 @@ static void K_drawKartAccessibilityIcons(INT32 fx)
} }
else else
{ {
fy += 4; fx = LAPS_X+43;
fy = LAPS_Y;
if (!(stplyr == &players[displayplayers[0]] || stplyr == &players[displayplayers[2]])) // If we are not P1 or P3... if (!(stplyr == &players[displayplayers[0]] || stplyr == &players[displayplayers[2]])) // If we are not P1 or P3...
{ {
splitflags ^= (V_SNAPTOLEFT|V_SNAPTORIGHT); splitflags ^= (V_SNAPTOLEFT|V_SNAPTORIGHT);
@ -2492,25 +2543,81 @@ static void K_drawBlueSphereMeter(void)
UINT8 numBars = min((sphere / 10), maxBars); UINT8 numBars = min((sphere / 10), maxBars);
UINT8 colorIndex = (sphere * sizeof(segColors)) / (40 + 1); UINT8 colorIndex = (sphere * sizeof(segColors)) / (40 + 1);
INT32 x = LAPS_X + 25; INT32 fx, fy;
UINT8 i; UINT8 i;
INT32 splitflags = V_HUDTRANS|V_SLIDEIN|V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_SPLITSCREEN;
INT32 flipflag = 0;
INT32 xstep = 15;
V_DrawScaledPatch(LAPS_X, LAPS_Y - 22, V_HUDTRANS|V_SLIDEIN|V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_SPLITSCREEN, kp_spheresticker); // pain and suffering defined below
if (r_splitscreen < 2) // don't change shit for THIS splitscreen.
{
fx = LAPS_X;
fy = LAPS_Y-22;
V_DrawScaledPatch(fx, fy, splitflags|flipflag, kp_spheresticker);
}
else
{
xstep = 8;
if (stplyr == &players[displayplayers[0]] || stplyr == &players[displayplayers[2]]) // If we are P1 or P3...
{
fx = LAPS_X-2;
fy = LAPS_Y;
}
else // else, that means we're P2 or P4.
{
fx = LAPS2_X+(SHORT(kp_splitspheresticker->width) - 10);
fy = LAPS2_Y;
splitflags ^= V_SNAPTOLEFT|V_SNAPTORIGHT;
flipflag = V_FLIP; // make the string right aligned and other shit
xstep = -xstep;
}
fy -= 16;
V_DrawScaledPatch(fx, fy, splitflags|flipflag, kp_splitspheresticker);
}
if (r_splitscreen < 2)
{
fx += 25;
}
else
{
fx += (flipflag) ? -18 : 13;
}
for (i = 0; i <= numBars; i++) for (i = 0; i <= numBars; i++)
{ {
UINT8 segLen = 10; UINT8 segLen = (r_splitscreen < 2) ? 10 : 5;
if (i == numBars) if (i == numBars)
{ {
segLen = (sphere % 10); segLen = (sphere % 10);
if (r_splitscreen < 2)
;
else
{
segLen = (segLen+1)/2; // offset so nonzero spheres shows up IMMEDIATELY
if (!segLen)
break;
if (flipflag)
fx += (5-segLen);
}
} }
V_DrawFill(x, LAPS_Y - 16, segLen, 3, segColors[max(colorIndex-1, 0)] | V_HUDTRANS|V_SLIDEIN|V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_SPLITSCREEN); if (r_splitscreen < 2)
V_DrawFill(x, LAPS_Y - 15, segLen, 1, segColors[max(colorIndex-2, 0)] | V_HUDTRANS|V_SLIDEIN|V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_SPLITSCREEN); {
V_DrawFill(x, LAPS_Y - 13, segLen, 3, segColors[colorIndex] | V_HUDTRANS|V_SLIDEIN|V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_SPLITSCREEN); V_DrawFill(fx, fy + 6, segLen, 3, segColors[max(colorIndex-1, 0)] | splitflags);
V_DrawFill(fx, fy + 7, segLen, 1, segColors[max(colorIndex-2, 0)] | splitflags);
V_DrawFill(fx, fy + 9, segLen, 3, segColors[colorIndex] | splitflags);
}
else
{
V_DrawFill(fx, fy + 5, segLen, 1, segColors[max(colorIndex-1, 0)] | splitflags);
V_DrawFill(fx, fy + 6, segLen, 1, segColors[max(colorIndex-2, 0)] | splitflags);
V_DrawFill(fx, fy + 7, segLen, 2, segColors[colorIndex] | splitflags);
}
x += 15; fx += xstep;
} }
} }
@ -2536,13 +2643,13 @@ static void K_drawKartBumpersOrKarma(void)
{ {
fx = LAPS_X; fx = LAPS_X;
fy = LAPS_Y; fy = LAPS_Y;
splitflags = V_SNAPTOLEFT|((stplyr == &players[displayplayers[2]]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P3 to the bottom. splitflags = V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_SPLITSCREEN;
} }
else // else, that means we're P2 or P4. else // else, that means we're P2 or P4.
{ {
fx = LAPS2_X; fx = LAPS2_X;
fy = LAPS2_Y; fy = LAPS2_Y;
splitflags = V_SNAPTORIGHT|((stplyr == &players[displayplayers[3]]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P4 to the bottom splitflags = V_SNAPTORIGHT|V_SNAPTOBOTTOM|V_SPLITSCREEN;
flipflag = V_FLIP; // make the string right aligned and other shit flipflag = V_FLIP; // make the string right aligned and other shit
} }
} }
@ -3316,7 +3423,8 @@ static void K_drawKartMinimap(void)
patch_t *AutomapPic; patch_t *AutomapPic;
INT32 i = 0; INT32 i = 0;
INT32 x, y; INT32 x, y;
INT32 minimaptrans, splitflags = (r_splitscreen == 3 ? 0 : (V_SLIDEIN|V_SNAPTORIGHT)); // flags should only be 0 when it's centered (4p split) INT32 minimaptrans = cv_kartminimap.value;
INT32 splitflags = 0;
UINT8 skin = 0; UINT8 skin = 0;
UINT8 *colormap = NULL; UINT8 *colormap = NULL;
SINT8 localplayers[4]; SINT8 localplayers[4];
@ -3342,20 +3450,26 @@ static void K_drawKartMinimap(void)
else else
return; // no pic, just get outta here return; // no pic, just get outta here
x = MINI_X - (AutomapPic->width/2); if (r_splitscreen < 2) // 1/2P right aligned
y = MINI_Y - (AutomapPic->height/2); {
splitflags = (V_SLIDEIN|V_SNAPTORIGHT);
}
else if (r_splitscreen == 3) // 4P centered
{ {
const tic_t length = TICRATE/2; const tic_t length = TICRATE/2;
if (!lt_exitticker) if (!lt_exitticker)
return; return;
minimaptrans = cv_kartminimap.value;
if (lt_exitticker < length) if (lt_exitticker < length)
minimaptrans = (((INT32)lt_exitticker)*minimaptrans)/((INT32)length); minimaptrans = (((INT32)lt_exitticker)*minimaptrans)/((INT32)length);
if (!minimaptrans)
return;
} }
// 3P lives in the middle of the bottom right player and shouldn't fade in OR slide
if (!minimaptrans)
return;
x = MINI_X - (AutomapPic->width/2);
y = MINI_Y - (AutomapPic->height/2);
minimaptrans = ((10-minimaptrans)<<FF_TRANSSHIFT); minimaptrans = ((10-minimaptrans)<<FF_TRANSSHIFT);
splitflags |= minimaptrans; splitflags |= minimaptrans;
@ -3365,7 +3479,6 @@ static void K_drawKartMinimap(void)
else else
V_DrawScaledPatch(x, y, splitflags, AutomapPic); V_DrawScaledPatch(x, y, splitflags, AutomapPic);
if (r_splitscreen != 2)
{ {
splitflags &= ~minimaptrans; splitflags &= ~minimaptrans;
splitflags |= V_HUDTRANSHALF; splitflags |= V_HUDTRANSHALF;
@ -3515,8 +3628,10 @@ static void K_drawKartMinimap(void)
} }
// draw our local players here, opaque. // draw our local players here, opaque.
splitflags &= ~V_HUDTRANSHALF; {
splitflags |= V_HUDTRANS; splitflags &= ~V_HUDTRANSHALF;
splitflags |= V_HUDTRANS;
}
// ...but first, any boss targets. // ...but first, any boss targets.
if (bossinfo.boss) if (bossinfo.boss)
@ -4571,7 +4686,7 @@ static void K_DrawWaypointDebugger(void)
void K_drawKartHUD(void) void K_drawKartHUD(void)
{ {
boolean isfreeplay = false; boolean islonesome = false;
boolean battlefullscreen = false; boolean battlefullscreen = false;
boolean freecam = demo.freecam; //disable some hud elements w/ freecam boolean freecam = demo.freecam; //disable some hud elements w/ freecam
UINT8 i; UINT8 i;
@ -4645,12 +4760,7 @@ void K_drawKartHUD(void)
if (LUA_HudEnabled(hud_time)) if (LUA_HudEnabled(hud_time))
K_drawKartTimestamp(stplyr->realtime, TIME_X, TIME_Y, gamemap, 0); K_drawKartTimestamp(stplyr->realtime, TIME_X, TIME_Y, gamemap, 0);
if (!modeattacking) islonesome = K_drawKartPositionFaces();
{
// The top-four faces on the left
//if (LUA_HudEnabled(hud_minirankings))
isfreeplay = K_drawKartPositionFaces();
}
} }
if (!stplyr->spectator && !demo.freecam) // Bottom of the screen elements, don't need in spectate mode if (!stplyr->spectator && !demo.freecam) // Bottom of the screen elements, don't need in spectate mode
@ -4669,48 +4779,65 @@ void K_drawKartHUD(void)
V_DrawTinyScaledPatch(x-54, y, snapflags|V_SLIDEIN, W_CachePatchName("TTKBANNR", PU_CACHE)); V_DrawTinyScaledPatch(x-54, y, snapflags|V_SLIDEIN, W_CachePatchName("TTKBANNR", PU_CACHE));
V_DrawTinyScaledPatch(x-54, y+25, snapflags|V_SLIDEIN, W_CachePatchName("TTKART", PU_CACHE)); V_DrawTinyScaledPatch(x-54, y+25, snapflags|V_SLIDEIN, W_CachePatchName("TTKART", PU_CACHE));
} }
else if (gametype == GT_RACE) // Race-only elements else
{ {
// Draw the lap counter if (LUA_HudEnabled(hud_position))
if (LUA_HudEnabled(hud_gametypeinfo))
K_drawKartLapsAndRings();
if (isfreeplay)
;
else if (!modeattacking)
{ {
// Draw the numerical position if (bossinfo.boss)
if (LUA_HudEnabled(hud_position)) {
K_DrawKartPositionNum(stplyr->position); K_drawBossHealthBar();
}
else if (gametype == GT_RACE) // Race-only elements (not currently gametyperuleable)
{
if (!islonesome)
{
// Draw the numerical position
K_DrawKartPositionNum(stplyr->position);
}
}
else if (gametype == GT_BATTLE) // Battle-only (ditto)
{
if (!freecam && !battlecapsules)
{
K_drawKartEmeralds();
}
}
} }
else //if (!(demo.playback && hu_showscores))
if (LUA_HudEnabled(hud_gametypeinfo))
{
if (gametyperules & GTR_CIRCUIT)
{
K_drawKartLapsAndRings();
}
else if (gametyperules & GTR_BUMPERS)
{
K_drawKartBumpersOrKarma();
}
}
// Draw the speedometer and/or accessibility icons
if (cv_kartspeedometer.value && !r_splitscreen && (LUA_HudEnabled(hud_speedometer)))
{
K_drawKartSpeedometer();
}
else
{
K_drawKartAccessibilityIcons(0);
}
if (gametyperules & GTR_SPHERES)
{
K_drawBlueSphereMeter();
}
if (modeattacking && !bossinfo.boss)
{ {
// Draw the input UI // Draw the input UI
if (LUA_HudEnabled(hud_position)) if (LUA_HudEnabled(hud_position))
K_drawInput(); K_drawInput();
} }
} }
else if (gametype == GT_BATTLE) // Battle-only
{
// Draw the hits left!
if (LUA_HudEnabled(hud_gametypeinfo))
K_drawKartBumpersOrKarma();
}
// Draw the speedometer and/or accessibility icons
if (cv_kartspeedometer.value && !r_splitscreen && (LUA_HudEnabled(hud_speedometer)))
{
K_drawKartSpeedometer();
}
else
{
K_drawKartAccessibilityIcons((r_splitscreen > 1) ? 0 : 8);
}
if (gametyperules & GTR_SPHERES)
{
K_drawBlueSphereMeter();
}
} }
// Draw the countdowns after everything else. // Draw the countdowns after everything else.
@ -4746,18 +4873,6 @@ void K_drawKartHUD(void)
if (stplyr->karthud[khud_trickcool]) if (stplyr->karthud[khud_trickcool])
K_drawTrickCool(); K_drawTrickCool();
if (gametype == GT_BATTLE)
{
if (bossinfo.boss)
{
K_drawBossHealthBar();
}
else if (!freecam)
{
K_drawKartEmeralds();
}
}
if (modeattacking || freecam) // everything after here is MP and debug only if (modeattacking || freecam) // everything after here is MP and debug only
return; return;
@ -4765,7 +4880,7 @@ void K_drawKartHUD(void)
V_DrawScaledPatch(BASEVIDWIDTH/2 - (SHORT(kp_yougotem->width)/2), 32, V_HUDTRANS, kp_yougotem); V_DrawScaledPatch(BASEVIDWIDTH/2 - (SHORT(kp_yougotem->width)/2), 32, V_HUDTRANS, kp_yougotem);
// Draw FREE PLAY. // Draw FREE PLAY.
if (isfreeplay && !bossinfo.boss && !stplyr->spectator) if (islonesome && !modeattacking && !bossinfo.boss && !stplyr->spectator)
{ {
if (LUA_HudEnabled(hud_freeplay)) if (LUA_HudEnabled(hud_freeplay))
K_drawKartFreePlay(); K_drawKartFreePlay();

View file

@ -103,7 +103,7 @@ void K_TimerInit(void)
starttime = (introtime + (3*TICRATE)) + ((2*TICRATE) + (numbulbs * bulbtime)); // Start countdown time, + buffer time starttime = (introtime + (3*TICRATE)) + ((2*TICRATE) + (numbulbs * bulbtime)); // Start countdown time, + buffer time
// NOW you can try to spawn in the Battle capsules, if there's not enough players for a match // NOW you can try to spawn in the Battle capsules, if there's not enough players for a match
K_SpawnBattleCapsules(); K_BattleInit();
//CONS_Printf("numbulbs set to %d (%d players, %d spectators) on tic %d\n", numbulbs, numPlayers, numspec, leveltime); //CONS_Printf("numbulbs set to %d (%d players, %d spectators) on tic %d\n", numbulbs, numPlayers, numspec, leveltime);
} }

View file

@ -6369,7 +6369,7 @@ static void M_RetryResponse(INT32 ch)
static void M_Retry(INT32 choice) static void M_Retry(INT32 choice)
{ {
(void)choice; (void)choice;
M_StartMessage(va("Start this %s over?\n\n(Press 'Y' to confirm)\n", (bossinfo.boss == true) ? "boss" : "race"),M_RetryResponse,MM_YESNO); M_StartMessage(va("Start this %s over?\n\n(Press 'Y' to confirm)\n", (gametyperules & GTR_CIRCUIT) ? "race" : "battle"),M_RetryResponse,MM_YESNO);
} }
static void M_SelectableClearMenus(INT32 choice) static void M_SelectableClearMenus(INT32 choice)

View file

@ -634,10 +634,10 @@ void P_CheckTimeLimit(void)
if (!(gametyperules & GTR_TIMELIMIT)) if (!(gametyperules & GTR_TIMELIMIT))
return; return;
if (leveltime < (timelimitintics + starttime)) if (bossinfo.boss == true)
return; return;
if (bossinfo.boss == true) if (leveltime < (timelimitintics + starttime))
return; return;
if (gameaction == ga_completed) if (gameaction == ga_completed)
@ -736,6 +736,9 @@ void P_CheckPointLimit(void)
if (!(gametyperules & GTR_POINTLIMIT)) if (!(gametyperules & GTR_POINTLIMIT))
return; return;
if (bossinfo.boss == true)
return;
// pointlimit is nonzero, check if it's been reached by this player // pointlimit is nonzero, check if it's been reached by this player
if (G_GametypeHasTeams()) if (G_GametypeHasTeams())
{ {

View file

@ -10935,29 +10935,14 @@ void P_SpawnPlayer(INT32 playernum)
{ {
if ((leveltime < starttime) || (pcount <= 1)) // Start of the map? if ((leveltime < starttime) || (pcount <= 1)) // Start of the map?
{ {
// Reset those bumpers! if (leveltime > 2) // Reset those bumpers!
p->bumpers = K_StartingBumperCount();
}
if (p->bumpers)
{
angle_t diff = FixedAngle(360*FRACUNIT/p->bumpers);
angle_t newangle = mobj->angle;
fixed_t newx = mobj->x + P_ReturnThrustX(mobj, newangle + ANGLE_180, 64*FRACUNIT);
fixed_t newy = mobj->y + P_ReturnThrustY(mobj, newangle + ANGLE_180, 64*FRACUNIT);
mobj_t *mo;
for (i = 0; i < p->bumpers; i++)
{ {
mo = P_SpawnMobj(newx, newy, mobj->z, MT_BATTLEBUMPER); p->bumpers = K_StartingBumperCount();
mo->threshold = i; K_SpawnPlayerBattleBumpers(p);
P_SetTarget(&mo->target, mobj); }
mo->angle = (diff * (i-1)); else // temp, will get overwritten in K_BattleInit
mo->color = mobj->color; {
if (mobj->renderflags & RF_DONTDRAW) p->bumpers = 1;
mo->renderflags |= RF_DONTDRAW;
else
mo->renderflags &= ~RF_DONTDRAW;
} }
} }
} }

View file

@ -86,7 +86,7 @@
// SRB2Kart // SRB2Kart
#include "k_kart.h" #include "k_kart.h"
#include "k_race.h" #include "k_race.h"
#include "k_battle.h" // K_SpawnBattleCapsules #include "k_battle.h" // K_BattleInit
#include "k_pwrlv.h" #include "k_pwrlv.h"
#include "k_waypoint.h" #include "k_waypoint.h"
#include "k_bot.h" #include "k_bot.h"