Merge branch 'master' into update-version

This commit is contained in:
TehRealSalt 2018-11-02 23:57:28 -04:00
commit 0eab0c5a14
46 changed files with 8993 additions and 2393 deletions

View File

@ -1600,6 +1600,31 @@ void CV_AddValue(consvar_t *var, INT32 increment)
return;
}
}
else if (var == &cv_kartspeed)
{
INT32 maxspeed = (M_SecretUnlocked(SECRET_HARDSPEED) ? 2 : 1);
// Special case for the kartspeed variable, used only directly from the menu to prevent selecting hard mode
if (increment > 0) // Going up!
{
newvalue = var->value + 1;
if (newvalue > maxspeed)
newvalue = 0;
var->value = newvalue;
var->string = var->PossibleValue[var->value].strvalue;
var->func();
return;
}
else if (increment < 0) // Going down!
{
newvalue = var->value - 1;
if (newvalue < 0)
newvalue = maxspeed;
var->value = newvalue;
var->string = var->PossibleValue[var->value].strvalue;
var->func();
return;
}
}
#ifdef PARANOIA
if (currentindice == -1)
I_Error("CV_AddValue: current value %d not found in possible value\n",

View File

@ -134,11 +134,15 @@ static CV_PossibleValue_t backpic_cons_t[] = {{0, "translucent"}, {1, "picture"}
// whether to use console background picture, or translucent mode
static consvar_t cons_backpic = {"con_backpic", "translucent", CV_SAVE, backpic_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t backcolor_cons_t[] = {{0, "White"}, {1, "Gray"}, {2, "Brown"},
{3, "Red"}, {4, "Orange"}, {5, "Yellow"},
{6, "Green"}, {7, "Blue"}, {8, "Cyan"},
static CV_PossibleValue_t backcolor_cons_t[] = {{0, "White"}, {1, "Black"}, {2, "Sepia"},
{3, "Brown"}, {4, "Pink"}, {5, "Raspberry"},
{6, "Red"}, {7, "Creamsicle"}, {8, "Orange"},
{9, "Gold"}, {10,"Yellow"}, {11,"Emerald"},
{12,"Green"}, {13,"Cyan"}, {14,"Steel"},
{15,"Periwinkle"}, {16,"Blue"}, {17,"Purple"},
{18,"Lavender"},
{0, NULL}};
consvar_t cons_backcolor = {"con_backcolor", "Green", CV_CALL|CV_SAVE, backcolor_cons_t, CONS_backcolor_Change, 0, NULL, NULL, 0, 0, NULL};
consvar_t cons_backcolor = {"con_backcolor", "Black", CV_CALL|CV_SAVE, backcolor_cons_t, CONS_backcolor_Change, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t menuhighlight_cons_t[] =
{
@ -255,21 +259,32 @@ void CON_SetupBackColormap(void)
UINT16 i, palsum;
UINT8 j, palindex;
UINT8 *pal = W_CacheLumpName(GetPalette(), PU_CACHE);
INT32 shift = 6;
if (!consolebgmap)
consolebgmap = (UINT8 *)Z_Malloc(256, PU_STATIC, NULL);
switch (cons_backcolor.value)
{
case 0: palindex = 15; break; // White
case 1: palindex = 31; break; // Gray
case 2: palindex = 63; break; // Brown
case 3: palindex = 143; break; // Red
case 4: palindex = 95; break; // Orange
case 5: palindex = 111; break; // Yellow
case 6: palindex = 175; break; // Green
case 7: palindex = 239; break; // Blue
case 8: palindex = 219; break; // Cyan
case 0: palindex = 15; break; // White
case 1: palindex = 31; break; // Gray
case 2: palindex = 47; break; // Sepia
case 3: palindex = 63; break; // Brown
case 4: palindex = 150; shift = 7; break; // Pink
case 5: palindex = 127; shift = 7; break; // Raspberry
case 6: palindex = 143; break; // Red
case 7: palindex = 86; shift = 7; break; // Creamsicle
case 8: palindex = 95; break; // Orange
case 9: palindex = 119; shift = 7; break; // Gold
case 10: palindex = 111; break; // Yellow
case 11: palindex = 191; shift = 7; break; // Emerald
case 12: palindex = 175; break; // Green
case 13: palindex = 219; break; // Cyan
case 14: palindex = 207; shift = 7; break; // Steel
case 15: palindex = 230; shift = 7; break; // Periwinkle
case 16: palindex = 239; break; // Blue
case 17: palindex = 199; shift = 7; break; // Purple
case 18: palindex = 255; shift = 7; break; // Lavender
// Default green
default: palindex = 175; break;
}
@ -277,7 +292,7 @@ void CON_SetupBackColormap(void)
// setup background colormap
for (i = 0, j = 0; i < 768; i += 3, j++)
{
palsum = (pal[i] + pal[i+1] + pal[i+2]) >> 6;
palsum = (pal[i] + pal[i+1] + pal[i+2]) >> shift;
consolebgmap[j] = (UINT8)(palindex - palsum);
}
}
@ -748,6 +763,19 @@ boolean CON_Responder(event_t *ev)
if (modeattacking || metalrecording)
return false;
if (ev->data1 >= KEY_MOUSE1) // See also: HUD_Responder
{
INT32 i;
for (i = 0; i < num_gamecontrols; i++)
{
if (gamecontrol[i][0] == ev->data1 || gamecontrol[i][1] == ev->data1)
break;
}
if (i == num_gamecontrols)
return false;
}
if (key == gamecontrol[gc_console][0] || key == gamecontrol[gc_console][1])
{
if (consdown) // ignore repeat

View File

@ -563,6 +563,8 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i)
for (j = 0; j < NUMKARTSTUFF; ++j)
rsp->kartstuff[j] = LONG(players[i].kartstuff[j]); // SRB2kart
rsp->frameangle = (angle_t)LONG(players[i].frameangle); // SRB2kart
// Score is resynched in the rspfirm resync packet
rsp->health = 0; // resynched with mo health
rsp->lives = players[i].lives;
@ -576,8 +578,8 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i)
// Just in case Lua does something like
// modify these at runtime
// SRB2kart
rsp->kartspeed = (UINT8)LONG(players[i].kartspeed);
rsp->kartweight = (UINT8)LONG(players[i].kartweight);
rsp->kartspeed = (UINT8)players[i].kartspeed;
rsp->kartweight = (UINT8)players[i].kartweight;
//
rsp->normalspeed = (fixed_t)LONG(players[i].normalspeed);
rsp->runspeed = (fixed_t)LONG(players[i].runspeed);
@ -644,6 +646,8 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i)
rsp->timeshit = players[i].timeshit;
rsp->onconveyor = LONG(players[i].onconveyor);
rsp->jointime = (tic_t)LONG(players[i].jointime);
rsp->hasmo = false;
//Transfer important mo information if the player has a body.
//This lets us resync players even if they are dead.
@ -654,26 +658,26 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i)
rsp->health = LONG(players[i].mo->health);
rsp->angle = (angle_t)LONG(players[i].mo->angle);
rsp->x = LONG(players[i].mo->x);
rsp->y = LONG(players[i].mo->y);
rsp->z = LONG(players[i].mo->z);
rsp->momx = LONG(players[i].mo->momx);
rsp->momy = LONG(players[i].mo->momy);
rsp->momz = LONG(players[i].mo->momz);
rsp->friction = LONG(players[i].mo->friction);
rsp->movefactor = LONG(players[i].mo->movefactor);
rsp->x = (fixed_t)LONG(players[i].mo->x);
rsp->y = (fixed_t)LONG(players[i].mo->y);
rsp->z = (fixed_t)LONG(players[i].mo->z);
rsp->momx = (fixed_t)LONG(players[i].mo->momx);
rsp->momy = (fixed_t)LONG(players[i].mo->momy);
rsp->momz = (fixed_t)LONG(players[i].mo->momz);
rsp->friction = (fixed_t)LONG(players[i].mo->friction);
rsp->movefactor = (fixed_t)LONG(players[i].mo->movefactor);
rsp->tics = LONG(players[i].mo->tics);
rsp->statenum = (statenum_t)LONG(players[i].mo->state-states); // :(
rsp->flags = (UINT32)LONG(players[i].mo->flags);
rsp->flags2 = (UINT32)LONG(players[i].mo->flags2);
rsp->eflags = (UINT16)SHORT(players[i].mo->eflags);
rsp->flags = LONG(players[i].mo->flags);
rsp->flags2 = LONG(players[i].mo->flags2);
rsp->radius = LONG(players[i].mo->radius);
rsp->height = LONG(players[i].mo->height);
rsp->scale = LONG(players[i].mo->scale);
rsp->destscale = LONG(players[i].mo->destscale);
rsp->scalespeed = LONG(players[i].mo->scalespeed);
rsp->radius = (fixed_t)LONG(players[i].mo->radius);
rsp->height = (fixed_t)LONG(players[i].mo->height);
rsp->scale = (fixed_t)LONG(players[i].mo->scale);
rsp->destscale = (fixed_t)LONG(players[i].mo->destscale);
rsp->scalespeed = (fixed_t)LONG(players[i].mo->scalespeed);
}
static void resynch_read_player(resynch_pak *rsp)
@ -696,6 +700,8 @@ static void resynch_read_player(resynch_pak *rsp)
for (j = 0; j < NUMKARTSTUFF; ++j)
players[i].kartstuff[j] = LONG(rsp->kartstuff[j]); // SRB2kart
players[i].frameangle = (angle_t)LONG(rsp->frameangle); // SRB2kart
// Score is resynched in the rspfirm resync packet
players[i].health = rsp->health;
players[i].lives = rsp->lives;
@ -708,8 +714,8 @@ static void resynch_read_player(resynch_pak *rsp)
players[i].skin = LONG(rsp->skin);
// Just in case Lua does something like
// modify these at runtime
players[i].kartspeed = (UINT8)LONG(rsp->kartspeed);
players[i].kartweight = (UINT8)LONG(rsp->kartweight);
players[i].kartspeed = (UINT8)rsp->kartspeed;
players[i].kartweight = (UINT8)rsp->kartweight;
players[i].normalspeed = (fixed_t)LONG(rsp->normalspeed);
players[i].runspeed = (fixed_t)LONG(rsp->runspeed);
@ -776,6 +782,8 @@ static void resynch_read_player(resynch_pak *rsp)
players[i].timeshit = rsp->timeshit;
players[i].onconveyor = LONG(rsp->onconveyor);
players[i].jointime = (tic_t)LONG(rsp->jointime);
//We get a packet for each player in game.
if (!playeringame[i])
return;
@ -794,27 +802,30 @@ static void resynch_read_player(resynch_pak *rsp)
//At this point, the player should have a body, whether they were respawned or not.
P_UnsetThingPosition(players[i].mo);
players[i].mo->angle = (angle_t)LONG(rsp->angle);
players[i].mo->eflags = (UINT16)SHORT(rsp->eflags);
players[i].mo->flags = LONG(rsp->flags);
players[i].mo->flags2 = LONG(rsp->flags2);
players[i].mo->friction = LONG(rsp->friction);
players[i].mo->health = LONG(rsp->health);
players[i].mo->momx = LONG(rsp->momx);
players[i].mo->momy = LONG(rsp->momy);
players[i].mo->momz = LONG(rsp->momz);
players[i].mo->movefactor = LONG(rsp->movefactor);
players[i].mo->angle = (angle_t)LONG(rsp->angle);
players[i].mo->x = (fixed_t)LONG(rsp->x);
players[i].mo->y = (fixed_t)LONG(rsp->y);
players[i].mo->z = (fixed_t)LONG(rsp->z);
players[i].mo->momx = (fixed_t)LONG(rsp->momx);
players[i].mo->momy = (fixed_t)LONG(rsp->momy);
players[i].mo->momz = (fixed_t)LONG(rsp->momz);
players[i].mo->friction = (fixed_t)LONG(rsp->friction);
players[i].mo->movefactor = (fixed_t)LONG(rsp->movefactor);
players[i].mo->tics = LONG(rsp->tics);
P_SetMobjStateNF(players[i].mo, LONG(rsp->statenum));
players[i].mo->x = LONG(rsp->x);
players[i].mo->y = LONG(rsp->y);
players[i].mo->z = LONG(rsp->z);
players[i].mo->radius = LONG(rsp->radius);
players[i].mo->height = LONG(rsp->height);
P_SetMobjStateNF(players[i].mo, (statenum_t)LONG(rsp->statenum));
players[i].mo->flags = (UINT32)LONG(rsp->flags);
players[i].mo->flags2 = (UINT32)LONG(rsp->flags2);
players[i].mo->eflags = (UINT16)SHORT(rsp->eflags);
players[i].mo->radius = (fixed_t)LONG(rsp->radius);
players[i].mo->height = (fixed_t)LONG(rsp->height);
// P_SetScale is redundant for this, as all related variables are already restored properly.
players[i].mo->scale = LONG(rsp->scale);
players[i].mo->destscale = LONG(rsp->destscale);
players[i].mo->scalespeed = LONG(rsp->scalespeed);
players[i].mo->scale = (fixed_t)LONG(rsp->scale);
players[i].mo->destscale = (fixed_t)LONG(rsp->destscale);
players[i].mo->scalespeed = (fixed_t)LONG(rsp->scalespeed);
// And finally, SET THE MOBJ SKIN damn it.
players[i].mo->skin = &skins[players[i].skin];
@ -939,8 +950,7 @@ static inline void resynch_write_others(resynchend_pak *rst)
{
rst->ctfteam[i] = 0;
rst->score[i] = 0;
rst->numboxes[i] = 0;
rst->totalring[i] = 0;
rst->marescore[i] = 0;
rst->realtime[i] = 0;
rst->laps[i] = 0;
continue;
@ -950,8 +960,7 @@ static inline void resynch_write_others(resynchend_pak *rst)
rst->ingame |= (1<<i);
rst->ctfteam[i] = (INT32)LONG(players[i].ctfteam);
rst->score[i] = (UINT32)LONG(players[i].score);
rst->numboxes[i] = SHORT(players[i].numboxes);
rst->totalring[i] = SHORT(players[i].totalring);
rst->marescore[i] = (UINT32)LONG(players[i].marescore);
rst->realtime[i] = (tic_t)LONG(players[i].realtime);
rst->laps[i] = players[i].laps;
}
@ -971,8 +980,7 @@ static inline void resynch_read_others(resynchend_pak *p)
players[i].spectator = !(loc_ingame & (1<<i));
players[i].ctfteam = (INT32)LONG(p->ctfteam[i]); // no, 0 does not mean spectator, at least not in Match
players[i].score = (UINT32)LONG(p->score[i]);
players[i].numboxes = SHORT(p->numboxes[i]);
players[i].totalring = SHORT(p->totalring[i]);
players[i].marescore = (UINT32)LONG(p->marescore[i]);
players[i].realtime = (tic_t)LONG(p->realtime[i]);
players[i].laps = p->laps[i];
}
@ -993,7 +1001,8 @@ static void SV_RequireResynch(INT32 node)
resynch_delay[node] = 10; // Delay before you can fail sync again
resynch_score[node] += 200; // Add score for initial desynch
resynch_status[node] = 0xFFFFFFFF; // No players assumed synched
for (i = 0; i < MAXPLAYERS; ++i)
resynch_status[node] |= (1<<i); // No players assumed synched
resynch_inprogress[node] = true; // so we know to send a PT_RESYNCHEND after sync
// Initial setup
@ -1633,18 +1642,18 @@ static void CL_LoadReceivedSavegame(void)
// load a base level
if (P_LoadNetGame())
{
CONS_Printf(M_GetText("Map is now \"%s"), G_BuildMapName(gamemap));
CON_LogMessage(va(M_GetText("Map is now \"%s"), G_BuildMapName(gamemap)));
if (strlen(mapheaderinfo[gamemap-1]->lvlttl) > 0)
{
CONS_Printf(": %s", mapheaderinfo[gamemap-1]->lvlttl);
CON_LogMessage(va(": %s", mapheaderinfo[gamemap-1]->lvlttl));
if (strlen(mapheaderinfo[gamemap-1]->zonttl) > 0)
CONS_Printf(" %s", mapheaderinfo[gamemap-1]->zonttl);
CON_LogMessage(va(" %s", mapheaderinfo[gamemap-1]->zonttl));
else if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE))
CONS_Printf(M_GetText(" ZONE"));
CON_LogMessage(M_GetText(" ZONE"));
if (strlen(mapheaderinfo[gamemap-1]->actnum) > 0)
CONS_Printf(" %s", mapheaderinfo[gamemap-1]->actnum);
CON_LogMessage(va(" %s", mapheaderinfo[gamemap-1]->actnum));
}
CONS_Printf("\"\n");
CON_LogMessage("\"\n");
}
else
{
@ -2375,8 +2384,11 @@ static void Command_connect(void)
CONS_Alert(CONS_ERROR, M_GetText("There is no network driver\n"));
}
splitscreen = 0;
SplitScreen_OnChange();
if (splitscreen != cv_splitplayers.value-1)
{
splitscreen = cv_splitplayers.value-1;
SplitScreen_OnChange();
}
botingame = false;
botskin = 0;
CL_ConnectToServer(viams);
@ -2417,14 +2429,15 @@ static void CL_RemovePlayer(INT32 playernum)
if (server && !demoplayback)
{
INT32 node = playernode[playernum];
//playerpernode[node] = 0; // It'd be better to remove them all at once, but ghosting happened, so continue to let CL_RemovePlayer do it one-by-one
playerpernode[node]--;
if (playerpernode[node] <= 0)
{
// If a resynch was in progress, well, it no longer needs to be.
SV_InitResynchVars(playernode[playernum]);
SV_InitResynchVars(node);
nodeingame[playernode[playernum]] = false;
Net_CloseConnection(playernode[playernum]);
nodeingame[node] = false;
Net_CloseConnection(node);
ResetNode(node);
}
}
@ -2759,11 +2772,7 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
}
// Is playernum authorized to make this kick?
if (playernum != serverplayer && !IsPlayerAdmin(playernum)
&& !(playerpernode[playernode[playernum]] >= 2
&& (nodetoplayer2[playernode[playernum]] == pnum
|| nodetoplayer3[playernode[playernum]] == pnum
|| nodetoplayer4[playernode[playernum]] == pnum)))
if (playernum != serverplayer && !IsPlayerAdmin(playernum))
{
// We received a kick command from someone who isn't the
// server or admin, and who isn't in splitscreen removing
@ -2775,12 +2784,6 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
// "consistency failure" and kicking the offending user
// instead.
// Note: Splitscreen in netgames is broken because of
// this. Only the server has any idea of which players
// are using splitscreen on the same computer, so
// clients cannot always determine if a kick is
// legitimate.
CONS_Alert(CONS_WARNING, M_GetText("Illegal kick command received from %s for player %d\n"), player_names[playernum], pnum);
// In debug, print a longer message with more details.
@ -2810,7 +2813,7 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
msg = KICK_MSG_CON_FAIL;
}
CONS_Printf("\x82%s ", player_names[pnum]);
//CONS_Printf("\x82%s ", player_names[pnum]);
// If a verified admin banned someone, the server needs to know about it.
// If the playernum isn't zero (the server) then the server needs to record the ban.
@ -2827,15 +2830,15 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
switch (msg)
{
case KICK_MSG_GO_AWAY:
CONS_Printf(M_GetText("has been kicked (Go away)\n"));
HU_AddChatText(va("\x82*%s has been kicked (Go away)", player_names[pnum]), false);
break;
#ifdef NEWPING
case KICK_MSG_PING_HIGH:
CONS_Printf(M_GetText("left the game (Broke ping limit)\n"));
HU_AddChatText(va("\x82*%s left the game (Broke ping limit)", player_names[pnum]), false);
break;
#endif
case KICK_MSG_CON_FAIL:
CONS_Printf(M_GetText("left the game (Synch failure)\n"));
HU_AddChatText(va("\x82*%s left the game (Synch Failure)", player_names[pnum]), false);
if (M_CheckParm("-consisdump")) // Helps debugging some problems
{
@ -2871,26 +2874,26 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
}
break;
case KICK_MSG_TIMEOUT:
CONS_Printf(M_GetText("left the game (Connection timeout)\n"));
HU_AddChatText(va("\x82*%s left the game (Connection timeout)", player_names[pnum]), false);
break;
case KICK_MSG_PLAYER_QUIT:
if (netgame) // not splitscreen/bots
CONS_Printf(M_GetText("left the game\n"));
HU_AddChatText(va("\x82*%s left the game", player_names[pnum]), false);
break;
case KICK_MSG_BANNED:
CONS_Printf(M_GetText("has been banned (Don't come back)\n"));
HU_AddChatText(va("\x82*%s has been banned (Don't come back)", player_names[pnum]), false);
break;
case KICK_MSG_CUSTOM_KICK:
READSTRINGN(*p, reason, MAX_REASONLENGTH+1);
CONS_Printf(M_GetText("has been kicked (%s)\n"), reason);
HU_AddChatText(va("\x82*%s has been kicked (%s)", player_names[pnum], reason), false);
break;
case KICK_MSG_CUSTOM_BAN:
READSTRINGN(*p, reason, MAX_REASONLENGTH+1);
CONS_Printf(M_GetText("has been banned (%s)\n"), reason);
HU_AddChatText(va("\x82*%s has been banned (%s)", player_names[pnum], reason), false);
break;
}
if (pnum == consoleplayer)
if (playernode[pnum] == playernode[consoleplayer])
{
#ifdef DUMPCONSISTENCY
if (msg == KICK_MSG_CON_FAIL) SV_SavedGame();
@ -2899,7 +2902,7 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
CL_Reset();
D_StartTitle();
if (msg == KICK_MSG_CON_FAIL)
M_StartMessage(M_GetText("Server closed connection\n(synch failure)\nPress ESC\n"), NULL, MM_NOTHING);
M_StartMessage(M_GetText("Server closed connection\n(Synch failure)\nPress ESC\n"), NULL, MM_NOTHING);
#ifdef NEWPING
else if (msg == KICK_MSG_PING_HIGH)
M_StartMessage(M_GetText("Server closed connection\n(Broke ping limit)\nPress ESC\n"), NULL, MM_NOTHING);
@ -2913,8 +2916,32 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
else
M_StartMessage(M_GetText("You have been kicked by the server\n\nPress ESC\n"), NULL, MM_NOTHING);
}
else
CL_RemovePlayer(pnum);
else if (server)
{
XBOXSTATIC UINT8 buf[0];
// Sal: Because kicks (and a lot of other commands) are player-based, we can't tell which player pnum is on the node from a glance.
// When we want to remove everyone from a node, we have to get the kicked player's node, then remove everyone on that node manually so we don't miss any.
// This avoids the bugs with older SRB2 version's online splitscreen kicks, specifically ghosting.
// On top of this, it can't just be a CL_RemovePlayer call; it has to be a server-sided.
// Clients don't bother setting any nodes for anything but THE server player (even ignoring the server's extra players!), so it'll often remove everyone because they all have node -1/255, insta-desync!
// And yes. This is a netxcmd wrap for just CL_RemovePlayer! :V
#define removethisplayer(otherp) \
if (otherp >= 0) \
{ \
if (otherp != pnum) \
HU_AddChatText(va("\x82*%s left the game (Joined with %s)", player_names[otherp], player_names[pnum]), false); \
buf[0] = (UINT8)otherp; \
SendNetXCmd(XD_REMOVEPLAYER, &buf, 1); \
otherp = -1; \
}
removethisplayer(nodetoplayer[playernode[pnum]])
removethisplayer(nodetoplayer2[playernode[pnum]])
removethisplayer(nodetoplayer3[playernode[pnum]])
removethisplayer(nodetoplayer4[playernode[pnum]])
#undef removethisplayer
}
}
consvar_t cv_allownewplayer = {"allowjoin", "On", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL };
@ -2937,6 +2964,7 @@ static CV_PossibleValue_t downloadspeed_cons_t[] = {{0, "MIN"}, {32, "MAX"}, {0,
consvar_t cv_downloadspeed = {"downloadspeed", "16", CV_SAVE, downloadspeed_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static void Got_AddPlayer(UINT8 **p, INT32 playernum);
static void Got_RemovePlayer(UINT8 **p, INT32 playernum);
// called one time at init
void D_ClientServerInit(void)
@ -2964,6 +2992,7 @@ void D_ClientServerInit(void)
RegisterNetXCmd(XD_KICK, Got_KickCmd);
RegisterNetXCmd(XD_ADDPLAYER, Got_AddPlayer);
RegisterNetXCmd(XD_REMOVEPLAYER, Got_RemovePlayer);
#ifndef NONET
CV_RegisterVar(&cv_allownewplayer);
#ifdef VANILLAJOINNEXTROUND
@ -3157,17 +3186,13 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
newplayernum %= MAXPLAYERS;
// Clear player before joining, lest some things get set incorrectly
// HACK: don't do this for splitscreen, it relies on preset values
if (!splitscreen && !botingame)
CL_ClearPlayer(newplayernum);
CL_ClearPlayer(newplayernum);
playeringame[newplayernum] = true;
G_AddPlayer(newplayernum);
if (newplayernum+1 > doomcom->numslots)
doomcom->numslots = (INT16)(newplayernum+1);
if (netgame)
CONS_Printf(M_GetText("Player %d has joined the game (node %d)\n"), newplayernum+1, node);
// the server is creating my player
if (node == mynode)
{
@ -3226,11 +3251,17 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
D_SendPlayerConfig();
addedtogame = true;
}
else if (server && netgame && cv_showjoinaddress.value)
if (netgame)
{
const char *address;
if (I_GetNodeAddress && (address = I_GetNodeAddress(node)) != NULL)
CONS_Printf(M_GetText("Player Address is %s\n"), address);
if (server && netgame && cv_showjoinaddress.value)
{
const char *address;
if (I_GetNodeAddress && (address = I_GetNodeAddress(node)) != NULL)
HU_AddChatText(va("\x82*Player %d has joined the game (node %d) (%s)", newplayernum+1, node, address), false); // merge join notification + IP to avoid clogging console/chat.
}
else
HU_AddChatText(va("\x82*Player %d has joined the game (node %d)", newplayernum+1, node), false);
}
if (server && multiplayer && motd[0] != '\0')
@ -3241,6 +3272,27 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
#endif
}
// Xcmd XD_REMOVEPLAYER
static void Got_RemovePlayer(UINT8 **p, INT32 playernum)
{
if (playernum != serverplayer && !IsPlayerAdmin(playernum))
{
// protect against hacked/buggy client
CONS_Alert(CONS_WARNING, M_GetText("Illegal remove player command received from %s\n"), player_names[playernum]);
if (server)
{
XBOXSTATIC UINT8 buf[2];
buf[0] = (UINT8)playernum;
buf[1] = KICK_MSG_CON_FAIL;
SendNetXCmd(XD_KICK, &buf, 2);
}
return;
}
CL_RemovePlayer(READUINT8(*p));
}
static boolean SV_AddWaitingPlayers(void)
{
INT32 node, n, newplayer = false;
@ -3258,69 +3310,17 @@ static boolean SV_AddWaitingPlayers(void)
{
newplayer = true;
if (netgame)
// !!!!!!!!! EXTREMELY SUPER MEGA GIGA ULTRA ULTIMATELY TERRIBLY IMPORTANT !!!!!!!!!
//
// The line just after that comment is an awful, horrible, terrible, TERRIBLE hack.
//
// Basically, the fix I did in order to fix the download freezes happens
// to cause situations in which a player number does not match
// the node number associated to that player.
// That is totally normal, there is absolutely *nothing* wrong with that.
// Really. Player 7 being tied to node 29, for instance, is totally fine.
//
// HOWEVER. A few (broken) parts of the netcode do the TERRIBLE mistake
// of mixing up the concepts of node and player, resulting in
// incorrect handling of cases where a player is tied to a node that has
// a different number (which is a totally normal case, or at least should be).
// This incorrect handling can go as far as literally
// anyone from joining your server at all, forever.
//
// Given those two facts, there are two options available
// in order to let this download freeze fix be:
// 1) Fix the broken parts that assume a node is a player or similar bullshit.
// 2) Change the part this comment is located at, so that any player who joins
// is given the same number as their associated node.
//
// No need to say, 1) is by far the obvious best, whereas 2) is a terrible hack.
// Unfortunately, after trying 1), I most likely didn't manage to find all
// of those broken parts, and thus 2) has become the only safe option that remains.
//
// So I did this hack.
//
// If it isn't clear enough, in order to get rid of this ugly hack,
// you will have to fix all parts of the netcode that
// make a confusion between nodes and players.
//
// And if it STILL isn't clear enough, a node and a player
// is NOT the same thing. Never. NEVER. *NEVER*.
//
// And if someday you make the terrible mistake of
// daring to have the unforgivable idea to try thinking
// that a node might possibly be the same as a player,
// or that a player should have the same number as its node,
// be sure that I will somehow know about it and
// hunt you down tirelessly and make you regret it,
// even if you live on the other side of the world.
//
// TODO: vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
// \todo >>>>>>>>>> Remove this horrible hack as soon as possible <<<<<<<<<<
// TODO: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//
// !!!!!!!!! EXTREMELY SUPER MEGA GIGA ULTRA ULTIMATELY TERRIBLY IMPORTANT !!!!!!!!!
newplayernum = node; // OMFG SAY WELCOME TO TEH NEW HACK FOR FIX FIL DOWNLOAD!!1!
else // Don't use the hack if we don't have to
// search for a free playernum
// we can't use playeringame since it is not updated here
for (; newplayernum < MAXPLAYERS; newplayernum++)
{
for (n = 0; n < MAXNETNODES; n++)
if (nodetoplayer[n] == newplayernum || nodetoplayer2[n] == newplayernum
|| nodetoplayer3[n] == newplayernum || nodetoplayer4[n] == newplayernum)
break;
if (n == MAXNETNODES)
// search for a free playernum
// we can't use playeringame since it is not updated here
for (; newplayernum < MAXPLAYERS; newplayernum++)
{
for (n = 0; n < MAXNETNODES; n++)
if (nodetoplayer[n] == newplayernum || nodetoplayer2[n] == newplayernum
|| nodetoplayer3[n] == newplayernum || nodetoplayer4[n] == newplayernum)
break;
}
if (n == MAXNETNODES)
break;
}
// should never happen since we check the playernum
// before accepting the join
@ -3495,7 +3495,7 @@ static void HandleConnect(SINT8 node)
SV_SendRefuse(node, M_GetText("The server is not accepting\njoins for the moment"));
else if (D_NumPlayers() >= cv_maxplayers.value)
SV_SendRefuse(node, va(M_GetText("Maximum players reached: %d"), cv_maxplayers.value));
else if (netgame && netbuffer->u.clientcfg.localplayers > 1) // Hacked client?
else if (netgame && netbuffer->u.clientcfg.localplayers > 4) // Hacked client?
SV_SendRefuse(node, M_GetText("Too many players from\nthis node."));
else if (netgame && !netbuffer->u.clientcfg.localplayers) // Stealth join?
SV_SendRefuse(node, M_GetText("No players from\nthis node."));
@ -3529,8 +3529,8 @@ static void HandleConnect(SINT8 node)
{
G_SetGamestate(backupstate);
/// \note Shouldn't SV_SendRefuse be called before ResetNode?
ResetNode(node);
SV_SendRefuse(node, M_GetText("Server couldn't send info, please try again"));
ResetNode(node); // Yeah, lets try it!
/// \todo fix this !!!
return; // restart the while
}
@ -3983,10 +3983,10 @@ FILESTAMP
--resynch_score[node];
break;
case PT_TEXTCMD:
case PT_TEXTCMD2: // splitscreen special
case PT_TEXTCMD2:
case PT_TEXTCMD3:
case PT_TEXTCMD4:
if (netbuffer->packettype == PT_TEXTCMD2)
if (netbuffer->packettype == PT_TEXTCMD2) // splitscreen special
netconsole = nodetoplayer2[node];
else if (netbuffer->packettype == PT_TEXTCMD3)
netconsole = nodetoplayer3[node];
@ -4073,9 +4073,9 @@ FILESTAMP
else
buf[1] = KICK_MSG_PLAYER_QUIT;
SendNetXCmd(XD_KICK, &buf, 2);
nodetoplayer[node] = -1;
//nodetoplayer[node] = -1;
if (nodetoplayer2[node] != -1 && nodetoplayer2[node] >= 0
/*if (nodetoplayer2[node] != -1 && nodetoplayer2[node] >= 0
&& playeringame[(UINT8)nodetoplayer2[node]])
{
buf[0] = nodetoplayer2[node];
@ -4097,7 +4097,7 @@ FILESTAMP
buf[0] = nodetoplayer4[node];
SendNetXCmd(XD_KICK, &buf, 2);
nodetoplayer4[node] = -1;
}
}*/
}
Net_CloseConnection(node);
nodeingame[node] = false;
@ -4353,7 +4353,7 @@ static INT16 Consistancy(void)
{
ret += players[i].mo->x;
ret -= players[i].mo->y;
ret += players[i].powers[pw_shield];
ret += players[i].kartstuff[k_itemtype]; // powers[pw_shield]
ret *= i+1;
}
}
@ -4430,6 +4430,47 @@ static INT16 Consistancy(void)
}
else
ret ^= 0xAAAA;
// SRB2Kart: We use hnext & hprev very extensively
if (mo->hnext)
{
ret += mo->hnext->type;
ret -= mo->hnext->x;
ret += mo->hnext->y;
ret -= mo->hnext->z;
ret += mo->hnext->momx;
ret -= mo->hnext->momy;
ret += mo->hnext->momz;
ret -= mo->hnext->angle;
ret += mo->hnext->flags;
ret -= mo->hnext->flags2;
ret += mo->hnext->eflags;
ret -= mo->hnext->state - states;
ret += mo->hnext->tics;
ret -= mo->hnext->sprite;
ret += mo->hnext->frame;
}
else
ret ^= 0x5555;
if (mo->hprev)
{
ret += mo->hprev->type;
ret -= mo->hprev->x;
ret += mo->hprev->y;
ret -= mo->hprev->z;
ret += mo->hprev->momx;
ret -= mo->hprev->momy;
ret += mo->hprev->momz;
ret -= mo->hprev->angle;
ret += mo->hprev->flags;
ret -= mo->hprev->flags2;
ret += mo->hprev->eflags;
ret -= mo->hprev->state - states;
ret += mo->hprev->tics;
ret -= mo->hprev->sprite;
ret += mo->hprev->frame;
}
else
ret ^= 0xCCCC;
ret -= mo->state - states;
ret += mo->tics;
ret -= mo->sprite;

View File

@ -166,8 +166,7 @@ typedef struct
// Resynch game scores and the like all at once
UINT32 score[MAXPLAYERS]; // Everyone's score
INT16 numboxes[MAXPLAYERS];
INT16 totalring[MAXPLAYERS];
UINT32 marescore[MAXPLAYERS]; // SRB2kart: Battle score
tic_t realtime[MAXPLAYERS];
UINT8 laps[MAXPLAYERS];
} ATTRPACK resynchend_pak;
@ -186,6 +185,7 @@ typedef struct
angle_t aiming;
INT32 currentweapon;
INT32 ringweapons;
UINT16 powers[NUMPOWERS];
INT32 kartstuff[NUMKARTSTUFF]; // SRB2kart
@ -271,6 +271,8 @@ typedef struct
UINT8 timeshit;
INT32 onconveyor;
tic_t jointime;
//player->mo stuff
UINT8 hasmo; // Boolean

View File

@ -1362,11 +1362,26 @@ void D_SRB2Main(void)
#endif
}
// Set up splitscreen players before joining!
if (!dedicated && (M_CheckParm("-splitscreen") && M_IsNextParm()))
{
UINT8 num = atoi(M_GetNextParm());
if (num >= 1 && num <= 4)
{
CV_StealthSetValue(&cv_splitplayers, num);
splitscreen = num-1;
SplitScreen_OnChange();
}
}
// init all NETWORK
CONS_Printf("D_CheckNetGame(): Checking network game status.\n");
if (D_CheckNetGame())
autostart = true;
if (splitscreen) // Make sure multiplayer & autostart is set if you have splitscreen, even after D_CheckNetGame
multiplayer = autostart = true;
// check for a driver that wants intermission stats
// start the apropriate game based on parms
if (M_CheckParm("-metal"))

View File

@ -375,6 +375,7 @@ consvar_t cv_kartdebugdistribution = {"kartdebugdistribution", "Off", CV_NETVAR|
consvar_t cv_kartdebughuddrop = {"kartdebughuddrop", "Off", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_kartdebugcheckpoint = {"kartdebugcheckpoint", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_kartdebugnodes = {"kartdebugnodes", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t votetime_cons_t[] = {{10, "MIN"}, {3600, "MAX"}, {0, NULL}};
consvar_t cv_votetime = {"votetime", "20", CV_NETVAR, votetime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
@ -419,9 +420,6 @@ consvar_t cv_numlaps = {"numlaps", "3", CV_NETVAR|CV_CALL|CV_NOINIT, numlaps_con
static CV_PossibleValue_t basenumlaps_cons_t[] = {{1, "MIN"}, {50, "MAX"}, {0, "Map default"}, {0, NULL}};
consvar_t cv_basenumlaps = {"basenumlaps", "Map default", CV_NETVAR|CV_CALL|CV_CHEAT, basenumlaps_cons_t, BaseNumLaps_OnChange, 0, NULL, NULL, 0, 0, NULL};
// log elemental hazards -- not a netvar, is local to current player
consvar_t cv_hazardlog = {"hazardlog", "Yes", 0, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_forceskin = {"forceskin", "-1", CV_NETVAR|CV_CALL|CV_CHEAT, NULL, ForceSkin_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_downloading = {"downloading", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_allowexitlevel = {"allowexitlevel", "No", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
@ -594,8 +592,6 @@ void D_RegisterServerCommands(void)
CV_RegisterVar(&cv_numlaps);
CV_RegisterVar(&cv_basenumlaps);
CV_RegisterVar(&cv_hazardlog);
CV_RegisterVar(&cv_autobalance);
CV_RegisterVar(&cv_teamscramble);
CV_RegisterVar(&cv_scrambleonchange);
@ -758,6 +754,8 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_playername4);
CV_RegisterVar(&cv_playercolor4);
CV_RegisterVar(&cv_skin4);
// preferred number of players
CV_RegisterVar(&cv_splitplayers);
#ifdef SEENAMES
CV_RegisterVar(&cv_seenames);
@ -1140,8 +1138,8 @@ static void SetPlayerName(INT32 playernum, char *newname)
if (strcasecmp(newname, player_names[playernum]) != 0)
{
if (netgame)
CONS_Printf(M_GetText("%s renamed to %s\n"),
player_names[playernum], newname);
HU_AddChatText(va("\x82*%s renamed to %s", player_names[playernum], newname), false);
strcpy(player_names[playernum], newname);
}
}
@ -1350,16 +1348,23 @@ static void SendNameAndColor(void)
// splitscreen
static void SendNameAndColor2(void)
{
INT32 secondplaya;
INT32 secondplaya = -1;
XBOXSTATIC char buf[MAXPLAYERNAME+2];
char *p;
if (splitscreen < 1 && !botingame)
return; // can happen if skin2/color2/name2 changed
if (secondarydisplayplayer != consoleplayer)
secondplaya = secondarydisplayplayer;
else // HACK
else if (!netgame) // HACK
secondplaya = 1;
if (secondplaya == -1)
return;
p = buf;
// normal player colors
if (G_GametypeHasTeams())
{
@ -1436,21 +1441,53 @@ static void SendNameAndColor2(void)
return;
}
// Don't actually send anything because splitscreen isn't actually allowed in netgames anyway!
snac2pending++;
// Don't change name if muted
if (cv_mute.value && !(server || IsPlayerAdmin(secondarydisplayplayer)))
CV_StealthSet(&cv_playername2, player_names[secondarydisplayplayer]);
else // Cleanup name if changing it
CleanupPlayerName(secondarydisplayplayer, cv_playername2.zstring);
// Don't change skin if the server doesn't want you to.
if (!CanChangeSkin(secondarydisplayplayer))
CV_StealthSet(&cv_skin2, skins[players[secondarydisplayplayer].skin].name);
// check if player has the skin loaded (cv_skin2 may have
// the name of a skin that was available in the previous game)
cv_skin2.value = R_SkinAvailable(cv_skin2.string);
if (cv_skin2.value < 0)
{
CV_StealthSet(&cv_skin2, DEFAULTSKIN);
cv_skin2.value = 0;
}
// Finally write out the complete packet and send it off.
WRITESTRINGN(p, cv_playername2.zstring, MAXPLAYERNAME);
WRITEUINT8(p, (UINT8)cv_playercolor2.value);
WRITEUINT8(p, (UINT8)cv_skin2.value);
SendNetXCmd2(XD_NAMEANDCOLOR, buf, p - buf);
}
static void SendNameAndColor3(void)
{
INT32 thirdplaya;
INT32 thirdplaya = -1;
XBOXSTATIC char buf[MAXPLAYERNAME+2];
char *p;
if (splitscreen < 2)
return; // can happen if skin3/color3/name3 changed
if (thirddisplayplayer != consoleplayer)
thirdplaya = thirddisplayplayer;
else // HACK
else if (!netgame) // HACK
thirdplaya = 2;
if (thirdplaya == -1)
return;
p = buf;
// normal player colors
if (G_GametypeHasTeams())
{
@ -1519,21 +1556,53 @@ static void SendNameAndColor3(void)
return;
}
// Don't actually send anything because splitscreen isn't actually allowed in netgames anyway!
snac3pending++;
// Don't change name if muted
if (cv_mute.value && !(server || IsPlayerAdmin(thirddisplayplayer)))
CV_StealthSet(&cv_playername3, player_names[thirddisplayplayer]);
else // Cleanup name if changing it
CleanupPlayerName(thirddisplayplayer, cv_playername3.zstring);
// Don't change skin if the server doesn't want you to.
if (!CanChangeSkin(thirddisplayplayer))
CV_StealthSet(&cv_skin3, skins[players[thirddisplayplayer].skin].name);
// check if player has the skin loaded (cv_skin3 may have
// the name of a skin that was available in the previous game)
cv_skin3.value = R_SkinAvailable(cv_skin3.string);
if (cv_skin3.value < 0)
{
CV_StealthSet(&cv_skin3, DEFAULTSKIN);
cv_skin3.value = 0;
}
// Finally write out the complete packet and send it off.
WRITESTRINGN(p, cv_playername3.zstring, MAXPLAYERNAME);
WRITEUINT8(p, (UINT8)cv_playercolor3.value);
WRITEUINT8(p, (UINT8)cv_skin3.value);
SendNetXCmd3(XD_NAMEANDCOLOR, buf, p - buf);
}
static void SendNameAndColor4(void)
{
INT32 fourthplaya;
INT32 fourthplaya = -1;
XBOXSTATIC char buf[MAXPLAYERNAME+2];
char *p;
if (splitscreen < 3)
return; // can happen if skin4/color4/name4 changed
if (fourthdisplayplayer != consoleplayer)
fourthplaya = fourthdisplayplayer;
else // HACK
else if (!netgame) // HACK
fourthplaya = 3;
if (fourthplaya == -1)
return;
p = buf;
// normal player colors
if (G_GametypeHasTeams())
{
@ -1610,7 +1679,32 @@ static void SendNameAndColor4(void)
return;
}
// Don't actually send anything because splitscreen isn't actually allowed in netgames anyway!
snac4pending++;
// Don't change name if muted
if (cv_mute.value && !(server || IsPlayerAdmin(fourthdisplayplayer)))
CV_StealthSet(&cv_playername4, player_names[fourthdisplayplayer]);
else // Cleanup name if changing it
CleanupPlayerName(fourthdisplayplayer, cv_playername4.zstring);
// Don't change skin if the server doesn't want you to.
if (!CanChangeSkin(fourthdisplayplayer))
CV_StealthSet(&cv_skin4, skins[players[fourthdisplayplayer].skin].name);
// check if player has the skin loaded (cv_skin4 may have
// the name of a skin that was available in the previous game)
cv_skin4.value = R_SkinAvailable(cv_skin4.string);
if (cv_skin4.value < 0)
{
CV_StealthSet(&cv_skin4, DEFAULTSKIN);
cv_skin4.value = 0;
}
// Finally write out the complete packet and send it off.
WRITESTRINGN(p, cv_playername4.zstring, MAXPLAYERNAME);
WRITEUINT8(p, (UINT8)cv_playercolor4.value);
WRITEUINT8(p, (UINT8)cv_skin4.value);
SendNetXCmd4(XD_NAMEANDCOLOR, buf, p - buf);
}
static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
@ -2010,16 +2104,20 @@ void D_SetupVote(void)
void D_ModifyClientVote(SINT8 voted, UINT8 splitplayer)
{
char buf[1];
char buf[2];
char *p = buf;
UINT8 player = consoleplayer;
if (splitplayer > 0) // Don't actually send anything for splitscreen
votes[splitplayer] = voted;
else
{
WRITESINT8(p, voted);
SendNetXCmd(XD_MODIFYVOTE, &buf, 1);
}
if (splitplayer == 1)
player = secondarydisplayplayer;
else if (splitplayer == 2)
player = thirddisplayplayer;
else if (splitplayer == 3)
player = fourthdisplayplayer;
WRITESINT8(p, voted);
WRITEUINT8(p, player);
SendNetXCmd(XD_MODIFYVOTE, &buf, 2);
}
void D_PickVote(void)
@ -2388,11 +2486,12 @@ static void Command_Suicide(void)
}*/
// Retry is quicker. Probably should force people to use it.
if (!(netgame || multiplayer))
// nope, this is srb2kart - a complete retry is overkill
/*if (!(netgame || multiplayer))
{
CONS_Printf(M_GetText("You can't use this in Single Player! Use \"retry\" instead.\n"));
return;
}
}*/
SendNetXCmd(XD_SUICIDE, &buf, 4);
}
@ -3135,6 +3234,8 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
players[playernum].playerstate = PST_REBORN;
}
players[playernum].pflags &= ~PF_WANTSTOJOIN;
//Now that we've done our error checking and killed the player
//if necessary, put the player on the correct team/status.
if (G_TagGametype())
@ -3216,12 +3317,8 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
else
CONS_Printf(M_GetText("%s switched to the %c%s%c.\n"), player_names[playernum], '\x84', M_GetText("Blue Team"), '\x80');
}
else if (NetPacket.packet.newteam == 3)
/*CONS_Printf(M_GetText("%s entered the game.\n"), player_names[playernum])*/;
else if (players[playernum].pflags & PF_WANTSTOJOIN)
players[playernum].pflags &= ~PF_WANTSTOJOIN;
else
CONS_Printf(M_GetText("%s became a spectator.\n"), player_names[playernum]);
else if (NetPacket.packet.newteam == 0)
HU_AddChatText(va("\x82*%s became a spectator.", player_names[playernum]), false); // "entered the game" text was moved to P_SpectatorJoinGame
//reset view if you are changed, or viewing someone who was changed.
if (playernum == consoleplayer || displayplayer == playernum)
@ -4635,7 +4732,10 @@ static void Got_SetupVotecmd(UINT8 **cp, INT32 playernum)
static void Got_ModifyVotecmd(UINT8 **cp, INT32 playernum)
{
SINT8 voted = READSINT8(*cp);
votes[playernum] = voted;
UINT8 p = READUINT8(*cp);
(void)playernum;
votes[p] = voted;
}
static void Got_PickVotecmd(UINT8 **cp, INT32 playernum)
@ -4753,9 +4853,13 @@ static void Command_RestartAudio_f(void)
I_SetSfxVolume(cv_soundvolume.value);
I_SetDigMusicVolume(cv_digmusicvolume.value);
//I_SetMIDIMusicVolume(cv_midimusicvolume.value);
S_StartSound(NULL, sfx_strpst);
if (Playing()) // Gotta make sure the player is in a level
P_RestoreMusic(&players[consoleplayer]);
else
S_ChangeMusicInternal("titles", looptitle);
}
/** Quits a game and returns to the title screen.
@ -4792,10 +4896,10 @@ void Command_Retry_f(void)
CONS_Printf(M_GetText("You must be in a level to use this.\n"));
else if (netgame || multiplayer)
CONS_Printf(M_GetText("This only works in single player.\n"));
else if (!&players[consoleplayer] || players[consoleplayer].lives <= 1)
/*else if (!&players[consoleplayer] || players[consoleplayer].lives <= 1)
CONS_Printf(M_GetText("You can't retry without any lives remaining!\n"));
else if (G_IsSpecialStage(gamemap))
CONS_Printf(M_GetText("You can't retry special stages!\n"));
CONS_Printf(M_GetText("You can't retry special stages!\n"));*/
else
{
M_ClearMenus(true);
@ -5156,13 +5260,17 @@ static void Color4_OnChange(void)
*/
static void Mute_OnChange(void)
{
if (server || (IsPlayerAdmin(consoleplayer)))
return;
/*if (server || (IsPlayerAdmin(consoleplayer)))
return;*/
// Kinda dumb IMO, you should be able to see confirmation for having muted the chat as the host or admin.
if (leveltime <= 1)
return; // avoid having this notification put in our console / log when we boot the server.
if (cv_mute.value)
CONS_Printf(M_GetText("Chat has been muted.\n"));
HU_AddChatText(M_GetText("\x82*Chat has been muted."), false);
else
CONS_Printf(M_GetText("Chat is no longer muted.\n"));
HU_AddChatText(M_GetText("\x82*Chat is no longer muted."), false);
}
/** Hack to clear all changed flags after game start.
@ -5245,6 +5353,13 @@ static void KartFrantic_OnChange(void)
static void KartSpeed_OnChange(void)
{
if (!M_SecretUnlocked(SECRET_HARDSPEED) && cv_kartspeed.value == 2)
{
CONS_Printf(M_GetText("You haven't earned this yet.\n"));
CV_StealthSetValue(&cv_kartspeed, 1);
return;
}
if (G_RaceGametype())
{
if ((UINT8)cv_kartspeed.value != gamespeed && gamestate == GS_LEVEL && leveltime > starttime)

View File

@ -81,8 +81,6 @@ extern consvar_t cv_basenumlaps;
extern UINT32 timelimitintics;
extern consvar_t cv_allowexitlevel;
extern consvar_t cv_hazardlog;
extern consvar_t cv_autobalance;
extern consvar_t cv_teamscramble;
extern consvar_t cv_scrambleonchange;
@ -134,7 +132,7 @@ extern consvar_t cv_karteliminatelast;
extern consvar_t cv_votetime;
extern consvar_t cv_kartdebugitem, cv_kartdebugamount, cv_kartdebugshrink, cv_kartdebugdistribution, cv_kartdebughuddrop;
extern consvar_t cv_kartdebugcheckpoint;
extern consvar_t cv_kartdebugcheckpoint, cv_kartdebugnodes;
extern consvar_t cv_itemfinder;
@ -197,9 +195,10 @@ typedef enum
XD_SETUPVOTE, // 22
XD_MODIFYVOTE, // 23
XD_PICKVOTE, // 24
XD_REMOVEPLAYER,// 25
#ifdef HAVE_BLUA
XD_LUACMD, // 25
XD_LUAVAR, // 26
XD_LUACMD, // 26
XD_LUAVAR, // 27
#endif
MAXNETXCMD
} netxcmd_t;

View File

@ -280,6 +280,7 @@ typedef enum
k_throwdir, // Held dir of controls; 1 = forward, 0 = none, -1 = backward (was "player->heldDir")
k_lapanimation, // Used to show the lap start wing logo animation
k_laphand, // Lap hand gfx to use; 0 = none, 1 = :ok_hand:, 2 = :thumbs_up:, 3 = :thumps_down:
k_cardanimation, // Used to determine the position of some full-screen Battle Mode graphics
k_voices, // Used to stop the player saying more voices than it should
k_tauntvoices, // Used to specifically stop taunt voice spam
@ -306,7 +307,9 @@ typedef enum
k_accelboost, // Boost value smoothing for acceleration
k_boostcam, // Camera push forward on boost
k_destboostcam, // Ditto
k_timeovercam, // Camera timer for leaving behind or not
k_aizdriftstrat, // Let go of your drift while boosting? Helper for the SICK STRATZ you have just unlocked
k_brakedrift, // Helper for brake-drift spark spawning
k_itemroulette, // Used for the roulette when deciding what item to give you (was "pw_kartitem")
k_roulettetype, // Used for the roulette, for deciding type (currently only used for Battle, to give you better items from Karma items)
@ -327,7 +330,6 @@ typedef enum
k_squishedtimer, // Squished frame timer
k_rocketsneakertimer, // Rocket Sneaker duration timer
k_invincibilitytimer, // Invincibility timer
k_deathsentence, // 30 seconds to live... (SPB murder timer (not actually 30 sec, I just couldn't help the FF reference :p))
k_eggmanheld, // Eggman monitor held, separate from k_itemheld so it doesn't stop you from getting items
k_eggmanexplode, // Fake item recieved, explode in a few seconds
k_eggmanblame, // Fake item recieved, who set this fake
@ -344,6 +346,7 @@ typedef enum
k_comebackpoints, // Number of times you've bombed or gave an item to someone; once it's 3 it gets set back to 0 and you're given a bumper
k_comebackmode, // 0 = bomb, 1 = item
k_wanted, // Timer for determining WANTED status, lowers when hitting people, prevents the game turning into Camp Lazlo
k_yougotem, // "You Got Em" gfx when hitting someone as a karma player via a method that gets you back in the game instantly
NUMKARTSTUFF
} kartstufftype_t;

View File

@ -990,7 +990,7 @@ static const struct {
{"2D",TOL_2D},
{"MARIO",TOL_MARIO},
{"NIGHTS",TOL_NIGHTS},
//{"OLDBRAK",TOL_ERZ3},
{"TV",TOL_TV},
{"XMAS",TOL_XMAS},
{"CHRISTMAS",TOL_XMAS},
@ -1835,9 +1835,17 @@ static actionpointer_t actionpointers[] =
{{A_ItemPop}, "A_ITEMPOP"}, // SRB2kart
{{A_JawzChase}, "A_JAWZCHASE"}, // SRB2kart
{{A_JawzExplode}, "A_JAWZEXPLODE"}, // SRB2kart
{{A_SPBChase}, "A_SPBCHASE"}, // SRB2kart
{{A_MineExplode}, "A_MINEEXPLODE"}, // SRB2kart
{{A_BallhogExplode}, "A_BALLHOGEXPLODE"}, // SRB2kart
{{A_LightningFollowPlayer}, "A_LIGHTNINGFOLLOWPLAYER"}, //SRB2kart
{{A_LightningFollowPlayer},"A_LIGHTNINGFOLLOWPLAYER"}, //SRB2kart
{{A_FZBoomFlash}, "A_FZBOOMFLASH"}, //SRB2kart
{{A_FZBoomSmoke}, "A_FZBOOMSMOKE"}, //SRB2kart
{{A_RandomShadowFrame}, "A_RANDOMSHADOWFRAME"}, //SRB2kart
{{A_RoamingShadowThinker}, "A_ROAMINGSHADOWTHINKER"}, //SRB2kart
{{A_ReaperThinker}, "A_REAPERTHINKER"}, //SRB2kart
{{A_MementosTPParticles}, "A_MEMENTOSTPPARTICLES"}, //SRB2kart
{{A_FlameParticle}, "A_FLAMEPARTICLE"}, // SRB2kart
{{A_OrbitNights}, "A_ORBITNIGHTS"},
{{A_GhostMe}, "A_GHOSTME"},
{{A_SetObjectState}, "A_SETOBJECTSTATE"},
@ -2430,6 +2438,8 @@ static void readunlockable(MYFILE *f, INT32 num)
unlockables[num].type = SECRET_ENCORE;
else if (fastcmp(word2, "HELLATTACK"))
unlockables[num].type = SECRET_HELLATTACK;
else if (fastcmp(word2, "HARDSPEED"))
unlockables[num].type = SECRET_HARDSPEED;
else
unlockables[num].type = (INT16)i;
}
@ -5265,6 +5275,10 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_XMASPOLE",
"S_CANDYCANE",
"S_SNOWMAN",
"S_SNOWMANHAT",
"S_LAMPPOST1",
"S_LAMPPOST2",
"S_HANGSTAR",
// Botanic Serenity's loads of scenery states
"S_BSZTALLFLOWER_RED",
@ -6238,6 +6252,9 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_DRIFTSPARK_C1",
"S_DRIFTSPARK_C2",
// Brake drift sparks
"S_BRAKEDRIFT",
// Drift Smoke
"S_DRIFTDUST1",
"S_DRIFTDUST2",
@ -6311,32 +6328,38 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_WIPEOUTTRAIL4",
"S_WIPEOUTTRAIL5",
// Rocket sneaker
"S_ROCKETSNEAKER_L",
"S_ROCKETSNEAKER_R",
"S_ROCKETSNEAKER_LVIBRATE",
"S_ROCKETSNEAKER_RVIBRATE",
//{ Eggman Monitor
"S_FAKEITEM1",
"S_FAKEITEM2",
"S_FAKEITEM3",
"S_FAKEITEM4",
"S_FAKEITEM5",
"S_FAKEITEM6",
"S_FAKEITEM7",
"S_FAKEITEM8",
"S_FAKEITEM9",
"S_FAKEITEM10",
"S_FAKEITEM11",
"S_FAKEITEM12",
"S_FAKEITEM13",
"S_FAKEITEM14",
"S_FAKEITEM15",
"S_FAKEITEM16",
"S_FAKEITEM17",
"S_FAKEITEM18",
"S_FAKEITEM19",
"S_FAKEITEM20",
"S_FAKEITEM21",
"S_FAKEITEM22",
"S_FAKEITEM23",
"S_FAKEITEM24",
"S_DEADFAKEITEM",
"S_EGGMANITEM1",
"S_EGGMANITEM2",
"S_EGGMANITEM3",
"S_EGGMANITEM4",
"S_EGGMANITEM5",
"S_EGGMANITEM6",
"S_EGGMANITEM7",
"S_EGGMANITEM8",
"S_EGGMANITEM9",
"S_EGGMANITEM10",
"S_EGGMANITEM11",
"S_EGGMANITEM12",
"S_EGGMANITEM13",
"S_EGGMANITEM14",
"S_EGGMANITEM15",
"S_EGGMANITEM16",
"S_EGGMANITEM17",
"S_EGGMANITEM18",
"S_EGGMANITEM19",
"S_EGGMANITEM20",
"S_EGGMANITEM21",
"S_EGGMANITEM22",
"S_EGGMANITEM23",
"S_EGGMANITEM24",
"S_EGGMANITEM_DEAD",
//}
// Banana
@ -6467,17 +6490,27 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_BALLHOGBOOM16",
// Self-Propelled Bomb - just an explosion for now...
"S_BLUELIGHTNING1",
"S_BLUELIGHTNING2",
"S_BLUELIGHTNING3",
"S_BLUELIGHTNING4",
"S_BLUEEXPLODE",
// Grow/shrink beams
"S_LIGHTNING1",
"S_LIGHTNING2",
"S_LIGHTNING3",
"S_LIGHTNING4",
"S_SPB1",
"S_SPB2",
"S_SPB3",
"S_SPB4",
"S_SPB5",
"S_SPB6",
"S_SPB7",
"S_SPB8",
"S_SPB9",
"S_SPB10",
"S_SPB11",
"S_SPB12",
"S_SPB13",
"S_SPB14",
"S_SPB15",
"S_SPB16",
"S_SPB17",
"S_SPB18",
"S_SPB19",
"S_SPB20",
"S_SPB_DEAD",
// Thunder Shield
"S_THUNDERSHIELD1",
@ -6708,12 +6741,61 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_PLAYERARROW_WANTED6",
"S_PLAYERARROW_WANTED7",
"S_PLAYERBOMB", // Player bomb overlay
"S_PLAYERBOMB1", // Player bomb overlay
"S_PLAYERBOMB2",
"S_PLAYERBOMB3",
"S_PLAYERBOMB4",
"S_PLAYERBOMB5",
"S_PLAYERBOMB6",
"S_PLAYERBOMB7",
"S_PLAYERBOMB8",
"S_PLAYERBOMB9",
"S_PLAYERBOMB10",
"S_PLAYERBOMB11",
"S_PLAYERBOMB12",
"S_PLAYERBOMB13",
"S_PLAYERBOMB14",
"S_PLAYERBOMB15",
"S_PLAYERBOMB16",
"S_PLAYERBOMB17",
"S_PLAYERBOMB18",
"S_PLAYERBOMB19",
"S_PLAYERBOMB20",
"S_PLAYERITEM", // Player item overlay
"S_PLAYERFAKE", // Player fake overlay
"S_KARMAWHEEL", // Karma player wheels
"S_BATTLEPOINT1A", // Battle point indicators
"S_BATTLEPOINT1B",
"S_BATTLEPOINT1C",
"S_BATTLEPOINT1D",
"S_BATTLEPOINT1E",
"S_BATTLEPOINT1F",
"S_BATTLEPOINT1G",
"S_BATTLEPOINT1H",
"S_BATTLEPOINT1I",
"S_BATTLEPOINT2A",
"S_BATTLEPOINT2B",
"S_BATTLEPOINT2C",
"S_BATTLEPOINT2D",
"S_BATTLEPOINT2E",
"S_BATTLEPOINT2F",
"S_BATTLEPOINT2G",
"S_BATTLEPOINT2H",
"S_BATTLEPOINT2I",
"S_BATTLEPOINT3A",
"S_BATTLEPOINT3B",
"S_BATTLEPOINT3C",
"S_BATTLEPOINT3D",
"S_BATTLEPOINT3E",
"S_BATTLEPOINT3F",
"S_BATTLEPOINT3G",
"S_BATTLEPOINT3H",
"S_BATTLEPOINT3I",
// Thunder shield use stuff;
"S_KSPARK1", // Sparkling Radius
"S_KSPARK2",
@ -6762,6 +6844,254 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_KLIT11",
"S_KLIT12",
"S_FZEROSMOKE1", // F-Zero NO CONTEST explosion
"S_FZEROSMOKE2",
"S_FZEROSMOKE3",
"S_FZEROSMOKE4",
"S_FZEROSMOKE5",
"S_FZEROBOOM1",
"S_FZEROBOOM2",
"S_FZEROBOOM3",
"S_FZEROBOOM4",
"S_FZEROBOOM5",
"S_FZEROBOOM6",
"S_FZEROBOOM7",
"S_FZEROBOOM8",
"S_FZEROBOOM9",
"S_FZEROBOOM10",
"S_FZEROBOOM11",
"S_FZEROBOOM12",
"S_FZSLOWSMOKE1",
"S_FZSLOWSMOKE2",
"S_FZSLOWSMOKE3",
"S_FZSLOWSMOKE4",
"S_FZSLOWSMOKE5",
// Various plants
"S_SONICBUSH",
"S_SHRUB",
"S_TALLBUSH",
"S_AZURECITYTREE",
// Marble Zone
"S_FLAMEPARTICLE",
"S_MARBLETORCH",
"S_MARBLELIGHT",
"S_MARBLEBURNER",
// CD Special Stage
"S_CDUFO",
"S_CDUFO_DIE",
// Rusty Rig
"S_RUSTYLAMP_ORANGE",
"S_RUSTYCHAIN",
// D2 Balloon Panic
"S_BALLOON",
"S_BALLOONPOP1",
"S_BALLOONPOP2",
"S_BALLOONPOP3",
// Smokin' & Vapin' (Don't try this at home, kids!)
"S_PETSMOKE0",
"S_PETSMOKE1",
"S_PETSMOKE2",
"S_PETSMOKE3",
"S_PETSMOKE4",
"S_PETSMOKE5",
"S_VVVAPING0",
"S_VVVAPING1",
"S_VVVAPING2",
"S_VVVAPING3",
"S_VVVAPING4",
"S_VVVAPING5",
"S_VVVAPE",
// Hill Top Zone
"S_HTZTREE",
"S_HTZBUSH",
// Ports of gardens
"S_SGVINE1",
"S_SGVINE2",
"S_SGVINE3",
"S_PGTREE",
"S_PGFLOWER1",
"S_PGFLOWER2",
"S_PGFLOWER3",
"S_PGBUSH",
"S_DHPILLAR",
// Midnight Channel stuff:
"S_SPOTLIGHT", // Spotlight decoration
"S_RANDOMSHADOW", // Random Shadow. They're static and don't do nothing.
"S_GARU1",
"S_GARU2",
"S_GARU3",
"S_TGARU",
"S_TGARU1",
"S_TGARU2",
"S_TGARU3", // Wind attack used by Roaming Shadows on Players.
"S_ROAMINGSHADOW", // Roaming Shadow (the one that uses above's wind attack or smth)
"S_MAYONAKAARROW", // Arrow sign
// Mementos stuff:
"S_REAPER_INVIS", // Reaper waiting for spawning
"S_REAPER", // Reaper main frame where its thinker is handled
"S_MEMENTOSTP", // Mementos teleporter state. (Used for spawning particles)
// JackInTheBox
"S_JITB1",
"S_JITB2",
"S_JITB3",
"S_JITB4",
"S_JITB5",
"S_JITB6",
// Color Drive
"S_CDMOONSP",
"S_CDBUSHSP",
"S_CDTREEASP",
"S_CDTREEBSP",
// Daytona Speedway
"S_PINETREE",
"S_PINETREE_SIDE",
// Egg Zeppelin
"S_EZZPROPELLER",
"S_EZZPROPELLER_BLADE",
// Desert Palace
"S_DP_PALMTREE",
// Aurora Atoll
"S_AAZTREE_SEG",
"S_AAZTREE_COCONUT",
"S_AAZTREE_LEAF",
// Barren Badlands
"S_BBZDUST1", // Dust
"S_BBZDUST2",
"S_BBZDUST3",
"S_BBZDUST4",
"S_FROGGER", // Frog badniks
"S_FROGGER_ATTACK",
"S_FROGGER_JUMP",
"S_FROGTONGUE",
"S_FROGTONGUE_JOINT",
"S_ROBRA", // Black cobra badniks
"S_ROBRA_HEAD",
"S_ROBRA_JOINT",
"S_ROBRASHELL_INSIDE",
"S_ROBRASHELL_OUTSIDE",
"S_BLUEROBRA", // Blue cobra badniks
"S_BLUEROBRA_HEAD",
"S_BLUEROBRA_JOINT",
// Eerie Grove
"S_EERIEFOG1",
"S_EERIEFOG2",
"S_EERIEFOG3",
"S_EERIEFOG4",
"S_EERIEFOG5",
// SMK ports
"S_SMK_PIPE1", // Generic pipes
"S_SMK_PIPE2",
"S_SMK_MOLE", // Donut Plains Monty Moles
"S_SMK_THWOMP", // Bowser Castle Thwomps
"S_SMK_SNOWBALL", // Vanilla Lake snowballs
"S_SMK_ICEBLOCK", // Vanilla Lake breakable ice blocks
"S_SMK_ICEBLOCK2",
"S_SMK_ICEBLOCK_DEBRIS",
"S_SMK_ICEBLOCK_DEBRIS2",
// Ezo's maps
"S_BLUEFIRE1",
"S_BLUEFIRE2",
"S_BLUEFIRE3",
"S_BLUEFIRE4",
"S_GREENFIRE1",
"S_GREENFIRE2",
"S_GREENFIRE3",
"S_GREENFIRE4",
"S_REGALCHEST",
"S_CHIMERASTATUE",
"S_DRAGONSTATUE",
"S_LIZARDMANSTATUE",
"S_PEGASUSSTATUE",
"S_ZELDAFIRE1",
"S_ZELDAFIRE2",
"S_ZELDAFIRE3",
"S_ZELDAFIRE4",
"S_GANBARETHING",
"S_GANBAREDUCK",
"S_GANBARETREE",
"S_MONOIDLE",
"S_MONOCHASE1",
"S_MONOCHASE2",
"S_MONOCHASE3",
"S_MONOCHASE4",
"S_MONOPAIN",
"S_REDZELDAFIRE1",
"S_REDZELDAFIRE2",
"S_REDZELDAFIRE3",
"S_REDZELDAFIRE4",
"S_BOWLINGPIN",
"S_BOWLINGHIT1",
"S_BOWLINGHIT2",
"S_BOWLINGHIT3",
"S_BOWLINGHIT4",
"S_ARIDTOAD",
"S_TOADHIT1",
"S_TOADHIT2",
"S_TOADHIT3",
"S_TOADHIT4",
"S_EBARRELIDLE",
"S_EBARREL1",
"S_EBARREL2",
"S_EBARREL3",
"S_EBARREL4",
"S_EBARREL5",
"S_EBARREL6",
"S_EBARREL7",
"S_EBARREL8",
"S_EBARREL9",
"S_EBARREL10",
"S_EBARREL11",
"S_EBARREL12",
"S_EBARREL13",
"S_EBARREL14",
"S_EBARREL15",
"S_EBARREL16",
"S_EBARREL17",
"S_EBARREL18",
"S_MERRYHORSE",
"S_BLUEFRUIT",
"S_ORANGEFRUIT",
"S_REDFRUIT",
"S_PINKFRUIT",
"S_ADVENTURESPIKEA1",
"S_ADVENTURESPIKEA2",
"S_ADVENTURESPIKEB1",
"S_ADVENTURESPIKEB2",
"S_ADVENTURESPIKEC1",
"S_ADVENTURESPIKEC2",
"S_BOOSTPROMPT1",
"S_BOOSTPROMPT2",
"S_BOOSTOFF1",
"S_BOOSTOFF2",
"S_BOOSTON1",
"S_BOOSTON2",
"S_LIZARDMAN",
"S_LIONMAN",
"S_MOUSEMAN1",
"S_MOUSEMAN2",
#ifdef SEENAMES
"S_NAMECHECK",
#endif
@ -7048,6 +7378,10 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_XMASPOLE",
"MT_CANDYCANE",
"MT_SNOWMAN",
"MT_SNOWMANHAT",
"MT_LAMPPOST1",
"MT_LAMPPOST2",
"MT_HANGSTAR",
// Botanic Serenity
"MT_BSZTALLFLOWER_RED",
@ -7292,10 +7626,13 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_INVULNFLASH",
"MT_WIPEOUTTRAIL",
"MT_DRIFTSPARK",
"MT_BRAKEDRIFT",
"MT_DRIFTDUST",
"MT_FAKESHIELD",
"MT_FAKEITEM",
"MT_ROCKETSNEAKER", // Rocket sneakers
"MT_EGGMANITEM", // Eggman items
"MT_EGGMANITEM_SHIELD",
"MT_BANANA", // Banana Stuff
"MT_BANANA_SHIELD",
@ -7305,7 +7642,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_JAWZ", // Jawz stuff
"MT_JAWZ_DUD",
"MT_JAWZ_SHIELD",
"MT_JAWZ_SHIELD",
"MT_PLAYERRETICULE", // Jawz reticule
@ -7321,9 +7658,8 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_BALLHOG", // Ballhog
"MT_BALLHOGBOOM",
"MT_BLUELIGHTNING", // Grow/shrink stuff
"MT_BLUEEXPLOSION",
"MT_LIGHTNING",
"MT_SPB", // Self-Propelled Bomb
"MT_SPBEXPLOSION",
"MT_THUNDERSHIELD", // Thunder Shield stuff
@ -7413,6 +7749,149 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_KARMAHITBOX",
"MT_KARMAWHEEL",
"MT_BATTLEPOINT",
"MT_FZEROBOOM",
// Various plants
"MT_SONICBUSH",
"MT_SHRUB",
"MT_TALLBUSH",
"MT_AZURECITYTREE",
// Marble Zone
"MT_FLAMEPARTICLE",
"MT_MARBLETORCH",
"MT_MARBLELIGHT",
"MT_MARBLEBURNER",
// CD Special Stage
"MT_CDUFO",
// Rusty Rig
"MT_RUSTYLAMP_ORANGE",
"MT_RUSTYCHAIN",
// D2 Balloon Panic
"MT_BALLOON",
// Smokin' & Vapin' (Don't try this at home, kids!)
"MT_PETSMOKER",
"MT_PETSMOKE",
"MT_VVVAPE",
// Hill Top Zone
"MT_HTZTREE",
"MT_HTZBUSH",
// Ports of gardens
"MT_SGVINE1",
"MT_SGVINE2",
"MT_SGVINE3",
"MT_PGTREE",
"MT_PGFLOWER1",
"MT_PGFLOWER2",
"MT_PGFLOWER3",
"MT_PGBUSH",
"MT_DHPILLAR",
// Midnight Channel stuff:
"MT_SPOTLIGHT", // Spotlight Object
"MT_RANDOMSHADOW", // Random static Shadows.
"MT_ROAMINGSHADOW", // Roaming Shadows.
"MT_MAYONAKAARROW", // Arrow static signs for Mayonaka
// Mementos stuff
"MT_REAPERWAYPOINT",
"MT_REAPER",
"MT_MEMENTOSTP",
"MT_MEMENTOSPARTICLE",
"MT_JACKINTHEBOX",
// Color Drive:
"MT_CDMOON",
"MT_CDBUSH",
"MT_CDTREEA",
"MT_CDTREEB",
// Daytona Speedway
"MT_PINETREE",
"MT_PINETREE_SIDE",
// Egg Zeppelin
"MT_EZZPROPELLER",
"MT_EZZPROPELLER_BLADE",
// Desert Palace
"MT_DP_PALMTREE",
// Aurora Atoll
"MT_AAZTREE_HELPER",
"MT_AAZTREE_SEG",
"MT_AAZTREE_COCONUT",
"MT_AAZTREE_LEAF",
// Barren Badlands
"MT_BBZDUST",
"MT_FROGGER",
"MT_FROGTONGUE",
"MT_FROGTONGUE_JOINT",
"MT_ROBRA",
"MT_ROBRA_HEAD",
"MT_ROBRA_JOINT",
"MT_BLUEROBRA",
"MT_BLUEROBRA_HEAD",
"MT_BLUEROBRA_JOINT",
// Eerie Grove
"MT_EERIEFOG",
"MT_EERIEFOGGEN",
// SMK ports
"MT_SMK_PIPE",
"MT_SMK_MOLESPAWNER",
"MT_SMK_MOLE",
"MT_SMK_THWOMP",
"MT_SMK_SNOWBALL",
"MT_SMK_ICEBLOCK",
"MT_SMK_ICEBLOCK_SIDE",
"MT_SMK_ICEBLOCK_DEBRIS",
// Ezo's maps
"MT_BLUEFIRE",
"MT_GREENFIRE",
"MT_REGALCHEST",
"MT_CHIMERASTATUE",
"MT_DRAGONSTATUE",
"MT_LIZARDMANSTATUE",
"MT_PEGASUSSTATUE",
"MT_ZELDAFIRE",
"MT_GANBARETHING",
"MT_GANBAREDUCK",
"MT_GANBARETREE",
"MT_MONOKUMA",
"MT_REDZELDAFIRE",
"MT_BOWLINGPIN",
"MT_MERRYAMBIENCE",
"MT_TWINKLECARTAMBIENCE",
"MT_EXPLODINGBARREL",
"MT_MERRYHORSE",
"MT_ARIDTOAD",
"MT_BLUEFRUIT",
"MT_ORANGEFRUIT",
"MT_REDFRUIT",
"MT_PINKFRUIT",
"MT_ADVENTURESPIKEA",
"MT_ADVENTURESPIKEB",
"MT_ADVENTURESPIKEC",
"MT_BOOSTPROMPT",
"MT_BOOSTOFF",
"MT_BOOSTON",
"MT_LIZARDMAN",
"MT_LIONMAN",
"MT_MOUSEMAN",
#ifdef SEENAMES
"MT_NAMECHECK",
#endif
@ -7743,6 +8222,7 @@ static const char *const KARTSTUFF_LIST[] = {
"THROWDIR",
"LAPANIMATION",
"LAPHAND",
"CARDANIMATION",
"VOICES",
"TAUNTVOICES",
@ -7769,7 +8249,9 @@ static const char *const KARTSTUFF_LIST[] = {
"ACCELBOOST",
"BOOSTCAM",
"DESTBOOSTCAM",
"TIMEOVERCAM",
"AIZDRIFTSTRAT",
"BRAKEDRIFT",
"ITEMROULETTE",
"ROULETTETYPE",
@ -7787,7 +8269,6 @@ static const char *const KARTSTUFF_LIST[] = {
"SQUISHEDTIMER",
"ROCKETSNEAKERTIMER",
"INVINCIBILITYTIMER",
"DEATHSENTENCE",
"EGGMANHELD",
"EGGMANEXPLODE",
"EGGMANBLAME",
@ -7803,6 +8284,7 @@ static const char *const KARTSTUFF_LIST[] = {
"COMEBACKPOINTS",
"COMEBACKMODE",
"WANTED",
"YOUGOTEM",
};
static const char *const HUDITEMS_LIST[] = {

View File

@ -302,7 +302,7 @@ enum TypeOfLevel
TOL_2D = 0x0100, ///< 2D
TOL_MARIO = 0x0200, ///< Mario
TOL_NIGHTS = 0x0400, ///< NiGHTS
//TOL_ERZ3 = 0x0800, ///< ERZ3
TOL_TV = 0x0800, ///< Midnight Channel specific: draw TV like overlay on HUD
TOL_XMAS = 0x1000 ///< Christmas NiGHTS
//TOL_KART = 0x4000 ///< Kart 32768
};
@ -458,9 +458,9 @@ extern boolean comeback;
extern SINT8 battlewanted[4];
extern tic_t wantedcalcdelay;
extern tic_t indirectitemcooldown;
extern tic_t spbincoming;
extern UINT8 spbplayer;
extern tic_t mapreset;
extern UINT8 nospectategrief;
extern boolean thwompsactive;
extern boolean legitimateexit;
extern boolean comebackshowninfo;

View File

@ -264,9 +264,9 @@ SINT8 pickedvote; // What vote the host rolls
SINT8 battlewanted[4]; // WANTED players in battle, worth x2 points
tic_t wantedcalcdelay; // Time before it recalculates WANTED
tic_t indirectitemcooldown; // Cooldown before any more Shrink, SPB, or any other item that works indirectly is awarded
tic_t spbincoming; // Timer before SPB hits, can switch targets at this point
UINT8 spbplayer; // Player num that used the last SPB
tic_t mapreset; // Map reset delay when enough players have joined an empty game
UINT8 nospectategrief; // How many players need to be in-game to eliminate last; for preventing spectate griefing
boolean thwompsactive; // Thwomps activate on lap 2
// Client-sided, unsynched variables (NEVER use in anything that needs to be synced with other players)
boolean legitimateexit; // Did this client actually finish the match?
@ -425,7 +425,7 @@ consvar_t cv_chatspamprotection = {"chatspamprotection", "On", CV_SAVE, CV_OnOff
consvar_t cv_chatbacktint = {"chatbacktint", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
// old shit console chat. (mostly exists for stuff like terminal, not because I cared if anyone liked the old chat.)
static CV_PossibleValue_t consolechat_cons_t[] = {{0, "Window"}, {1, "Console"}, {0, NULL}};
static CV_PossibleValue_t consolechat_cons_t[] = {{0, "Window"}, {1, "Console"}, {2, "Window (Hidden)"}, {0, NULL}};
consvar_t cv_consolechat = {"chatmode", "Window", CV_SAVE, consolechat_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
/*consvar_t cv_crosshair = {"crosshair", "Off", CV_SAVE, crosshair_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
@ -1839,6 +1839,9 @@ boolean G_Responder(event_t *ev)
if (players[displayplayer].exiting)
continue;
if (players[displayplayer].pflags & PF_TIMEOVER)
continue;
// I don't know if we want this actually, but I'll humor the suggestion anyway
if (G_BattleGametype())
{
@ -2100,10 +2103,12 @@ void G_Ticker(boolean run)
G_ClearRetryFlag();
// Costs a life to retry ... unless the player in question is dead already.
if (G_GametypeUsesLives() && players[consoleplayer].playerstate == PST_LIVE)
/*if (G_GametypeUsesLives() && players[consoleplayer].playerstate == PST_LIVE)
players[consoleplayer].lives -= 1;
G_DoReborn(consoleplayer);
G_DoReborn(consoleplayer);*/
D_MapChange(gamemap, gametype, cv_kartencore.value, true, 1, false, false);
}
for (i = 0; i < MAXPLAYERS; i++)
@ -2353,6 +2358,7 @@ void G_PlayerReborn(INT32 player)
INT32 itemamount;
INT32 itemroulette;
INT32 roulettetype;
INT32 growshrinktimer;
INT32 bumper;
INT32 comebackpoints;
INT32 wanted;
@ -2365,7 +2371,7 @@ void G_PlayerReborn(INT32 player)
exiting = players[player].exiting;
jointime = players[player].jointime;
spectator = players[player].spectator;
pflags = (players[player].pflags & (PF_TIMEOVER|PF_FLIPCAM|PF_TAGIT|PF_TAGGED|PF_ANALOGMODE));
pflags = (players[player].pflags & (PF_TIMEOVER|PF_FLIPCAM|PF_TAGIT|PF_TAGGED|PF_ANALOGMODE|PF_WANTSTOJOIN));
// As long as we're not in multiplayer, carry over cheatcodes from map to map
if (!(netgame || multiplayer))
@ -2416,6 +2422,7 @@ void G_PlayerReborn(INT32 player)
roulettetype = 0;
itemtype = 0;
itemamount = 0;
growshrinktimer = 0;
bumper = (G_BattleGametype() ? cv_kartbumpers.value : 0);
comebackpoints = 0;
wanted = 0;
@ -2439,6 +2446,9 @@ void G_PlayerReborn(INT32 player)
itemamount = players[player].kartstuff[k_itemamount];
}
// Keep Shrink status, remove Grow status
growshrinktimer = min(players[player].kartstuff[k_growshrinktimer], 0);
bumper = players[player].kartstuff[k_bumper];
comebackpoints = players[player].kartstuff[k_comebackpoints];
wanted = players[player].kartstuff[k_wanted];
@ -2503,6 +2513,7 @@ void G_PlayerReborn(INT32 player)
p->kartstuff[k_roulettetype] = roulettetype;
p->kartstuff[k_itemtype] = itemtype;
p->kartstuff[k_itemamount] = itemamount;
p->kartstuff[k_growshrinktimer] = growshrinktimer;
p->kartstuff[k_bumper] = bumper;
p->kartstuff[k_comebackpoints] = comebackpoints;
p->kartstuff[k_comebacktimer] = comebacktime;
@ -2935,7 +2946,7 @@ void G_DoReborn(INT32 playernum)
if (oldmo)
G_ChangePlayerReferences(oldmo, players[playernum].mo);
}
else if (countdowntimeup || (!multiplayer && gametype == GT_COOP))
/*else if (countdowntimeup || (!multiplayer && !modeattacking))
{
// reload the level from scratch
if (countdowntimeup)
@ -3004,7 +3015,7 @@ void G_DoReborn(INT32 playernum)
#ifdef HAVE_BLUA
}
#endif
}
}*/
else
{
// respawn at the start
@ -3051,7 +3062,7 @@ void G_ExitLevel(void)
}
if (netgame || multiplayer)
CONS_Printf(M_GetText("The round has ended.\n"));
CON_LogMessage(M_GetText("The round has ended.\n"));
// Remove CEcho text on round end.
HU_DoCEcho("");
@ -3119,7 +3130,7 @@ boolean G_GametypeHasSpectators(void)
#if 0
return (gametype != GT_COOP && gametype != GT_COMPETITION && gametype != GT_RACE);
#else
return (!splitscreen);//true;
return (netgame); //true
#endif
}
@ -4023,6 +4034,7 @@ static void M_ForceLoadGameResponse(INT32 ch)
displayplayer = consoleplayer;
multiplayer = false;
splitscreen = 0;
SplitScreen_OnChange(); // not needed?
if (setsizeneeded)
R_ExecuteSetViewSize();
@ -4112,6 +4124,7 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride)
displayplayer = consoleplayer;
multiplayer = false;
splitscreen = 0;
SplitScreen_OnChange(); // not needed?
// G_DeferedInitNew(sk_medium, G_BuildMapName(1), 0, 0, 1);
if (setsizeneeded)
@ -4339,13 +4352,13 @@ void G_InitNew(UINT8 pencoremode, const char *mapname, boolean resetplayer, bool
{
char *title = G_BuildMapTitle(gamemap);
CONS_Printf(M_GetText("Map is now \"%s"), G_BuildMapName(gamemap));
CON_LogMessage(va(M_GetText("Map is now \"%s"), G_BuildMapName(gamemap)));
if (title)
{
CONS_Printf(": %s", title);
CON_LogMessage(va(": %s", title));
Z_Free(title);
}
CONS_Printf("\"\n");
CON_LogMessage("\"\n");
}
}
@ -4496,6 +4509,13 @@ void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum)
G_CopyTiccmd(cmd, &oldcmd, 1);
// SRB2kart: Copy-pasted from ticcmd building, removes that crappy demo cam
if (((players[displayplayer].mo && players[displayplayer].speed > 0) // Moving
|| (leveltime > starttime && (cmd->buttons & BT_ACCELERATE && cmd->buttons & BT_BRAKE)) // Rubber-burn turn
|| (players[displayplayer].spectator || objectplacing)) // Not a physical player
&& !(players[displayplayer].kartstuff[k_spinouttimer] && players[displayplayer].kartstuff[k_sneakertimer])) // Spinning and boosting cancels out spinout
localangle += (cmd->angleturn<<16);
if (!(demoflags & DF_GHOST) && *demo_p == DEMOMARKER)
{
// end of demo data stream

View File

@ -62,6 +62,7 @@ extern consvar_t cv_turnaxis2,cv_moveaxis2,cv_brakeaxis2,cv_aimaxis2,cv_lookaxis
extern consvar_t cv_turnaxis3,cv_moveaxis3,cv_brakeaxis3,cv_aimaxis3,cv_lookaxis3,cv_fireaxis3,cv_driftaxis3;
extern consvar_t cv_turnaxis4,cv_moveaxis4,cv_brakeaxis4,cv_aimaxis4,cv_lookaxis4,cv_fireaxis4,cv_driftaxis4;
extern consvar_t cv_ghost_besttime, cv_ghost_bestlap, cv_ghost_last, cv_ghost_guest, cv_ghost_staff;
extern consvar_t cv_splitplayers;
typedef enum
{
@ -188,7 +189,6 @@ void G_StopMetalDemo(void);
ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(void);
void G_StopDemo(void);
boolean G_CheckDemoStatus(void);
char *G_DemoPlayerName(char *defdemoname);
boolean G_IsSpecialStage(INT32 mapnum);
boolean G_GametypeUsesLives(void);

View File

@ -1321,21 +1321,21 @@ void G_Controldefault(void)
gamecontrolbis[gc_accelerate ][0] = KEY_2JOY1+0; // A
gamecontrolbis[gc_lookback ][0] = KEY_2JOY1+1; // X
gamecontrolbis[gc_brake ][0] = KEY_2JOY1+2; // B
gamecontrolbis[gc_fire ][0] = KEY_2JOY1+4; // LB
gamecontrolbis[gc_fire ][0] = KEY_2JOY1+4; // LB
gamecontrolbis[gc_drift ][0] = KEY_2JOY1+5; // RB
// Player 3 controls
gamecontrol3[gc_accelerate ][0] = KEY_3JOY1+0; // A
gamecontrol3[gc_lookback ][0] = KEY_3JOY1+1; // X
gamecontrol3[gc_brake ][0] = KEY_3JOY1+2; // B
gamecontrol3[gc_fire ][0] = KEY_3JOY1+4; // LB
gamecontrol3[gc_fire ][0] = KEY_3JOY1+4; // LB
gamecontrol3[gc_drift ][0] = KEY_3JOY1+5; // RB
// Player 4 controls
gamecontrol4[gc_accelerate ][0] = KEY_4JOY1+0; // A
gamecontrol4[gc_lookback ][0] = KEY_4JOY1+1; // X
gamecontrol4[gc_brake ][0] = KEY_4JOY1+2; // B
gamecontrol4[gc_fire ][0] = KEY_4JOY1+4; // LB
gamecontrol4[gc_fire ][0] = KEY_4JOY1+4; // LB
gamecontrol4[gc_drift ][0] = KEY_4JOY1+5; // RB
}
//#endif

View File

@ -1328,6 +1328,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
frame = (spr->mobj->frame & FF_FRAMEMASK) % md2->model->header.numFrames;
buff = md2->model->glCommandBuffer;
curr = &md2->model->frames[frame];
#if 0
if (cv_grmd2.value == 1 && tics <= durs)
{
// frames are handled differently for states with FF_ANIMATE, so get the next frame differently for the interpolation
@ -1348,6 +1349,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
}
}
}
#endif
//Hurdler: it seems there is still a small problem with mobj angle
p.x = FIXED_TO_FLOAT(spr->mobj->x);

View File

@ -87,7 +87,6 @@ patch_t *rmatcico;
patch_t *bmatcico;
patch_t *tagico;
patch_t *tallminus;
patch_t *iconprefix[MAXSKINS]; // minimap icons
//-------------------------------------------
// coop hud
@ -109,8 +108,8 @@ static patch_t *crosshair[HU_CROSSHAIRS]; // 3 precached crosshair graphics
// protos.
// -------
static void HU_DrawRankings(void);
static void HU_DrawCoopOverlay(void);
static void HU_DrawNetplayCoopOverlay(void);
//static void HU_DrawCoopOverlay(void);
//static void HU_DrawNetplayCoopOverlay(void);
//======================================================================
// KEYBOARD LAYOUTS FOR ENTERING TEXT
@ -386,12 +385,11 @@ static void HU_removeChatText_Log(void)
chat_nummsg_log--; // lost 1 msg.
}
void HU_AddChatText(const char *text)
void HU_AddChatText(const char *text, boolean playsound)
{
if (cv_chatnotifications.value)
if (playsound && cv_consolechat.value != 2) // Don't play the sound if we're using hidden chat.
S_StartSound(NULL, sfx_radio);
// TODO: check if we're oversaturating the log (we can only log CHAT_BUFSIZE messages.)
// reguardless of our preferences, put all of this in the chat buffer in case we decide to change from oldchat mid-game.
if (chat_nummsg_log >= CHAT_BUFSIZE)
HU_removeChatText_Log();
@ -405,6 +403,11 @@ void HU_AddChatText(const char *text)
strcpy(chat_mini[chat_nummsg_min], text);
chat_timers[chat_nummsg_min] = TICRATE*cv_chattime.value;
chat_nummsg_min++;
if (OLDCHAT) // if we're using oldchat, print directly in console
CONS_Printf("%s\n", text);
else // if we aren't, still save the message to log.txt
CON_LogMessage(va("%s\n", text));
}
/** Runs a say command, sending an ::XD_SAY message.
@ -437,7 +440,7 @@ static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags)
if (CHAT_MUTE) // TODO: Per Player mute.
{
HU_AddChatText(va("%s>ERROR: The chat is muted. You can't say anything.", "\x85"));
HU_AddChatText(va("%s>ERROR: The chat is muted. You can't say anything.", "\x85"), false);
return;
}
@ -478,7 +481,7 @@ static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags)
// let it slide
else
{
HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<node> \'.");
HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<node> \'.", false);
return;
}
}
@ -487,7 +490,7 @@ static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags)
{
if (msg[5] != ' ')
{
HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<node> \'.");
HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<node> \'.", false);
return;
}
}
@ -500,7 +503,7 @@ static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags)
target++; // even though playernums are from 0 to 31, target is 1 to 32, so up that by 1 to have it work!
else
{
HU_AddChatText(va("\x82NOTICE: \x80Player %d does not exist.", target)); // same
HU_AddChatText(va("\x82NOTICE: \x80Player %d does not exist.", target), false); // same
return;
}
buf[0] = target;
@ -716,7 +719,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
|| target == 0 // To everyone
|| consoleplayer == target-1) // To you
{
const char *prefix = "", *cstart = "", *cend = "", *adminchar = "\x82~\x83", *remotechar = "\x82@\x83", *fmt, *fmt2, *textcolor = "\x80";
const char *prefix = "", *cstart = "", *cend = "", *adminchar = "\x82~\x83", *remotechar = "\x82@\x83", *fmt2, *textcolor = "\x80";
char *tempchar = NULL;
// player is a spectator?
@ -796,16 +799,12 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
// name, color end, and the message itself.
// '\4' makes the message yellow and beeps; '\3' just beeps.
if (action)
{
fmt = "\3* %s%s%s%s \x82%s%s\n"; // don't make /me yellow, yellow will be for mentions and PMs!
fmt2 = "* %s%s%s%s \x82%s%s";
}
else if (target-1 == consoleplayer) // To you
{
prefix = "\x82[PM]";
cstart = "\x82";
textcolor = "\x82";
fmt = "\4%s<%s%s>%s\x80 %s%s\n"; // make this yellow, however.
fmt2 = "%s<%s%s>%s\x80 %s%s";
}
else if (target > 0) // By you, to another player
@ -814,15 +813,11 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
dispname = player_names[target-1];
prefix = "\x82[TO]";
cstart = "\x82";
fmt = "\4%s<%s%s>%s\x80 %s%s\n"; // make this yellow, however.
fmt2 = "%s<%s%s>%s\x80 %s%s";
}
else // To everyone or sayteam, it doesn't change anything.
{
fmt = "\3%s<%s%s%s>\x80 %s%s\n";
fmt2 = "%s<%s%s%s>\x80 %s%s";
}
/*else // To your team
{
if (players[playernum].ctfteam == 1) // red
@ -836,12 +831,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
fmt2 = "%s<%s%s>\x80%s %s%s";
}*/
HU_AddChatText(va(fmt2, prefix, cstart, dispname, cend, textcolor, msg)); // add it reguardless, in case we decide to change our mind about our chat type.
if OLDCHAT
CONS_Printf(fmt, prefix, cstart, dispname, cend, textcolor, msg);
else
CON_LogMessage(va(fmt, prefix, cstart, dispname, cend, textcolor, msg)); // save to log.txt
HU_AddChatText(va(fmt2, prefix, cstart, dispname, cend, textcolor, msg), cv_chatnotifications.value); // add to chat
if (tempchar)
Z_Free(tempchar);
@ -968,7 +958,7 @@ static void HU_queueChatChar(INT32 c)
// last minute mute check
if (CHAT_MUTE)
{
HU_AddChatText(va("%s>ERROR: The chat is muted. You can't say anything.", "\x85"));
HU_AddChatText(va("%s>ERROR: The chat is muted. You can't say anything.", "\x85"), false);
return;
}
@ -983,7 +973,7 @@ static void HU_queueChatChar(INT32 c)
// teamtalk can't send PMs, just don't send it, else everyone would be able to see it, and no one wants to see your sex RP sicko.
if (teamtalk)
{
HU_AddChatText(va("%sCannot send sayto in Say-Team.", "\x85"));
HU_AddChatText(va("%sCannot send sayto in Say-Team.", "\x85"), false);
return;
}
@ -999,7 +989,7 @@ static void HU_queueChatChar(INT32 c)
// let it slide
else
{
HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<node> \'.");
HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<node> \'.", false);
return;
}
}
@ -1008,7 +998,7 @@ static void HU_queueChatChar(INT32 c)
{
if (msg[5] != ' ')
{
HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<node> \'.");
HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<node> \'.", false);
return;
}
}
@ -1021,7 +1011,7 @@ static void HU_queueChatChar(INT32 c)
target++; // even though playernums are from 0 to 31, target is 1 to 32, so up that by 1 to have it work!
else
{
HU_AddChatText(va("\x82NOTICE: \x80Player %d does not exist.", target)); // same
HU_AddChatText(va("\x82NOTICE: \x80Player %d does not exist.", target), false); // same
return;
}
// we need to get rid of the /pm<node>
@ -1066,6 +1056,26 @@ boolean HU_Responder(event_t *ev)
// only KeyDown events now...
// Shoot, to prevent P1 chatting from ruining the game for everyone else, it's either:
// A. completely disallow opening chat entirely in online splitscreen
// or B. iterate through all controls to make sure it's bound to player 1 before eating
// You can see which one I chose.
// (Unless if you're sharing a keyboard, since you probably establish when you start chatting that you have dibs on it...)
// (Ahhh, the good ol days when I was a kid who couldn't afford an extra USB controller...)
if (ev->data1 >= KEY_MOUSE1)
{
INT32 i;
for (i = 0; i < num_gamecontrols; i++)
{
if (gamecontrol[i][0] == ev->data1 || gamecontrol[i][1] == ev->data1)
break;
}
if (i == num_gamecontrols)
return false;
}
if (!chat_on)
{
// enter chat mode
@ -1269,6 +1279,7 @@ static void HU_drawMiniChat(void)
{
INT32 x = chatx+2;
INT32 charwidth = 4, charheight = 6;
INT32 boxw = cv_chatwidth.value;
INT32 dx = 0, dy = 0;
size_t i = chat_nummsg_min;
boolean prev_linereturn = false; // a hack to prevent double \n while I have no idea why they happen in the first place.
@ -1280,9 +1291,12 @@ static void HU_drawMiniChat(void)
if (!chat_nummsg_min)
return; // needless to say it's useless to do anything if we don't have anything to draw.
if (splitscreen > 1)
boxw = max(64, boxw/2);
for (; i>0; i--)
{
const char *msg = CHAT_WordWrap(x+2, cv_chatwidth.value-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i-1]);
const char *msg = CHAT_WordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i-1]);
size_t j = 0;
INT32 linescount = 0;
@ -1315,7 +1329,7 @@ static void HU_drawMiniChat(void)
}
prev_linereturn = false;
dx += charwidth;
if (dx >= cv_chatwidth.value)
if (dx >= boxw)
{
dx = 0;
linescount += 1;
@ -1326,7 +1340,17 @@ static void HU_drawMiniChat(void)
msglines += linescount+1;
}
y = chaty - charheight*(msglines+1) - (cv_kartspeedometer.value ? 16 : 0);
y = chaty - charheight*(msglines+1);
if (splitscreen)
{
y -= BASEVIDHEIGHT/2;
if (splitscreen > 1)
y += 16;
}
else
y -= (cv_kartspeedometer.value ? 16 : 0);
dx = 0;
dy = 0;
i = 0;
@ -1338,7 +1362,7 @@ static void HU_drawMiniChat(void)
INT32 timer = ((cv_chattime.value*TICRATE)-chat_timers[i]) - cv_chattime.value*TICRATE+9; // see below...
INT32 transflag = (timer >= 0 && timer <= 9) ? (timer*V_10TRANS) : 0; // you can make bad jokes out of this one.
size_t j = 0;
const char *msg = CHAT_WordWrap(x+2, cv_chatwidth.value-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i]); // get the current message, and word wrap it.
const char *msg = CHAT_WordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i]); // get the current message, and word wrap it.
UINT8 *colormap = NULL;
while(msg[j]) // iterate through msg
@ -1376,7 +1400,7 @@ static void HU_drawMiniChat(void)
dx += charwidth;
prev_linereturn = false;
if (dx >= cv_chatwidth.value)
if (dx >= boxw)
{
dx = 0;
dy += charheight;
@ -1397,26 +1421,45 @@ static void HU_drawMiniChat(void)
static void HU_drawChatLog(INT32 offset)
{
INT32 charwidth = 4, charheight = 6;
INT32 boxw = cv_chatwidth.value, boxh = cv_chatheight.value;
INT32 x = chatx+2, y, dx = 0, dy = 0;
UINT32 i = 0;
INT32 chat_topy, chat_bottomy;
INT32 highlight = HU_GetHighlightColor();
boolean atbottom = false;
// make sure that our scroll position isn't "illegal";
if (chat_scroll > chat_maxscroll)
chat_scroll = chat_maxscroll;
y = chaty - offset*charheight - (chat_scroll*charheight) - cv_chatheight.value*charheight - 12 - (cv_kartspeedometer.value ? 16 : 0);
chat_topy = y + chat_scroll*charheight;
chat_bottomy = chat_topy + cv_chatheight.value*charheight;
if (splitscreen)
{
boxh = max(6, boxh/2);
if (splitscreen > 1)
boxw = max(64, boxw/2);
}
V_DrawFillConsoleMap(chatx, chat_topy, cv_chatwidth.value, cv_chatheight.value*charheight +2, 239|V_SNAPTOBOTTOM|V_SNAPTOLEFT); // log box
y = chaty - offset*charheight - (chat_scroll*charheight) - boxh*charheight - 12;
if (splitscreen)
{
y -= BASEVIDHEIGHT/2;
if (splitscreen > 1)
y += 16;
}
else
y -= (cv_kartspeedometer.value ? 16 : 0);
chat_topy = y + chat_scroll*charheight;
chat_bottomy = chat_topy + boxh*charheight;
V_DrawFillConsoleMap(chatx, chat_topy, boxw, boxh*charheight +2, 239|V_SNAPTOBOTTOM|V_SNAPTOLEFT); // log box
for (i=0; i<chat_nummsg_log; i++) // iterate through our chatlog
{
INT32 clrflag = 0;
INT32 j = 0;
const char *msg = CHAT_WordWrap(x+2, cv_chatwidth.value-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_log[i]); // get the current message, and word wrap it.
const char *msg = CHAT_WordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_log[i]); // get the current message, and word wrap it.
UINT8 *colormap = NULL;
while(msg[j]) // iterate through msg
{
@ -1448,7 +1491,7 @@ static void HU_drawChatLog(INT32 offset)
}
dx += charwidth;
if (dx >= cv_chatwidth.value-charwidth-2 && i<chat_nummsg_log && msg[j] >= HU_FONTSTART) // end of message shouldn't count, nor should invisible characters!!!!
if (dx >= boxw-charwidth-2 && i<chat_nummsg_log && msg[j] >= HU_FONTSTART) // end of message shouldn't count, nor should invisible characters!!!!
{
dx = 0;
dy += charheight;
@ -1466,10 +1509,10 @@ static void HU_drawChatLog(INT32 offset)
// getmaxscroll through a lazy hack. We do all these loops, so let's not do more loops that are gonna lag the game more. :P
chat_maxscroll = (dy/charheight); // welcome to C, we don't know what min() and max() are.
if (chat_maxscroll <= (UINT32)cv_chatheight.value)
if (chat_maxscroll <= (UINT32)boxh)
chat_maxscroll = 0;
else
chat_maxscroll -= cv_chatheight.value;
chat_maxscroll -= boxh;
// if we're not bound by the time, autoscroll for next frame:
if (atbottom)
@ -1480,12 +1523,12 @@ static void HU_drawChatLog(INT32 offset)
if (chat_scroll > 0)
{
V_DrawCharacter(chatx-9, ((justscrolledup) ? (chat_topy-1) : (chat_topy)),
'\x1A' | V_SNAPTOBOTTOM | V_SNAPTOLEFT, false); // up arrow
'\x1A' | V_SNAPTOBOTTOM | V_SNAPTOLEFT | highlight, false); // up arrow
}
if (chat_scroll < chat_maxscroll)
{
V_DrawCharacter(chatx-9, chat_bottomy-((justscrolleddown) ? 5 : 6),
'\x1B' | V_SNAPTOBOTTOM | V_SNAPTOLEFT, false); // down arrow
'\x1B' | V_SNAPTOBOTTOM | V_SNAPTOLEFT | highlight, false); // down arrow
}
justscrolleddown = false;
@ -1502,13 +1545,26 @@ static INT16 typelines = 1; // number of drawfill lines we need. it's some weird
static void HU_DrawChat(void)
{
INT32 charwidth = 4, charheight = 6;
INT32 t = 0, c = 0, y = chaty - (typelines*charheight) - (cv_kartspeedometer.value ? 16 : 0);
INT32 boxw = cv_chatwidth.value;
INT32 t = 0, c = 0, y = chaty - (typelines*charheight);
UINT32 i = 0, saylen = strlen(w_chat); // You learn new things everyday!
INT32 cflag = 0;
const char *ntalk = "Say: ", *ttalk = "Team: ";
const char *talk = ntalk;
const char *mute = "Chat has been muted.";
if (splitscreen)
{
y -= BASEVIDHEIGHT/2;
if (splitscreen > 1)
{
y += 16;
boxw = max(64, boxw/2);
}
}
else
y -= (cv_kartspeedometer.value ? 16 : 0);
if (teamtalk)
{
talk = ttalk;
@ -1527,7 +1583,7 @@ static void HU_DrawChat(void)
cflag = V_GRAYMAP; // set text in gray if chat is muted.
}
V_DrawFillConsoleMap(chatx, y-1, cv_chatwidth.value, (typelines*charheight), 239 | V_SNAPTOBOTTOM | V_SNAPTOLEFT);
V_DrawFillConsoleMap(chatx, y-1, boxw, (typelines*charheight), 239 | V_SNAPTOBOTTOM | V_SNAPTOLEFT);
while (talk[i])
{
@ -1560,7 +1616,7 @@ static void HU_DrawChat(void)
boolean skippedline = false;
if (c_input == (i+1))
{
int cursorx = (c+charwidth < cv_chatwidth.value-charwidth) ? (chatx + 2 + c+charwidth) : (chatx+1); // we may have to go down.
int cursorx = (c+charwidth < boxw-charwidth) ? (chatx + 2 + c+charwidth) : (chatx+1); // we may have to go down.
int cursory = (cursorx != chatx+1) ? (y) : (y+charheight);
if (hu_tick < 4)
V_DrawChatCharacter(cursorx, cursory+1, '_' |V_SNAPTOBOTTOM|V_SNAPTOLEFT|t, !cv_allcaps.value, NULL);
@ -1580,7 +1636,7 @@ static void HU_DrawChat(void)
V_DrawChatCharacter(chatx + c + 2, y, w_chat[i++] | V_SNAPTOBOTTOM|V_SNAPTOLEFT | t, !cv_allcaps.value, NULL);
c += charwidth;
if (c > cv_chatwidth.value-(charwidth*2) && !skippedline)
if (c > boxw-(charwidth*2) && !skippedline)
{
c = 0;
y += charheight;
@ -1593,6 +1649,14 @@ static void HU_DrawChat(void)
{
INT32 count = 0;
INT32 p_dispy = chaty - charheight -1;
if (splitscreen)
{
p_dispy -= BASEVIDHEIGHT/2;
if (splitscreen > 1)
p_dispy += 16;
}
else
p_dispy -= (cv_kartspeedometer.value ? 16 : 0);
i = 0;
for(i=0; (i<MAXPLAYERS); i++)
{
@ -1643,8 +1707,8 @@ static void HU_DrawChat(void)
{
char name[MAXPLAYERNAME+1];
strlcpy(name, player_names[i], 7); // shorten name to 7 characters.
V_DrawFillConsoleMap(chatx+ cv_chatwidth.value + 2, p_dispy- (6*count), 48, 6, 239 | V_SNAPTOBOTTOM | V_SNAPTOLEFT); // fill it like the chat so the text doesn't become hard to read because of the hud.
V_DrawSmallString(chatx+ cv_chatwidth.value + 4, p_dispy- (6*count), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, va("\x82%d\x80 - %s", i, name));
V_DrawFillConsoleMap(chatx+ boxw + 2, p_dispy- (6*count), 48, 6, 239 | V_SNAPTOBOTTOM | V_SNAPTOLEFT); // fill it like the chat so the text doesn't become hard to read because of the hud.
V_DrawSmallString(chatx+ boxw + 4, p_dispy- (6*count), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, va("\x82%d\x80 - %s", i, name));
count++;
}
}
@ -1659,6 +1723,7 @@ static void HU_DrawChat(void)
}
// why the fuck would you use this...
static void HU_DrawChat_Old(void)
@ -1954,26 +2019,27 @@ UINT32 hu_demolap;
static void HU_DrawDemoInfo(void)
{
V_DrawString(4, 188-16, V_YELLOWMAP, va(M_GetText("%s's replay"), player_names[0]));
V_DrawCenteredString((BASEVIDWIDTH/2), BASEVIDHEIGHT-40, 0, M_GetText("Replay:"));
V_DrawCenteredString((BASEVIDWIDTH/2), BASEVIDHEIGHT-32, V_ALLOWLOWERCASE, player_names[0]);
if (modeattacking)
{
V_DrawString(4, 188-8, V_YELLOWMAP|V_MONOSPACE, "BEST TIME:");
V_DrawRightAlignedString((BASEVIDWIDTH/2)-4, BASEVIDHEIGHT-24, V_YELLOWMAP|V_MONOSPACE, "BEST TIME:");
if (hu_demotime != UINT32_MAX)
V_DrawRightAlignedString(120, 188-8, V_MONOSPACE, va("%i:%02i.%02i",
V_DrawString((BASEVIDWIDTH/2)+4, BASEVIDHEIGHT-24, V_MONOSPACE, va("%i'%02i\"%02i",
G_TicsToMinutes(hu_demotime,true),
G_TicsToSeconds(hu_demotime),
G_TicsToCentiseconds(hu_demotime)));
else
V_DrawRightAlignedString(120, 188-8, V_MONOSPACE, "--:--.--");
V_DrawString((BASEVIDWIDTH/2)+4, BASEVIDHEIGHT-24, V_MONOSPACE, "--'--\"--");
V_DrawString(4, 188, V_YELLOWMAP|V_MONOSPACE, "BEST LAP:");
V_DrawRightAlignedString((BASEVIDWIDTH/2)-4, BASEVIDHEIGHT-16, V_YELLOWMAP|V_MONOSPACE, "BEST LAP:");
if (hu_demolap != UINT32_MAX)
V_DrawRightAlignedString(120, 188, V_MONOSPACE, va("%i:%02i.%02i",
V_DrawString((BASEVIDWIDTH/2)+4, BASEVIDHEIGHT-16, V_MONOSPACE, va("%i'%02i\"%02i",
G_TicsToMinutes(hu_demolap,true),
G_TicsToSeconds(hu_demolap),
G_TicsToCentiseconds(hu_demolap)));
else
V_DrawRightAlignedString(120, 188, V_MONOSPACE, "--:--.--");
V_DrawString((BASEVIDWIDTH/2)+4, BASEVIDHEIGHT-16, V_MONOSPACE, "--'--\"--");
}
}
@ -1998,7 +2064,7 @@ void HU_Drawer(void)
{
chat_scrolltime = 0; // do scroll anyway.
typelines = 1; // make sure that the chat doesn't have a weird blinking huge ass square if we typed a lot last time.
if (!OLDCHAT)
if (!OLDCHAT && cv_consolechat.value < 2) // Don't display minimized chat if you set the mode to Window (Hidden)
HU_drawMiniChat(); // draw messages in a cool fashion.
}
}
@ -2046,11 +2112,11 @@ void HU_Drawer(void)
if (LUA_HudEnabled(hud_rankings))
#endif
HU_DrawRankings();
if (gametype == GT_COOP)
HU_DrawNetplayCoopOverlay();
//if (gametype == GT_COOP)
//HU_DrawNetplayCoopOverlay();
}
else
HU_DrawCoopOverlay();
//else
//HU_DrawCoopOverlay();
#ifdef HAVE_BLUA
LUAh_ScoresHUD();
#endif
@ -2202,93 +2268,8 @@ void HU_drawPing(INT32 x, INT32 y, INT32 ping, boolean notext)
}
//
// HU_DrawTabRankings
// HU_DrawTabRankings -- moved to k_kart.c
//
void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer, INT32 hilicol)
{
INT32 i, j, rightoffset = 240;
const UINT8 *colormap;
//this function is designed for 9 or less score lines only
//I_Assert(scorelines <= 9); -- not today bitch, kart fixed it up
V_DrawFill(1, 26, 318, 1, 0); // Draw a horizontal line because it looks nice!
if (scorelines > 8)
{
V_DrawFill(160, 26, 1, 154, 0); // Draw a vertical line to separate the two sides.
V_DrawFill(1, 180, 318, 1, 0); // And a horizontal line near the bottom.
rightoffset = 156;
}
for (i = 0; i < scorelines; i++)
{
char strtime[MAXPLAYERNAME+1];
if (players[tab[i].num].spectator || !players[tab[i].num].mo)
continue; //ignore them.
if (!splitscreen) // don't draw it on splitscreen,
{
if (!(tab[i].num == serverplayer))
HU_drawPing(x+ 253, y+2, playerpingtable[tab[i].num], false);
}
if (scorelines > 8)
strlcpy(strtime, tab[i].name, 6);
else
STRBUFCPY(strtime, tab[i].name);
V_DrawString(x + 20, y,
((tab[i].num == whiteplayer)
? hilicol|V_ALLOWLOWERCASE
: V_ALLOWLOWERCASE),
strtime);
if (players[tab[i].num].mo->color)
{
colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo->color, GTC_CACHE);
if (players[tab[i].num].mo->colorized)
colormap = R_GetTranslationColormap(TC_RAINBOW, players[tab[i].num].mo->color, GTC_CACHE);
else
colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo->color, GTC_CACHE);
V_DrawSmallMappedPatch(x, y-4, 0, faceprefix[players[tab[i].num].skin], colormap);
if (G_BattleGametype() && players[tab[i].num].kartstuff[k_bumper] > 0)
{
INT32 bumperx = x-5;
for (j = 0; j < players[tab[i].num].kartstuff[k_bumper]; j++)
{
bumperx -= 3;
V_DrawSmallMappedPatch(bumperx, y+6, 0, W_CachePatchName("K_BLNICO", PU_CACHE), colormap);
}
}
}
if (G_BattleGametype() && players[tab[i].num].kartstuff[k_bumper] <= 0)
V_DrawSmallScaledPatch(x-2, y-4, 0, W_CachePatchName("K_NOBLNS", PU_CACHE));
if (G_RaceGametype())
{
#define timestring(time) va("%i'%02i\"%02i", G_TicsToMinutes(time, true), G_TicsToSeconds(time), G_TicsToCentiseconds(time))
if (players[tab[i].num].exiting)
V_DrawRightAlignedString(x+rightoffset, y, hilicol, timestring(players[tab[i].num].realtime));
else if (players[tab[i].num].pflags & PF_TIMEOVER)
V_DrawRightAlignedThinString(x+rightoffset, y-1, 0, "NO CONTEST.");
else if (circuitmap)
V_DrawRightAlignedString(x+rightoffset, y, 0, va("Lap %d", tab[i].count));
#undef timestring
}
else
V_DrawRightAlignedString(x+rightoffset, y, 0, va("%u", tab[i].count));
y += 16;
if (i == 7)
{
y = 32;
x += BASEVIDWIDTH/2;
}
}
}
//
// HU_DrawTeamTabRankings
@ -2350,15 +2331,15 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I
if (players[tab[i].num].powers[pw_super])
{
colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo ? players[tab[i].num].mo->color : tab[i].color, GTC_CACHE);
V_DrawSmallMappedPatch (x, y-4, 0, superprefix[players[tab[i].num].skin], colormap);
V_DrawSmallMappedPatch (x, y-4, 0, facewantprefix[players[tab[i].num].skin], colormap);
}
else
{
colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo ? players[tab[i].num].mo->color : tab[i].color, GTC_CACHE);
if (players[tab[i].num].health <= 0)
V_DrawSmallTranslucentMappedPatch (x, y-4, 0, faceprefix[players[tab[i].num].skin], colormap);
V_DrawSmallTranslucentMappedPatch (x, y-4, 0, facerankprefix[players[tab[i].num].skin], colormap);
else
V_DrawSmallMappedPatch (x, y-4, 0, faceprefix[players[tab[i].num].skin], colormap);
V_DrawSmallMappedPatch (x, y-4, 0, facerankprefix[players[tab[i].num].skin], colormap);
}
V_DrawRightAlignedThinString(x+120, y-1, ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count));
if (!splitscreen)
@ -2412,13 +2393,13 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline
{
colormap = colormaps;
if (players[tab[i].num].powers[pw_super])
V_DrawSmallScaledPatch (x, y-4, 0, superprefix[players[tab[i].num].skin]);
V_DrawSmallScaledPatch (x, y-4, 0, facewantprefix[players[tab[i].num].skin]);
else
{
if (players[tab[i].num].health <= 0)
V_DrawSmallTranslucentPatch (x, y-4, 0, faceprefix[players[tab[i].num].skin]);
V_DrawSmallTranslucentPatch (x, y-4, 0, facerankprefix[players[tab[i].num].skin]);
else
V_DrawSmallScaledPatch (x, y-4, 0, faceprefix[players[tab[i].num].skin]);
V_DrawSmallScaledPatch (x, y-4, 0, facerankprefix[players[tab[i].num].skin]);
}
}
else
@ -2426,15 +2407,15 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline
if (players[tab[i].num].powers[pw_super])
{
colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo ? players[tab[i].num].mo->color : tab[i].color, GTC_CACHE);
V_DrawSmallMappedPatch (x, y-4, 0, superprefix[players[tab[i].num].skin], colormap);
V_DrawSmallMappedPatch (x, y-4, 0, facewantprefix[players[tab[i].num].skin], colormap);
}
else
{
colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo ? players[tab[i].num].mo->color : tab[i].color, GTC_CACHE);
if (players[tab[i].num].health <= 0)
V_DrawSmallTranslucentMappedPatch (x, y-4, 0, faceprefix[players[tab[i].num].skin], colormap);
V_DrawSmallTranslucentMappedPatch (x, y-4, 0, facerankprefix[players[tab[i].num].skin], colormap);
else
V_DrawSmallMappedPatch (x, y-4, 0, faceprefix[players[tab[i].num].skin], colormap);
V_DrawSmallMappedPatch (x, y-4, 0, facerankprefix[players[tab[i].num].skin], colormap);
}
}
@ -2496,16 +2477,17 @@ void HU_DrawEmeralds(INT32 x, INT32 y, INT32 pemeralds)
//
static inline void HU_DrawSpectatorTicker(void)
{
int i;
int length = 0, height = 174;
int totallength = 0, templength = 0;
INT32 i;
INT32 length = 0, height = 174;
INT32 totallength = 0, templength = -8;
INT32 dupadjust = (vid.width/vid.dupx), duptweak = (dupadjust - BASEVIDWIDTH)/2;
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].spectator)
totallength += (signed)strlen(player_names[i]) * 8 + 16;
length -= (leveltime % (totallength + BASEVIDWIDTH));
length += BASEVIDWIDTH;
length -= (leveltime % (totallength + dupadjust+8));
length += dupadjust;
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].spectator)
@ -2513,15 +2495,18 @@ static inline void HU_DrawSpectatorTicker(void)
char *pos;
char initial[MAXPLAYERNAME+1];
char current[MAXPLAYERNAME+1];
INT32 len;
len = ((signed)strlen(player_names[i]) * 8 + 16);
strcpy(initial, player_names[i]);
pos = initial;
if (length >= -((signed)strlen(player_names[i]) * 8 + 16) && length <= BASEVIDWIDTH)
if (length >= -len)
{
if (length < 0)
if (length < -8)
{
UINT8 eatenchars = (UINT8)(abs(length) / 8 + 1);
UINT8 eatenchars = (UINT8)(abs(length) / 8);
if (eatenchars <= strlen(initial))
{
@ -2529,7 +2514,7 @@ static inline void HU_DrawSpectatorTicker(void)
// then compensate the drawing position.
pos += eatenchars;
strcpy(current, pos);
templength = length % 8 + 8;
templength = ((length + 8) % 8);
}
else
{
@ -2543,10 +2528,11 @@ static inline void HU_DrawSpectatorTicker(void)
templength = length;
}
V_DrawString(templength, height + 8, V_TRANSLUCENT, current);
V_DrawString(templength - duptweak, height, V_TRANSLUCENT|V_ALLOWLOWERCASE, current);
}
length += (signed)strlen(player_names[i]) * 8 + 16;
if ((length += len) >= dupadjust+8)
break;
}
}
@ -2561,6 +2547,8 @@ static void HU_DrawRankings(void)
boolean completed[MAXPLAYERS];
UINT32 whiteplayer = MAXPLAYERS;
V_DrawFadeScreen(0xFF00, 16); // A little more readable, and prevents cheating the fades under other circumstances.
if (cons_menuhighlight.value)
hilicol = cons_menuhighlight.value;
else if (modeattacking)
@ -2570,9 +2558,9 @@ static void HU_DrawRankings(void)
// draw the current gametype in the lower right
if (modeattacking)
V_DrawString(4, 188, hilicol, "Record Attack");
V_DrawString(4, 188, hilicol|V_SNAPTOBOTTOM|V_SNAPTOLEFT, "Record Attack");
else
V_DrawString(4, 188, hilicol, gametype_cons_t[gametype].strvalue);
V_DrawString(4, 188, hilicol|V_SNAPTOBOTTOM|V_SNAPTOLEFT, gametype_cons_t[gametype].strvalue);
if (G_GametypeHasTeams())
{
@ -2661,21 +2649,18 @@ static void HU_DrawRankings(void)
tab[i].name = NULL;
tab[i].count = INT32_MAX;
if (!playeringame[i] || players[i].spectator)
if (!playeringame[i] || players[i].spectator || !players[i].mo)
continue;
numplayersingame++;
}
if (netgame && numplayersingame <= 1)
K_drawKartFreePlay(leveltime);
for (j = 0; j < numplayersingame; j++)
{
UINT8 lowestposition = MAXPLAYERS;
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator || completed[i])
if (completed[i] || !playeringame[i] || players[i].spectator || !players[i].mo)
continue;
if (players[i].kartstuff[k_position] >= lowestposition)
@ -2712,16 +2697,16 @@ static void HU_DrawRankings(void)
/*if (G_GametypeHasTeams())
HU_DrawTeamTabRankings(tab, whiteplayer); //separate function for Spazzo's silly request -- gotta fix this up later
else if (scorelines > 10)*/
HU_DrawTabRankings(((scorelines > 8) ? 32 : 40), 32, tab, scorelines, whiteplayer, hilicol);
HU_DrawTabRankings(((scorelines > 8) ? 32 : 40), 33, tab, scorelines, whiteplayer, hilicol);
/*else
HU_DrawDualTabRankings(32, 32, tab, scorelines, whiteplayer);*/
// draw spectators in a ticker across the bottom
if (!splitscreen && G_GametypeHasSpectators())
if (netgame && G_GametypeHasSpectators())
HU_DrawSpectatorTicker();
}
static void HU_DrawCoopOverlay(void)
/*static void HU_DrawCoopOverlay(void)
{
if (token
#ifdef HAVE_BLUA
@ -2777,7 +2762,7 @@ static void HU_DrawNetplayCoopOverlay(void)
if (emeralds & (1 << i))
V_DrawScaledPatch(20 + (i * 20), 6, 0, emeraldpics[i]);
}
}
}*/
// Interface to CECHO settings for the outside world, avoiding the

View File

@ -76,16 +76,15 @@ extern patch_t *rmatcico;
extern patch_t *bmatcico;
extern patch_t *tagico;
extern patch_t *tallminus;
extern patch_t *iconprefix[MAXSKINS];
#define CHAT_BUFSIZE 64 // that's enough messages, right? We'll delete the older ones when that gets out of hand.
#define OLDCHAT (cv_consolechat.value || dedicated || vid.width < 640)
#define OLDCHAT (cv_consolechat.value == 1 || dedicated || vid.width < 640)
#define CHAT_MUTE (cv_mute.value && !(server || IsPlayerAdmin(consoleplayer))) // this still allows to open the chat but not to type. That's used for scrolling and whatnot.
#define OLD_MUTE (OLDCHAT && cv_mute.value && !(server || IsPlayerAdmin(consoleplayer))) // this is used to prevent oldchat from opening when muted.
// some functions
void HU_AddChatText(const char *text);
void HU_AddChatText(const char *text, boolean playsound);
// set true when entering a chat message
extern boolean chat_on;

3546
src/info.c

File diff suppressed because it is too large Load Diff

View File

@ -166,9 +166,18 @@ void A_ToggleFlameJet();
void A_ItemPop(); // SRB2kart
void A_JawzChase(); // SRB2kart
void A_JawzExplode(); // SRB2kart
void A_SPBChase(); // SRB2kart
void A_MineExplode(); // SRB2kart
void A_BallhogExplode(); // SRB2kart
void A_LightningFollowPlayer(); // SRB2kart: Lightning shield effect player chasing
void A_FZBoomFlash(); // SRB2kart
void A_FZBoomSmoke(); // SRB2kart
void A_RandomShadowFrame(); //SRB2kart: Shadow spawner frame randomizer
void A_RoamingShadowThinker(); // SRB2kart: Roaming Shadow moving + attacking players.
void A_MayonakaArrow(); //SRB2kart: midnight channel arrow sign
void A_ReaperThinker(); //SRB2kart: mementos reaper
void A_MementosTPParticles(); //SRB2kart: mementos teleporter particles. Man that's a lot of actions for my shite.
void A_FlameParticle(); // SRB2kart
void A_OrbitNights();
void A_GhostMe();
void A_SetObjectState();
@ -593,9 +602,11 @@ typedef enum sprite
SPR_KINF, // Invincibility flash
SPR_WIPD, // Wipeout dust trail
SPR_DRIF, // Drift Sparks
SPR_BDRF, // Brake drift sparks
SPR_DUST, // Drift Dust
// Kart Items
SPR_RSHE, // Rocket sneaker
SPR_FITM, // Eggman Monitor
SPR_BANA, // Banana Peel
SPR_ORBN, // Orbinaut
@ -604,8 +615,7 @@ typedef enum sprite
SPR_KRBM, // SS Mine BOOM
SPR_BHOG, // Ballhog
SPR_BHBM, // Ballhog BOOM
SPR_BLIG, // Self-Propelled Bomb
SPR_LIGH, // Grow/shrink beams (Metallic Maddness)
SPR_SPBM, // Self-Propelled Bomb
SPR_THNS, // Thunder Shield
SPR_SINK, // Kitchen Sink
SPR_SITR, // Kitchen Sink Trail
@ -643,6 +653,11 @@ typedef enum sprite
SPR_WANT,
SPR_PBOM, // player bomb
SPR_HIT1, // battle points
SPR_HIT2, // battle points
SPR_HIT3, // battle points
SPR_RETI, // player reticule
SPR_AIDU,
@ -652,8 +667,123 @@ typedef enum sprite
SPR_LZI2, // ditto
SPR_KLIT, // You have a twisted mind. But this actually is for the diagonal lightning.
SPR_VIEW, // First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw!
SPR_FZSM, // F-Zero NO CONTEST explosion
SPR_FZBM,
SPR_FPRT,
// Various plants
SPR_SBUS,
SPR_SHRB,
SPR_TWEE,
SPR_MARB, // Marble Zone sprites
SPR_FUFO, // CD Special Stage UFO (don't ask me why it begins with an F)
SPR_RUST, // Rusty Rig sprites
SPR_BLON, // D2 Balloon Panic
SPR_VAPE, // Volcanic Valley
// Hill Top Zone
SPR_HTZA,
SPR_HTZB,
// Ports of gardens
SPR_SGVA,
SPR_SGVB,
SPR_SGVC,
SPR_PGTR,
SPR_PGF1,
SPR_PGF2,
SPR_PGF3,
SPR_PGBH,
SPR_DPLR,
// Midnight Channel stuff:
SPR_SPTL, // Spotlight
SPR_ENM1, // Shadows (Roaming and static)
SPR_GARU, // Wind attack roaming shadows use.
SPR_MARR, // Mayonaka Arrow
//Mementos stuff:
SPR_REAP,
SPR_JITB, // Jack In The Box
// Color Drive stuff:
SPR_CDMO,
SPR_CDBU,
// Daytona Speedway
SPR_PINE,
// Egg Zeppelin
SPR_PPLR,
// Desert Palace
SPR_DPPT,
// Aurora Atoll
SPR_AATR,
SPR_COCO,
// Barren Badlands
SPR_BDST,
SPR_FROG,
SPR_CBRA,
SPR_HOLE,
SPR_BBRA,
// Eerie Grove
SPR_EGFG,
// SMK ports
SPR_SMKP,
SPR_MTYM,
SPR_THWP,
SPR_SNOB,
SPR_ICEB,
// Ezo's maps - many single-use sprites!
SPR_CNDL,
SPR_DOCH,
SPR_DUCK,
SPR_GTRE,
SPR_CHES,
SPR_CHIM,
SPR_DRGN,
SPR_LZMN,
SPR_PGSS,
SPR_ZTCH,
SPR_MKMA,
SPR_MKMP,
SPR_RTCH,
SPR_BOWL,
SPR_BOWH,
SPR_BRRL,
SPR_BRRR,
SPR_HRSE,
SPR_TOAH,
SPR_BFRT,
SPR_OFRT,
SPR_RFRT,
SPR_PFRT,
SPR_ASPK,
SPR_HBST,
SPR_HBSO,
SPR_HBSF,
SPR_WBLZ,
SPR_WBLN,
SPR_MSMF,
// Xmas-specific sprites that don't fit aboxe
SPR_XMS4,
SPR_XMS5,
// First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw later
SPR_VIEW,
SPR_FIRSTFREESLOT,
SPR_LASTFREESLOT = SPR_FIRSTFREESLOT + NUMSPRITEFREESLOTS - 1,
NUMSPRITES
@ -2109,6 +2239,10 @@ typedef enum state
S_XMASPOLE,
S_CANDYCANE,
S_SNOWMAN,
S_SNOWMANHAT,
S_LAMPPOST1,
S_LAMPPOST2,
S_HANGSTAR,
// Botanic Serenity's loads of scenery states
S_BSZTALLFLOWER_RED,
@ -3082,6 +3216,9 @@ typedef enum state
S_DRIFTSPARK_C1,
S_DRIFTSPARK_C2,
// Brake drift sparks
S_BRAKEDRIFT,
// Drift Smoke
S_DRIFTDUST1,
S_DRIFTDUST2,
@ -3155,32 +3292,38 @@ typedef enum state
S_WIPEOUTTRAIL4,
S_WIPEOUTTRAIL5,
// Rocket sneaker
S_ROCKETSNEAKER_L,
S_ROCKETSNEAKER_R,
S_ROCKETSNEAKER_LVIBRATE,
S_ROCKETSNEAKER_RVIBRATE,
//{ Eggman Monitor
S_FAKEITEM1,
S_FAKEITEM2,
S_FAKEITEM3,
S_FAKEITEM4,
S_FAKEITEM5,
S_FAKEITEM6,
S_FAKEITEM7,
S_FAKEITEM8,
S_FAKEITEM9,
S_FAKEITEM10,
S_FAKEITEM11,
S_FAKEITEM12,
S_FAKEITEM13,
S_FAKEITEM14,
S_FAKEITEM15,
S_FAKEITEM16,
S_FAKEITEM17,
S_FAKEITEM18,
S_FAKEITEM19,
S_FAKEITEM20,
S_FAKEITEM21,
S_FAKEITEM22,
S_FAKEITEM23,
S_FAKEITEM24,
S_DEADFAKEITEM,
S_EGGMANITEM1,
S_EGGMANITEM2,
S_EGGMANITEM3,
S_EGGMANITEM4,
S_EGGMANITEM5,
S_EGGMANITEM6,
S_EGGMANITEM7,
S_EGGMANITEM8,
S_EGGMANITEM9,
S_EGGMANITEM10,
S_EGGMANITEM11,
S_EGGMANITEM12,
S_EGGMANITEM13,
S_EGGMANITEM14,
S_EGGMANITEM15,
S_EGGMANITEM16,
S_EGGMANITEM17,
S_EGGMANITEM18,
S_EGGMANITEM19,
S_EGGMANITEM20,
S_EGGMANITEM21,
S_EGGMANITEM22,
S_EGGMANITEM23,
S_EGGMANITEM24,
S_EGGMANITEM_DEAD,
//}
// Banana
@ -3310,18 +3453,28 @@ typedef enum state
S_BALLHOGBOOM15,
S_BALLHOGBOOM16,
// Self-Propelled Bomb - just an explosion for now...
S_BLUELIGHTNING1,
S_BLUELIGHTNING2,
S_BLUELIGHTNING3,
S_BLUELIGHTNING4,
S_BLUEEXPLODE,
// Grow/Shrink
S_LIGHTNING1,
S_LIGHTNING2,
S_LIGHTNING3,
S_LIGHTNING4,
// Self-Propelled Bomb
S_SPB1,
S_SPB2,
S_SPB3,
S_SPB4,
S_SPB5,
S_SPB6,
S_SPB7,
S_SPB8,
S_SPB9,
S_SPB10,
S_SPB11,
S_SPB12,
S_SPB13,
S_SPB14,
S_SPB15,
S_SPB16,
S_SPB17,
S_SPB18,
S_SPB19,
S_SPB20,
S_SPB_DEAD,
// Thunder Shield
S_THUNDERSHIELD1,
@ -3552,12 +3705,61 @@ typedef enum state
S_PLAYERARROW_WANTED6,
S_PLAYERARROW_WANTED7,
S_PLAYERBOMB,
S_PLAYERBOMB1, // Karma player overlays
S_PLAYERBOMB2,
S_PLAYERBOMB3,
S_PLAYERBOMB4,
S_PLAYERBOMB5,
S_PLAYERBOMB6,
S_PLAYERBOMB7,
S_PLAYERBOMB8,
S_PLAYERBOMB9,
S_PLAYERBOMB10,
S_PLAYERBOMB11,
S_PLAYERBOMB12,
S_PLAYERBOMB13,
S_PLAYERBOMB14,
S_PLAYERBOMB15,
S_PLAYERBOMB16,
S_PLAYERBOMB17,
S_PLAYERBOMB18,
S_PLAYERBOMB19,
S_PLAYERBOMB20,
S_PLAYERITEM,
S_PLAYERFAKE,
S_KARMAWHEEL,
S_BATTLEPOINT1A, // Battle point indicators
S_BATTLEPOINT1B,
S_BATTLEPOINT1C,
S_BATTLEPOINT1D,
S_BATTLEPOINT1E,
S_BATTLEPOINT1F,
S_BATTLEPOINT1G,
S_BATTLEPOINT1H,
S_BATTLEPOINT1I,
S_BATTLEPOINT2A,
S_BATTLEPOINT2B,
S_BATTLEPOINT2C,
S_BATTLEPOINT2D,
S_BATTLEPOINT2E,
S_BATTLEPOINT2F,
S_BATTLEPOINT2G,
S_BATTLEPOINT2H,
S_BATTLEPOINT2I,
S_BATTLEPOINT3A,
S_BATTLEPOINT3B,
S_BATTLEPOINT3C,
S_BATTLEPOINT3D,
S_BATTLEPOINT3E,
S_BATTLEPOINT3F,
S_BATTLEPOINT3G,
S_BATTLEPOINT3H,
S_BATTLEPOINT3I,
// Thunder shield use stuff;
S_KSPARK1, // Sparkling Radius
S_KSPARK2,
@ -3606,6 +3808,270 @@ typedef enum state
S_KLIT11,
S_KLIT12,
S_FZEROSMOKE1, // F-Zero NO CONTEST explosion
S_FZEROSMOKE2,
S_FZEROSMOKE3,
S_FZEROSMOKE4,
S_FZEROSMOKE5,
S_FZEROBOOM1,
S_FZEROBOOM2,
S_FZEROBOOM3,
S_FZEROBOOM4,
S_FZEROBOOM5,
S_FZEROBOOM6,
S_FZEROBOOM7,
S_FZEROBOOM8,
S_FZEROBOOM9,
S_FZEROBOOM10,
S_FZEROBOOM11,
S_FZEROBOOM12,
S_FZSLOWSMOKE1,
S_FZSLOWSMOKE2,
S_FZSLOWSMOKE3,
S_FZSLOWSMOKE4,
S_FZSLOWSMOKE5,
// Various plants
S_SONICBUSH,
S_SHRUB,
S_TALLBUSH,
S_AZURECITYTREE,
// Marble Zone
S_FLAMEPARTICLE,
S_MARBLETORCH,
S_MARBLELIGHT,
S_MARBLEBURNER,
// CD Special Stage
S_CDUFO,
S_CDUFO_DIE,
// Rusty Rig
S_RUSTYLAMP_ORANGE,
S_RUSTYCHAIN,
// D2 Balloon Panic
S_BALLOON,
S_BALLOONPOP1,
S_BALLOONPOP2,
S_BALLOONPOP3,
// Smokin' & Vapin' (Don't try this at home, kids!)
S_PETSMOKE0,
S_PETSMOKE1,
S_PETSMOKE2,
S_PETSMOKE3,
S_PETSMOKE4,
S_PETSMOKE5,
S_VVVAPING0,
S_VVVAPING1,
S_VVVAPING2,
S_VVVAPING3,
S_VVVAPING4,
S_VVVAPING5,
S_VVVAPE,
// Hill Top Zone
S_HTZTREE,
S_HTZBUSH,
// Ports of gardens
S_SGVINE1,
S_SGVINE2,
S_SGVINE3,
S_PGTREE,
S_PGFLOWER1,
S_PGFLOWER2,
S_PGFLOWER3,
S_PGBUSH,
S_DHPILLAR,
// Midnight Channel stuff:
S_SPOTLIGHT, // Spotlight decoration
S_RANDOMSHADOW, // Random Shadow. They're static and don't do nothing.
S_GARU1,
S_GARU2,
S_GARU3,
S_TGARU0,
S_TGARU1,
S_TGARU2,
S_TGARU3, // Wind attack used by Roaming Shadows on Players.
S_ROAMINGSHADOW, // Roaming Shadow (the one that uses above's wind attack or smth)
S_MAYONAKAARROW, // Arrow sign
// Mementos stuff:
S_REAPER_INVIS, // Reaper waiting for spawning
S_REAPER, // Reaper main frame where its thinker is handled
S_MEMENTOSTP, // Mementos teleporter state. (Used for spawning particles)
// JackInTheBox
S_JITB1,
S_JITB2,
S_JITB3,
S_JITB4,
S_JITB5,
S_JITB6,
// Color Drive
S_CDMOONSP,
S_CDBUSHSP,
S_CDTREEASP,
S_CDTREEBSP,
// Daytona Speedway
S_PINETREE,
S_PINETREE_SIDE,
// Egg Zeppelin
S_EZZPROPELLER,
S_EZZPROPELLER_BLADE,
// Desert Palace
S_DP_PALMTREE,
// Aurora Atoll
S_AAZTREE_SEG,
S_AAZTREE_COCONUT,
S_AAZTREE_LEAF,
// Barren Badlands
S_BBZDUST1, // Dust
S_BBZDUST2,
S_BBZDUST3,
S_BBZDUST4,
S_FROGGER, // Frog badniks
S_FROGGER_ATTACK,
S_FROGGER_JUMP,
S_FROGTONGUE,
S_FROGTONGUE_JOINT,
S_ROBRA, // Black cobra badniks
S_ROBRA_HEAD,
S_ROBRA_JOINT,
S_ROBRASHELL_INSIDE,
S_ROBRASHELL_OUTSIDE,
S_BLUEROBRA, // Blue cobra badniks
S_BLUEROBRA_HEAD,
S_BLUEROBRA_JOINT,
// Eerie Grove
S_EERIEFOG1,
S_EERIEFOG2,
S_EERIEFOG3,
S_EERIEFOG4,
S_EERIEFOG5,
// SMK ports
S_SMK_PIPE1, // Generic pipes
S_SMK_PIPE2,
S_SMK_MOLE, // Donut Plains Monty Moles
S_SMK_THWOMP, // Bowser Castle Thwomps
S_SMK_SNOWBALL, // Vanilla Lake snowballs
S_SMK_ICEBLOCK, // Vanilla Lake breakable ice blocks
S_SMK_ICEBLOCK2,
S_SMK_ICEBLOCK_DEBRIS,
S_SMK_ICEBLOCK_DEBRIS2,
// Ezo's maps
S_BLUEFIRE1,
S_BLUEFIRE2,
S_BLUEFIRE3,
S_BLUEFIRE4,
S_GREENFIRE1,
S_GREENFIRE2,
S_GREENFIRE3,
S_GREENFIRE4,
S_REGALCHEST,
S_CHIMERASTATUE,
S_DRAGONSTATUE,
S_LIZARDMANSTATUE,
S_PEGASUSSTATUE,
S_ZELDAFIRE1,
S_ZELDAFIRE2,
S_ZELDAFIRE3,
S_ZELDAFIRE4,
S_GANBARETHING,
S_GANBAREDUCK,
S_GANBARETREE,
S_MONOIDLE,
S_MONOCHASE1,
S_MONOCHASE2,
S_MONOCHASE3,
S_MONOCHASE4,
S_MONOPAIN,
S_REDZELDAFIRE1,
S_REDZELDAFIRE2,
S_REDZELDAFIRE3,
S_REDZELDAFIRE4,
S_BOWLINGPIN,
S_BOWLINGHIT1,
S_BOWLINGHIT2,
S_BOWLINGHIT3,
S_BOWLINGHIT4,
S_ARIDTOAD,
S_TOADHIT1,
S_TOADHIT2,
S_TOADHIT3,
S_TOADHIT4,
S_EBARRELIDLE,
S_EBARREL1,
S_EBARREL2,
S_EBARREL3,
S_EBARREL4,
S_EBARREL5,
S_EBARREL6,
S_EBARREL7,
S_EBARREL8,
S_EBARREL9,
S_EBARREL10,
S_EBARREL11,
S_EBARREL12,
S_EBARREL13,
S_EBARREL14,
S_EBARREL15,
S_EBARREL16,
S_EBARREL17,
S_EBARREL18,
S_MERRYHORSE,
S_BLUEFRUIT,
S_ORANGEFRUIT,
S_REDFRUIT,
S_PINKFRUIT,
S_ADVENTURESPIKEA1,
S_ADVENTURESPIKEA2,
S_ADVENTURESPIKEB1,
S_ADVENTURESPIKEB2,
S_ADVENTURESPIKEC1,
S_ADVENTURESPIKEC2,
S_BOOSTPROMPT1,
S_BOOSTPROMPT2,
S_BOOSTOFF1,
S_BOOSTOFF2,
S_BOOSTON1,
S_BOOSTON2,
S_LIZARDMAN,
S_LIONMAN,
S_MOUSEMAN1,
S_MOUSEMAN2,
#ifdef SEENAMES
S_NAMECHECK,
#endif
@ -3909,6 +4375,10 @@ typedef enum mobj_type
MT_XMASPOLE,
MT_CANDYCANE,
MT_SNOWMAN,
MT_SNOWMANHAT,
MT_LAMPPOST1,
MT_LAMPPOST2,
MT_HANGSTAR,
// Botanic Serenity scenery
MT_BSZTALLFLOWER_RED,
@ -4153,10 +4623,13 @@ typedef enum mobj_type
MT_INVULNFLASH,
MT_WIPEOUTTRAIL,
MT_DRIFTSPARK,
MT_BRAKEDRIFT,
MT_DRIFTDUST,
MT_FAKESHIELD,
MT_FAKEITEM,
MT_ROCKETSNEAKER,
MT_EGGMANITEM, // Eggman items
MT_EGGMANITEM_SHIELD,
MT_BANANA, // Banana Stuff
MT_BANANA_SHIELD,
@ -4182,9 +4655,8 @@ typedef enum mobj_type
MT_BALLHOG, // Ballhog
MT_BALLHOGBOOM,
MT_BLUELIGHTNING, // Grow/shrink stuff
MT_BLUEEXPLOSION,
MT_LIGHTNING,
MT_SPB, // SPB stuff
MT_SPBEXPLOSION,
MT_THUNDERSHIELD, // Thunder Shield stuff
@ -4274,6 +4746,149 @@ typedef enum mobj_type
MT_KARMAHITBOX,
MT_KARMAWHEEL,
MT_BATTLEPOINT,
MT_FZEROBOOM,
// Various plants
MT_SONICBUSH,
MT_SHRUB,
MT_TALLBUSH,
MT_AZURECITYTREE,
// Marble Zone
MT_FLAMEPARTICLE,
MT_MARBLETORCH,
MT_MARBLELIGHT,
MT_MARBLEBURNER,
// CD Special Stage
MT_CDUFO,
// Rusty Rig
MT_RUSTYLAMP_ORANGE,
MT_RUSTYCHAIN,
// D2 Balloon Panic
MT_BALLOON,
// Smokin' & Vapin' (Don't try this at home, kids!)
MT_PETSMOKER,
MT_PETSMOKE,
MT_VVVAPE,
// Hill Top Zone
MT_HTZTREE,
MT_HTZBUSH,
// Ports of gardens
MT_SGVINE1,
MT_SGVINE2,
MT_SGVINE3,
MT_PGTREE,
MT_PGFLOWER1,
MT_PGFLOWER2,
MT_PGFLOWER3,
MT_PGBUSH,
MT_DHPILLAR,
// Midnight Channel stuff:
MT_SPOTLIGHT, // Spotlight Object
MT_RANDOMSHADOW, // Random static Shadows.
MT_ROAMINGSHADOW, // Roaming Shadows.
MT_MAYONAKAARROW, // Arrow static signs for Mayonaka
// Mementos stuff
MT_REAPERWAYPOINT,
MT_REAPER,
MT_MEMENTOSTP,
MT_MEMENTOSPARTICLE,
MT_JACKINTHEBOX,
// Color Drive:
MT_CDMOON,
MT_CDBUSH,
MT_CDTREEA,
MT_CDTREEB,
// Daytona Speedway
MT_PINETREE,
MT_PINETREE_SIDE,
// Egg Zeppelin
MT_EZZPROPELLER,
MT_EZZPROPELLER_BLADE,
// Desert Palace
MT_DP_PALMTREE,
// Aurora Atoll
MT_AAZTREE_HELPER,
MT_AAZTREE_SEG,
MT_AAZTREE_COCONUT,
MT_AAZTREE_LEAF,
// Barren Badlands
MT_BBZDUST,
MT_FROGGER,
MT_FROGTONGUE,
MT_FROGTONGUE_JOINT,
MT_ROBRA,
MT_ROBRA_HEAD,
MT_ROBRA_JOINT,
MT_BLUEROBRA,
MT_BLUEROBRA_HEAD,
MT_BLUEROBRA_JOINT,
// Eerie Grove
MT_EERIEFOG,
MT_EERIEFOGGEN,
// SMK ports
MT_SMK_PIPE,
MT_SMK_MOLESPAWNER,
MT_SMK_MOLE,
MT_SMK_THWOMP,
MT_SMK_SNOWBALL,
MT_SMK_ICEBLOCK,
MT_SMK_ICEBLOCK_SIDE,
MT_SMK_ICEBLOCK_DEBRIS,
// Ezo's maps
MT_BLUEFIRE,
MT_GREENFIRE,
MT_REGALCHEST,
MT_CHIMERASTATUE,
MT_DRAGONSTATUE,
MT_LIZARDMANSTATUE,
MT_PEGASUSSTATUE,
MT_ZELDAFIRE,
MT_GANBARETHING,
MT_GANBAREDUCK,
MT_GANBARETREE,
MT_MONOKUMA,
MT_REDZELDAFIRE,
MT_BOWLINGPIN,
MT_MERRYAMBIENCE,
MT_TWINKLECARTAMBIENCE,
MT_EXPLODINGBARREL,
MT_MERRYHORSE,
MT_ARIDTOAD,
MT_BLUEFRUIT,
MT_ORANGEFRUIT,
MT_REDFRUIT,
MT_PINKFRUIT,
MT_ADVENTURESPIKEA,
MT_ADVENTURESPIKEB,
MT_ADVENTURESPIKEC,
MT_BOOSTPROMPT,
MT_BOOSTOFF,
MT_BOOSTON,
MT_LIZARDMAN,
MT_LIONMAN,
MT_MOUSEMAN,
#ifdef SEENAMES
MT_NAMECHECK,
#endif

File diff suppressed because it is too large Load Diff

View File

@ -21,14 +21,16 @@ void K_RegisterKartStuff(void);
boolean K_IsPlayerLosing(player_t *player);
boolean K_IsPlayerWanted(player_t *player);
void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid);
void K_MatchGenericExtraFlags(mobj_t *mo, mobj_t *master);
void K_RespawnChecker(player_t *player);
void K_KartMoveAnimation(player_t *player);
void K_KartPlayerThink(player_t *player, ticcmd_t *cmd);
void K_KartPlayerAfterThink(player_t *player);
void K_DoInstashield(player_t *player);
void K_SpawnBattlePoints(player_t *source, player_t *victim, UINT8 amount);
void K_SpinPlayer(player_t *player, mobj_t *source, INT32 type, boolean trapitem);
void K_SquishPlayer(player_t *player, mobj_t *source);
void K_ExplodePlayer(player_t *player, mobj_t *source);
void K_ExplodePlayer(player_t *player, mobj_t *source, mobj_t *inflictor);
void K_StealBumper(player_t *player, player_t *victim, boolean force);
void K_SpawnKartExplosion(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, angle_t rotangle, boolean spawncenter, boolean ghostit, mobj_t *source);
void K_SpawnMineExplosion(mobj_t *source, UINT8 color);
@ -36,7 +38,7 @@ void K_SpawnBoostTrail(player_t *player);
void K_SpawnSparkleTrail(mobj_t *mo);
void K_SpawnWipeoutTrail(mobj_t *mo, boolean translucent);
void K_DriftDustHandling(mobj_t *spawner);
void K_DoSneaker(player_t *player, boolean doPFlag);
void K_DoSneaker(player_t *player, INT32 type);
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_UpdateHnextList(player_t *player, boolean clean);
@ -66,8 +68,6 @@ fixed_t K_FindCheckX(fixed_t px, fixed_t py, angle_t ang, fixed_t mx, fixed_t my
void K_drawKartHUD(void);
void K_drawKartFreePlay(UINT32 flashtime);
void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT16 emblemmap, boolean playing);
void K_LoadIconGraphics(char *facestr, INT32 skinnum);
void K_ReloadSkinIconGraphics(void);
// =========================================================================
#endif // __K_KART__

View File

@ -92,6 +92,7 @@ static int lib_print(lua_State *L)
static int lib_chatprint(lua_State *L)
{
const char *str = luaL_checkstring(L, 1); // retrieve string
boolean sound = luaL_checkboolean(L, 2); // retrieve sound boolean
int len;
if (str == NULL) // error if we don't have a string!
return luaL_error(L, LUA_QL("tostring") " must return a string to " LUA_QL("chatprint"));
@ -99,12 +100,7 @@ static int lib_chatprint(lua_State *L)
if (len > 255) // string is too long!!!
return luaL_error(L, "String exceeds the 255 characters limit of the chat buffer.");
HU_AddChatText(str);
if OLDCHAT
CONS_Printf("%s\n", str);
else
CON_LogMessage(str); // save to log.txt
HU_AddChatText(str, sound);
return 0;
}
@ -115,6 +111,7 @@ static int lib_chatprintf(lua_State *L)
int n = lua_gettop(L); /* number of arguments */
player_t *plr;
const char *str;
boolean sound = luaL_checkboolean(L, 3);
int len;
if (n < 2)
return luaL_error(L, "chatprintf requires at least two arguments: player and text.");
@ -132,12 +129,7 @@ static int lib_chatprintf(lua_State *L)
if (len > 255) // string is too long!!!
return luaL_error(L, "String exceeds the 255 characters limit of the chat buffer.");
HU_AddChatText(str);
if OLDCHAT
CONS_Printf("%s\n", str);
else
CON_LogMessage(str); // save to log.txt
HU_AddChatText(str, sound);
return 0;
}
@ -2094,6 +2086,19 @@ static int lib_kKartBouncing(lua_State *L)
return 0;
}
static int lib_kMatchGenericExtraFlags(lua_State *L)
{
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
mobj_t *master = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
NOHUD
if (!mo)
return LUA_ErrInvalid(L, "mobj_t");
if (!master)
return LUA_ErrInvalid(L, "mobj_t");
K_MatchGenericExtraFlags(mo, master);
return 0;
}
static int lib_kDoInstashield(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
@ -2104,6 +2109,20 @@ static int lib_kDoInstashield(lua_State *L)
return 0;
}
static int lib_kSpawnBattlePoints(lua_State *L)
{
player_t *source = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
player_t *victim = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
UINT8 amount = (UINT8)luaL_checkinteger(L, 3);
NOHUD
if (!source)
return LUA_ErrInvalid(L, "player_t");
if (!victim)
return LUA_ErrInvalid(L, "player_t");
K_SpawnBattlePoints(source, victim, amount);
return 0;
}
static int lib_kSpinPlayer(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
@ -2136,12 +2155,15 @@ static int lib_kExplodePlayer(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
mobj_t *source = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
mobj_t *inflictor = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
NOHUD
if (!player)
return LUA_ErrInvalid(L, "player_t");
if (!source)
return LUA_ErrInvalid(L, "mobj_t");
K_ExplodePlayer(player, source);
if (!inflictor)
return LUA_ErrInvalid(L, "mobj_t");
K_ExplodePlayer(player, source, inflictor);
return 0;
}
@ -2222,11 +2244,11 @@ static int lib_kDriftDustHandling(lua_State *L)
static int lib_kDoSneaker(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
boolean doPFlag = luaL_checkboolean(L, 2);
INT32 type = luaL_checkinteger(L, 2);
NOHUD
if (!player)
return LUA_ErrInvalid(L, "player_t");
K_DoSneaker(player, doPFlag);
K_DoSneaker(player, type);
return 0;
}
@ -2490,7 +2512,9 @@ static luaL_Reg lib[] = {
{"K_IsPlayerLosing",lib_kIsPlayerLosing},
{"K_IsPlayerWanted",lib_kIsPlayerWanted},
{"K_KartBouncing",lib_kKartBouncing},
{"K_MatchGenericExtraFlags",lib_kMatchGenericExtraFlags},
{"K_DoInstashield",lib_kDoInstashield},
{"K_SpawnBattlePoints",lib_kSpawnBattlePoints},
{"K_SpinPlayer",lib_kSpinPlayer},
{"K_SquishPlayer",lib_kSquishPlayer},
{"K_ExplodePlayer",lib_kExplodePlayer},

View File

@ -27,9 +27,9 @@ enum skin {
skin_flags,
skin_realname,
skin_hudname,
skin_charsel,
skin_face,
skin_superface,
skin_facerank,
skin_facewant,
skin_facemmap,
skin_ability,
skin_ability2,
skin_thokitem,
@ -61,9 +61,9 @@ static const char *const skin_opt[] = {
"flags",
"realname",
"hudname",
"charsel",
"face",
"superface",
"facerank",
"facewant",
"facemmap",
"ability",
"ability2",
"thokitem",
@ -121,23 +121,23 @@ static int skin_get(lua_State *L)
case skin_hudname:
lua_pushstring(L, skin->hudname);
break;
case skin_charsel:
case skin_facerank:
for (i = 0; i < 8; i++)
if (!skin->charsel[i])
if (!skin->facerank[i])
break;
lua_pushlstring(L, skin->charsel, i);
lua_pushlstring(L, skin->facerank, i);
break;
case skin_face:
case skin_facewant:
for (i = 0; i < 8; i++)
if (!skin->face[i])
if (!skin->facewant[i])
break;
lua_pushlstring(L, skin->face, i);
lua_pushlstring(L, skin->facewant, i);
break;
case skin_superface:
case skin_facemmap:
for (i = 0; i < 8; i++)
if (!skin->superface[i])
if (!skin->facemmap[i])
break;
lua_pushlstring(L, skin->superface, i);
lua_pushlstring(L, skin->facemmap, i);
break;
case skin_ability:
lua_pushinteger(L, skin->ability);

View File

@ -33,64 +33,64 @@ conditionset_t conditionSets[MAXCONDITIONSETS];
emblem_t emblemlocations[MAXEMBLEMS] =
{
// SILVER TIME TROPHIES
{ET_TIME, 0,0,0, 1, 'T', SKINCOLOR_GREY, 90*TICRATE, "", 0}, // Green Hills Zone - Time: 1:30
{ET_TIME, 0,0,0, 2, 'T', SKINCOLOR_GREY, 110*TICRATE, "", 0}, // Pipe Speedway Zone - Time: 1:50
{ET_TIME, 0,0,0, 3, 'T', SKINCOLOR_GREY, 135*TICRATE, "", 0}, // Dark Race - 2:15
{ET_TIME, 0,0,0, 4, 'T', SKINCOLOR_GREY, 105*TICRATE, "", 0}, // Darkvile Garden Zone - 1:45
{ET_TIME, 0,0,0, 5, 'T', SKINCOLOR_GREY, 140*TICRATE, "", 0}, // Northern District Zone - 2:20
{ET_TIME, 0,0,0, 6, 'T', SKINCOLOR_GREY, 120*TICRATE, "", 0}, // Sonic Speedway Zone - 2:00
{ET_TIME, 0,0,0, 7, 'T', SKINCOLOR_GREY, 120*TICRATE, "", 0}, // Egg Zeppelin Zone - 2:00
{ET_TIME, 0,0,0, 8, 'T', SKINCOLOR_GREY, 95*TICRATE, "", 0}, // Hill Top Zone - 1:35
{ET_TIME, 0,0,0, 9, 'T', SKINCOLOR_GREY, 110*TICRATE, "", 0}, // Sunbeam Paradise Zone - 1:50
{ET_TIME, 0,0,0, 10, 'T', SKINCOLOR_GREY, 110*TICRATE, "", 0}, // Diamond Square Zone - 1:50
{ET_TIME, 0,0,0, 11, 'T', SKINCOLOR_GREY, 150*TICRATE, "", 0}, // Misty Maze Zone - 2:30
{ET_TIME, 0,0,0, 12, 'T', SKINCOLOR_GREY, 120*TICRATE, "", 0}, // Midnight Meadow Zone - 2:00
{ET_TIME, 0,0,0, 13, 'T', SKINCOLOR_GREY, 130*TICRATE, "", 0}, // Megablock Castle Zone - 2:10
{ET_TIME, 0,0,0, 14, 'T', SKINCOLOR_GREY, 150*TICRATE, "", 0}, // Sub-Zero Peak Zone - 2:30
{ET_TIME, 0,0,0, 15, 'T', SKINCOLOR_GREY, 110*TICRATE, "", 0}, // Sapphire Coast Zone - 1:50
{ET_TIME, 0,0,0, 16, 'T', SKINCOLOR_GREY, 140*TICRATE, "", 0}, // Silvercloud Island Zone - 2:20
{ET_TIME, 0,0,0, 17, 'T', SKINCOLOR_GREY, 135*TICRATE, "", 0}, // Petroleum Refinery Zone - 2:15
{ET_TIME, 0,0,0, 18, 'T', SKINCOLOR_GREY, 130*TICRATE, "", 0}, // Canyon Rush Zone - 2:10
{ET_TIME, 0,0,0, 19, 'T', SKINCOLOR_GREY, 160*TICRATE, "", 0}, // Blue Mountain Zone - 2:40
{ET_TIME, 0,0,0, 20, 'T', SKINCOLOR_GREY, 110*TICRATE, "", 0}, // Casino Resort Zone - 1:50
{ET_TIME, 0,0,0, 21, 'T', SKINCOLOR_GREY, 105*TICRATE, "", 0}, // Desert Palace Zone - 1:45
{ET_TIME, 0,0,0, 22, 'T', SKINCOLOR_GREY, 165*TICRATE, "", 0}, // Red Barrage Area - 2:45
{ET_TIME, 0,0,0, 23, 'T', SKINCOLOR_GREY, 105*TICRATE, "", 0}, // Vanilla Hotel Zone - 1:45
{ET_TIME, 0,0,0, 24, 'T', SKINCOLOR_GREY, 110*TICRATE, "", 0}, // Twinkle Cart - 1:50
{ET_TIME, 0,0,0, 25, 'T', SKINCOLOR_GREY, 110*TICRATE, "", 0}, // Pleasure Castle - 1:50
{ET_TIME, 0,0,0, 26, 'T', SKINCOLOR_GREY, 140*TICRATE, "", 0}, // Aurora Atoll Zone - 2:20
{ET_TIME, 0,0,0, 27, 'T', SKINCOLOR_GREY, 130*TICRATE, "", 0}, // Barren Badlands Zone - 2:10
{ET_TIME, 0,0,0, 28, 'T', SKINCOLOR_GREY, 155*TICRATE, "", 0}, // Toxic Palace Zone - 2:35
{ET_TIME, 0,0,0, 29, 'T', SKINCOLOR_GREY, 130*TICRATE, "", 0}, // Ancient Tomb Zone - 2:10
{ET_TIME, 0,0,0, 30, 'T', SKINCOLOR_GREY, 120*TICRATE, "", 0}, // Cloud Cradle Zone K - 2:00
{ET_TIME, 0,0,0, 31, 'T', SKINCOLOR_GREY, 110*TICRATE, "", 0}, // Kodachrome Void Zone - 1:50
{ET_TIME, 0,0,0, 32, 'T', SKINCOLOR_GREY, 140*TICRATE, "", 0}, // Egg Quarters - 2:20
{ET_TIME, 0,0,0, 33, 'T', SKINCOLOR_GREY, 115*TICRATE, "", 0}, // Boiling Bedrock Zone - 1:55
{ET_TIME, 0,0,0, 34, 'T', SKINCOLOR_GREY, 140*TICRATE, "", 0}, // Virtual Highway Zone - 2:20
{ET_TIME, 0,0,0, 35, 'T', SKINCOLOR_GREY, 120*TICRATE, "", 0}, // Eggman's Nightclub Zone - 2:00
{ET_TIME, 0,0,0, 36, 'T', SKINCOLOR_GREY, 90*TICRATE, "", 0}, // KKR Ganbare Dochu 2 - 1:30
{ET_TIME, 0,0,0, 37, 'T', SKINCOLOR_GREY, 80*TICRATE, "", 0}, // CK Chao Circuit 1 - 1:20
{ET_TIME, 0,0,0, 38, 'T', SKINCOLOR_GREY, 130*TICRATE, "", 0}, // CK Chao Circuit 2 - 2:10
{ET_TIME, 0,0,0, 39, 'T', SKINCOLOR_GREY, 100*TICRATE, "", 0}, // CK Cloud Tops 2 - 1:40
{ET_TIME, 0,0,0, 40, 'T', SKINCOLOR_GREY, 130*TICRATE, "", 0}, // CK Regal Raceway - 2:10
{ET_TIME, 0,0,0, 41, 'T', SKINCOLOR_GREY, 130*TICRATE, "", 0}, // SM Dimension Heist - 2:10
{ET_TIME, 0,0,0, 42, 'T', SKINCOLOR_GREY, 100*TICRATE, "", 0}, // SRB2 Frozen Night - 1:40
{ET_TIME, 0,0,0, 43, 'T', SKINCOLOR_GREY, 100*TICRATE, "", 0}, // MKSC Sky Garden - 1:40
{ET_TIME, 0,0,0, 44, 'T', SKINCOLOR_GREY, 95*TICRATE, "", 0}, // MKDS Peach Gardens - 1:35
{ET_TIME, 0,0,0, 45, 'T', SKINCOLOR_GREY, 105*TICRATE, "", 0}, // MKSC Rainbow Road - 1:45
{ET_TIME, 0,0,0, 46, 'T', SKINCOLOR_GREY, 70*TICRATE, "", 0}, // SMK Mario Circuit 1 - 1:10
{ET_TIME, 0,0,0, 47, 'T', SKINCOLOR_GREY, 90*TICRATE, "", 0}, // SMK Donut Plains 1 - 1:30
{ET_TIME, 0,0,0, 48, 'T', SKINCOLOR_GREY, 75*TICRATE, "", 0}, // SMK Ghost Valley 2 - 1:15
{ET_TIME, 0,0,0, 49, 'T', SKINCOLOR_GREY, 105*TICRATE, "", 0}, // SMK Mario Circuit 3 - 1:45
{ET_TIME, 0,0,0, 50, 'T', SKINCOLOR_GREY, 130*TICRATE, "", 0} // SMK Rainbow Road - 2:10
{ET_TIME, 0,0,0, 1, 'B', SKINCOLOR_GREY, 90*TICRATE, "", 0}, // Green Hills Zone - Time: 1:30
{ET_TIME, 0,0,0, 2, 'B', SKINCOLOR_GREY, 110*TICRATE, "", 0}, // Pipe Speedway Zone - Time: 1:50
{ET_TIME, 0,0,0, 3, 'B', SKINCOLOR_GREY, 135*TICRATE, "", 0}, // Dark Race - 2:15
{ET_TIME, 0,0,0, 4, 'B', SKINCOLOR_GREY, 105*TICRATE, "", 0}, // Darkvile Garden Zone - 1:45
{ET_TIME, 0,0,0, 5, 'B', SKINCOLOR_GREY, 140*TICRATE, "", 0}, // Northern District Zone - 2:20
{ET_TIME, 0,0,0, 6, 'B', SKINCOLOR_GREY, 120*TICRATE, "", 0}, // Sonic Speedway Zone - 2:00
{ET_TIME, 0,0,0, 7, 'B', SKINCOLOR_GREY, 120*TICRATE, "", 0}, // Egg Zeppelin Zone - 2:00
{ET_TIME, 0,0,0, 8, 'B', SKINCOLOR_GREY, 95*TICRATE, "", 0}, // Hill Top Zone - 1:35
{ET_TIME, 0,0,0, 9, 'B', SKINCOLOR_GREY, 110*TICRATE, "", 0}, // Sunbeam Paradise Zone - 1:50
{ET_TIME, 0,0,0, 10, 'B', SKINCOLOR_GREY, 110*TICRATE, "", 0}, // Diamond Square Zone - 1:50
{ET_TIME, 0,0,0, 11, 'B', SKINCOLOR_GREY, 150*TICRATE, "", 0}, // Misty Maze Zone - 2:30
{ET_TIME, 0,0,0, 12, 'B', SKINCOLOR_GREY, 120*TICRATE, "", 0}, // Midnight Meadow Zone - 2:00
{ET_TIME, 0,0,0, 13, 'B', SKINCOLOR_GREY, 130*TICRATE, "", 0}, // Megablock Castle Zone - 2:10
{ET_TIME, 0,0,0, 14, 'B', SKINCOLOR_GREY, 150*TICRATE, "", 0}, // Sub-Zero Peak Zone - 2:30
{ET_TIME, 0,0,0, 15, 'B', SKINCOLOR_GREY, 110*TICRATE, "", 0}, // Sapphire Coast Zone - 1:50
{ET_TIME, 0,0,0, 16, 'B', SKINCOLOR_GREY, 140*TICRATE, "", 0}, // Silvercloud Island Zone - 2:20
{ET_TIME, 0,0,0, 17, 'B', SKINCOLOR_GREY, 135*TICRATE, "", 0}, // Petroleum Refinery Zone - 2:15
{ET_TIME, 0,0,0, 18, 'B', SKINCOLOR_GREY, 130*TICRATE, "", 0}, // Canyon Rush Zone - 2:10
{ET_TIME, 0,0,0, 19, 'B', SKINCOLOR_GREY, 160*TICRATE, "", 0}, // Blue Mountain Zone - 2:40
{ET_TIME, 0,0,0, 20, 'B', SKINCOLOR_GREY, 110*TICRATE, "", 0}, // Casino Resort Zone - 1:50
{ET_TIME, 0,0,0, 21, 'B', SKINCOLOR_GREY, 105*TICRATE, "", 0}, // Desert Palace Zone - 1:45
{ET_TIME, 0,0,0, 22, 'B', SKINCOLOR_GREY, 165*TICRATE, "", 0}, // Red Barrage Area - 2:45
{ET_TIME, 0,0,0, 23, 'B', SKINCOLOR_GREY, 105*TICRATE, "", 0}, // Vanilla Hotel Zone - 1:45
{ET_TIME, 0,0,0, 24, 'B', SKINCOLOR_GREY, 110*TICRATE, "", 0}, // Twinkle Cart - 1:50
{ET_TIME, 0,0,0, 25, 'B', SKINCOLOR_GREY, 110*TICRATE, "", 0}, // Pleasure Castle - 1:50
{ET_TIME, 0,0,0, 26, 'B', SKINCOLOR_GREY, 140*TICRATE, "", 0}, // Aurora Atoll Zone - 2:20
{ET_TIME, 0,0,0, 27, 'B', SKINCOLOR_GREY, 130*TICRATE, "", 0}, // Barren Badlands Zone - 2:10
{ET_TIME, 0,0,0, 28, 'B', SKINCOLOR_GREY, 155*TICRATE, "", 0}, // Toxic Palace Zone - 2:35
{ET_TIME, 0,0,0, 29, 'B', SKINCOLOR_GREY, 130*TICRATE, "", 0}, // Ancient Tomb Zone - 2:10
{ET_TIME, 0,0,0, 30, 'B', SKINCOLOR_GREY, 120*TICRATE, "", 0}, // Cloud Cradle Zone K - 2:00
{ET_TIME, 0,0,0, 31, 'B', SKINCOLOR_GREY, 110*TICRATE, "", 0}, // Kodachrome Void Zone - 1:50
{ET_TIME, 0,0,0, 32, 'B', SKINCOLOR_GREY, 140*TICRATE, "", 0}, // Egg Quarters - 2:20
{ET_TIME, 0,0,0, 33, 'B', SKINCOLOR_GREY, 115*TICRATE, "", 0}, // Boiling Bedrock Zone - 1:55
{ET_TIME, 0,0,0, 34, 'B', SKINCOLOR_GREY, 140*TICRATE, "", 0}, // Virtual Highway Zone - 2:20
{ET_TIME, 0,0,0, 35, 'B', SKINCOLOR_GREY, 120*TICRATE, "", 0}, // Eggman's Nightclub Zone - 2:00
{ET_TIME, 0,0,0, 36, 'B', SKINCOLOR_GREY, 90*TICRATE, "", 0}, // KKR Ganbare Dochu 2 - 1:30
{ET_TIME, 0,0,0, 37, 'B', SKINCOLOR_GREY, 80*TICRATE, "", 0}, // CK Chao Circuit 1 - 1:20
{ET_TIME, 0,0,0, 38, 'B', SKINCOLOR_GREY, 130*TICRATE, "", 0}, // CK Chao Circuit 2 - 2:10
{ET_TIME, 0,0,0, 39, 'B', SKINCOLOR_GREY, 100*TICRATE, "", 0}, // CK Cloud Tops 2 - 1:40
{ET_TIME, 0,0,0, 40, 'B', SKINCOLOR_GREY, 130*TICRATE, "", 0}, // CK Regal Raceway - 2:10
{ET_TIME, 0,0,0, 41, 'B', SKINCOLOR_GREY, 130*TICRATE, "", 0}, // SM Dimension Heist - 2:10
{ET_TIME, 0,0,0, 42, 'B', SKINCOLOR_GREY, 100*TICRATE, "", 0}, // SRB2 Frozen Night - 1:40
{ET_TIME, 0,0,0, 43, 'B', SKINCOLOR_GREY, 100*TICRATE, "", 0}, // MKSC Sky Garden - 1:40
{ET_TIME, 0,0,0, 44, 'B', SKINCOLOR_GREY, 95*TICRATE, "", 0}, // MKDS Peach Gardens - 1:35
{ET_TIME, 0,0,0, 45, 'B', SKINCOLOR_GREY, 105*TICRATE, "", 0}, // MKSC Rainbow Road - 1:45
{ET_TIME, 0,0,0, 46, 'B', SKINCOLOR_GREY, 70*TICRATE, "", 0}, // SMK Mario Circuit 1 - 1:10
{ET_TIME, 0,0,0, 47, 'B', SKINCOLOR_GREY, 90*TICRATE, "", 0}, // SMK Donut Plains 1 - 1:30
{ET_TIME, 0,0,0, 48, 'B', SKINCOLOR_GREY, 75*TICRATE, "", 0}, // SMK Ghost Valley 2 - 1:15
{ET_TIME, 0,0,0, 49, 'B', SKINCOLOR_GREY, 105*TICRATE, "", 0}, // SMK Mario Circuit 3 - 1:45
{ET_TIME, 0,0,0, 50, 'B', SKINCOLOR_GREY, 130*TICRATE, "", 0} // SMK Rainbow Road - 2:10
// GOLD DEV TIME TROPHIES
// ...none yet!
// ...none yet! uses 'A'
};
// Default Extra Emblems
extraemblem_t extraemblems[MAXEXTRAEMBLEMS] =
{
{"Experienced Driver", "Play 100 Matches", 10, 'X', SKINCOLOR_BLUE, 0},
{"Experienced Driver", "Play 100 Matches", 10, 'C', SKINCOLOR_RED, 0},
};
// Default Unlockables
@ -101,10 +101,11 @@ unlockable_t unlockables[MAXUNLOCKABLES] =
/* 02 */ {"SMK Cup", "", -1, 2, SECRET_NONE, 0, false, false, 0},
/* 03 */ {"Chao Cup", "", -1, 3, SECRET_NONE, 0, false, false, 0},
/* 04 */ {"Encore Mode", "", 3, 4, SECRET_ENCORE, 0, false, false, 0},
/* 05 */ {"Hell Attack", "", 5, 5, SECRET_HELLATTACK, 0, false, false, 0},
/* 04 */ {"Hard Game Speed", "", -1, 4, SECRET_HARDSPEED, 0, false, false, 0},
/* 05 */ {"Encore Mode", "", 4, 5, SECRET_ENCORE, 0, false, false, 0},
/* 06 */ {"Hell Attack", "", 6, 6, SECRET_HELLATTACK, 0, false, false, 0},
/* 06 */ {"Record Attack", "", -1, -1, SECRET_RECORDATTACK, 0, true, true, 0},
/* 07 */ {"Record Attack", "", -1, -1, SECRET_RECORDATTACK, 0, true, true, 0},
};
// Default number of emblems and extra emblems
@ -120,23 +121,27 @@ void M_SetupDefaultConditionSets(void)
M_AddRawCondition(1, 1, UC_TOTALEMBLEMS, 5, 0, 0);
M_AddRawCondition(1, 2, UC_MATCHESPLAYED, 10, 0, 0);
// -- 2: Collect 15 emblems OR play 25 matches
M_AddRawCondition(2, 1, UC_TOTALEMBLEMS, 15, 0, 0);
// -- 2: Collect 10 emblems OR play 25 matches
M_AddRawCondition(2, 1, UC_TOTALEMBLEMS, 10, 0, 0);
M_AddRawCondition(2, 2, UC_MATCHESPLAYED, 25, 0, 0);
// -- 3: Collect 30 emblems OR play 50 matches
M_AddRawCondition(3, 1, UC_TOTALEMBLEMS, 30, 0, 0);
// -- 3: Collect 20 emblems OR play 50 matches
M_AddRawCondition(3, 1, UC_TOTALEMBLEMS, 20, 0, 0);
M_AddRawCondition(3, 2, UC_MATCHESPLAYED, 50, 0, 0);
// -- 4: Collect 40 emblems OR play 150 matches
M_AddRawCondition(4, 1, UC_TOTALEMBLEMS, 40, 0, 0);
M_AddRawCondition(4, 2, UC_MATCHESPLAYED, 150, 0, 0);
// -- 4: Collect 30 emblems OR play 100 matches
M_AddRawCondition(4, 1, UC_TOTALEMBLEMS, 30, 0, 0);
M_AddRawCondition(4, 2, UC_MATCHESPLAYED, 100, 0, 0);
// -- 5: Collect 50 emblems ONLY
M_AddRawCondition(5, 1, UC_TOTALEMBLEMS, 50, 0, 0);
// -- 5: Collect 40 emblems OR play 150 matches
M_AddRawCondition(5, 1, UC_TOTALEMBLEMS, 40, 0, 0);
M_AddRawCondition(5, 2, UC_MATCHESPLAYED, 150, 0, 0);
// -- 10: Play 100 matches
M_AddRawCondition(10, 1, UC_MATCHESPLAYED, 100, 0, 0);
// -- 6: Collect 50 emblems ONLY
M_AddRawCondition(6, 1, UC_TOTALEMBLEMS, 50, 0, 0);
// -- 10: Play 300 matches
M_AddRawCondition(10, 1, UC_MATCHESPLAYED, 300, 0, 0);
}
void M_AddRawCondition(UINT8 set, UINT8 id, conditiontype_t c, INT32 r, INT16 x1, INT16 x2)

View File

@ -113,7 +113,7 @@ typedef struct
} unlockable_t;
// I have NO idea why these are going negative, but whatever.
#define SECRET_NONE -6 // Does nil. Use with levels locked by UnlockRequired
#define SECRET_NONE -6 // Does nil. Use with levels locked by UnlockRequired
#define SECRET_ITEMFINDER -5 // Enables Item Finder/Emblem Radar
#define SECRET_EMBLEMHINTS -4 // Enables Emblem Hints
#define SECRET_PANDORA -3 // Enables Pandora's Box
@ -124,8 +124,9 @@ typedef struct
#define SECRET_WARP 2 // Selectable warp
#define SECRET_SOUNDTEST 3 // Sound Test
#define SECRET_CREDITS 4 // Enables Credits
#define SECRET_ENCORE 5 // Enables Encore mode cvar
#define SECRET_HELLATTACK 6 // Map Hell in record attack
#define SECRET_ENCORE 5 // Enables Encore mode cvar
#define SECRET_HELLATTACK 6 // Map Hell in record attack
#define SECRET_HARDSPEED 7 // Enables Hard gamespeed
// If you have more secrets than these variables allow in your game,
// you seriously need to get a life.

File diff suppressed because it is too large Load Diff

View File

@ -228,6 +228,8 @@ void Screenshot_option_Onchange(void);
// Addons menu updating
void Addons_option_Onchange(void);
INT32 HU_GetHighlightColor(void);
// These defines make it a little easier to make menus
#define DEFAULTMENUSTYLE(header, source, prev, x, y)\
{\

View File

@ -190,9 +190,18 @@ void A_ToggleFlameJet(mobj_t *actor);
void A_ItemPop(mobj_t *actor); // SRB2kart
void A_JawzChase(mobj_t *actor); // SRB2kart
void A_JawzExplode(mobj_t *actor); // SRB2kart
void A_SPBChase(mobj_t *actor); // SRB2kart
void A_MineExplode(mobj_t *actor); // SRB2kart
void A_BallhogExplode(mobj_t *actor); // SRB2kart
void A_LightningFollowPlayer(mobj_t *actor); // SRB2kart
void A_LightningFollowPlayer(mobj_t *actor); // SRB2kart
void A_FZBoomFlash(mobj_t *actor); // SRB2kart
void A_FZBoomSmoke(mobj_t *actor); // SRB2kart
void A_RandomShadowFrame(mobj_t *actor); // SRB2kart
void A_RoamingShadowThinker(mobj_t *actor); //SRB2kart
void A_MayonakaArrow(mobj_t *actor); //SRB2kart
void A_ReaperThinker(mobj_t *actor); //SRB2kart
void A_MementosTPParticles(mobj_t *actor); //SRB2kart
void A_FlameParticle(mobj_t *actor); // SRB2kart
void A_OrbitNights(mobj_t *actor);
void A_GhostMe(mobj_t *actor);
void A_SetObjectState(mobj_t *actor);
@ -3406,7 +3415,7 @@ void A_ParticleSpawn(mobj_t *actor)
P_SetScale(spawn, actor->scale);
spawn->momz = speed;
spawn->destscale = FixedDiv(spawn->scale<<FRACBITS, 100<<FRACBITS);
spawn->scalespeed = FixedDiv(((actor->spawnpoint->angle >> 8) & 63) << FRACBITS, 100<<FRACBITS);
spawn->scalespeed = FixedDiv(((actor->spawnpoint->angle >> 8) & 63) * actor->scale, 100<<FRACBITS);
actor->tics = actor->spawnpoint->extrainfo + 1;
}
@ -4014,7 +4023,7 @@ static inline boolean PIT_MineExplode(mobj_t *thing)
grenade->flags2 |= MF2_DEBRIS;
if (thing->player) // Looks like we're going to have to need a seperate function for this too
K_ExplodePlayer(thing->player, grenade->target);
K_ExplodePlayer(thing->player, grenade->target, grenade);
else
P_DamageMobj(thing, grenade, grenade->target, 1);
@ -4053,7 +4062,7 @@ void A_MineExplode(mobj_t *actor)
if (actor->target && actor->target->player)
K_SpawnMineExplosion(actor, actor->target->player->skincolor);
else
K_SpawnMineExplosion(actor, SKINCOLOR_RED);
K_SpawnMineExplosion(actor, SKINCOLOR_KETCHUP);
P_SpawnMobj(actor->x, actor->y, actor->z, MT_MINEEXPLOSIONSOUND);
}
@ -8173,7 +8182,7 @@ void A_ToggleFlameJet(mobj_t* actor)
}
}
//{ SRB2kart - A_ItemPop, A_JawzChase, A_JawzExplode, A_MineExplode, and A_BallhogExplode
//{ SRB2kart Actions
void A_ItemPop(mobj_t *actor)
{
mobj_t *remains;
@ -8252,6 +8261,9 @@ void A_JawzChase(mobj_t *actor)
if (actor->tracer)
{
if (G_RaceGametype()) // Stop looking after first target in race
actor->extravalue1 = 1;
if (actor->tracer->health)
{
mobj_t *ret;
@ -8271,13 +8283,13 @@ void A_JawzChase(mobj_t *actor)
if (actor->extravalue1) // Disable looking by setting this
return;
if (actor->target && !P_MobjWasRemoved(actor->target)) // No source!
return;
player = K_FindJawzTarget(actor, actor->target->player);
if (player)
P_SetTarget(&actor->tracer, player->mo);
if (G_RaceGametype()) // Stop looking after first tic in race
actor->extravalue1 = 1;
return;
}
@ -8293,7 +8305,7 @@ void A_JawzExplode(mobj_t *actor)
truc = P_SpawnMobj(actor->x, actor->y, actor->z, MT_BOOMEXPLODE);
truc->scale = actor->scale*2;
truc->color = SKINCOLOR_RED;
truc->color = SKINCOLOR_KETCHUP;
while (shrapnel)
{
@ -8311,7 +8323,7 @@ void A_JawzExplode(mobj_t *actor)
speed2 = FixedMul(15*FRACUNIT, actor->scale)>>FRACBITS;
truc->momz = P_RandomRange(speed, speed2)*FRACUNIT;
truc->tics = TICRATE*2;
truc->color = SKINCOLOR_RED;
truc->color = SKINCOLOR_KETCHUP;
shrapnel--;
}
@ -8319,65 +8331,221 @@ void A_JawzExplode(mobj_t *actor)
return;
}
/* old A_MineExplode - see elsewhere in the file
void A_MineExplode(mobj_t *actor)
void A_SPBChase(mobj_t *actor)
{
mobj_t *mo2;
thinker_t *th;
INT32 d;
INT32 locvar1 = var1;
mobjtype_t type;
fixed_t range;
player_t *player = NULL;
UINT8 i;
UINT8 bestrank = UINT8_MAX;
fixed_t dist;
angle_t hang, vang;
fixed_t wspeed, xyspeed, zspeed;
#ifdef HAVE_BLUA
if (LUA_CallAction("A_MineExplode", actor))
if (LUA_CallAction("A_SPBChase", actor))
return;
#endif
type = (mobjtype_t)locvar1;
range = FixedMul(actor->info->painchance, mapheaderinfo[gamemap-1]->mobj_scale);
// Default speed
wspeed = FixedMul(actor->info->speed, mapheaderinfo[gamemap-1]->mobj_scale);
if (gamespeed == 0)
wspeed = FixedMul(wspeed, FRACUNIT-FRACUNIT/4);
else if (gamespeed == 2)
wspeed = FixedMul(wspeed, FRACUNIT+FRACUNIT/4);
for (th = thinkercap.next; th != &thinkercap; th = th->next)
if (actor->threshold) // Just fired, go straight.
{
if (P_MobjWasRemoved(actor))
return; // There's the possibility these can chain react onto themselves after they've already died if there are enough all in one spot
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2 == actor || mo2->type == MT_MINEEXPLOSIONSOUND) // Don't explode yourself! Endless loop!
continue;
if (!(mo2->flags & MF_SHOOTABLE) || (mo2->flags & MF_SCENERY))
continue;
if (G_BattleGametype() && actor->target && actor->target->player && actor->target->player->kartstuff[k_bumper] <= 0 && mo2 == actor->target)
continue;
if (P_AproxDistance(P_AproxDistance(mo2->x - actor->x, mo2->y - actor->y), mo2->z - actor->z) > range)
continue;
actor->flags2 |= MF2_DEBRIS;
if (mo2->player) // Looks like we're going to have to need a seperate function for this too
K_ExplodePlayer(mo2->player, actor->target);
else
P_DamageMobj(mo2, actor, actor->target, 1);
P_InstaThrust(actor, actor->angle, wspeed);
return;
}
for (d = 0; d < 16; d++)
K_SpawnKartExplosion(actor->x, actor->y, actor->z, range + 32*mapheaderinfo[gamemap-1]->mobj_scale, 32, type, d*(ANGLE_45/4), true, false, actor->target); // 32 <-> 64
if (actor->extravalue1) // MODE: TARGETING
{
if (actor->tracer && actor->tracer->health)
{
fixed_t defspeed = wspeed;
fixed_t range = (160*actor->tracer->scale);
if (actor->target && actor->target->player)
K_SpawnMineExplosion(actor, actor->target->player->skincolor);
else
K_SpawnMineExplosion(actor, SKINCOLOR_RED);
// Maybe we want SPB to target an object later? IDK lol
if (actor->tracer->player) // 7/8ths max speed for Knuckles, 3/4ths max speed for min accel, exactly max speed for max accel
{
if (!P_IsObjectOnGround(actor->tracer) && !actor->tracer->player->kartstuff[k_pogospring])
defspeed = 7*actor->tracer->player->speed/8; // In the air you have no control; basically don't hit unless you make a near complete stop
else
defspeed = ((33 - actor->tracer->player->kartspeed) * K_GetKartSpeed(actor->tracer->player, false)) / 32;
}
P_SpawnMobj(actor->x, actor->y, actor->z, MT_MINEEXPLOSIONSOUND);
// Play the intimidating gurgle
if (!S_SoundPlaying(actor, actor->info->activesound))
S_StartSound(actor, actor->info->activesound);
dist = P_AproxDistance(P_AproxDistance(actor->x-actor->tracer->x, actor->y-actor->tracer->y), actor->z-actor->tracer->z);
wspeed = FixedMul(defspeed, FRACUNIT + FixedDiv(dist-range, range));
if (wspeed < defspeed)
wspeed = defspeed;
if (wspeed > (3*defspeed)/2)
wspeed = (3*defspeed)/2;
hang = R_PointToAngle2(actor->x, actor->y, actor->tracer->x, actor->tracer->y);
vang = R_PointToAngle2(0, actor->z, dist, actor->tracer->z);
{
// Smoothly rotate horz angle
angle_t input = hang - actor->angle;
boolean invert = (input > ANGLE_180);
if (invert)
input = InvAngle(input);
// Slow down when turning; it looks better and makes U-turns not unfair
xyspeed = FixedMul(wspeed, max(0, (((180<<FRACBITS) - AngleFixed(input)) / 90) - FRACUNIT));
input = FixedAngle(AngleFixed(input)/4);
if (invert)
input = InvAngle(input);
actor->angle += input;
// Smoothly rotate vert angle
input = vang - actor->movedir;
invert = (input > ANGLE_180);
if (invert)
input = InvAngle(input);
// Slow down when turning; might as well do it for momz, since we do it above too
zspeed = FixedMul(wspeed, max(0, (((180<<FRACBITS) - AngleFixed(input)) / 90) - FRACUNIT));
input = FixedAngle(AngleFixed(input)/4);
if (invert)
input = InvAngle(input);
actor->movedir += input;
}
actor->momx = FixedMul(FixedMul(xyspeed, FINECOSINE(actor->angle>>ANGLETOFINESHIFT)), FINECOSINE(actor->movedir>>ANGLETOFINESHIFT));
actor->momy = FixedMul(FixedMul(xyspeed, FINESINE(actor->angle>>ANGLETOFINESHIFT)), FINECOSINE(actor->movedir>>ANGLETOFINESHIFT));
actor->momz = FixedMul(zspeed, FINESINE(actor->movedir>>ANGLETOFINESHIFT));
// Red speed lines for when it's gaining on its target. A tell for when you're starting to lose too much speed!
if (R_PointToDist2(0, 0, actor->momx, actor->momy) > (actor->tracer->player ? (16*actor->tracer->player->speed)/15
: (16*R_PointToDist2(0, 0, actor->tracer->momx, actor->tracer->momy))/15) // Going faster than the target
&& xyspeed > K_GetKartSpeed(actor->tracer->player, false)/4) // Don't display speedup lines at pitifully low speeds
{
mobj_t *fast = P_SpawnMobj(actor->x + (P_RandomRange(-24,24) * actor->scale),
actor->y + (P_RandomRange(-24,24) * actor->scale),
actor->z + (actor->height/2) + (P_RandomRange(-24,24) * actor->scale),
MT_FASTLINE);
fast->angle = R_PointToAngle2(0, 0, actor->momx, actor->momy);
//fast->momx = 3*actor->momx/4;
//fast->momy = 3*actor->momy/4;
//fast->momz = 3*actor->momz/4;
fast->color = SKINCOLOR_RED;
fast->colorized = true;
K_MatchGenericExtraFlags(fast, actor);
}
return;
}
else // Target's gone, return to SEEKING
{
P_SetTarget(&actor->tracer, NULL);
actor->extravalue1 = 0; // Find someone new next tic
return;
}
}
else // MODE: SEEKING
{
// Find the player with the best rank
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator || players[i].exiting)
continue; // not in-game
if (!players[i].mo)
continue; // no mobj
if (players[i].mo->health <= 0)
continue; // dead
if (players[i].kartstuff[k_respawn])
continue; // respawning
if (players[i].kartstuff[k_position] < bestrank)
{
bestrank = players[i].kartstuff[k_position];
player = &players[i];
}
}
// No one there?
if (player == NULL || !player->mo)
{
#if 0
// SELF-DESTRUCT?
mobj_t *spbexplode;
S_StopSound(actor); // Don't continue playing the gurgle or the siren
spbexplode = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SPBEXPLOSION);
P_SetTarget(&spbexplode->target, actor->target);
P_RemoveMobj(actor);
#else
actor->momx = actor->momy = actor->momz = 0;
#endif
return;
}
// Found someone, now get close enough to initiate the slaughter...
P_SetTarget(&actor->tracer, player->mo);
dist = P_AproxDistance(P_AproxDistance(actor->x-actor->tracer->x, actor->y-actor->tracer->y), actor->z-actor->tracer->z);
hang = R_PointToAngle2(actor->x, actor->y, actor->tracer->x, actor->tracer->y);
vang = R_PointToAngle2(0, actor->z, dist, actor->tracer->z);
{
// Smoothly rotate horz angle
angle_t input = hang - actor->angle;
boolean invert = (input > ANGLE_180);
if (invert)
input = InvAngle(input);
// Slow down when turning; it looks better and makes U-turns not unfair
xyspeed = FixedMul(wspeed, max(0, (((180<<FRACBITS) - AngleFixed(input)) / 90) - FRACUNIT));
input = FixedAngle(AngleFixed(input)/4);
if (invert)
input = InvAngle(input);
actor->angle += input;
// Smoothly rotate vert angle
input = vang - actor->movedir;
invert = (input > ANGLE_180);
if (invert)
input = InvAngle(input);
// Slow down when turning; might as well do it for momz, since we do it above too
zspeed = FixedMul(wspeed, max(0, (((180<<FRACBITS) - AngleFixed(input)) / 90) - FRACUNIT));
input = FixedAngle(AngleFixed(input)/4);
if (invert)
input = InvAngle(input);
actor->movedir += input;
}
actor->momx = FixedMul(FixedMul(xyspeed, FINECOSINE(actor->angle>>ANGLETOFINESHIFT)), FINECOSINE(actor->movedir>>ANGLETOFINESHIFT));
actor->momy = FixedMul(FixedMul(xyspeed, FINESINE(actor->angle>>ANGLETOFINESHIFT)), FINECOSINE(actor->movedir>>ANGLETOFINESHIFT));
actor->momz = FixedMul(zspeed, FINESINE(actor->movedir>>ANGLETOFINESHIFT));
if (dist <= (3072*actor->tracer->scale)) // Close enough to target?
{
S_StartSound(actor, actor->info->attacksound); // Siren sound; might not need this anymore, but I'm keeping it for now just for debugging.
actor->extravalue1 = 1; // TARGET ACQUIRED
}
}
return;
}*/
}
void A_BallhogExplode(mobj_t *actor)
{
@ -8403,7 +8571,9 @@ void A_LightningFollowPlayer(mobj_t *actor)
if (LUA_CallAction("A_LightningFollowPlayer", actor))
return;
#endif
if (actor->target)
if (!actor->target)
return;
{
if (actor->extravalue1) // Make the radius also follow the player somewhat accuratly
{
@ -8418,9 +8588,444 @@ void A_LightningFollowPlayer(mobj_t *actor)
actor->momy = actor->target->momy;
actor->momz = actor->target->momz; // Give momentum since we don't teleport to our player literally every frame.
}
}
// A_FZBoomFlash:
// Flash everyone close enough to the boom
void A_FZBoomFlash(mobj_t *actor)
{
UINT8 i;
#ifdef HAVE_BLUA
if (LUA_CallAction("A_FZBoomFlash", actor))
return;
#endif
for (i = 0; i < MAXPLAYERS; i++)
{
fixed_t dist;
if (!playeringame[i] || !players[i].mo)
continue;
dist = P_AproxDistance(P_AproxDistance(actor->x-players[i].mo->x, actor->y-players[i].mo->y), actor->z-players[i].mo->z);
if (dist < 1536<<FRACBITS)
P_FlashPal(&players[i], PAL_WHITE, 2);
}
return;
}
// A_FZBoomSmoke:
// Spawns pinkish smoke around the object
// Var1 is radius add
void A_FZBoomSmoke(mobj_t *actor)
{
INT32 i;
INT32 rad = 47+(23*var1);
#ifdef HAVE_BLUA
if (LUA_CallAction("A_FZBoomSmoke", actor))
return;
#endif
for (i = 0; i < 8+(4*var1); i++)
{
mobj_t *smoke = P_SpawnMobj(actor->x + (P_RandomRange(-rad, rad)*actor->scale), actor->y + (P_RandomRange(-rad, rad)*actor->scale),
actor->z + (P_RandomRange(0, 72)*actor->scale), MT_THOK);
P_SetMobjState(smoke, S_FZEROSMOKE1);
smoke->tics += P_RandomRange(-3, 4);
smoke->scale = actor->scale*3;
}
return;
}
// A_RandomShadowFrame
// Gives a random sprite for the Mayonaka static shadows. Dumb and simple.
void A_RandomShadowFrame(mobj_t *actor)
{
mobj_t *fire;
mobj_t *fake;
#ifdef HAVE_BLUA
if (LUA_CallAction("A_RandomShadowFrame", (actor)))
return;
#endif
if (!actor->extravalue1) // Hack that spawns thoks that look like random shadows. Otherwise the state would overwrite our frame and that's a pain.
{
fake = P_SpawnMobj(actor->x, actor->y, actor->z, MT_THOK);
fake->sprite = SPR_ENM1;
fake->frame = P_RandomRange(0, 6);
P_SetScale(fake, FRACUNIT*3/2);
fake->scale = FRACUNIT*3/2;
fake->destscale = FRACUNIT*3/2;
fake->angle = actor->angle;
fake->tics = -1;
actor->flags2 |= MF2_DONTDRAW;
actor->extravalue1 = 1;
}
P_SetScale(actor, FRACUNIT*3/2);
// I have NO CLUE how to hardcode all of that fancy Linedef Executor shit so the fire spinout will be done by these entities directly.
if (P_LookForPlayers(actor, false, false, 380<<FRACBITS)) // got target
{
if (actor->target && !actor->target->player->powers[pw_flashing]
&& !actor->target->player->kartstuff[k_invincibilitytimer]
&& !actor->target->player->kartstuff[k_growshrinktimer]
&& !actor->target->player->kartstuff[k_spinouttimer]
&& P_IsObjectOnGround(actor->target)
&& actor->z == actor->target->z)
{
P_DamageMobj(actor->target, actor, actor, 1);
P_InstaThrust(actor->target, actor->angle, 16<<FRACBITS);
fire = P_SpawnMobj(actor->target->x, actor->target->y, actor->target->z, MT_THOK);
P_SetMobjStateNF(fire, S_QUICKBOOM1);
P_SetScale(fire, 4<<FRACBITS);
fire->color = SKINCOLOR_RED;
S_StartSound(actor->target, sfx_fire2);
}
}
return;
}
// A_RoamingShadowThinker
// Thinker for Midnight Channel's Roaming Shadows:
void A_RoamingShadowThinker(mobj_t *actor)
{
mobj_t *wind;
#ifdef HAVE_BLUA
if (LUA_CallAction("A_RoamingShadowThinker", (actor)))
return;
#endif
// extravalue1 replaces "movetimer"
// extravalue2 replaces "stoptimer"
P_SetScale(actor, FRACUNIT*3/2);
if (!actor->extravalue2)
{
P_InstaThrust(actor, actor->angle, 8<<FRACBITS); // move at 8 fracs / sec
actor->extravalue1 = ((actor->extravalue1) ? (actor->extravalue1-1) : (TICRATE*5+1)); // deplete timer if set, set to 5 ticrate otherwise.
if (actor->extravalue1 == 1) // if timer reaches 1, do a u-turn.
{
actor->extravalue1 = 0;
actor->extravalue2 = 60;
}
// Search for and attack Players venturing too close in front of us.
if (P_LookForPlayers(actor, false, false, 256<<FRACBITS)) // got target
{
if (actor->target && !actor->target->player->powers[pw_flashing]
&& !actor->target->player->kartstuff[k_invincibilitytimer]
&& !actor->target->player->kartstuff[k_growshrinktimer]
&& !actor->target->player->kartstuff[k_spinouttimer])
{
// send them flying and spawn the WIND!
P_InstaThrust(actor->target, 0, 0);
P_DamageMobj(actor->target, actor, actor, 1);
P_SetObjectMomZ(actor->target, 16<<FRACBITS, false);
S_StartSound(actor->target, sfx_wind1);
// Spawn the WIND:
wind = P_SpawnMobj(actor->target->x, actor->target->y, actor->target->z, MT_THOK); // Opaque layer:
P_SetMobjState(wind, S_GARU1);
P_SetScale(wind, FRACUNIT*3/2);
wind = P_SpawnMobj(actor->target->x, actor->target->y, actor->target->z, MT_THOK); // Translucent layer:
P_SetMobjState(wind, S_TGARU0);
P_SetScale(wind, FRACUNIT*3/2);
wind->destscale = 30<<FRACBITS;
}
}
}
else // Handle U-Turn
{
actor->angle += ANG1*3;
actor->extravalue2--;
}
return;
}
// A_MayonakaArrow
// Used for the arrow sprite animations in Mayonaka. It's only extra visual bullshit to make em more random.
void A_MayonakaArrow(mobj_t *actor)
{
INT32 flip = 0;
INT32 iswarning;
#ifdef HAVE_BLUA
if (LUA_CallAction("A_MayonakaArrow", (actor)))
return;
#endif
iswarning = actor->spawnpoint->options & MTF_OBJECTSPECIAL; // is our object a warning sign?
// "animtimer" is replaced by "extravalue1" here.
actor->extravalue1 = ((actor->extravalue1) ? (actor->extravalue1+1) : (P_RandomRange(0, (iswarning) ? (TICRATE/2) : TICRATE*3)));
flip = ((actor->spawnpoint->options & 1) ? (3) : (0)); // flip adds 3 frames, which is the flipped version of the sign.
// special warning behavior:
if (iswarning)
flip = 6;
actor->frame = flip + actor->extravalue2*3;
if (actor->extravalue1 >= TICRATE*7/2)
{
actor->extravalue1 = 0; // reset to 0 and start a new cycle.
// special behavior for warning sign; swap from warning to sneaker & reverse
if (iswarning)
actor->extravalue2 = (actor->extravalue2) ? (0) : (1);
}
else if (actor->extravalue1 > TICRATE*7/2 -4)
actor->frame = flip+2;
else if (actor->extravalue1 > TICRATE*3 && leveltime%2 > 0)
actor->frame = flip+1;
actor->frame |= FF_PAPERSPRITE;
actor->momz = 0;
return;
}
// A_MementosTPParticles
// Mementos teleporters particles effects. Short and simple.
void A_MementosTPParticles(mobj_t *actor)
{
mobj_t *particle;
mobj_t *mo2;
int i = 0;
thinker_t *th;
#ifdef HAVE_BLUA
if (LUA_CallAction("A_MementosTPParticles", (actor)))
return;
#endif
for (; i<4; i++)
{
particle = P_SpawnMobj(actor->x + (P_RandomRange(-256, 256)<<FRACBITS), actor->y + (P_RandomRange(-256, 256)<<FRACBITS), actor->z + (P_RandomRange(48, 256)<<FRACBITS), MT_MEMENTOSPARTICLE);
particle->frame = 0;
particle->color = ((i%2) ? (SKINCOLOR_RED) : (SKINCOLOR_BLACK));
particle->destscale = 1;
P_HomingAttack(particle, actor);
}
// Although this is mostly used to spawn particles, we will also save the OTHER teleport inside actor->target. That way teleporting doesn't require a thinker iteration.
// Doesn't seem like much given the small amount of mobjs this map has but heh.
if (!actor->target)
{
for (th = thinkercap.next; th != &thinkercap; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2->type == MT_MEMENTOSTP && mo2 != actor)
{
P_SetTarget(&actor->target, mo2); // The main target we're pursing.
break;
}
}
}
}
// A_ReaperThinker
// Mementos's Reaper's thinker. A huge pain in the Derek Bum to translate from Lua to this shite if you ask me.
void A_ReaperThinker(mobj_t *actor)
{
mobj_t *particle; // particles to spawn
int i = 0; // for loops
angle_t an = ANGLE_22h; // Reminder that angle constants suck.
//Waypoint stuff:
mobj_t *mo2;
thinker_t *th;
//Player targetting stuff:
UINT32 maxscore = 0; // we target the player with the highest score so yeah there you go.
player_t *player; // used as a shortcut in a loop.
mobj_t *targetplayermo = NULL; // the player mo we can eventually target, or whatever.
#ifdef HAVE_BLUA
if (LUA_CallAction("A_ReaperThinker", (actor)))
return;
#endif
// We don't have custom variables or whatever so we'll do with whatever the fuck we have left.
if (actor->health == 1000) // if health is 1000, set it to a small scale and have it start growing with destscale. Then set the health to uh, not 1000.
{
actor->scale = 1;
actor->destscale = 2<<FRACBITS;
actor->scalespeed = FRACUNIT/24; // Should take a bit less than 2 seconds to fully grow.
S_StartSound(NULL, sfx_chain);
actor->health--; // now we have 999 health, so that above won't happen again. Awesome.
}
if (actor->scale < 2<<FRACBITS) // we haven't finished growing YET.
{
// Spawn particles as we grow out of the floor, ゴ ゴ ゴ ゴ
for (; i<16; i++)
{
particle = P_SpawnMobj(actor->x + (P_RandomRange(-60, 60)<<FRACBITS), actor->y + (P_RandomRange(-60, 60)<<FRACBITS), actor->z, MT_THOK);
particle->momz = 20<<FRACBITS;
particle->color = ((i%2 !=0) ? (SKINCOLOR_RED) : (SKINCOLOR_BLACK));
particle->frame = 0;
P_SetScale(particle, FRACUNIT/2);
}
// Spawn particles in some edgy circle or w/e.
if (leveltime%5 != 0) // spawn the thing under that every tic.
return;
i=0;
for (; i<15; i++) // spawn in a circle formation or w/e.
{
particle = P_SpawnMobj(actor->x, actor->y, actor->z, MT_THOK);
particle->momz = 20<<FRACBITS;
particle->color = ((i%2 !=0) ? (SKINCOLOR_RED) : (SKINCOLOR_BLACK));
particle->frame = 0;
P_SetScale(particle, FRACUNIT/2);
P_InstaThrust(particle, an*i, 30<<FRACBITS);
}
return; // don't continue, what lies beyond that is the movement code.
}
// We finished growing and can now be a dangerous piece o' garbage scaring the living heck outta players!
actor->flags = MF_NOGRAVITY|MF_PAIN|MF_SPECIAL|MF_NOCLIP|MF_NOCLIPHEIGHT; // set our flags to be a damaging thing.
// Handle animation:
if (!(leveltime%5))
actor->extravalue2 = (actor->extravalue2 < 9) ? (actor->extravalue2+1) : (0); // Ghetto animation, but hey it works for what it's worth
// Chain sfx
if (!S_SoundPlaying(actor, sfx_chain))
S_StartSound(actor, sfx_chain);
actor->frame = actor->extravalue2; // yes i'm that bad at maths don't @ me.
if (!actor->target)
{
if (actor->hnext)
{
P_SetTarget(&actor->target, actor->hnext); // Default back to last waypoint.
return;
}
// We have no target and oughta find one, so let's scan through thinkers for a waypoint of angle 0, or something.
for (th = thinkercap.next; th != &thinkercap; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2->type != MT_REAPERWAYPOINT)
continue;
if (mo2->spawnpoint->angle != 0)
continue;
P_SetTarget(&actor->target, mo2); // The main target we're pursing.
P_SetTarget(&actor->hnext, mo2); // The last waypoint we hit. We will default back to that if a player goes out of our range!
actor->extravalue1 = 0; // This will store the angle of the last waypoint we touched. This will essentially be useful later on.
if (!actor->tracer) // If we already have a tracer (Waypoint #0), don't do anything.
{
P_SetTarget(&actor->tracer, mo2); // Because our target might be a player OR a waypoint, we need some sort of fallback option. This will always be waypoint 0.
break;
}
}
}
else // Awesome, we now have a target.
{
// Follow target:
P_InstaThrust(actor, R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y), 20<<FRACBITS);
actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y);
// The player we should target if it's near us:
for (i=0; i<MAXPLAYERS; i++)
{
if (!playeringame[i])
continue;
player = &players[i];
if (player && player->mo && player->kartstuff[k_bumper] && player->score >= maxscore)
{
targetplayermo = player->mo;
maxscore = player->score;
}
}
// Try to target that player:
if (targetplayermo)
{
if (P_LookForPlayers(actor, false, false, 1024<<FRACBITS)) // got target
{
if (!(actor->target == targetplayermo && actor->target && !actor->target->player->powers[pw_flashing]
&& !actor->target->player->kartstuff[k_invincibilitytimer]
&& !actor->target->player->kartstuff[k_growshrinktimer]
&& !actor->target->player->kartstuff[k_spinouttimer]))
P_SetTarget(&actor->target, actor->hnext);
// if the above isn't correct, then we should go back to targetting waypoints or something.
}
}
// Waypoint behavior.
if (actor->target->type == MT_REAPERWAYPOINT)
{
if (R_PointToDist2(actor->x, actor->y, actor->target->x, actor->target->y) < 22<<FRACBITS)
{
P_SetTarget(&actor->target, NULL); // remove target so we can default back to first waypoint if things go ham.
// If we reach close to a waypoint, then we should go to the NEXT one.
for (th = thinkercap.next; th != &thinkercap; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2->type != MT_REAPERWAYPOINT)
continue;
if (mo2->spawnpoint->angle != actor->extravalue1+1)
continue;
P_SetTarget(&actor->target, mo2); // The main target we're pursing.
P_SetTarget(&actor->hnext, mo2); // The last waypoint we hit. We will default back to that if a player goes out of our range!
actor->extravalue1++; // This will store the angle of the last waypoint we touched. This will essentially be useful later on.
break;
}
}
if (!actor->target) // If we have no target, revert back to waypoint 0.
{
actor->extravalue1 = 0;
P_SetTarget(&actor->target, actor->tracer);
}
}
else // if our target ISN'T a waypoint, then it can only be a player.
{
if (!P_CheckSight(actor, actor->target) || R_PointToDist2(actor->x, actor->y, actor->target->x, actor->target->y) > 1024<<FRACBITS)
P_SetTarget(&actor->target, actor->hnext);
}
}
}
void A_FlameParticle(mobj_t *actor)
{
fixed_t rad = actor->radius>>FRACBITS, hei = actor->radius>>FRACBITS;
mobj_t *par;
#ifdef HAVE_BLUA
if (LUA_CallAction("A_FlameParticle", actor))
return;
#endif
par = P_SpawnMobj(
actor->x + (P_RandomRange(-rad, rad)<<FRACBITS),
actor->y + (P_RandomRange(-rad, rad)<<FRACBITS),
actor->z + (P_RandomRange(hei/2, hei)<<FRACBITS),
actor->info->painchance);
par->momz = actor->scale<<1;
}
//}
// Function: A_OrbitNights
@ -9736,6 +10341,8 @@ void A_SetScale(mobj_t *actor)
return;
}
locvar1 = FixedMul(locvar1, mapheaderinfo[gamemap-1]->mobj_scale); // SRB2Kart
target->destscale = locvar1; // destination scale
if (!(locvar2 & 65535))
P_SetScale(target, locvar1); // this instantly changes current scale to var1 if used, if not destscale will alter scale to var1 anyway
@ -10564,4 +11171,6 @@ void A_SpawnFreshCopy(mobj_t *actor)
if (newObject->info->seesound)
S_StartSound(newObject, newObject->info->seesound);
newObject->color = actor->color; // SRB2Kart
}

View File

@ -3003,6 +3003,7 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover)
fixed_t topz;
fixed_t a, b, c;
mobjtype_t type = MT_ROCKCRUMBLE1;
const fixed_t spacing = 48*mapheaderinfo[gamemap-1]->mobj_scale;
// If the control sector has a special
// of Section3:7-15, use the custom debris.
@ -3034,16 +3035,16 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover)
rightx = sec->lines[rightmostvertex]->v1->x;
topy = sec->lines[topmostvertex]->v1->y-(16<<FRACBITS);
bottomy = sec->lines[bottommostvertex]->v1->y;
topz = *rover->topheight-(16<<FRACBITS);
topz = *rover->topheight-(spacing/2);
for (a = leftx; a < rightx; a += (32<<FRACBITS))
for (a = leftx; a < rightx; a += spacing)
{
for (b = topy; b > bottomy; b -= (32<<FRACBITS))
for (b = topy; b > bottomy; b -= spacing)
{
if (R_PointInSubsector(a, b)->sector == sec)
{
mobj_t *spawned = NULL;
for (c = topz; c > *rover->bottomheight; c -= (32<<FRACBITS))
for (c = topz; c > *rover->bottomheight; c -= spacing)
{
spawned = P_SpawnMobj(a, b, c, type);
spawned->fuse = 3*TICRATE;

View File

@ -324,48 +324,10 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
return;
}
else if ((special->flags & MF_ENEMY) && !(special->flags & MF_MISSILE))
else if ((special->flags & MF_ENEMY) && !(special->flags & MF_MISSILE)
&& (special->type != MT_SPRINGSHELL)) // Kart: prevent random hits from these things
{
////////////////////////////////////////////////////////
/////ENEMIES!!//////////////////////////////////////////
////////////////////////////////////////////////////////
/*if (special->type == MT_GSNAPPER && !(((player->pflags & PF_NIGHTSMODE) && (player->pflags & PF_DRILLING))
|| player->powers[pw_invulnerability] || player->powers[pw_super])
&& toucher->z < special->z + special->height && toucher->z + toucher->height > special->z)
{
// Can only hit snapper from above
P_DamageMobj(toucher, special, special, 1);
}
else if (special->type == MT_SHARP
&& ((special->state == &states[special->info->xdeathstate]) || (toucher->z > special->z + special->height/2)))
{
// Cannot hit sharp from above or when red and angry
P_DamageMobj(toucher, special, special, 1);
}
else if (((player->pflags & PF_NIGHTSMODE) && (player->pflags & PF_DRILLING))
|| (player->pflags & (PF_JUMPED|PF_SPINNING|PF_GLIDING))
|| player->powers[pw_invulnerability] || player->powers[pw_super]) // Do you possess the ability to subdue the object?
{
if (P_MobjFlip(toucher)*toucher->momz < 0)
toucher->momz = -toucher->momz;
P_DamageMobj(special, toucher, toucher, 1);
}
else if (((toucher->z < special->z && !(toucher->eflags & MFE_VERTICALFLIP))
|| (toucher->z + toucher->height > special->z + special->height && (toucher->eflags & MFE_VERTICALFLIP))) // Flame is bad at logic - JTE
&& player->charability == CA_FLY
&& (player->powers[pw_tailsfly]
|| (toucher->state >= &states[S_PLAY_SPC1] && toucher->state <= &states[S_PLAY_SPC4]))) // Tails can shred stuff with his propeller.
{
if (P_MobjFlip(toucher)*toucher->momz < 0)
toucher->momz = -toucher->momz/2;
P_DamageMobj(special, toucher, toucher, 1);
}
// SRB2kart - Removed: No more fly states
else*/
P_DamageMobj(toucher, special, special, 1);
P_DamageMobj(toucher, special, special, 1);
return;
}
else if (special->flags & MF_FIRE)
@ -378,6 +340,16 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
// We now identify by object type, not sprite! Tails 04-11-2001
switch (special->type)
{
case MT_MEMENTOSTP: // Mementos teleport
// Teleport player to the other teleporter (special->target). We'll assume there's always only ever 2.
if (!special->target)
return; // foolproof crash prevention check!!!!!
P_TeleportMove(player->mo, special->target->x, special->target->y, special->target->z + (48<<FRACBITS));
player->mo->angle = special->target->angle;
P_SetObjectMomZ(player->mo, 12<<FRACBITS, false);
P_InstaThrust(player->mo, player->mo->angle, 20<<FRACBITS);
return;
case MT_FLOATINGITEM: // SRB2kart
if (!P_CanPickupItem(player, 3) || (player->kartstuff[k_itemamount] && player->kartstuff[k_itemtype] != special->threshold))
return;
@ -414,8 +386,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
P_SetTarget(&special->target, toucher);
P_KillMobj(special, toucher, toucher);
break;
case MT_FAKESHIELD: // SRB2kart
case MT_FAKEITEM:
case MT_EGGMANITEM_SHIELD: // SRB2kart
case MT_EGGMANITEM:
if ((special->target == toucher || special->target == toucher->target) && (special->threshold > 0))
return;
@ -484,13 +456,15 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
else
{
mobj_t *boom = P_SpawnMobj(special->target->x, special->target->y, special->target->z, MT_BOOMEXPLODE);
UINT8 ptadd = (K_IsPlayerWanted(player) ? 2 : 1);
boom->scale = special->target->scale;
boom->destscale = special->target->scale;
boom->momz = 5*FRACUNIT;
if (special->target->color)
boom->color = special->target->color;
else
boom->color = SKINCOLOR_RED;
boom->color = SKINCOLOR_KETCHUP;
S_StartSound(boom, special->info->attacksound);
if (player->kartstuff[k_bumper] == 1) // If you have only one bumper left, and see if it's a 1v1
@ -506,17 +480,20 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
}
if (numingame <= 2) // If so, then an extra karma point so they are 100% certain to switch places; it's annoying to end matches with a bomb kill
special->target->player->kartstuff[k_comebackpoints]++;
ptadd++;
}
special->target->player->kartstuff[k_comebackpoints] += 2 * (K_IsPlayerWanted(player) ? 2 : 1);
if (netgame && cv_hazardlog.value)
CONS_Printf(M_GetText("%s bombed %s!\n"), player_names[special->target->player-players], player_names[player-players]);
if (special->target->player->kartstuff[k_comebackpoints] >= 3)
special->target->player->kartstuff[k_comebackpoints] += ptadd;
if (ptadd > 1)
special->target->player->kartstuff[k_yougotem] = 2*TICRATE;
if (special->target->player->kartstuff[k_comebackpoints] >= 2)
K_StealBumper(special->target->player, player, true);
special->target->player->kartstuff[k_comebacktimer] = comebacktime;
K_ExplodePlayer(player, special->target);
K_ExplodePlayer(player, special->target, special);
}
}
else if (special->target->player->kartstuff[k_comebackmode] == 1 && P_CanPickupItem(player, 1))
@ -527,9 +504,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
special->target->player->kartstuff[k_comebackmode] = 0;
special->target->player->kartstuff[k_comebackpoints]++;
if (netgame && cv_hazardlog.value)
CONS_Printf(M_GetText("%s gave an item to %s.\n"), player_names[special->target->player-players], player_names[player-players]);
if (special->target->player->kartstuff[k_comebackpoints] >= 3)
if (special->target->player->kartstuff[k_comebackpoints] >= 2)
K_StealBumper(special->target->player, player, true);
special->target->player->kartstuff[k_comebacktimer] = comebacktime;
@ -539,6 +514,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
else if (special->target->player->kartstuff[k_comebackmode] == 2 && P_CanPickupItem(player, 2))
{
mobj_t *poof = P_SpawnMobj(special->x, special->y, special->z, MT_EXPLODE);
UINT8 ptadd = 1; // No WANTED bonus for tricking
S_StartSound(poof, special->info->seesound);
if (player->kartstuff[k_bumper] == 1) // If you have only one bumper left, and see if it's a 1v1
@ -553,17 +530,19 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
numingame++;
}
if (numingame <= 2) // If so, then an extra two karma points so they are 100% certain to switch places; it's annoying to end matches with a fake kill
special->target->player->kartstuff[k_comebackpoints] += 2;
if (numingame <= 2) // If so, then an extra karma point so they are 100% certain to switch places; it's annoying to end matches with a fake kill
ptadd++;
}
special->target->player->kartstuff[k_comebackmode] = 0;
special->target->player->kartstuff[k_comebackpoints]++;
special->target->player->kartstuff[k_comebackpoints] += ptadd;
if (netgame && cv_hazardlog.value)
CONS_Printf(M_GetText("%s gave an \"item\" to %s.\n"), player_names[special->target->player-players], player_names[player-players]);
if (special->target->player->kartstuff[k_comebackpoints] >= 3)
if (ptadd > 1)
special->target->player->kartstuff[k_yougotem] = 2*TICRATE;
if (special->target->player->kartstuff[k_comebackpoints] >= 2)
K_StealBumper(special->target->player, player, true);
special->target->player->kartstuff[k_comebacktimer] = comebacktime;
K_DropItems(player); //K_StripItems(player);
@ -583,6 +562,85 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
special->target->player->kartstuff[k_eggmanblame] = -1;
}
return;
case MT_SPB:
if ((special->target == toucher || special->target == toucher->target) && (special->threshold > 0))
return;
if (special->health <= 0 || toucher->health <= 0)
return;
if (!player->mo || player->spectator)
return;
if (special->tracer && toucher == special->tracer)
{
mobj_t *spbexplode;
S_StopSound(special); // Don't continue playing the gurgle or the siren
if (!player->kartstuff[k_invincibilitytimer] && !player->kartstuff[k_growshrinktimer])
{
K_DropHnextList(player);
K_StripItems(player);
//player->powers[pw_flashing] = 0;
}
spbexplode = P_SpawnMobj(toucher->x, toucher->y, toucher->z, MT_SPBEXPLOSION);
spbexplode->extravalue1 = 1; // Tell K_ExplodePlayer to use extra knockback
P_SetTarget(&spbexplode->target, special->target);
P_RemoveMobj(special);
}
else
K_SpinPlayer(player, special, 0, false);
return;
/*case MT_EERIEFOG:
special->frame &= ~FF_TRANS80;
special->frame |= FF_TRANS90;
return;*/
case MT_SMK_MOLE:
if (special->target && !P_MobjWasRemoved(special->target))
return;
if (special->health <= 0 || toucher->health <= 0)
return;
if (!player->mo || player->spectator)
return;
// kill
if (player->kartstuff[k_invincibilitytimer] > 0 || player->kartstuff[k_growshrinktimer] > 0)
{
P_KillMobj(special, toucher, toucher);
return;
}
// no interaction
if (player->powers[pw_flashing] > 0 || player->kartstuff[k_hyudorotimer] > 0
|| player->kartstuff[k_squishedtimer] > 0 || player->kartstuff[k_spinouttimer] > 0)
return;
// attach to player!
P_SetTarget(&special->target, toucher);
S_StartSound(special, sfx_s1a2);
return;
case MT_CDUFO: // SRB2kart
if (special->fuse || !P_CanPickupItem(player, 1) || (G_BattleGametype() && player->kartstuff[k_bumper] <= 0))
return;
player->kartstuff[k_itemroulette] = 1;
player->kartstuff[k_roulettetype] = 1;
S_StartSound(toucher, sfx_cdfm73); // they don't make this sound in the original game but it's nice to have a "reward" for good play
//special->momx = special->momy = special->momz = 0;
special->momz = -(3*special->scale)/2;
//P_SetTarget(&special->target, toucher);
special->fuse = 2*TICRATE;
break;
case MT_BALLOON: // SRB2kart
P_SetObjectMomZ(toucher, 20<<FRACBITS, false);
break;
// ***************************************** //
// Rings, coins, spheres, weapon panels, etc //
@ -1667,199 +1725,6 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
}
}
//
/** Prints death messages relating to a dying or hit player.
*
* \param player Affected player.
* \param inflictor The attack weapon used, can be NULL.
* \param source The attacker, can be NULL.
*/
static void P_HitDeathMessages(player_t *player, mobj_t *inflictor, mobj_t *source)
{
const char *str = NULL;
boolean deathonly = false;
boolean deadsource = false;
boolean deadtarget = false;
// player names complete with control codes
char targetname[MAXPLAYERNAME+4];
char sourcename[MAXPLAYERNAME+4];
if (G_RaceGametype())
return; // Not in coop, etc.
if (!player)
return; // Impossible!
if (player->spectator)
return; // No messages for dying (crushed) spectators.
if (!netgame)
return; // Presumably it's obvious what's happening in splitscreen.
#ifdef HAVE_BLUA
if (LUAh_HurtMsg(player, inflictor, source))
return;
#endif
deadtarget = (player->health <= 0);
// Target's name
snprintf(targetname, sizeof(targetname), "%s%s%s",
CTFTEAMCODE(player),
player_names[player - players],
CTFTEAMENDCODE(player));
if (source)
{
// inflictor shouldn't be NULL if source isn't
I_Assert(inflictor != NULL);
if (source->player)
{
// Source's name (now that we know there is one)
snprintf(sourcename, sizeof(sourcename), "%s%s%s",
CTFTEAMCODE(source->player),
player_names[source->player - players],
CTFTEAMENDCODE(source->player));
// We don't care if it's us.
// "Player 1's [redacted] killed Player 1."
if (source->player->playerstate == PST_DEAD && source->player != player &&
(inflictor->flags2 & MF2_BEYONDTHEGRAVE))
deadsource = true;
if (inflictor->flags & MF_PUSHABLE)
{
str = M_GetText("%s%s's playtime with heavy objects %s %s.\n");
}
else switch (inflictor->type)
{
case MT_PLAYER:
if ((inflictor->player->powers[pw_shield] & SH_NOSTACK) == SH_BOMB)
str = M_GetText("%s%s's armageddon blast %s %s.\n");
else if (inflictor->player->powers[pw_invulnerability])
str = M_GetText("%s%s's invincibility aura %s %s.\n");
else if (inflictor->player->powers[pw_super])
str = M_GetText("%s%s's super aura %s %s.\n");
else
str = M_GetText("%s%s's tagging hand %s %s.\n");
break;
case MT_SPINFIRE:
str = M_GetText("%s%s's elemental fire trail %s %s.\n");
break;
case MT_THROWNBOUNCE:
str = M_GetText("%s%s's bounce ring %s %s.\n");
break;
case MT_THROWNINFINITY:
str = M_GetText("%s%s's infinity ring %s %s.\n");
break;
case MT_THROWNAUTOMATIC:
str = M_GetText("%s%s's automatic ring %s %s.\n");
break;
case MT_THROWNSCATTER:
str = M_GetText("%s%s's scatter ring %s %s.\n");
break;
// TODO: For next two, figure out how to determine if it was a direct hit or splash damage. -SH
case MT_THROWNEXPLOSION:
str = M_GetText("%s%s's explosion ring %s %s.\n");
break;
case MT_THROWNGRENADE:
str = M_GetText("%s%s's grenade ring %s %s.\n");
break;
case MT_REDRING:
if (inflictor->flags2 & MF2_RAILRING)
str = M_GetText("%s%s's rail ring %s %s.\n");
else
str = M_GetText("%s%s's thrown ring %s %s.\n");
break;
default:
str = M_GetText("%s%s %s %s.\n");
break;
}
CONS_Printf(str,
deadsource ? M_GetText("The late ") : "",
sourcename,
deadtarget ? M_GetText("killed") : M_GetText("hit"),
targetname);
return;
}
else switch (source->type)
{
case MT_NULL:
switch(source->threshold)
{
case 42:
deathonly = true;
str = M_GetText("%s drowned.\n");
break;
case 43:
str = M_GetText("%s was %s by spikes.\n");
break;
case 44:
deathonly = true;
str = M_GetText("%s was crushed.\n");
break;
}
break;
case MT_EGGMANICO:
case MT_EGGMANBOX:
str = M_GetText("%s was %s by Eggman's nefarious TV magic.\n");
break;
case MT_SPIKE:
str = M_GetText("%s was %s by spikes.\n");
break;
default:
str = M_GetText("%s was %s by an environmental hazard.\n");
break;
}
}
else
{
// null source, environment kills
// TERRIBLE HACK for hit damage because P_DoPlayerPain moves the player...
// I'll put it back, I promise!
player->mo->z -= player->mo->momz+1;
if (P_PlayerTouchingSectorSpecial(player, 1, 2))
str = M_GetText("%s was %s by chemical water.\n");
else if (P_PlayerTouchingSectorSpecial(player, 1, 3))
str = M_GetText("%s was %s by molten lava.\n");
else if (P_PlayerTouchingSectorSpecial(player, 1, 4))
str = M_GetText("%s was %s by electricity.\n");
else if (deadtarget)
{
deathonly = true;
if (P_PlayerTouchingSectorSpecial(player, 1, 6)
|| P_PlayerTouchingSectorSpecial(player, 1, 7))
str = M_GetText("%s fell into a bottomless pit.\n");
else if (P_PlayerTouchingSectorSpecial(player, 1, 12))
str = M_GetText("%s asphyxiated in space.\n");
else
str = M_GetText("%s died.\n");
}
if (!str)
str = M_GetText("%s was %s by an environmental hazard.\n");
player->mo->z += player->mo->momz+1;
}
if (!str) // Should not happen! Unless we missed catching something above.
return;
// Don't log every hazard hit if they don't want us to.
if (!deadtarget && !cv_hazardlog.value)
return;
if (deathonly)
{
if (!deadtarget)
return;
CONS_Printf(str, targetname);
}
else
CONS_Printf(str, targetname, deadtarget ? M_GetText("killed") : M_GetText("hit"));
}
/** Checks if the level timer is over the timelimit and the round should end,
* unless you are in overtime. In which case leveltime may stretch out beyond
* timelimitintics and overtime's status will be checked here each tick.
@ -2150,7 +2015,7 @@ boolean P_CheckRacers(void)
numplayersingame++;
}
if (numplayersingame > 1) // if there's more than one player in-game, this is safe to do
if (numplayersingame > 1 && nospectategrief > 0 && numplayersingame >= nospectategrief) // prevent spectate griefing
{
// check if we just got unlucky and there was only one guy who was a problem
for (j = i+1; j < MAXPLAYERS; j++)
@ -2200,8 +2065,8 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source)
&& !(target->type == MT_ORBINAUT || target->type == MT_ORBINAUT_SHIELD
|| target->type == MT_JAWZ || target->type == MT_JAWZ_DUD || target->type == MT_JAWZ_SHIELD
|| target->type == MT_BANANA || target->type == MT_BANANA_SHIELD
|| target->type == MT_FAKEITEM || target->type == MT_FAKESHIELD
|| target->type == MT_BALLHOG)) // kart dead items
|| target->type == MT_EGGMANITEM || target->type == MT_EGGMANITEM_SHIELD
|| target->type == MT_BALLHOG || target->type == MT_SPB)) // kart dead items
target->flags |= MF_NOGRAVITY; // Don't drop Tails 03-08-2000
else
target->flags &= ~MF_NOGRAVITY; // lose it if you for whatever reason have it, I'm looking at you shields
@ -2224,7 +2089,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source)
// I wish I knew a better way to do this
if (target->target && target->target->player && target->target->player->mo)
{
if (target->target->player->kartstuff[k_eggmanheld] && target->type == MT_FAKESHIELD)
if (target->target->player->kartstuff[k_eggmanheld] && target->type == MT_EGGMANITEM_SHIELD)
target->target->player->kartstuff[k_eggmanheld] = 0;
if (target->target->player->kartstuff[k_itemheld])
@ -2554,8 +2419,12 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source)
break;
case MT_PLAYER:
target->fuse = TICRATE*3; // timer before mobj disappears from view (even if not an actual player)
target->momx = target->momy = target->momz = 0;
if (target->player && target->player->pflags & PF_TIMEOVER)
break;
target->fuse = TICRATE*3; // timer before mobj disappears from view (even if not an actual player)
if (!(source && source->type == MT_NULL && source->threshold == 42)) // Don't jump up when drowning
P_SetObjectMomZ(target, 14*FRACUNIT, false);
@ -2566,6 +2435,21 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source)
else
P_PlayDeathSound(target);
break;
// SRB2Kart:
case MT_SMK_ICEBLOCK:
{
mobj_t *cur = target->hnext;
while (cur && !P_MobjWasRemoved(cur))
{
P_SetMobjState(cur, S_SMK_ICEBLOCK2);
cur = cur->hnext;
}
target->fuse = 10;
S_StartSound(target, sfx_s3k80);
}
break;
default:
break;
}
@ -2626,6 +2510,40 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source)
target->z += P_MobjFlip(target)*20*target->scale;
}
// kill tracer
if (target->type == MT_FROGGER)
{
if (target->tracer && !P_MobjWasRemoved(target->tracer))
P_KillMobj(target->tracer, inflictor, source);
}
if (target->type == MT_FROGGER || target->type == MT_ROBRA_HEAD || target->type == MT_BLUEROBRA_HEAD) // clean hnext list
{
mobj_t *cur = target->hnext;
while (cur && !P_MobjWasRemoved(cur))
{
P_KillMobj(cur, inflictor, source);
cur = cur->hnext;
}
}
// Bounce up on death
if (target->type == MT_SMK_PIPE || target->type == MT_SMK_MOLE || target->type == MT_SMK_THWOMP)
{
target->flags &= (~MF_NOGRAVITY);
if (target->eflags & MFE_VERTICALFLIP)
target->z -= target->height;
else
target->z += target->height;
S_StartSound(target, target->info->deathsound);
P_SetObjectMomZ(target, 8<<FRACBITS, false);
if (inflictor)
P_InstaThrust(target, R_PointToAngle2(inflictor->x, inflictor->y, target->x, target->y)+ANGLE_90, 16<<FRACBITS);
}
if (target->type == MT_SPIKE && inflictor && target->info->deathstate != S_NULL)
{
const fixed_t x=target->x,y=target->y,z=target->z;
@ -2819,7 +2737,6 @@ static inline boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *sou
/*if (source->player->pflags & PF_TAGIT && !(player->pflags & PF_TAGIT))
{
P_AddPlayerScore(source->player, 1); //award points to tagger.
P_HitDeathMessages(player, inflictor, source);
if (gametype == GT_TAG) //survivor
{
@ -2923,6 +2840,7 @@ static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage)
// Get rid of shield
player->powers[pw_shield] = SH_NONE;
player->mo->color = player->skincolor;
player->mo->colorized = false;
// Get rid of emeralds
player->powers[pw_emeralds] = 0;
@ -2932,6 +2850,7 @@ static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage)
P_ResetPlayer(player);
P_SetPlayerMobjState(player->mo, player->mo->info->deathstate);
/*if (gametype == GT_CTF && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG)))
{
P_PlayerFlagBurst(player, false);
@ -2958,6 +2877,17 @@ static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage)
HU_DoCEcho(va("%s\\is no longer super.\\\\\\\\", player_names[player-players]));
}*/
if (player->pflags & PF_TIMEOVER)
{
mobj_t *boom;
player->mo->flags |= (MF_NOGRAVITY|MF_NOCLIP);
player->mo->flags2 |= MF2_DONTDRAW;
boom = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_FZEROBOOM);
boom->scale = player->mo->scale;
boom->angle = player->mo->angle;
P_SetTarget(&boom->target, player->mo);
}
if (G_BattleGametype())
{
if (player->kartstuff[k_bumper] > 0)
@ -3329,7 +3259,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
if (!player->kartstuff[k_invincibilitytimer] && player->kartstuff[k_growshrinktimer] <= 0)
{
// Start shrinking!
player->mo->scalespeed = FRACUNIT/TICRATE;
player->mo->scalespeed = mapheaderinfo[gamemap-1]->mobj_scale/TICRATE;
player->mo->destscale = 6*(mapheaderinfo[gamemap-1]->mobj_scale)/8;
if (cv_kartdebugshrink.value && !player->bot)
player->mo->destscale = 6*player->mo->destscale/8;
@ -3355,8 +3285,6 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
player->kartstuff[k_growshrinktimer] = 2;
}
player->kartstuff[k_sneakertimer] = 0;
// Invincible or not, we still need this.
//P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_LIGHTNING);
S_StartSound(player->mo, sfx_kc59);
return true;
}
@ -3392,7 +3320,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
{
if (inflictor && (inflictor->type == MT_ORBINAUT || inflictor->type == MT_ORBINAUT_SHIELD
|| inflictor->type == MT_JAWZ || inflictor->type == MT_JAWZ_SHIELD || inflictor->type == MT_JAWZ_DUD
|| inflictor->player))
|| inflictor->type == MT_SMK_THWOMP || inflictor->player))
{
player->kartstuff[k_sneakertimer] = 0;
K_SpinPlayer(player, source, 1, false);
@ -3509,8 +3437,6 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
if (player->health < 0)
player->health = 0;
P_HitDeathMessages(player, inflictor, source);
P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2);
}

View File

@ -663,10 +663,66 @@ static boolean PIT_CheckThing(mobj_t *thing)
}
}
// SRB2kart 011617 - Colission code for kart items //{
// SRB2kart 011617 - Colission[sic] code for kart items //{
if (thing->type == MT_SMK_ICEBLOCK)
{
// see if it went over / under
if (tmthing->z > thing->z + thing->height)
return true; // overhead
if (tmthing->z + tmthing->height < thing->z)
return true; // underneath
if (!(tmthing->flags & MF_SOLID || tmthing->flags & MF_SHOOTABLE || tmthing->flags & MF_BOUNCE))
return true;
if (!(tmthing->health))
return true;
if (tmthing->type == MT_BANANA || tmthing->type == MT_BANANA_SHIELD
|| tmthing->type == MT_EGGMANITEM || tmthing->type == MT_EGGMANITEM_SHIELD
|| tmthing->type == MT_SSMINE || tmthing->type == MT_SSMINE_SHIELD
|| tmthing->type == MT_ORBINAUT_SHIELD || tmthing->type == MT_JAWZ_SHIELD)
return false;
if (thing->health)
P_KillMobj(thing, tmthing, tmthing);
/*if (tmthing->player && (tmthing->player->kartstuff[k_invincibilitytimer] > 0
|| tmthing->player->kartstuff[k_growshrinktimer] > 0))
return true;*/
K_KartBouncing(tmthing, thing, false, true);
return false;
}
// Push fakes out of other items
if (tmthing->type == MT_EGGMANITEM && (thing->type == MT_RANDOMITEM || thing->type == MT_EGGMANITEM))
{
// see if it went over / under
if (tmthing->z > thing->z + thing->height)
return true; // overhead
if (tmthing->z + tmthing->height < thing->z)
return true; // underneath
P_InstaThrust(tmthing, R_PointToAngle2(thing->x, thing->y, tmthing->x, tmthing->y), thing->radius/4);
return true;
}
else if (thing->type == MT_EGGMANITEM && (tmthing->type == MT_RANDOMITEM || tmthing->type == MT_EGGMANITEM))
{
// see if it went over / under
if (tmthing->z > thing->z + thing->height)
return true; // overhead
if (tmthing->z + tmthing->height < thing->z)
return true; // underneath
P_InstaThrust(thing, R_PointToAngle2(tmthing->x, tmthing->y, thing->x, thing->y), tmthing->radius/4);
return true;
}
if (tmthing->type == MT_RANDOMITEM)
return true;
if (tmthing->type == MT_ORBINAUT || tmthing->type == MT_JAWZ || tmthing->type == MT_JAWZ_DUD
|| tmthing->type == MT_ORBINAUT_SHIELD || tmthing->type == MT_JAWZ_SHIELD)
{
@ -824,7 +880,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (thing->type == MT_PLAYER && thing->player)
{
if (tmthing->state == &states[S_MINEEXPLOSION1])
K_ExplodePlayer(thing->player, tmthing->target);
K_ExplodePlayer(thing->player, tmthing->target, tmthing);
else
K_SpinPlayer(thing->player, tmthing->target, 0, false);
}
@ -1033,7 +1089,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
{
// Player Damage
if (thing->state == &states[S_MINEEXPLOSION1])
K_ExplodePlayer(tmthing->player, thing->target);
K_ExplodePlayer(tmthing->player, thing->target, thing);
else
K_SpinPlayer(tmthing->player, thing->target, 0, false);
@ -1077,7 +1133,8 @@ static boolean PIT_CheckThing(mobj_t *thing)
//}
if (thing->type == MT_FALLINGROCK || tmthing->type == MT_FALLINGROCK)
if ((thing->type == MT_FALLINGROCK && (tmthing->player || tmthing->type == MT_FALLINGROCK))
|| (tmthing->type == MT_FALLINGROCK && (thing->player || thing->type == MT_FALLINGROCK)))
{
// see if it went over / under
if (tmthing->z > thing->z + thing->height)
@ -1385,19 +1442,17 @@ static boolean PIT_CheckThing(mobj_t *thing)
// Make sure they aren't able to damage you ANYWHERE along the Z axis, you have to be TOUCHING the person.
&& !(thing->z + thing->height < tmthing->z || thing->z > tmthing->z + tmthing->height))
{
// SRB2kart - Squish!
if (tmthing->scale > thing->scale + (FRACUNIT/8))
if (tmthing->scale > thing->scale + (FRACUNIT/8)) // SRB2kart - Handle squishes first!
K_SquishPlayer(thing->player, tmthing);
else if (thing->scale > tmthing->scale + (FRACUNIT/8))
K_SquishPlayer(tmthing->player, thing);
// SRB2kart - Invincibility!
if (tmthing->player->kartstuff[k_invincibilitytimer] && !thing->player->kartstuff[k_invincibilitytimer])
else if (tmthing->player->kartstuff[k_invincibilitytimer] && !thing->player->kartstuff[k_invincibilitytimer]) // SRB2kart - Then invincibility!
P_DamageMobj(thing, tmthing, tmthing, 1);
else if (thing->player->kartstuff[k_invincibilitytimer] && !tmthing->player->kartstuff[k_invincibilitytimer])
P_DamageMobj(tmthing, thing, thing, 1);
if (G_BattleGametype() && (!G_GametypeHasTeams() || tmthing->player->ctfteam != thing->player->ctfteam))
/*if (G_BattleGametype() && (!G_GametypeHasTeams() || tmthing->player->ctfteam != thing->player->ctfteam))
{
if ((tmthing->player->powers[pw_invulnerability] || tmthing->player->powers[pw_super])
&& !thing->player->powers[pw_super])
@ -1415,7 +1470,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
P_DamageMobj(thing, tmthing, tmthing, 1);
else if ((thing->player->pflags & PF_TAGIT) && !(tmthing->player->pflags & PF_TAGIT))
P_DamageMobj(tmthing, thing, tmthing, 1);
}
}*/
}
// Force solid players in hide and seek to avoid corner stacking.
@ -1538,6 +1593,106 @@ static boolean PIT_CheckThing(mobj_t *thing)
return true;
}
else if (thing->type == MT_BLUEROBRA_HEAD || thing->type == MT_BLUEROBRA_JOINT)
{
// see if it went over / under
if (tmthing->z > thing->z + thing->height)
return true; // overhead
if (tmthing->z + tmthing->height < thing->z)
return true; // underneath
if (!thing->health)
return true; // dead
if (tmthing->player->kartstuff[k_invincibilitytimer] > 0
|| tmthing->player->kartstuff[k_growshrinktimer] > 0)
{
if (thing->type == MT_BLUEROBRA_JOINT)
P_KillMobj(thing->target, tmthing, tmthing);
else
P_KillMobj(thing, tmthing, tmthing);
return true;
}
else
{
K_KartBouncing(tmthing, thing, false, true);
return false;
}
}
else if (thing->type == MT_SMK_PIPE)
{
// see if it went over / under
if (tmthing->z > thing->z + thing->height)
return true; // overhead
if (tmthing->z + tmthing->height < thing->z)
return true; // underneath
if (!thing->health)
return true; // dead
if (tmthing->player->kartstuff[k_invincibilitytimer] > 0
|| tmthing->player->kartstuff[k_growshrinktimer] > 0)
{
P_KillMobj(thing, tmthing, tmthing);
return true; // kill
}
K_KartBouncing(tmthing, thing, false, true);
return false;
}
else if (thing->type == MT_SMK_THWOMP)
{
if (!thing->health)
return true; // dead
if (!thwompsactive)
return true; // not active yet
if ((tmthing->z < thing->z) && (thing->z >= thing->movefactor-(256<<FRACBITS)))
{
thing->extravalue1 = 1; // purposely try to stomp on players early
//S_StartSound(thing, sfx_s1bb);
}
// see if it went over / under
if (tmthing->z > thing->z + thing->height)
return true; // overhead
if (tmthing->z + tmthing->height < thing->z)
return true; // underneath
// kill
if (tmthing->player->kartstuff[k_invincibilitytimer] > 0
|| tmthing->player->kartstuff[k_growshrinktimer] > 0)
{
P_KillMobj(thing, tmthing, tmthing);
return true;
}
// continue to squish
if (tmthing->player->kartstuff[k_squishedtimer])
{
tmthing->player->kartstuff[k_squishedtimer] = 2*TICRATE;
tmthing->player->powers[pw_flashing] = K_GetKartFlashing(tmthing->player);
return true;
}
// no interaction
if (tmthing->player->powers[pw_flashing] > 0 || tmthing->player->kartstuff[k_hyudorotimer] > 0
|| tmthing->player->kartstuff[k_spinouttimer] > 0) //|| tmthing->player->kartstuff[k_squishedtimer] > 0
return true;
// collide
if (tmthing->z < thing->z && thing->momz < 0)
K_SquishPlayer(tmthing->player, thing);
else
{
if (thing->flags2 & MF2_AMBUSH)
P_DamageMobj(tmthing, thing, thing, 1);
K_KartBouncing(tmthing, thing, false, true);
}
return false;
}
else if (thing->flags & MF_SOLID)
{
// see if it went over / under
@ -1551,7 +1706,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
else
K_KartBouncing(tmthing, thing, false, true);
return true;
return false;
}
// Are you touching the side of the object you're interacting with?
else if (thing->z - FixedMul(FRACUNIT, thing->scale) <= tmthing->z + tmthing->height
@ -2381,6 +2536,11 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam)
|| (thiscam == &camera3 && (players[thirddisplayplayer].pflags & PF_NOCLIP))
|| (thiscam == &camera4 && (players[fourthdisplayplayer].pflags & PF_NOCLIP))
|| (leveltime < introtime))
#else
if ((thiscam == &camera && !(players[displayplayer].pflags & PF_TIMEOVER))
|| (thiscam == &camera2 && !(players[secondarydisplayplayer].pflags & PF_TIMEOVER))
|| (thiscam == &camera3 && !(players[thirddisplayplayer].pflags & PF_TIMEOVER))
|| (thiscam == &camera4 && !(players[fourthdisplayplayer].pflags & PF_TIMEOVER)))
#endif
{ // Noclipping player camera noclips too!!
floatok = true;
@ -3778,6 +3938,7 @@ void P_BouncePlayerMove(mobj_t *mo)
S_StartSound(mo, sfx_s3k49);
}
mo->player->kartstuff[k_pogospring] = 0; // Cancel pogo spring effect so you aren't shoved forward back into the wall you just bounced off
P_PlayerHitBounceLine(bestslideline);
mo->eflags |= MFE_JUSTBOUNCEDWALL;

File diff suppressed because it is too large Load Diff

View File

@ -1116,7 +1116,7 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
diff |= MD_SCALE;
if (mobj->destscale != mobj->scale)
diff |= MD_DSCALE;
if (mobj->scalespeed != FRACUNIT/12)
if (mobj->scalespeed != mapheaderinfo[gamemap-1]->mobj_scale/12)
diff2 |= MD2_SCALESPEED;
if (mobj == redflag)
@ -2123,7 +2123,7 @@ static void LoadMobjThinker(actionf_p1 thinker)
if (diff2 & MD2_SCALESPEED)
mobj->scalespeed = READFIXED(save_p);
else
mobj->scalespeed = FRACUNIT/12;
mobj->scalespeed = mapheaderinfo[gamemap-1]->mobj_scale/12;
if (diff2 & MD2_CUSVAL)
mobj->cusval = READINT32(save_p);
if (diff2 & MD2_CVMEM)
@ -3284,9 +3284,9 @@ static void P_NetArchiveMisc(void)
WRITEUINT32(save_p, wantedcalcdelay);
WRITEUINT32(save_p, indirectitemcooldown);
WRITEUINT32(save_p, spbincoming);
WRITEUINT8(save_p, spbplayer);
WRITEUINT32(save_p, mapreset);
WRITEUINT8(save_p, nospectategrief);
WRITEUINT8(save_p, thwompsactive);
// Is it paused?
if (paused)
@ -3390,9 +3390,9 @@ static inline boolean P_NetUnArchiveMisc(void)
wantedcalcdelay = READUINT32(save_p);
indirectitemcooldown = READUINT32(save_p);
spbincoming = READUINT32(save_p);
spbplayer = READUINT8(save_p);
mapreset = READUINT32(save_p);
nospectategrief = READUINT8(save_p);
thwompsactive = (boolean)READUINT8(save_p);
// Is it paused?
if (READUINT8(save_p) == 0x2f)

View File

@ -2209,7 +2209,7 @@ static void P_LevelInitStuff(void)
players[i].lives = cv_startinglives.value;
}
#else
players[i].lives = 1;
players[i].lives = 1; // SRB2Kart
#endif
players[i].realtime = countdown = countdown2 = 0;
@ -3023,9 +3023,9 @@ boolean P_SetupLevel(boolean skipprecip)
wantedcalcdelay = wantedfrequency*2;
indirectitemcooldown = 0;
spbincoming = 0;
spbplayer = 0;
mapreset = 0;
nospectategrief = 0;
thwompsactive = false;
// clear special respawning que
iquehead = iquetail = 0;
@ -3210,7 +3210,6 @@ boolean P_AddWadFile(const char *wadfilename, char **firstmapname)
HU_LoadGraphics();
ST_LoadGraphics();
ST_ReloadSkinFaceGraphics();
K_ReloadSkinIconGraphics();
//
// look for skins

View File

@ -36,6 +36,7 @@
#include "lua_hook.h" // LUAh_LinedefExecute
#include "k_kart.h" // SRB2kart
#include "console.h" // CON_LogMessage
#ifdef HW3SOUND
#include "hardware/hw3sound.h"
@ -3218,7 +3219,7 @@ void P_SetupSignExit(player_t *player)
// SRB2Kart: Set sign spinning variables
thing->movefactor = thing->z;
thing->z += (768<<FRACBITS) * P_MobjFlip(thing);
thing->z += (768*thing->scale) * P_MobjFlip(thing);
thing->movecount = 1;
++numfound;
@ -3246,7 +3247,7 @@ void P_SetupSignExit(player_t *player)
// SRB2Kart: Set sign spinning variables
thing->movefactor = thing->z;
thing->z += (768<<FRACBITS) * P_MobjFlip(thing);
thing->z += (768*thing->scale) * P_MobjFlip(thing);
thing->movecount = 1;
++numfound;
@ -3258,7 +3259,7 @@ void P_SetupSignExit(player_t *player)
// SRB2Kart: FINALLY, add in an alternative if no place is found
if (player->mo)
{
mobj_t *sign = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + (768<<FRACBITS), MT_SIGN);
mobj_t *sign = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + (768*mapheaderinfo[gamemap-1]->mobj_scale), MT_SIGN);
P_SetTarget(&sign->target, player->mo);
P_SetMobjState(sign, S_SIGN1);
@ -4022,7 +4023,7 @@ DoneSection2:
player->kartstuff[k_floorboost] = 3;
else
player->kartstuff[k_floorboost] = 2;
K_DoSneaker(player, false);
K_DoSneaker(player, 0);
}
break;
@ -4195,21 +4196,41 @@ DoneSection2:
{
if (player->starpostcount >= numstarposts/2) // srb2kart: must have touched *enough* starposts (was originally "(player->starpostnum == numstarposts)")
{
UINT8 i;
UINT8 nump = 0;
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator)
continue;
nump++;
}
player->laps++;
// Set up lap animation vars
if (nump > 1)
{
if (K_IsPlayerLosing(player))
player->kartstuff[k_laphand] = 3;
else
{
if (nump > 2 && player->kartstuff[k_position] == 1) // 1st place in 1v1 uses thumbs up
player->kartstuff[k_laphand] = 1;
else
player->kartstuff[k_laphand] = 2;
}
}
else
player->kartstuff[k_laphand] = 0; // No hands in FREE PLAY
player->kartstuff[k_lapanimation] = 80;
if (player->pflags & PF_NIGHTSMODE)
player->drillmeter += 48*20;
if (netgame)
{
if (player->laps >= (UINT8)cv_numlaps.value)
CONS_Printf(M_GetText("%s has finished the race.\n"), player_names[player-players]);
else if (player->laps == (UINT8)(cv_numlaps.value - 1))
CONS_Printf("%s started the final lap\n", player_names[player-players]);
else
CONS_Printf(M_GetText("%s started lap %u\n"), player_names[player-players], (UINT32)player->laps+1);
}
if (netgame && player->laps >= (UINT8)cv_numlaps.value)
CON_LogMessage(va(M_GetText("%s has finished the race.\n"), player_names[player-players]));
// SRB2Kart: save best lap for record attack
if (player == &players[consoleplayer])
@ -4235,12 +4256,17 @@ DoneSection2:
S_StartSound(NULL, sfx_s221);
}
//
//player->starpostangle = player->starposttime = player->starpostnum = 0;
//player->starpostx = player->starposty = player->starpostz = 0;
// Play the starpost sound for 'consistency'
// S_StartSound(player->mo, sfx_strpst);
// Figure out how many are playing on the last lap, to prevent spectate griefing
if (!nospectategrief && player->laps >= (UINT8)(cv_numlaps.value - 1))
nospectategrief = nump;
thwompsactive = true; // Lap 2 effects
}
else if (player->starpostnum)
{

View File

@ -678,38 +678,6 @@ void P_Ticker(boolean run)
if (countdown2)
countdown2--;
if (spbincoming && --spbincoming <= 0)
{
UINT8 best = 0;
SINT8 hurtthisguy = -1;
spbincoming = 0;
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator)
continue;
if (!players[i].mo)
continue;
if (players[i].exiting)
continue;
if (best <= 0 || players[i].kartstuff[k_position] < best)
{
best = players[i].kartstuff[k_position];
hurtthisguy = i;
}
}
if (hurtthisguy != -1)
{
players[hurtthisguy].kartstuff[k_deathsentence] = (2*TICRATE)+1;
S_StartSound(players[hurtthisguy].mo, sfx_kc57);
}
}
if (indirectitemcooldown)
indirectitemcooldown--;

View File

@ -45,6 +45,7 @@
// SRB2kart
#include "m_cond.h" // M_UpdateUnlockablesAndExtraEmblems
#include "k_kart.h"
#include "console.h" // CON_LogMessage
#ifdef HW3SOUND
#include "hardware/hw3sound.h"
@ -845,7 +846,8 @@ void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor)
fixed_t fallbackspeed;
if (inflictor && (inflictor->type != MT_PLAYER && inflictor->type != MT_ORBINAUT && inflictor->type != MT_ORBINAUT_SHIELD
&& inflictor->type != MT_JAWZ && inflictor->type != MT_JAWZ_DUD && inflictor->type != MT_JAWZ_SHIELD))
&& inflictor->type != MT_JAWZ && inflictor->type != MT_JAWZ_DUD && inflictor->type != MT_JAWZ_SHIELD
&& inflictor->type != MT_SMK_THWOMP))
{
if (player->mo->eflags & MFE_VERTICALFLIP)
player->mo->z--;
@ -1139,34 +1141,57 @@ boolean P_EndingMusic(player_t *player)
{
char buffer[9];
boolean looping = true;
INT32 bestlocalpos;
player_t *bestlocalplayer;
if (!P_IsLocalPlayer(player)) // Only applies to a local player
return false;
// Event - Level Finish
if (splitscreen
&& (players[displayplayer].exiting
|| players[secondarydisplayplayer].exiting
|| ((splitscreen < 2) && players[thirddisplayplayer].exiting)
|| ((splitscreen < 3) && players[fourthdisplayplayer].exiting)))
// Check for if this is valid or not
if (splitscreen)
{
sprintf(buffer, "k*ok");
if (!((players[displayplayer].exiting || (players[displayplayer].pflags & PF_TIMEOVER))
|| (players[secondarydisplayplayer].exiting || (players[secondarydisplayplayer].pflags & PF_TIMEOVER))
|| ((splitscreen < 2) && (players[thirddisplayplayer].exiting || (players[thirddisplayplayer].pflags & PF_TIMEOVER)))
|| ((splitscreen < 3) && (players[fourthdisplayplayer].exiting || (players[fourthdisplayplayer].pflags & PF_TIMEOVER)))))
return false;
bestlocalplayer = &players[displayplayer];
bestlocalpos = ((players[displayplayer].pflags & PF_TIMEOVER) ? MAXPLAYERS+1 : players[displayplayer].kartstuff[k_position]);
#define setbests(p) \
if (((players[p].pflags & PF_TIMEOVER) ? MAXPLAYERS+1 : players[p].kartstuff[k_position]) < bestlocalpos) \
{ \
bestlocalplayer = &players[p]; \
bestlocalpos = ((players[p].pflags & PF_TIMEOVER) ? MAXPLAYERS+1 : players[p].kartstuff[k_position]); \
}
else if (player->pflags & PF_TIMEOVER) // || !player->lives) -- outta lives, outta time
{
sprintf(buffer, "k*lose");
setbests(secondarydisplayplayer);
if (splitscreen > 1)
setbests(thirddisplayplayer);
if (splitscreen > 2)
setbests(fourthdisplayplayer);
#undef setbests
}
else if (player->exiting)
else
{
if (player->kartstuff[k_position] == 1)
if (!(player->exiting || (player->pflags & PF_TIMEOVER)))
return false;
bestlocalplayer = player;
bestlocalpos = ((player->pflags & PF_TIMEOVER) ? MAXPLAYERS+1 : player->kartstuff[k_position]);
}
if (G_RaceGametype() && bestlocalpos == MAXPLAYERS+1)
sprintf(buffer, "k*fail"); // F-Zero death results theme
else
{
if (bestlocalpos == 1)
sprintf(buffer, "k*win");
else if (K_IsPlayerLosing(player))
else if (K_IsPlayerLosing(bestlocalplayer))
sprintf(buffer, "k*lose");
else
sprintf(buffer, "k*ok");
}
else
return false;
S_SpeedMusic(1.0f);
@ -1193,6 +1218,8 @@ void P_RestoreMusic(player_t *player)
if (!P_IsLocalPlayer(player)) // Only applies to a local player
return;
S_SpeedMusic(1.0f);
// Event - HERE COMES A NEW CHALLENGER
if (mapreset)
{
@ -1204,24 +1231,58 @@ void P_RestoreMusic(player_t *player)
if (P_EndingMusic(player))
return;
S_SpeedMusic(1.0f);
// Event - Level Start
if (leveltime < (starttime + (TICRATE/2)))
S_ChangeMusicInternal((encoremode ? "estart" : "kstart"), false); //S_StopMusic();
else // see also where time overs are handled - search for "lives = 2" in this file
{
INT32 wantedmus = 0; // 0 is level music, 1 is invincibility, 2 is grow
if (splitscreen)
{
INT32 bestlocaltimer = 1;
#define setbests(p) \
if (players[p].playerstate == PST_LIVE) \
{ \
if (players[p].kartstuff[k_growshrinktimer] > bestlocaltimer) \
{ wantedmus = 2; bestlocaltimer = players[p].kartstuff[k_growshrinktimer]; } \
else if (players[p].kartstuff[k_invincibilitytimer] > bestlocaltimer) \
{ wantedmus = 1; bestlocaltimer = players[p].kartstuff[k_invincibilitytimer]; } \
}
setbests(displayplayer);
setbests(secondarydisplayplayer);
if (splitscreen > 1)
setbests(thirddisplayplayer);
if (splitscreen > 2)
setbests(fourthdisplayplayer);
#undef setbests
}
else
{
if (player->playerstate == PST_LIVE)
{
if (player->kartstuff[k_growshrinktimer] > 1)
wantedmus = 2;
else if (player->kartstuff[k_invincibilitytimer] > 1)
wantedmus = 1;
}
}
// Item - Grow
if (player->kartstuff[k_growshrinktimer] > 1 && player->playerstate == PST_LIVE)
if (wantedmus == 2)
S_ChangeMusicInternal("kgrow", true);
// Item - Invincibility
else if (player->kartstuff[k_invincibilitytimer] > 1 && player->playerstate == PST_LIVE)
else if (wantedmus == 1)
S_ChangeMusicInternal("kinvnc", true);
else
{
#if 0
// Event - Final Lap
// Still works for GME, but disabled for consistency
if (G_RaceGametype() && player->laps >= (UINT8)(cv_numlaps.value - 1))
S_SpeedMusic(1.2f);
#endif
S_ChangeMusic(mapmusname, mapmusflags, true);
}
}
@ -6628,13 +6689,24 @@ static void P_MovePlayer(player_t *player)
if (player->mo->state != &states[S_KART_SQUISH])
P_SetPlayerMobjState(player->mo, S_KART_SQUISH);
}
else if (player->kartstuff[k_spinouttimer] > 0 || player->pflags & PF_SLIDING)
else if (player->pflags & PF_SLIDING)
{
if (player->mo->state != &states[S_KART_SPIN])
P_SetPlayerMobjState(player->mo, S_KART_SPIN);
player->frameangle -= ANGLE_22h;
}
else if (player->kartstuff[k_spinouttimer] > 0)
{
INT32 speed = max(1, min(8, player->kartstuff[k_spinouttimer]/8));
if (player->mo->state != &states[S_KART_SPIN])
P_SetPlayerMobjState(player->mo, S_KART_SPIN);
if (speed == 1 && abs(player->mo->angle - player->frameangle) < ANGLE_22h)
player->frameangle = player->mo->angle; // Face forward at the end of the animation
else
player->frameangle -= (ANGLE_11hh * speed);
}
else if (player->powers[pw_nocontrol] && player->pflags & PF_SKIDDOWN)
{
if (player->mo->state != &states[S_KART_SPIN])
@ -7311,7 +7383,7 @@ static void P_DoZoomTube(player_t *player)
fixed_t dist;
boolean reverse;
player->mo->height = P_GetPlayerSpinHeight(player);
//player->mo->height = P_GetPlayerSpinHeight(player);
if (player->speed > 0)
reverse = false;
@ -7416,6 +7488,11 @@ static void P_DoZoomTube(player_t *player)
else if (player == &players[fourthdisplayplayer])
localangle4 = player->mo->angle;
}
#if 0
if (player->mo->state != &states[S_KART_SPIN])
P_SetPlayerMobjState(player->mo, S_KART_SPIN);
player->frameangle -= ANGLE_22h;
#endif
}
//
@ -7642,7 +7719,8 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius)
mo = (mobj_t *)think;
if (!(mo->flags & MF_SHOOTABLE) && !(mo->type == MT_EGGGUARD || mo->type == MT_MINUS))
if (!(mo->flags & MF_SHOOTABLE) && !(mo->type == MT_EGGGUARD || mo->type == MT_MINUS
|| mo->type == MT_SPB)) // Don't want to give SPB MF_SHOOTABLE, to ensure it's undamagable through other means
continue;
if (mo->flags & MF_MONITOR)
@ -7670,8 +7748,8 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius)
if (mo->type == MT_ORBINAUT || mo->type == MT_JAWZ || mo->type == MT_JAWZ_DUD
|| mo->type == MT_ORBINAUT_SHIELD || mo->type == MT_JAWZ_SHIELD
|| mo->type == MT_BANANA || mo->type == MT_BANANA_SHIELD
|| mo->type == MT_FAKEITEM || mo->type == MT_FAKESHIELD
|| mo->type == MT_BALLHOG)
|| mo->type == MT_EGGMANITEM || mo->type == MT_EGGMANITEM_SHIELD
|| mo->type == MT_BALLHOG || mo->type == MT_SPB)
{
if (mo->eflags & MFE_VERTICALFLIP)
mo->z -= mo->height;
@ -7685,6 +7763,9 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius)
P_InstaThrust(mo, R_PointToAngle2(inflictor->x, inflictor->y, mo->x, mo->y)+ANGLE_90, 16*FRACUNIT);
}
if (mo->type == MT_SPB) // If you destroy a SPB, you don't get the luxury of a cooldown.
indirectitemcooldown = 0;
if (mo == inflictor) // Don't nuke yourself, dummy!
continue;
@ -7859,25 +7940,22 @@ void P_FindEmerald(void)
//
static void P_DeathThink(player_t *player)
{
//ticcmd_t *cmd = &player->cmd;
//player->deltaviewheight = 0;
if (player->pflags & PF_TIMEOVER)
{
player->kartstuff[k_timeovercam]++;
if (player->mo)
{
player->mo->flags |= (MF_NOGRAVITY|MF_NOCLIP);
player->mo->flags2 |= MF2_DONTDRAW;
}
}
else
player->kartstuff[k_timeovercam] = 0;
if (player->deadtimer < INT32_MAX)
player->deadtimer++;
// continue logic
/*if (!(netgame || multiplayer) && player->lives <= 0)
{
if (player->deadtimer > TICRATE && (cmd->buttons & BT_BRAKE || cmd->buttons & BT_ACCELERATE || cmd->buttons & BT_DRIFT) && player->continues > 0)
G_UseContinue();
else if (player->deadtimer >= gameovertics)
G_UseContinue(); // Even if we don't have one this handles ending the game
}*/
// Force respawn if idle for more than 30 seconds in shooter modes.
/*if (player->deadtimer > 30*TICRATE && !G_RaceGametype())
player->playerstate = PST_REBORN;
else if (player->lives > 0 && !G_IsSpecialStage(gamemap)*/
if (player->lives > 0 /*&& leveltime >= starttime*/) // *could* you respawn?
{
// SRB2kart - spawn automatically after 1 second
@ -7886,55 +7964,6 @@ static void P_DeathThink(player_t *player)
: TICRATE)) // don't let them change it in record attack
player->playerstate = PST_REBORN;
}
/*else if ((netgame || multiplayer) && player->deadtimer == 8*TICRATE)
{
// In a net/multiplayer game, and out of lives
if (gametype == GT_COMPETITION)
{
INT32 i;
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && !players[i].exiting && players[i].lives > 0)
break;
if (i == MAXPLAYERS)
{
// Everyone's either done with the race, or dead.
if (!countdown2 || countdown2 > 1*TICRATE)
countdown2 = 1*TICRATE;
}
}
// In a coop game, and out of lives
if (gametype == GT_COOP)
{
INT32 i;
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && (players[i].exiting || players[i].lives > 0))
break;
if (i == MAXPLAYERS)
{
// They're dead, Jim.
//nextmapoverride = spstage_start;
nextmapoverride = gamemap;
countdown2 = 1*TICRATE;
skipstats = true;
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i])
players[i].score = 0;
}
//emeralds = 0;
tokenbits = 0;
tokenlist = 0;
token = 0;
}
}
}*/
// Keep time rolling
if (!(countdown2 && !countdown) && !(player->exiting || mapreset) && !(player->pflags & PF_TIMEOVER))
@ -7958,50 +7987,6 @@ static void P_DeathThink(player_t *player)
}
}
/*if (G_RaceGametype() && (player->lives <= 0))
{
// to the lose music!
if (player->deadtimer == 4*TICRATE)
P_EndingMusic(player);
// stuff below isn't for kart
// Return to level music
if (netgame)
{
if (player->deadtimer == gameovertics && P_IsLocalPlayer(player))
S_ChangeMusic(mapmusname, mapmusflags, true);
}
else if (multiplayer) // local multiplayer only
{
if (player->deadtimer != gameovertics)
;
// Restore the first available player's music once we're dead for long enough
// -- that is, as long as they aren't dead too
else
{
INT32 i;
for (i = 0; i < 4; i++)
{
if (i > splitscreen)
break;
if (i == 0 && player != &players[displayplayer] && players[displayplayer].lives > 0)
P_RestoreMusic(&players[displayplayer]);
else if (i == 1 && player != &players[secondarydisplayplayer] && players[secondarydisplayplayer].lives > 0)
P_RestoreMusic(&players[secondarydisplayplayer]);
else if (i == 2 && player != &players[thirddisplayplayer] && players[thirddisplayplayer].lives > 0)
P_RestoreMusic(&players[thirddisplayplayer]);
else if (i == 3 && player != &players[fourthdisplayplayer] && players[fourthdisplayplayer].lives > 0)
P_RestoreMusic(&players[fourthdisplayplayer]);
else
continue;
break;
}
}
}
}*/
if (!player->mo)
return;
@ -8138,25 +8123,36 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
fixed_t x, y, z, dist, height, viewpointx, viewpointy, camspeed, camdist, camheight, pviewheight;
fixed_t pan, xpan, ypan;
INT32 camrotate;
boolean camstill, cameranoclip, lookback;
boolean camstill, lookback;
UINT8 timeover;
mobj_t *mo;
subsector_t *newsubsec;
fixed_t f1, f2;
#ifndef NOCLIPCAM
boolean cameranoclip;
subsector_t *newsubsec;
#endif
// We probably shouldn't move the camera if there is no player or player mobj somehow
if (!player || !player->mo)
return true;
// This can happen when joining
if (thiscam->subsector == NULL || thiscam->subsector->sector == NULL)
return true;
mo = player->mo;
#ifdef NOCLIPCAM
cameranoclip = true; // We like camera noclip!
#else
#ifndef NOCLIPCAM
cameranoclip = ((player->pflags & (PF_NOCLIP|PF_NIGHTSMODE))
|| (mo->flags & (MF_NOCLIP|MF_NOCLIPHEIGHT)) // Noclipping player camera noclips too!!
|| (leveltime < introtime)); // Kart intro cam
#endif
if (player->pflags & PF_TIMEOVER) // 1 for momentum keep, 2 for turnaround
timeover = (player->kartstuff[k_timeovercam] > 2*TICRATE ? 2 : 1);
else
timeover = 0;
if (!(player->playerstate == PST_DEAD || player->exiting))
{
if (player->spectator) // force cam off for spectators
@ -8215,7 +8211,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
// if (leveltime > 0 && timeinmap <= 0)
// return true;
if (player->pflags & PF_NIGHTSMODE)
if (demoplayback)
{
focusangle = mo->angle;
focusaiming = 0;
@ -8286,7 +8282,12 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
lookback = camspin4;
}
if (leveltime < introtime) // Whoooshy camera!
if (timeover)
{
const INT32 timeovercam = max(0, min(180, (player->kartstuff[k_timeovercam] - 2*TICRATE)*15));
camrotate += timeovercam;
}
else if (leveltime < introtime) // Whoooshy camera!
{
const INT32 introcam = (introtime - leveltime);
camrotate += introcam*5;
@ -8306,10 +8307,15 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
if (mo->eflags & MFE_VERTICALFLIP)
camheight += thiscam->height;
if (camstill || resetcalled || player->playerstate == PST_DEAD)
angle = thiscam->angle;
if (splitscreen == 1)
camspeed = (3*camspeed)/4;
if (timeover)
angle = mo->angle + FixedAngle(camrotate*FRACUNIT);
else if (leveltime < starttime)
angle = focusangle + FixedAngle(camrotate*FRACUNIT);
else if (camstill || resetcalled || player->playerstate == PST_DEAD)
angle = thiscam->angle;
else
{
angle_t input = focusangle + FixedAngle(camrotate<<FRACBITS) - thiscam->angle;
@ -8322,12 +8328,9 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
input = InvAngle(input);
angle = thiscam->angle + input;
if (demoplayback && player == &players[consoleplayer])
localangle = angle;
}
if (!resetcalled && (leveltime > starttime)
if (!resetcalled && (leveltime > starttime && timeover != 2)
&& ((thiscam == &camera && t_cam_rotate != -42)
|| (thiscam == &camera2 && t_cam2_rotate != -42)
|| (thiscam == &camera3 && t_cam3_rotate != -42)
@ -8363,25 +8366,30 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
y = mo->y - FixedMul(FINESINE((angle>>ANGLETOFINESHIFT) & FINEMASK), dist);
// SRB2Kart: set camera panning
if (player->kartstuff[k_drift] != 0)
{
fixed_t panmax = (dist/5);
pan = FixedDiv(FixedMul(min((fixed_t)player->kartstuff[k_driftcharge], K_GetKartDriftSparkValue(player)), panmax), K_GetKartDriftSparkValue(player));
if (pan > panmax)
pan = panmax;
if (player->kartstuff[k_drift] < 0)
pan *= -1;
}
if (camstill || resetcalled || player->playerstate == PST_DEAD)
pan = xpan = ypan = 0;
else
pan = 0;
{
if (player->kartstuff[k_drift] != 0)
{
fixed_t panmax = (dist/5);
pan = FixedDiv(FixedMul(min((fixed_t)player->kartstuff[k_driftcharge], K_GetKartDriftSparkValue(player)), panmax), K_GetKartDriftSparkValue(player));
if (pan > panmax)
pan = panmax;
if (player->kartstuff[k_drift] < 0)
pan *= -1;
}
else
pan = 0;
pan = thiscam->pan + FixedMul(pan - thiscam->pan, camspeed/4);
pan = thiscam->pan + FixedMul(pan - thiscam->pan, camspeed/4);
xpan = FixedMul(FINECOSINE(((angle+ANGLE_90)>>ANGLETOFINESHIFT) & FINEMASK), pan);
ypan = FixedMul(FINESINE(((angle+ANGLE_90)>>ANGLETOFINESHIFT) & FINEMASK), pan);
xpan = FixedMul(FINECOSINE(((angle+ANGLE_90)>>ANGLETOFINESHIFT) & FINEMASK), pan);
ypan = FixedMul(FINESINE(((angle+ANGLE_90)>>ANGLETOFINESHIFT) & FINEMASK), pan);
x += xpan;
y += ypan;
x += xpan;
y += ypan;
}
pviewheight = FixedMul(32<<FRACBITS, mo->scale);
@ -8390,6 +8398,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
else
z = mo->z + pviewheight + camheight;
#ifndef NOCLIPCAM // Disable all z-clipping for noclip cam
// move camera down to move under lower ceilings
newsubsec = R_IsPointInSubsector(((mo->x>>FRACBITS) + (thiscam->x>>FRACBITS))<<(FRACBITS-1), ((mo->y>>FRACBITS) + (thiscam->y>>FRACBITS))<<(FRACBITS-1));
@ -8587,6 +8596,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
if (thiscam->z < thiscam->floorz && !cameranoclip)
thiscam->z = thiscam->floorz;
#endif // NOCLIPCAM
// point viewed by the camera
// this point is just 64 unit forward the player
@ -8594,15 +8604,19 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
viewpointx = mo->x + FixedMul(FINECOSINE((angle>>ANGLETOFINESHIFT) & FINEMASK), dist) + xpan;
viewpointy = mo->y + FixedMul(FINESINE((angle>>ANGLETOFINESHIFT) & FINEMASK), dist) + ypan;
if (!camstill && !resetcalled && !paused)
if (timeover)
thiscam->angle = angle;
else if (!camstill && !resetcalled && !paused && timeover != 1)
thiscam->angle = R_PointToAngle2(thiscam->x, thiscam->y, viewpointx, viewpointy);
if (player->exiting)
if (timeover == 1)
{
thiscam->momx = 0;
thiscam->momy = 0;
thiscam->momx = P_ReturnThrustX(NULL, mo->angle, 32*mo->scale); // Push forward
thiscam->momy = P_ReturnThrustY(NULL, mo->angle, 32*mo->scale);
thiscam->momz = 0;
}
else if (player->exiting || timeover == 2)
thiscam->momx = thiscam->momy = thiscam->momz = 0;
else if (leveltime < starttime)
{
thiscam->momx = FixedMul(x - thiscam->x, camspeed);
@ -8613,7 +8627,10 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
{
thiscam->momx = x - thiscam->x;
thiscam->momy = y - thiscam->y;
thiscam->momz = FixedMul(z - thiscam->z, camspeed/2);
if (splitscreen == 1) // Wide-screen needs to follow faster, due to a smaller vertical:horizontal ratio of screen space
thiscam->momz = FixedMul(z - thiscam->z, (3*camspeed)/4);
else
thiscam->momz = FixedMul(z - thiscam->z, camspeed/2);
}
thiscam->pan = pan;
@ -8628,10 +8645,10 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
else
angle = R_PointToAngle2(0, thiscam->z, dist, mo->z + P_GetPlayerHeight(player));
if (player->playerstate != PST_DEAD && !(player->pflags & PF_NIGHTSMODE && player->exiting))
if (player->playerstate != PST_DEAD && !((player->pflags & PF_NIGHTSMODE) && player->exiting))
angle += (focusaiming < ANGLE_180 ? focusaiming/2 : InvAngle(InvAngle(focusaiming)/2)); // overcomplicated version of '((signed)focusaiming)/2;'
if (twodlevel || (mo->flags2 & MF2_TWOD) || !camstill) // Keep the view still...
if (twodlevel || (mo->flags2 & MF2_TWOD) || (!camstill && !timeover)) // Keep the view still...
{
G_ClipAimingPitch((INT32 *)&angle);
dist = thiscam->aiming - angle;
@ -8730,7 +8747,7 @@ boolean P_SpectatorJoinGame(player_t *player)
if (P_IsLocalPlayer(player) && displayplayer != consoleplayer)
displayplayer = consoleplayer;
CONS_Printf(M_GetText("%s entered the game.\n"), player_names[player-players]);
HU_AddChatText(va(M_GetText("\x82*%s entered the game."), player_names[player-players]), false);
return true; // no more player->mo, cannot continue.
}
return false;
@ -8892,15 +8909,13 @@ void P_DoTimeOver(player_t *player)
S_StopSound(player->mo);
P_DamageMobj(player->mo, NULL, NULL, 10000);
}
player->lives = 0;
P_EndingMusic(player);
#if 0
// sal, when you do the f-zero explosion, this is how you make sure the map doesn't end before it's done ^u^ ~toast
if (!countdown2)
countdown2 = 5*TICRATE;
#endif
}
//
@ -8933,7 +8948,7 @@ void P_PlayerThink(player_t *player)
}
#ifdef SEENAMES
if (netgame && player == &players[displayplayer] && !(leveltime % (TICRATE/5)))
if (netgame && player == &players[displayplayer] && !(leveltime % (TICRATE/5)) && !splitscreen)
{
seenplayer = NULL;
@ -9147,10 +9162,10 @@ void P_PlayerThink(player_t *player)
}
}
if ((netgame || splitscreen) && player->spectator && cmd->buttons & BT_ATTACK && !player->powers[pw_flashing])
if ((netgame || multiplayer) && player->spectator && cmd->buttons & BT_ATTACK && !player->powers[pw_flashing])
{
player->pflags ^= PF_WANTSTOJOIN;
//player->powers[pw_flashing] = TICRATE + 1;
player->powers[pw_flashing] = TICRATE/2 + 1;
/*if (P_SpectatorJoinGame(player))
return; // player->mo was removed.*/
}
@ -9398,6 +9413,7 @@ void P_PlayerThink(player_t *player)
player->kartstuff[k_hyudorotimer] // SRB2kart - fixes Hyudoro not flashing when it should.
|| player->kartstuff[k_growshrinktimer] > 0 // Grow doesn't flash either.
|| player->kartstuff[k_respawn] // Respawn timer (for drop dash effect)
|| (player->pflags & PF_TIMEOVER) // NO CONTEST explosion
|| (G_BattleGametype() && player->kartstuff[k_bumper] <= 0 && player->kartstuff[k_comebacktimer])
|| leveltime < starttime)) // Level intro
{

View File

@ -185,16 +185,6 @@ void SplitScreen_OnChange(void)
{
UINT8 i;
if (!cv_debug && netgame)
{
if (splitscreen)
{
CONS_Alert(CONS_NOTICE, M_GetText("Splitscreen not supported in netplay, sorry!\n"));
splitscreen = 0;
}
return;
}
// recompute screen size
R_ExecuteSetViewSize();
@ -861,7 +851,7 @@ void R_SkyboxFrame(player_t *player)
{
aimingangle = player->aiming;
viewangle = player->mo->angle;
if (!demoplayback && player->playerstate != PST_DEAD)
if (/*!demoplayback && */player->playerstate != PST_DEAD)
{
if (player == &players[consoleplayer])
{
@ -1138,7 +1128,7 @@ void R_SetupFrame(player_t *player, boolean skybox)
aimingangle = player->aiming;
viewangle = viewmobj->angle;
if (!demoplayback && player->playerstate != PST_DEAD)
if (/*!demoplayback && */player->playerstate != PST_DEAD)
{
if (player == &players[consoleplayer])
{

View File

@ -2517,9 +2517,9 @@ static void Sk_SetDefaultValue(skin_t *skin)
strcpy(skin->realname, "Someone");
strcpy(skin->hudname, "???");
strncpy(skin->charsel, "CHRSONIC", 9);
strncpy(skin->face, "MISSING", 9);
strncpy(skin->superface, "MISSING", 9);
strncpy(skin->facerank, "PLAYRANK", 9);
strncpy(skin->facewant, "PLAYWANT", 9);
strncpy(skin->facemmap, "PLAYMMAP", 9);
skin->starttranscolor = 160;
skin->prefcolor = SKINCOLOR_GREEN;
@ -2551,7 +2551,6 @@ static void Sk_SetDefaultValue(skin_t *skin)
for (i = 0; i < sfx_skinsoundslot0; i++)
if (S_sfx[i].skinsound != -1)
skin->soundsid[S_sfx[i].skinsound] = i;
strncpy(skin->iconprefix, "SONICICN", 9);
}
//
@ -2584,17 +2583,17 @@ void R_InitSkins(void)
strcpy(skin->realname, "Sonic");
strcpy(skin->hudname, "SONIC");
strncpy(skin->charsel, "CHRSONIC", 9);
strncpy(skin->face, "LIVSONIC", 9);
strncpy(skin->superface, "LIVSUPER", 9);
strncpy(skin->facerank, "PLAYRANK", 9);
strncpy(skin->facewant, "PLAYWANT", 9);
strncpy(skin->facemmap, "PLAYMMAP", 9);
skin->prefcolor = SKINCOLOR_BLUE;
skin->ability = CA_THOK;
skin->actionspd = 60<<FRACBITS;
// SRB2kart
skin->kartspeed = 7;
skin->kartweight = 3;
skin->kartspeed = 8;
skin->kartweight = 2;
//
skin->normalspeed = 36<<FRACBITS;
@ -2605,9 +2604,7 @@ void R_InitSkins(void)
skin->spritedef.numframes = sprites[SPR_PLAY].numframes;
skin->spritedef.spriteframes = sprites[SPR_PLAY].spriteframes;
ST_LoadFaceGraphics(skin->face, skin->superface, 0);
strncpy(skin->iconprefix, "SONICICN", 9);
K_LoadIconGraphics(skin->iconprefix, 0);
ST_LoadFaceGraphics(skin->facerank, skin->facewant, skin->facemmap, 0);
//MD2 for sonic doesn't want to load in Linux.
#ifdef HWRENDER
@ -2699,7 +2696,7 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum)
player->jumpfactor = skin->jumpfactor;
if (!(cv_debug || devparm) && !(netgame || multiplayer || demoplayback || modeattacking))
/*if (!(cv_debug || devparm) && !(netgame || multiplayer || demoplayback || modeattacking))
{
if (playernum == consoleplayer)
CV_StealthSetValue(&cv_playercolor, skin->prefcolor);
@ -2712,7 +2709,7 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum)
player->skincolor = skin->prefcolor;
if (player->mo)
player->mo->color = player->skincolor;
}
}*/
if (player->mo)
P_SetScale(player->mo, player->mo->scale);
@ -2763,7 +2760,7 @@ void R_AddSkins(UINT16 wadnum)
char *value;
size_t size;
skin_t *skin;
boolean hudname, realname, superface;
boolean hudname, realname;
//
// search for all skin markers in pwad
@ -2793,7 +2790,7 @@ void R_AddSkins(UINT16 wadnum)
skin = &skins[numskins];
Sk_SetDefaultValue(skin);
skin->wadnum = wadnum;
hudname = realname = superface = false;
hudname = realname = false;
// parse
stoken = strtok (buf2, "\r\n= ");
while (stoken)
@ -2878,23 +2875,20 @@ void R_AddSkins(UINT16 wadnum)
strupr(value);
strncpy(skin->sprite, value, sizeof skin->sprite);
}
else if (!stricmp(stoken, "charsel"))
else if (!stricmp(stoken, "facerank"))
{
strupr(value);
strncpy(skin->charsel, value, sizeof skin->charsel);
strncpy(skin->facerank, value, sizeof skin->facerank);
}
else if (!stricmp(stoken, "face"))
else if (!stricmp(stoken, "facewant"))
{
strupr(value);
strncpy(skin->face, value, sizeof skin->face);
if (!superface)
strncpy(skin->superface, value, sizeof skin->superface);
strncpy(skin->facewant, value, sizeof skin->facewant);
}
else if (!stricmp(stoken, "superface"))
else if (!stricmp(stoken, "facemmap"))
{
superface = true;
strupr(value);
strncpy(skin->superface, value, sizeof skin->superface);
strncpy(skin->facemmap, value, sizeof skin->facemmap);
}
#define FULLPROCESS(field) else if (!stricmp(stoken, #field)) skin->field = get_number(value);
@ -2936,11 +2930,6 @@ void R_AddSkins(UINT16 wadnum)
skin->jumpfactor = FLOAT_TO_FIXED(atof(value));
else if (!stricmp(stoken, "highresscale"))
skin->highresscale = FLOAT_TO_FIXED(atof(value));
else if (!stricmp(stoken, "faceicon"))
{
strupr(value);
strncpy(skin->iconprefix, value, sizeof skin->iconprefix);
}
else
{
INT32 found = false;
@ -3041,10 +3030,7 @@ next_token:
#endif
// add face graphics
ST_LoadFaceGraphics(skin->face, skin->superface, numskins);
// load minimap icons
K_LoadIconGraphics(skin->iconprefix, numskins);
ST_LoadFaceGraphics(skin->facerank, skin->facewant, skin->facemmap, numskins);
#ifdef HWRENDER
if (rendermode == render_opengl)

View File

@ -81,7 +81,7 @@ typedef struct
char realname[SKINNAMESIZE+1]; // Display name for level completion.
char hudname[SKINNAMESIZE+1]; // HUD name to display (officially exactly 5 characters long)
char charsel[9], face[9], superface[9]; // Arbitrarily named patch lumps
char facerank[9], facewant[9], facemmap[9]; // Arbitrarily named patch lumps
UINT8 ability; // ability definition
UINT8 ability2; // secondary ability definition
@ -113,9 +113,6 @@ typedef struct
// specific sounds per skin
sfxenum_t soundsid[NUMSKINSOUNDS]; // sound # in S_sfx table
// minimap icons
char iconprefix[9];
} skin_t;
// -----------

View File

@ -531,6 +531,9 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume)
pitch = NORM_PITCH;
priority = NORM_PRIORITY;
if (splitscreen && origin)
volume = FixedDiv(volume<<FRACBITS, FixedSqrt((splitscreen+1)<<FRACBITS))>>FRACBITS;
if (splitscreen && listenmobj2) // Copy the sound for the split player
{
// Check to see if it is audible, and if not, modify the params
@ -1011,6 +1014,9 @@ void S_UpdateSounds(void)
pitch = NORM_PITCH;
sep = NORM_SEP;
if (splitscreen && c->origin)
volume = FixedDiv(volume<<FRACBITS, FixedSqrt((splitscreen+1)<<FRACBITS))>>FRACBITS;
// check non-local sounds for distance clipping
// or modify their params
if (c->origin && ((c->origin != players[consoleplayer].mo)
@ -1325,6 +1331,9 @@ INT32 S_AdjustSoundParams(const mobj_t *listener, const mobj_t *source, INT32 *v
*vol = (15 * ((S_CLIPPING_DIST - approx_dist)>>FRACBITS)) / S_ATTENUATOR;
}
if (splitscreen)
*vol = FixedDiv((*vol)<<FRACBITS, FixedSqrt((splitscreen+1)<<FRACBITS))>>FRACBITS;
return (*vol > 0);
}

View File

@ -705,7 +705,7 @@ sfxinfo_t S_sfx[NUMSFX] =
{"kc2e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"kc2f", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // Pogo Spring use
{"kc30", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"kc31", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"kc31", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR}, // NO CONTEST explosion
{"kc32", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"kc33", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"kc34", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR},
@ -737,7 +737,7 @@ sfxinfo_t S_sfx[NUMSFX] =
{"kc4e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"kc4f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"kc50", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"kc51", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"kc51", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR}, // NO CONTEST debris ambience
{"kc52", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"kc53", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"kc54", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR},
@ -813,6 +813,9 @@ sfxinfo_t S_sfx[NUMSFX] =
{"kpogos", false, 110, 8, -1, NULL, 0, -1, -1, LUMPERROR},
{"ddash", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"zio3", false, 110, 8, -1, NULL, 0, -1, -1, LUMPERROR},
{"wind1", false, 110, 8, -1, NULL, 0, -1, -1, LUMPERROR},
{"fire2", false, 110, 8, -1, NULL, 0, -1, -1, LUMPERROR},
{"chain", false, 128, 8, -1, NULL, 0, -1, -1, LUMPERROR},
{"mcitm1", false, 110, 8, -1, NULL, 0, -1, -1, LUMPERROR},
{"chaooo", false, 110, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"itfree", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR},
@ -946,6 +949,21 @@ sfxinfo_t S_sfx[NUMSFX] =
{"krti11", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR},
{"krti12", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR},
// SOC_CHAO SFX
{"mkuma", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"mkpop", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"bfare", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"merry", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"bowlh", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"tcart", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"tppop", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"toada", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"hsdoor",false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"hstrn", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"aspkb", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"msmnj1",false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"msmnj2",false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR},
// SRB2kart - Skin sounds
{"kwin", false, 64, 96, -1, NULL, 0, SKSKWIN, -1, LUMPERROR},
{"klose", false, 64, 96, -1, NULL, 0, SKSKLOSE, -1, LUMPERROR},

View File

@ -888,6 +888,9 @@ typedef enum
sfx_kpogos,
sfx_ddash,
sfx_zio3,
sfx_wind1,
sfx_fire2,
sfx_chain,
sfx_mcitm1,
sfx_chaooo,
sfx_itfree,
@ -1021,6 +1024,21 @@ typedef enum
sfx_krti11,
sfx_krti12,
// SOC_CHAO hardcode
sfx_mkuma,
sfx_mkpop,
sfx_bfare,
sfx_merry,
sfx_bowlh,
sfx_tcart,
sfx_tppop,
sfx_toada,
sfx_hsdoor,
sfx_hstrn,
sfx_aspkb,
sfx_msmnj1,
sfx_msmnj2,
// And LASTLY, Kart's skin sounds.
sfx_kwin,
sfx_klose,

View File

@ -50,8 +50,9 @@ UINT16 objectsdrawn = 0;
// STATUS BAR DATA
//
patch_t *faceprefix[MAXSKINS]; // face status patches
patch_t *superprefix[MAXSKINS]; // super face status patches
patch_t *facerankprefix[MAXSKINS]; // ranking
patch_t *facewantprefix[MAXSKINS]; // wanted
patch_t *facemmapprefix[MAXSKINS]; // minimap
// ------------------------------------------
// status bar overlay
@ -124,6 +125,10 @@ static patch_t *minicaps;
static patch_t *gotrflag;
static patch_t *gotbflag;
// Midnight Channel:
static patch_t *hud_tv1;
static patch_t *hud_tv2;
// SRB2kart
//
@ -345,31 +350,27 @@ void ST_LoadGraphics(void)
ngradeletters[i] = W_CachePatchName(va("GRADE%d", i), PU_HUDGFX);
K_LoadKartHUDGraphics();
// Midnight Channel:
hud_tv1 = W_CachePatchName("HUD_TV1", PU_HUDGFX);
hud_tv2 = W_CachePatchName("HUD_TV2", PU_HUDGFX);
}
// made separate so that skins code can reload custom face graphics
void ST_LoadFaceGraphics(char *facestr, char *superstr, INT32 skinnum)
void ST_LoadFaceGraphics(char *rankstr, char *wantstr, char *mmapstr, INT32 skinnum)
{
faceprefix[skinnum] = W_CachePatchName(facestr, PU_HUDGFX);
superprefix[skinnum] = W_CachePatchName(superstr, PU_HUDGFX);
facerankprefix[skinnum] = W_CachePatchName(rankstr, PU_HUDGFX);
facewantprefix[skinnum] = W_CachePatchName(wantstr, PU_HUDGFX);
facemmapprefix[skinnum] = W_CachePatchName(mmapstr, PU_HUDGFX);
facefreed[skinnum] = false;
}
#ifdef DELFILE
void ST_UnLoadFaceGraphics(INT32 skinnum)
{
Z_Free(faceprefix[skinnum]);
Z_Free(superprefix[skinnum]);
facefreed[skinnum] = true;
}
#endif
void ST_ReloadSkinFaceGraphics(void)
{
INT32 i;
for (i = 0; i < numskins; i++)
ST_LoadFaceGraphics(skins[i].face, skins[i].superface, i);
ST_LoadFaceGraphics(skins[i].facerank, skins[i].facewant, skins[i].facemmap, i);
}
static inline void ST_InitData(void)
@ -718,9 +719,9 @@ static void ST_drawLives(void) // SRB2kart - unused.
{
// skincolor face/super
UINT8 *colormap = R_GetTranslationColormap(stplyr->skin, stplyr->mo->color, GTC_CACHE);
patch_t *face = faceprefix[stplyr->skin];
patch_t *face = facerankprefix[stplyr->skin];
if (stplyr->powers[pw_super] || stplyr->pflags & PF_NIGHTSMODE)
face = superprefix[stplyr->skin];
face = facewantprefix[stplyr->skin];
V_DrawSmallMappedPatch(hudinfo[HUD_LIVESPIC].x, hudinfo[HUD_LIVESPIC].y + (v_splitflag ? -12 : 0),
V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANS|v_splitflag,face, colormap);
}
@ -729,7 +730,7 @@ static void ST_drawLives(void) // SRB2kart - unused.
// skincolor face
UINT8 *colormap = R_GetTranslationColormap(stplyr->skin, stplyr->skincolor, GTC_CACHE);
V_DrawSmallMappedPatch(hudinfo[HUD_LIVESPIC].x, hudinfo[HUD_LIVESPIC].y + (v_splitflag ? -12 : 0),
V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANS|v_splitflag,faceprefix[stplyr->skin], colormap);
V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANS|v_splitflag,facerankprefix[stplyr->skin], colormap);
}
// name
@ -1895,13 +1896,13 @@ static void ST_overlayDrawer(void)
if(!P_IsLocalPlayer(stplyr))
{
char name[MAXPLAYERNAME+1];
/*char name[MAXPLAYERNAME+1];
// shorten the name if its more than twelve characters.
strlcpy(name, player_names[stplyr-players], 13);
strlcpy(name, player_names[stplyr-players], 13);*/
// Show name of player being displayed
V_DrawCenteredString((BASEVIDWIDTH/2), BASEVIDHEIGHT-40, 0, M_GetText("Viewpoint:"));
V_DrawCenteredString((BASEVIDWIDTH/2), BASEVIDHEIGHT-32, V_ALLOWLOWERCASE, name);
V_DrawCenteredString((BASEVIDWIDTH/2), BASEVIDHEIGHT-32, V_ALLOWLOWERCASE, player_names[stplyr-players]);
}
// This is where we draw all the fun cheese if you have the chasecam off!
@ -1927,7 +1928,7 @@ static void ST_overlayDrawer(void)
)
ST_drawLevelTitle();
if (!hu_showscores && !splitscreen && netgame && displayplayer == consoleplayer && !mapreset)
if (!hu_showscores && netgame && !mapreset)
{
/*if (G_GametypeUsesLives() && stplyr->lives <= 0 && countdown != 1)
V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), 0, M_GetText("Press F12 to watch another player."));
@ -1952,21 +1953,50 @@ static void ST_overlayDrawer(void)
)
{
// SRB2kart: changed positions & text
V_DrawString(2, BASEVIDHEIGHT-40, V_HUDTRANSHALF|V_YELLOWMAP, M_GetText("- SPECTATING -"));
if (stplyr->pflags & PF_WANTSTOJOIN)
V_DrawString(2, BASEVIDHEIGHT-30, V_HUDTRANSHALF, M_GetText("Item - Cancel Join"));
/*else if (G_GametypeHasTeams())
V_DrawString(2, BASEVIDHEIGHT-30, V_HUDTRANSHALF, M_GetText("Item - Join Team"));*/
if (splitscreen)
{
INT32 splitflags = K_calcSplitFlags(0);
V_DrawThinString(2, (BASEVIDHEIGHT/2)-20, V_YELLOWMAP|V_HUDTRANSHALF|splitflags, M_GetText("- SPECTATING -"));
if (stplyr->powers[pw_flashing])
V_DrawThinString(2, (BASEVIDHEIGHT/2)-10, V_HUDTRANSHALF|splitflags, M_GetText("Item - . . ."));
else if (stplyr->pflags & PF_WANTSTOJOIN)
V_DrawThinString(2, (BASEVIDHEIGHT/2)-10, V_HUDTRANSHALF|splitflags, M_GetText("Item - Cancel Join"));
/*else if (G_GametypeHasTeams())
V_DrawThinString(2, (BASEVIDHEIGHT/2)-10, V_HUDTRANSHALF|splitflags, M_GetText("Item - Join Team"));*/
else
V_DrawThinString(2, (BASEVIDHEIGHT/2)-10, V_HUDTRANSHALF|splitflags, M_GetText("Item - Join Game"));
}
else
V_DrawString(2, BASEVIDHEIGHT-30, V_HUDTRANSHALF, M_GetText("Item - Join Game"));
V_DrawString(2, BASEVIDHEIGHT-20, V_HUDTRANSHALF, M_GetText("Accelerate - Float"));
V_DrawString(2, BASEVIDHEIGHT-10, V_HUDTRANSHALF, M_GetText("Brake - Sink"));
{
V_DrawString(2, BASEVIDHEIGHT-40, V_HUDTRANSHALF|V_YELLOWMAP, M_GetText("- SPECTATING -"));
if (stplyr->powers[pw_flashing])
V_DrawString(2, BASEVIDHEIGHT-30, V_HUDTRANSHALF, M_GetText("Item - . . ."));
else if (stplyr->pflags & PF_WANTSTOJOIN)
V_DrawString(2, BASEVIDHEIGHT-30, V_HUDTRANSHALF, M_GetText("Item - Cancel Join"));
/*else if (G_GametypeHasTeams())
V_DrawString(2, BASEVIDHEIGHT-30, V_HUDTRANSHALF, M_GetText("Item - Join Team"));*/
else
V_DrawString(2, BASEVIDHEIGHT-30, V_HUDTRANSHALF, M_GetText("Item - Join Game"));
V_DrawString(2, BASEVIDHEIGHT-20, V_HUDTRANSHALF, M_GetText("Accelerate - Float"));
V_DrawString(2, BASEVIDHEIGHT-10, V_HUDTRANSHALF, M_GetText("Brake - Sink"));
}
}
}
ST_drawDebugInfo();
}
// MayonakaStatic: draw Midnight Channel's TV-like borders
static void ST_MayonakaStatic(void)
{
INT32 flag = (leveltime%2) ? V_90TRANS : V_70TRANS;
V_DrawFixedPatch(0, 0, FRACUNIT, V_SNAPTOTOP|V_SNAPTOLEFT|flag, hud_tv1, NULL);
V_DrawFixedPatch(320<<FRACBITS, 0, FRACUNIT, V_SNAPTOTOP|V_SNAPTORIGHT|V_FLIP|flag, hud_tv1, NULL);
V_DrawFixedPatch(0, 142<<FRACBITS, FRACUNIT, V_SNAPTOBOTTOM|V_SNAPTOLEFT|flag, hud_tv2, NULL);
V_DrawFixedPatch(320<<FRACBITS, 142<<FRACBITS, FRACUNIT, V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_FLIP|flag, hud_tv2, NULL);
}
void ST_Drawer(void)
{
#ifdef SEENAMES
@ -2024,5 +2054,17 @@ void ST_Drawer(void)
}
}
}
// draw Midnight Channel's overlay ontop
if (mapheaderinfo[gamemap-1]->typeoflevel & TOL_TV) // Very specific Midnight Channel stuff.
ST_MayonakaStatic();
}
// Draw a white fade on level opening
if (leveltime < 15)
{
if (leveltime <= 5)
V_DrawFill(0,0,BASEVIDWIDTH,BASEVIDHEIGHT,120); // Pure white on first few frames, to hide SRB2's awful level load artifacts
else
V_DrawFadeScreen(120, 15-leveltime); // Then gradually fade out from there
}
}

View File

@ -42,7 +42,7 @@ void ST_UnloadGraphics(void);
void ST_LoadGraphics(void);
// face load graphics, called when skin changes
void ST_LoadFaceGraphics(char *facestr, char *superstr, INT32 playernum);
void ST_LoadFaceGraphics(char *rankstr, char *wantstr, char *mmapstr, INT32 playernum);
void ST_ReloadSkinFaceGraphics(void);
#ifdef DELFILE
void ST_UnLoadFaceGraphics(INT32 skinnum);
@ -66,8 +66,9 @@ extern patch_t *sboscore;
extern patch_t *sbotime;
extern patch_t *sbocolon;
extern patch_t *sboperiod;
extern patch_t *faceprefix[MAXSKINS]; // face status patches
extern patch_t *superprefix[MAXSKINS]; // super face status patches
extern patch_t *facerankprefix[MAXSKINS]; // ranking
extern patch_t *facewantprefix[MAXSKINS]; // wanted
extern patch_t *facemmapprefix[MAXSKINS]; // minimap
extern patch_t *livesback;
extern patch_t *ngradeletters[7];
extern boolean iconfreed[MAXPLAYERS];

View File

@ -78,9 +78,9 @@ consvar_t cv_grcoronas = {"gr_coronas", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL,
consvar_t cv_grcoronasize = {"gr_coronasize", "1", CV_SAVE| CV_FLOAT, 0, NULL, 0, NULL, NULL, 0, 0, NULL};
#endif
static CV_PossibleValue_t CV_MD2[] = {{0, "Off"}, {1, "On"}, {2, "Old"}, {0, NULL}};
//static CV_PossibleValue_t CV_MD2[] = {{0, "Off"}, {1, "On"}, {2, "Old"}, {0, NULL}};
// console variables in development
consvar_t cv_grmd2 = {"gr_md2", "Off", CV_SAVE, CV_MD2, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_grmd2 = {"gr_md2", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
#endif
const UINT8 gammatable[5][256] =
@ -952,6 +952,39 @@ void V_DrawDiag(INT32 x, INT32 y, INT32 wh, INT32 c)
}
}
#ifdef HWRENDER
// This is now a function since it's otherwise repeated 2 times and honestly looks retarded:
static UINT32 V_GetHWConsBackColor(void)
{
UINT32 hwcolor;
switch (cons_backcolor.value)
{
case 0: hwcolor = 0xffffff00; break; // White
case 1: hwcolor = 0x80808000; break; // Gray
case 2: hwcolor = 0xdeb88700; break; // Sepia
case 3: hwcolor = 0x40201000; break; // Brown
case 4: hwcolor = 0xfa807200; break; // Pink
case 5: hwcolor = 0xff69b400; break; // Raspberry
case 6: hwcolor = 0xff000000; break; // Red
case 7: hwcolor = 0xffd68300; break; // Creamsicle
case 8: hwcolor = 0xff800000; break; // Orange
case 9: hwcolor = 0xdaa52000; break; // Gold
case 10: hwcolor = 0x80800000; break; // Yellow
case 11: hwcolor = 0x00ff0000; break; // Emerald
case 12: hwcolor = 0x00800000; break; // Green
case 13: hwcolor = 0x4080ff00; break; // Cyan
case 14: hwcolor = 0x4682b400; break; // Steel
case 15: hwcolor = 0x1e90ff00; break; // Periwinkle
case 16: hwcolor = 0x0000ff00; break; // Blue
case 17: hwcolor = 0xff00ff00; break; // Purple
case 18: hwcolor = 0xee82ee00; break; // Lavender
// Default green
default: hwcolor = 0x00800000; break;
}
return hwcolor;
}
#endif
// THANK YOU MPC!!!
void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
@ -966,21 +999,7 @@ void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
#ifdef HWRENDER
if (rendermode != render_soft && rendermode != render_none)
{
UINT32 hwcolor;
switch (cons_backcolor.value)
{
case 0: hwcolor = 0xffffff00; break; // White
case 1: hwcolor = 0x80808000; break; // Gray
case 2: hwcolor = 0x40201000; break; // Brown
case 3: hwcolor = 0xff000000; break; // Red
case 4: hwcolor = 0xff800000; break; // Orange
case 5: hwcolor = 0x80800000; break; // Yellow
case 6: hwcolor = 0x00800000; break; // Green
case 7: hwcolor = 0x0000ff00; break; // Blue
case 8: hwcolor = 0x4080ff00; break; // Cyan
// Default green
default: hwcolor = 0x00800000; break;
}
UINT32 hwcolor = V_GetHWConsBackColor();
HWR_DrawConsoleFill(x, y, w, h, hwcolor, c); // we still use the regular color stuff but only for flags. actual draw color is "hwcolor" for this.
return;
}
@ -1226,21 +1245,7 @@ void V_DrawFadeConsBack(INT32 plines)
#ifdef HWRENDER // not win32 only 19990829 by Kin
if (rendermode != render_soft && rendermode != render_none)
{
UINT32 hwcolor;
switch (cons_backcolor.value)
{
case 0: hwcolor = 0xffffff00; break; // White
case 1: hwcolor = 0x80808000; break; // Gray
case 2: hwcolor = 0x40201000; break; // Brown
case 3: hwcolor = 0xff000000; break; // Red
case 4: hwcolor = 0xff800000; break; // Orange
case 5: hwcolor = 0x80800000; break; // Yellow
case 6: hwcolor = 0x00800000; break; // Green
case 7: hwcolor = 0x0000ff00; break; // Blue
case 8: hwcolor = 0x4080ff00; break; // Cyan
// Default green
default: hwcolor = 0x00800000; break;
}
UINT32 hwcolor = V_GetHWConsBackColor();
HWR_DrawConsoleBack(hwcolor, plines);
return;
}
@ -1347,10 +1352,10 @@ void V_DrawChatCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed, UI
w = (vid.width < 640 ) ? (SHORT(hu_font[c]->width)/2) : (SHORT(hu_font[c]->width)); // use normal sized characters if we're using a terribly low resolution.
if (x + w > vid.width)
return;
V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, (vid.width < 640) ? (FRACUNIT) : (FRACUNIT/2), flags, hu_font[c], colormap);
}
// Precompile a wordwrapped string to any given width.

View File

@ -275,6 +275,8 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32))
for (j = 0; j < numplayersingame; j++)
{
INT32 nump = ((G_RaceGametype() && nospectategrief > 0) ? nospectategrief : numplayersingame);
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator || completed[i])
@ -296,9 +298,9 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32))
else
data.match.pos[data.match.numplayers] = data.match.numplayers+1;
if (!rankingsmode && !(players[i].pflags & PF_TIMEOVER) && (data.match.pos[data.match.numplayers] != numplayersingame))
if (!rankingsmode && !(players[i].pflags & PF_TIMEOVER) && (data.match.pos[data.match.numplayers] < nump))
{
data.match.increase[i] = numplayersingame - data.match.pos[data.match.numplayers];
data.match.increase[i] = nump - data.match.pos[data.match.numplayers];
players[i].score += data.match.increase[i];
}
@ -346,7 +348,7 @@ void Y_IntermissionDrawer(void)
V_DrawPatchFill(bgtile);
if (usebuffer) // Fade everything out
V_DrawFadeScreen(0xFF00, 20);
V_DrawFadeScreen(0xFF00, 22);
if (!splitscreen)
whiteplayer = demoplayback ? displayplayer : consoleplayer;
@ -414,7 +416,7 @@ void Y_IntermissionDrawer(void)
else*/ if (intertype == int_race || intertype == int_match)
{
#define NUMFORNEWCOLUMN 8
INT32 y = 48, gutter = ((data.match.numplayers > NUMFORNEWCOLUMN) ? 0 : (BASEVIDWIDTH/2));
INT32 y = 41, gutter = ((data.match.numplayers > NUMFORNEWCOLUMN) ? 0 : (BASEVIDWIDTH/2));
const char *timeheader;
if (data.match.rankingsmode)
@ -423,26 +425,27 @@ void Y_IntermissionDrawer(void)
timeheader = (intertype == int_race ? "TIME" : "SCORE");
// draw the level name
V_DrawCenteredString(-4 + x + BASEVIDWIDTH/2, 20, 0, data.match.levelstring);
V_DrawFill(x, 42, 312, 1, 0);
V_DrawCenteredString(-4 + x + BASEVIDWIDTH/2, 12, 0, data.match.levelstring);
V_DrawFill(x, 34, 312, 1, 0);
if (data.match.encore)
V_DrawCenteredString(-4 + x + BASEVIDWIDTH/2, 20-8, hilicol, "ENCORE MODE");
V_DrawCenteredString(-4 + x + BASEVIDWIDTH/2, 12-8, hilicol, "ENCORE MODE");
if (!gutter)
{
V_DrawFill(x+156, 32, 1, 152, 0);
V_DrawFill(x+156, 24, 1, 158, 0);
V_DrawFill(x, 182, 312, 1, 0);
V_DrawCenteredString(x+6+(BASEVIDWIDTH/2), 32, hilicol, "#");
V_DrawString(x+36+(BASEVIDWIDTH/2), 32, hilicol, "NAME");
V_DrawCenteredString(x+6+(BASEVIDWIDTH/2), 24, hilicol, "#");
V_DrawString(x+36+(BASEVIDWIDTH/2), 24, hilicol, "NAME");
V_DrawRightAlignedString(x+152, 32, hilicol, timeheader);
V_DrawRightAlignedString(x+152, 24, hilicol, timeheader);
}
V_DrawCenteredString(x+6, 32, hilicol, "#");
V_DrawString(x+36, 32, hilicol, "NAME");
V_DrawCenteredString(x+6, 24, hilicol, "#");
V_DrawString(x+36, 24, hilicol, "NAME");
V_DrawRightAlignedString(x+(BASEVIDWIDTH/2)+152, 32, hilicol, timeheader);
V_DrawRightAlignedString(x+(BASEVIDWIDTH/2)+152, 24, hilicol, timeheader);
for (i = 0; i < data.match.numplayers; i++)
{
@ -458,12 +461,10 @@ void Y_IntermissionDrawer(void)
V_DrawCenteredString(x+6, y, 0, va("%d", data.match.pos[i]));
if (data.match.color[i] == 0)
V_DrawSmallScaledPatch(x+16, y-4, 0,faceprefix[*data.match.character[i]]);
else
if (data.match.color[i])
{
UINT8 *colormap = R_GetTranslationColormap(*data.match.character[i], *data.match.color[i], GTC_CACHE);
V_DrawSmallMappedPatch(x+16, y-4, 0,faceprefix[*data.match.character[i]], colormap);
V_DrawMappedPatch(x+16, y-4, 0,facerankprefix[*data.match.character[i]], colormap);
}
if (!gutter)
@ -518,11 +519,11 @@ void Y_IntermissionDrawer(void)
else
data.match.num[i] = MAXPLAYERS; // this should be the only field setting in this function
y += 16;
y += 18;
if (i == NUMFORNEWCOLUMN-1)
{
y = 48;
y = 41;
x += BASEVIDWIDTH/2;
}
#undef NUMFORNEWCOLUMN
@ -1146,12 +1147,10 @@ void Y_VoteDrawer(void)
V_DrawDiag(x, y, 6, V_SNAPTOLEFT|levelinfo[votes[i]].gtc);
}
if (players[i].skincolor == 0)
V_DrawSmallScaledPatch(x+24, y+9, V_SNAPTOLEFT, faceprefix[players[i].skin]);
else
if (players[i].skincolor)
{
UINT8 *colormap = R_GetTranslationColormap(players[i].skin, players[i].skincolor, GTC_CACHE);
V_DrawSmallMappedPatch(x+24, y+9, V_SNAPTOLEFT, faceprefix[players[i].skin], colormap);
V_DrawMappedPatch(x+24, y+9, V_SNAPTOLEFT, facerankprefix[players[i].skin], colormap);
}
}