Merge branch 'next' into udmf-next

# Conflicts:
#	src/p_mobj.c
#	src/p_polyobj.c
This commit is contained in:
MascaraSnake 2020-06-09 09:38:01 +02:00
commit 4a0206b38d
83 changed files with 3732 additions and 3417 deletions

View file

@ -750,12 +750,6 @@ linedeftypes
prefix = "(20)";
}
21
{
title = "Explicitly Include Line <disabled>";
prefix = "(21)";
}
22
{
title = "Parameters";
@ -766,6 +760,7 @@ linedeftypes
flags128text = "[7] Intangible";
flags256text = "[8] Stopped by pushables";
flags512text = "[9] Render flats";
flags8192text = "[13] Cut cyan flat pixels";
}
30
@ -920,6 +915,7 @@ linedeftypes
flags32text = "[5] Only block player";
flags64text = "[6] Render insides";
flags128text = "[7] Only block non-players";
flags8192text = "[13] Cut cyan flat pixels";
3dfloor = true;
3dfloorflags = "195F";
flags643dfloorflagsadd = "7C80";
@ -979,6 +975,7 @@ linedeftypes
flags32text = "[5] Only block player";
flags64text = "[6] Don't cast shadow";
flags128text = "[7] Render insides/block non-plr";
flags8192text = "[13] Cut cyan flat pixels";
3dfloor = true;
3dfloorflags = "200191F";
flags1283dfloorflagsadd = "7C80";
@ -992,6 +989,7 @@ linedeftypes
flags32text = "[5] Only block player";
flags64text = "[6] Don't cast shadow";
flags128text = "[7] Render insides/block non-plr";
flags8192text = "[13] Cut cyan flat pixels";
3dfloor = true;
3dfloorflags = "2001917";
flags1283dfloorflagsadd = "7C80";
@ -1019,6 +1017,7 @@ linedeftypes
flags32text = "[5] Only block player";
flags64text = "[6] Don't cast shadow";
flags128text = "[7] Render insides/block non-plr";
flags8192text = "[13] Cut cyan flat pixels";
3dfloor = true;
3dfloorflags = "400191F";
flags1283dfloorflagsadd = "7C80";
@ -1032,6 +1031,7 @@ linedeftypes
flags32text = "[5] Only block player";
flags64text = "[6] Don't cast shadow";
flags128text = "[7] Render insides/block non-plr";
flags8192text = "[13] Cut cyan flat pixels";
3dfloor = true;
3dfloorflags = "4001917";
flags1283dfloorflagsadd = "7C80";
@ -1077,6 +1077,7 @@ linedeftypes
flags64text = "[6] Use two light levels";
flags512text = "[9] Use target light level";
flags1024text = "[10] Ripple effect";
flags8192text = "[13] Cut cyan flat pixels";
3dfloor = true;
3dfloorflags = "9F39";
flags643dfloorflagsadd = "20000";
@ -1105,6 +1106,7 @@ linedeftypes
flags64text = "[6] Use two light levels";
flags512text = "[9] Use target light level";
flags1024text = "[10] Ripple effect";
flags8192text = "[13] Cut cyan flat pixels";
3dfloor = true;
3dfloorflags = "1F31";
flags643dfloorflagsadd = "20000";
@ -1120,6 +1122,7 @@ linedeftypes
flags64text = "[6] Use two light levels";
flags512text = "[9] Use target light level";
flags1024text = "[10] Ripple effect";
flags8192text = "[13] Cut cyan flat pixels";
3dfloor = true;
3dfloorflags = "209F39";
flags643dfloorflagsadd = "20000";
@ -1134,6 +1137,7 @@ linedeftypes
flags64text = "[6] Use two light levels";
flags512text = "[9] Use target light level";
flags1024text = "[10] Ripple effect";
flags8192text = "[13] Cut cyan flat pixels";
3dfloor = true;
3dfloorflags = "201F31";
flags643dfloorflagsadd = "20000";
@ -1156,6 +1160,7 @@ linedeftypes
prefix = "(221)";
flags8text = "[3] Slope skew sides";
flags64text = "[6] Cast shadow";
flags8192text = "[13] Cut cyan flat pixels";
3dfloor = true;
3dfloorflags = "1B59";
flags643dfloorflagsremove = "40";
@ -1279,6 +1284,7 @@ linedeftypes
flags32text = "[5] Only block player";
flags64text = "[6] Spindash to move";
flags128text = "[7] Only block non-players";
flags8192text = "[13] Cut cyan flat pixels";
3dfloor = true;
3dfloorflags = "195F";
}
@ -1318,6 +1324,7 @@ linedeftypes
flags32text = "[5] Only block player";
flags64text = "[6] Spindash, no shadow";
flags128text = "[7] Only block non-players";
flags8192text = "[13] Cut cyan flat pixels";
3dfloor = true;
3dfloorflags = "2009D1F";
flags643dfloorflagsadd = "40";
@ -1384,6 +1391,7 @@ linedeftypes
flags32text = "[5] Only block player";
flags64text = "[6] Don't cast shadow";
flags128text = "[7] Only block non-players";
flags8192text = "[13] Cut cyan flat pixels";
3dfloor = true;
3dfloorflags = "210959F";
flags643dfloorflagsadd = "40";
@ -1397,6 +1405,7 @@ linedeftypes
flags32text = "[5] Only block player";
flags64text = "[6] Don't cast shadow";
flags128text = "[7] Only block non-players";
flags8192text = "[13] Cut cyan flat pixels";
3dfloor = true;
3dfloorflags = "218959F";
flags643dfloorflagsadd = "40";
@ -1535,6 +1544,7 @@ linedeftypes
flags8text = "[3] Slope skew sides";
flags512text = "[9] Shattered by pushables";
flags1024text = "[10] Trigger linedef executor";
flags8192text = "[13] Cut cyan flat pixels";
3dfloor = true;
3dfloorflags = "880101D";
}
@ -1576,6 +1586,7 @@ linedeftypes
flags128text = "[7] Only block non-players";
flags512text = "[9] Shattered by pushables";
flags1024text = "[10] Trigger linedef executor";
flags8192text = "[13] Cut cyan flat pixels";
3dfloor = true;
3dfloorflags = "1080101F";
}
@ -1597,6 +1608,7 @@ linedeftypes
prefix = "(258)";
flags8text = "[3] Slope skew sides";
flags32text = "[5] Don't damage bosses";
flags8192text = "[13] Cut cyan flat pixels";
3dfloor = true;
3dfloorflags = "959";
}
@ -1610,6 +1622,7 @@ linedeftypes
flags128text = "[7] Only block non-players";
flags512text = "[9] Shattered by pushables";
flags1024text = "[10] Trigger linedef executor";
flags8192text = "[13] Cut cyan flat pixels";
3dfloor = true;
3dfloorcustom = true;
}
@ -2603,45 +2616,63 @@ linedeftypes
500
{
title = "Scroll Wall Front Side Left";
title = "Scroll Front Wall Left";
prefix = "(500)";
}
501
{
title = "Scroll Wall Front Side Right";
title = "Scroll Front Wall Right";
prefix = "(501)";
}
502
{
title = "Scroll Wall According to Linedef";
title = "Scroll Tagged Wall";
prefix = "(502)";
flags128text = "[7] Use texture offsets";
flags256text = "[8] Scroll back side";
}
503
{
title = "Scroll Wall According to Linedef (Accelerative)";
title = "Scroll Tagged Wall (Accelerative)";
prefix = "(503)";
flags128text = "[7] Use texture offsets";
flags256text = "[8] Scroll back side";
}
504
{
title = "Scroll Wall According to Linedef (Displacement)";
title = "Scroll Tagged Wall (Displacement)";
prefix = "(504)";
flags128text = "[7] Use texture offsets";
flags256text = "[8] Scroll back side";
}
505
{
title = "Scroll Texture by Front Side Offsets";
title = "Scroll Front Wall by Front Side Offsets";
prefix = "(505)";
}
506
{
title = "Scroll Texture by Back Side Offsets";
title = "Scroll Front Wall by Back Side Offsets";
prefix = "(506)";
}
507
{
title = "Scroll Back Wall by Front Side Offsets";
prefix = "(507)";
}
508
{
title = "Scroll Back Wall by Back Side Offsets";
prefix = "(508)";
}
}
planescroll

View file

@ -931,11 +931,8 @@ static inline void AM_drawWalls(void)
l.b.y = lines[i].v2->y >> FRACTOMAPBITS;
#define SLOPEPARAMS(slope, end1, end2, normalheight) \
if (slope) { \
end1 = P_GetZAt(slope, lines[i].v1->x, lines[i].v1->y); \
end2 = P_GetZAt(slope, lines[i].v2->x, lines[i].v2->y); \
} else \
end1 = end2 = normalheight;
end1 = P_GetZAt(slope, lines[i].v1->x, lines[i].v1->y, normalheight); \
end2 = P_GetZAt(slope, lines[i].v2->x, lines[i].v2->y, normalheight);
SLOPEPARAMS(lines[i].frontsector->f_slope, frontf1, frontf2, lines[i].frontsector->floorheight)
SLOPEPARAMS(lines[i].frontsector->c_slope, frontc1, frontc2, lines[i].frontsector->ceilingheight)

View file

@ -195,24 +195,25 @@ static inline void *G_ScpyTiccmd(ticcmd_t* dest, void* src, const size_t n)
// of 512 bytes is like 0.1)
UINT16 software_MAXPACKETLENGTH;
/** Guesses the value of a tic from its lowest byte and from maketic
/** Guesses the full value of a tic from its lowest byte, for a specific node
*
* \param low The lowest byte of the tic value
* \param node The node to deduce the tic for
* \return The full tic value
*
*/
tic_t ExpandTics(INT32 low)
tic_t ExpandTics(INT32 low, INT32 node)
{
INT32 delta;
delta = low - (maketic & UINT8_MAX);
delta = low - (nettics[node] & UINT8_MAX);
if (delta >= -64 && delta <= 64)
return (maketic & ~UINT8_MAX) + low;
return (nettics[node] & ~UINT8_MAX) + low;
else if (delta > 64)
return (maketic & ~UINT8_MAX) - 256 + low;
return (nettics[node] & ~UINT8_MAX) - 256 + low;
else //if (delta < -64)
return (maketic & ~UINT8_MAX) + 256 + low;
return (nettics[node] & ~UINT8_MAX) + 256 + low;
}
// -----------------------------------------------------------------
@ -522,6 +523,9 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i)
rsp->pflags = (UINT32)LONG(players[i].pflags); //pflags_t
rsp->panim = (UINT8)players[i].panim; //panim_t
rsp->angleturn = (INT16)SHORT(players[i].angleturn);
rsp->oldrelangleturn = (INT16)SHORT(players[i].oldrelangleturn);
rsp->aiming = (angle_t)LONG(players[i].aiming);
rsp->currentweapon = LONG(players[i].currentweapon);
rsp->ringweapons = LONG(players[i].ringweapons);
@ -663,6 +667,9 @@ static void resynch_read_player(resynch_pak *rsp)
players[i].pflags = (UINT32)LONG(rsp->pflags); //pflags_t
players[i].panim = (UINT8)rsp->panim; //panim_t
players[i].angleturn = (INT16)SHORT(rsp->angleturn);
players[i].oldrelangleturn = (INT16)SHORT(rsp->oldrelangleturn);
players[i].aiming = (angle_t)LONG(rsp->aiming);
players[i].currentweapon = LONG(rsp->currentweapon);
players[i].ringweapons = LONG(rsp->ringweapons);
@ -1495,7 +1502,7 @@ static boolean SV_SendServerConfig(INT32 node)
if (!playeringame[i])
continue;
netbuffer->u.servercfg.playerskins[i] = (UINT8)players[i].skin;
netbuffer->u.servercfg.playercolor[i] = (UINT8)players[i].skincolor;
netbuffer->u.servercfg.playercolor[i] = (UINT16)players[i].skincolor;
netbuffer->u.servercfg.playeravailabilities[i] = (UINT32)LONG(players[i].availabilities);
}
@ -1690,7 +1697,7 @@ static void CL_LoadReceivedSavegame(void)
// load a base level
if (P_LoadNetGame())
{
const INT32 actnum = mapheaderinfo[gamemap-1]->actnum;
const UINT8 actnum = mapheaderinfo[gamemap-1]->actnum;
CONS_Printf(M_GetText("Map is now \"%s"), G_BuildMapName(gamemap));
if (strcmp(mapheaderinfo[gamemap-1]->lvlttl, ""))
{
@ -3291,7 +3298,6 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
boolean splitscreenplayer;
boolean rejoined;
player_t *newplayer;
char *port;
if (playernum != serverplayer && !IsPlayerAdmin(playernum))
{
@ -3322,10 +3328,15 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
if (server && I_GetNodeAddress)
{
strcpy(playeraddress[newplayernum], I_GetNodeAddress(node));
port = strchr(playeraddress[newplayernum], ':');
if (port)
*port = '\0';
const char *address = I_GetNodeAddress(node);
char *port = NULL;
if (address) // MI: fix msvcrt.dll!_mbscat crash?
{
strcpy(playeraddress[newplayernum], address);
port = strchr(playeraddress[newplayernum], ':');
if (port)
*port = '\0';
}
}
}
@ -3346,6 +3357,7 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
displayplayer = newplayernum;
secondarydisplayplayer = newplayernum;
DEBFILE("spawning me\n");
ticcmd_oldangleturn[0] = newplayer->oldrelangleturn;
}
else
{
@ -3353,7 +3365,9 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
DEBFILE("spawning my brother\n");
if (botingame)
newplayer->bot = 1;
ticcmd_oldangleturn[1] = newplayer->oldrelangleturn;
}
P_ForceLocalAngle(newplayer, (angle_t)(newplayer->angleturn << 16));
D_SendPlayerConfig();
addedtogame = true;
@ -3361,11 +3375,6 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
{
if (newplayer->mo)
{
if (!splitscreenplayer)
localangle = newplayer->mo->angle;
else
localangle2 = newplayer->mo->angle;
newplayer->viewheight = 41*newplayer->height/48;
if (newplayer->mo->eflags & MFE_VERTICALFLIP)
@ -3877,7 +3886,7 @@ static void HandlePacketFromAwayNode(SINT8 node)
for (j = 0; j < MAXPLAYERS; j++)
{
if (netbuffer->u.servercfg.playerskins[j] == 0xFF
&& netbuffer->u.servercfg.playercolor[j] == 0xFF
&& netbuffer->u.servercfg.playercolor[j] == 0xFFFF
&& netbuffer->u.servercfg.playeravailabilities[j] == 0xFFFFFFFF)
continue; // not in game
@ -3999,8 +4008,8 @@ static void HandlePacketFromPlayer(SINT8 node)
// To save bytes, only the low byte of tic numbers are sent
// Use ExpandTics to figure out what the rest of the bytes are
realstart = ExpandTics(netbuffer->u.clientpak.client_tic);
realend = ExpandTics(netbuffer->u.clientpak.resendfrom);
realstart = ExpandTics(netbuffer->u.clientpak.client_tic, node);
realend = ExpandTics(netbuffer->u.clientpak.resendfrom, node);
if (netbuffer->packettype == PT_CLIENTMIS || netbuffer->packettype == PT_CLIENT2MIS
|| netbuffer->packettype == PT_NODEKEEPALIVEMIS
@ -4252,15 +4261,15 @@ static void HandlePacketFromPlayer(SINT8 node)
break;
}
realstart = ExpandTics(netbuffer->u.serverpak.starttic);
realstart = netbuffer->u.serverpak.starttic;
realend = realstart + netbuffer->u.serverpak.numtics;
if (!txtpak)
txtpak = (UINT8 *)&netbuffer->u.serverpak.cmds[netbuffer->u.serverpak.numslots
* netbuffer->u.serverpak.numtics];
if (realend > gametic + BACKUPTICS)
realend = gametic + BACKUPTICS;
if (realend > gametic + CLIENTBACKUPTICS)
realend = gametic + CLIENTBACKUPTICS;
cl_packetmissed = realstart > neededtic;
if (realstart <= neededtic && realend > neededtic)
@ -4603,11 +4612,11 @@ static void SV_SendTics(void)
for (n = 1; n < MAXNETNODES; n++)
if (nodeingame[n])
{
lasttictosend = maketic;
// assert supposedtics[n]>=nettics[n]
realfirsttic = supposedtics[n];
if (realfirsttic >= maketic)
lasttictosend = min(maketic, realfirsttic + CLIENTBACKUPTICS);
if (realfirsttic >= lasttictosend)
{
// well we have sent all tics we will so use extrabandwidth
// to resent packet that are supposed lost (this is necessary since lost
@ -4616,7 +4625,7 @@ static void SV_SendTics(void)
DEBFILE(va("Nothing to send node %u mak=%u sup=%u net=%u \n",
n, maketic, supposedtics[n], nettics[n]));
realfirsttic = nettics[n];
if (realfirsttic >= maketic || (I_GetTime() + n)&3)
if (realfirsttic >= lasttictosend || (I_GetTime() + n)&3)
// all tic are ok
continue;
DEBFILE(va("Sent %d anyway\n", realfirsttic));
@ -4659,7 +4668,7 @@ static void SV_SendTics(void)
// Send the tics
netbuffer->packettype = PT_SERVERTICS;
netbuffer->u.serverpak.starttic = (UINT8)realfirsttic;
netbuffer->u.serverpak.starttic = realfirsttic;
netbuffer->u.serverpak.numtics = (UINT8)(lasttictosend - realfirsttic);
netbuffer->u.serverpak.numslots = (UINT8)SHORT(doomcom->numslots);
bufpos = (UINT8 *)&netbuffer->u.serverpak.cmds;
@ -4721,41 +4730,6 @@ static void Local_Maketic(INT32 realtics)
localcmds2.angleturn |= TICCMD_RECEIVED;
}
// This function is utter bullshit and is responsible for
// the random desynch that happens when a player spawns.
// This is because ticcmds are resent to clients if a packet
// was dropped, and thus modifying them can lead to several
// clients having their ticcmds set to different values.
void SV_SpawnPlayer(INT32 playernum, INT32 x, INT32 y, angle_t angle)
{
tic_t tic;
UINT8 numadjust = 0;
(void)x;
(void)y;
// Revisionist history: adjust the angles in the ticcmds received
// for this player, because they actually preceded the player
// spawning, but will be applied afterwards.
for (tic = server ? maketic : (neededtic - 1); tic >= gametic; tic--)
{
if (numadjust++ == BACKUPTICS)
{
DEBFILE(va("SV_SpawnPlayer: All netcmds for player %d adjusted!\n", playernum));
// We already adjusted them all, waste of time doing the same thing over and over
// This shouldn't happen normally though, either gametic was 0 (which is handled now anyway)
// or maketic >= gametic + BACKUPTICS
// -- Monster Iestyn 16/01/18
break;
}
netcmds[tic%BACKUPTICS][playernum].angleturn = (INT16)((angle>>16) | TICCMD_RECEIVED);
if (!tic) // failsafe for gametic == 0 -- Monster Iestyn 16/01/18
break;
}
}
// create missed tic
static void SV_Maketic(void)
{

View file

@ -34,6 +34,7 @@ applications may follow different packet versions.
// Networking and tick handling related.
#define BACKUPTICS 96
#define CLIENTBACKUPTICS 32
#define MAXTEXTCMD 256
//
// Packet structure
@ -128,7 +129,7 @@ typedef struct
// this packet is too large
typedef struct
{
UINT8 starttic;
tic_t starttic;
UINT8 numtics;
UINT8 numslots; // "Slots filled": Highest player number in use plus one.
ticcmd_t cmds[45]; // Normally [BACKUPTIC][MAXPLAYERS] but too large
@ -171,6 +172,9 @@ typedef struct
UINT32 pflags; // pflags_t
UINT8 panim; // panim_t
INT16 angleturn;
INT16 oldrelangleturn;
angle_t aiming;
INT32 currentweapon;
INT32 ringweapons;
@ -188,7 +192,7 @@ typedef struct
SINT8 xtralife;
SINT8 pity;
UINT8 skincolor;
UINT16 skincolor;
INT32 skin;
UINT32 availabilities;
// Just in case Lua does something like
@ -308,7 +312,7 @@ typedef struct
// 0xFF == not in game; else player skin num
UINT8 playerskins[MAXPLAYERS];
UINT8 playercolor[MAXPLAYERS];
UINT16 playercolor[MAXPLAYERS];
UINT32 playeravailabilities[MAXPLAYERS];
UINT8 gametype;
@ -414,7 +418,7 @@ typedef struct
{
char name[MAXPLAYERNAME+1];
UINT8 skin;
UINT8 color;
UINT16 color;
UINT32 pflags;
UINT32 score;
UINT8 ctfteam;
@ -520,7 +524,7 @@ extern consvar_t cv_resynchattempts, cv_blamecfail;
extern consvar_t cv_maxsend, cv_noticedownload, cv_downloadspeed;
// Used in d_net, the only dependence
tic_t ExpandTics(INT32 low);
tic_t ExpandTics(INT32 low, INT32 node);
void D_ClientServerInit(void);
// Initialise the other field
@ -534,7 +538,6 @@ void NetUpdate(void);
void SV_StartSinglePlayerServer(void);
boolean SV_SpawnServer(void);
void SV_SpawnPlayer(INT32 playernum, INT32 x, INT32 y, angle_t angle);
void SV_StopServer(void);
void SV_ResetServer(void);
void CL_AddSplitscreenPlayer(void);

View file

@ -125,6 +125,9 @@ boolean advancedemo;
INT32 debugload = 0;
#endif
UINT16 numskincolors;
menucolor_t *menucolorhead, *menucolortail;
char savegamename[256];
char srb2home[256] = ".";
@ -1191,6 +1194,10 @@ void D_SRB2Main(void)
if (M_CheckParm("-password") && M_IsNextParm())
D_SetPassword(M_GetNextParm());
// player setup menu colors must be initialized before
// any wad file is added, as they may contain colors themselves
M_InitPlayerSetupColors();
CONS_Printf("Z_Init(): Init zone memory allocation daemon. \n");
Z_Init();

View file

@ -811,6 +811,7 @@ static const char *packettypename[NUMPACKETTYPE] =
"CLIENTJOIN",
"NODETIMEOUT",
"RESYNCHING",
"LOGIN",
"PING"
};
@ -837,7 +838,7 @@ static void DebugPrintpacket(const char *header)
size_t ntxtcmd = &((UINT8 *)netbuffer)[doomcom->datalength] - cmd;
fprintf(debugfile, " firsttic %u ply %d tics %d ntxtcmd %s\n ",
(UINT32)ExpandTics(serverpak->starttic), serverpak->numslots, serverpak->numtics, sizeu1(ntxtcmd));
(UINT32)serverpak->starttic, serverpak->numslots, serverpak->numtics, sizeu1(ntxtcmd));
/// \todo Display more readable information about net commands
fprintfstringnewline((char *)cmd, ntxtcmd);
/*fprintfstring((char *)cmd, 3);
@ -856,8 +857,8 @@ static void DebugPrintpacket(const char *header)
case PT_NODEKEEPALIVE:
case PT_NODEKEEPALIVEMIS:
fprintf(debugfile, " tic %4u resendfrom %u\n",
(UINT32)ExpandTics(netbuffer->u.clientpak.client_tic),
(UINT32)ExpandTics (netbuffer->u.clientpak.resendfrom));
(UINT32)ExpandTics(netbuffer->u.clientpak.client_tic, doomcom->remotenode),
(UINT32)ExpandTics (netbuffer->u.clientpak.resendfrom, doomcom->remotenode));
break;
case PT_TEXTCMD:
case PT_TEXTCMD2:

View file

@ -225,6 +225,7 @@ consvar_t cv_allowseenames = {"allowseenames", "Yes", CV_NETVAR, CV_YesNo, NULL,
consvar_t cv_playername = {"name", "Sonic", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Name_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_playername2 = {"name2", "Tails", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Name2_OnChange, 0, NULL, NULL, 0, 0, NULL};
// player colors
UINT16 lastgoodcolor = SKINCOLOR_BLUE, lastgoodcolor2 = SKINCOLOR_BLUE;
consvar_t cv_playercolor = {"color", "Blue", CV_CALL|CV_NOINIT, Color_cons_t, Color_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_playercolor2 = {"color2", "Orange", CV_CALL|CV_NOINIT, Color_cons_t, Color2_OnChange, 0, NULL, NULL, 0, 0, NULL};
// player's skin, saved for commodity, when using a favorite skins wad..
@ -619,7 +620,7 @@ void D_RegisterClientCommands(void)
for (i = 0; i < MAXSKINCOLORS; i++)
{
Color_cons_t[i].value = i;
Color_cons_t[i].strvalue = Color_Names[i];
Color_cons_t[i].strvalue = skincolors[i].name;
}
Color_cons_t[MAXSKINCOLORS].value = 0;
Color_cons_t[MAXSKINCOLORS].strvalue = NULL;
@ -1221,15 +1222,20 @@ static void SendNameAndColor(void)
CV_StealthSetValue(&cv_playercolor, skincolor_blueteam);
}
// never allow the color "none"
if (!cv_playercolor.value)
// don't allow inaccessible colors
if (!skincolors[cv_playercolor.value].accessible)
{
if (players[consoleplayer].skincolor)
if (players[consoleplayer].skincolor && skincolors[players[consoleplayer].skincolor].accessible)
CV_StealthSetValue(&cv_playercolor, players[consoleplayer].skincolor);
else if (skins[players[consoleplayer].skin].prefcolor)
CV_StealthSetValue(&cv_playercolor, skins[players[consoleplayer].skin].prefcolor);
else
else if (skincolors[atoi(cv_playercolor.defaultvalue)].accessible)
CV_StealthSet(&cv_playercolor, cv_playercolor.defaultvalue);
else if (skins[players[consoleplayer].skin].prefcolor && skincolors[skins[players[consoleplayer].skin].prefcolor].accessible)
CV_StealthSetValue(&cv_playercolor, skins[players[consoleplayer].skin].prefcolor);
else {
UINT16 i = 0;
while (i<numskincolors && !skincolors[i].accessible) i++;
CV_StealthSetValue(&cv_playercolor, (i != numskincolors) ? i : SKINCOLOR_BLUE);
}
}
if (!strcmp(cv_playername.string, player_names[consoleplayer])
@ -1276,10 +1282,10 @@ static void SendNameAndColor(void)
{
CV_StealthSetValue(&cv_playercolor, skins[cv_skin.value].prefcolor);
players[consoleplayer].skincolor = cv_playercolor.value % MAXSKINCOLORS;
players[consoleplayer].skincolor = cv_playercolor.value % numskincolors;
if (players[consoleplayer].mo)
players[consoleplayer].mo->color = (UINT8)players[consoleplayer].skincolor;
players[consoleplayer].mo->color = (UINT16)players[consoleplayer].skincolor;
}*/
}
else
@ -1317,7 +1323,7 @@ static void SendNameAndColor(void)
// Finally write out the complete packet and send it off.
WRITESTRINGN(p, cv_playername.zstring, MAXPLAYERNAME);
WRITEUINT32(p, (UINT32)players[consoleplayer].availabilities);
WRITEUINT8(p, (UINT8)cv_playercolor.value);
WRITEUINT16(p, (UINT16)cv_playercolor.value);
WRITEUINT8(p, (UINT8)cv_skin.value);
SendNetXCmd(XD_NAMEANDCOLOR, buf, p - buf);
}
@ -1344,15 +1350,20 @@ static void SendNameAndColor2(void)
CV_StealthSetValue(&cv_playercolor2, skincolor_blueteam);
}
// never allow the color "none"
if (!cv_playercolor2.value)
// don't allow inaccessible colors
if (!skincolors[cv_playercolor2.value].accessible)
{
if (players[secondplaya].skincolor)
if (players[secondplaya].skincolor && skincolors[players[secondplaya].skincolor].accessible)
CV_StealthSetValue(&cv_playercolor2, players[secondplaya].skincolor);
else if (skins[players[secondplaya].skin].prefcolor)
else if (skincolors[atoi(cv_playercolor2.defaultvalue)].accessible)
CV_StealthSet(&cv_playercolor, cv_playercolor2.defaultvalue);
else if (skins[players[secondplaya].skin].prefcolor && skincolors[skins[players[secondplaya].skin].prefcolor].accessible)
CV_StealthSetValue(&cv_playercolor2, skins[players[secondplaya].skin].prefcolor);
else
CV_StealthSet(&cv_playercolor2, cv_playercolor2.defaultvalue);
else {
UINT16 i = 0;
while (i<numskincolors && !skincolors[i].accessible) i++;
CV_StealthSetValue(&cv_playercolor2, (i != numskincolors) ? i : SKINCOLOR_BLUE);
}
}
players[secondplaya].availabilities = R_GetSkinAvailabilities();
@ -1405,7 +1416,7 @@ static void SendNameAndColor2(void)
{
CV_StealthSetValue(&cv_playercolor2, skins[players[secondplaya].skin].prefcolor);
players[secondplaya].skincolor = cv_playercolor2.value % MAXSKINCOLORS;
players[secondplaya].skincolor = cv_playercolor2.value % numskincolors;
if (players[secondplaya].mo)
players[secondplaya].mo->color = players[secondplaya].skincolor;
@ -1428,7 +1439,8 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
{
player_t *p = &players[playernum];
char name[MAXPLAYERNAME+1];
UINT8 color, skin;
UINT16 color;
UINT8 skin;
#ifdef PARANOIA
if (playernum < 0 || playernum > MAXPLAYERS)
@ -1447,7 +1459,7 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
READSTRINGN(*cp, name, MAXPLAYERNAME);
p->availabilities = READUINT32(*cp);
color = READUINT8(*cp);
color = READUINT16(*cp);
skin = READUINT8(*cp);
// set name
@ -1455,9 +1467,9 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
SetPlayerName(playernum, name);
// set color
p->skincolor = color % MAXSKINCOLORS;
p->skincolor = color % numskincolors;
if (p->mo)
p->mo->color = (UINT8)p->skincolor;
p->mo->color = (UINT16)p->skincolor;
// normal player colors
if (server && (p != &players[consoleplayer] && p != &players[secondarydisplayplayer]))
@ -1474,8 +1486,8 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
kick = true;
}
// don't allow color "none"
if (!p->skincolor)
// don't allow inaccessible colors
if (skincolors[p->skincolor].accessible == false)
kick = true;
// availabilities
@ -4473,25 +4485,30 @@ static void Skin2_OnChange(void)
*/
static void Color_OnChange(void)
{
if (!Playing())
return; // do whatever you want
if (!(cv_debug || devparm) && !(multiplayer || netgame)) // In single player.
{
CV_StealthSet(&cv_skin, skins[players[consoleplayer].skin].name);
return;
}
if (!P_PlayerMoving(consoleplayer))
{
// Color change menu scrolling fix is no longer necessary
SendNameAndColor();
if (!Playing()) {
if (!cv_playercolor.value || !skincolors[cv_playercolor.value].accessible)
CV_StealthSetValue(&cv_playercolor, lastgoodcolor);
}
else
{
CV_StealthSetValue(&cv_playercolor,
players[consoleplayer].skincolor);
if (!(cv_debug || devparm) && !(multiplayer || netgame)) // In single player.
{
CV_StealthSet(&cv_skin, skins[players[consoleplayer].skin].name);
return;
}
if (!P_PlayerMoving(consoleplayer) && skincolors[players[consoleplayer].skincolor].accessible == true)
{
// Color change menu scrolling fix is no longer necessary
SendNameAndColor();
}
else
{
CV_StealthSetValue(&cv_playercolor,
players[consoleplayer].skincolor);
}
}
lastgoodcolor = cv_playercolor.value;
}
/** Sends a color change for the secondary splitscreen player, unless that
@ -4502,18 +4519,24 @@ static void Color_OnChange(void)
static void Color2_OnChange(void)
{
if (!Playing() || !splitscreen)
return; // do whatever you want
if (!P_PlayerMoving(secondarydisplayplayer))
{
// Color change menu scrolling fix is no longer necessary
SendNameAndColor2();
if (!cv_playercolor2.value || !skincolors[cv_playercolor2.value].accessible)
CV_StealthSetValue(&cv_playercolor2, lastgoodcolor2);
}
else
{
CV_StealthSetValue(&cv_playercolor2,
players[secondarydisplayplayer].skincolor);
if (!P_PlayerMoving(secondarydisplayplayer) && skincolors[players[secondarydisplayplayer].skincolor].accessible == true)
{
// Color change menu scrolling fix is no longer necessary
SendNameAndColor2();
}
else
{
CV_StealthSetValue(&cv_playercolor2,
players[secondarydisplayplayer].skincolor);
}
}
lastgoodcolor2 = cv_playercolor2.value;
}
/** Displays the result of the chat being muted or unmuted.

View file

@ -239,7 +239,8 @@ typedef enum
CR_MACESPIN,
CR_MINECART,
CR_ROLLOUT,
CR_PTERABYTE
CR_PTERABYTE,
CR_DUSTDEVIL
} carrytype_t; // pw_carry
// Player powers. (don't edit this comment)
@ -331,6 +332,9 @@ typedef struct player_s
angle_t viewrollangle;
INT16 angleturn;
INT16 oldrelangleturn;
// Mouse aiming, where the guy is looking at!
// It is updated with cmd->aiming.
angle_t aiming;
@ -365,7 +369,7 @@ typedef struct player_s
UINT16 flashpal;
// Player skin colorshift, 0-15 for which color to draw player.
UINT8 skincolor;
UINT16 skincolor;
INT32 skin;
UINT32 availabilities;

View file

@ -56,10 +56,12 @@ int vsnprintf(char *str, size_t n, const char *fmt, va_list ap);
// The crazy word-reading stuff uses these.
static char *FREE_STATES[NUMSTATEFREESLOTS];
static char *FREE_MOBJS[NUMMOBJFREESLOTS];
static char *FREE_SKINCOLORS[NUMCOLORFREESLOTS];
static UINT8 used_spr[(NUMSPRITEFREESLOTS / 8) + 1]; // Bitwise flag for sprite freeslot in use! I would use ceil() here if I could, but it only saves 1 byte of memory anyway.
#define initfreeslots() {\
memset(FREE_STATES,0,sizeof(char *) * NUMSTATEFREESLOTS);\
memset(FREE_MOBJS,0,sizeof(char *) * NUMMOBJFREESLOTS);\
memset(FREE_SKINCOLORS,0,sizeof(char *) * NUMCOLORFREESLOTS);\
memset(used_spr,0,sizeof(UINT8) * ((NUMSPRITEFREESLOTS / 8) + 1));\
}
@ -77,6 +79,7 @@ static hudnum_t get_huditem(const char *word);
static menutype_t get_menutype(const char *word);
//static INT16 get_gametype(const char *word);
//static powertype_t get_power(const char *word);
skincolornum_t get_skincolor(const char *word);
boolean deh_loaded = false;
static int dbg_line;
@ -392,7 +395,7 @@ static void readPlayer(MYFILE *f, INT32 num)
// It works down here, though.
{
INT32 numline = 0;
for (i = 0; i < MAXLINELEN-1; i++)
for (i = 0; (size_t)i < sizeof(description[num].notes)-1; i++)
{
if (numline < 20 && description[num].notes[i] == '\n')
numline++;
@ -449,7 +452,7 @@ static void readPlayer(MYFILE *f, INT32 num)
else if (fastcmp(word, "OPPOSITECOLOR") || fastcmp(word, "OPPOSITECOLOUR"))
{
SLOTFOUND
description[num].oppositecolor = (UINT8)get_number(word2);
description[num].oppositecolor = (UINT16)get_number(word2);
}
else if (fastcmp(word, "NAMETAG") || fastcmp(word, "TAGNAME"))
{
@ -459,12 +462,12 @@ static void readPlayer(MYFILE *f, INT32 num)
else if (fastcmp(word, "TAGTEXTCOLOR") || fastcmp(word, "TAGTEXTCOLOUR"))
{
SLOTFOUND
description[num].tagtextcolor = (UINT8)get_number(word2);
description[num].tagtextcolor = (UINT16)get_number(word2);
}
else if (fastcmp(word, "TAGOUTLINECOLOR") || fastcmp(word, "TAGOUTLINECOLOUR"))
{
SLOTFOUND
description[num].tagoutlinecolor = (UINT8)get_number(word2);
description[num].tagoutlinecolor = (UINT16)get_number(word2);
}
else if (fastcmp(word, "STATUS"))
{
@ -571,6 +574,16 @@ static void readfreeslots(MYFILE *f)
break;
}
}
else if (fastcmp(type, "SKINCOLOR"))
{
for (i = 0; i < NUMCOLORFREESLOTS; i++)
if (!FREE_SKINCOLORS[i]) {
FREE_SKINCOLORS[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL);
strcpy(FREE_SKINCOLORS[i],word);
M_AddMenuColor(numskincolors++);
break;
}
}
else if (fastcmp(type, "SPR2"))
{
// Search if we already have an SPR2 by that name...
@ -753,6 +766,84 @@ static void readthing(MYFILE *f, INT32 num)
Z_Free(s);
}
static void readskincolor(MYFILE *f, INT32 num)
{
char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
char *word, *word2, *word3;
char *tmp;
Color_cons_t[num].value = num;
do
{
if (myfgets(s, MAXLINELEN, f))
{
if (s[0] == '\n')
break;
tmp = strchr(s, '#');
if (tmp)
*tmp = '\0';
if (s == tmp)
continue; // Skip comment lines, but don't break.
word = strtok(s, " ");
if (word)
strupr(word);
else
break;
word2 = strtok(NULL, " = ");
if (word2) {
word3 = Z_StrDup(word2);
strupr(word2);
} else
break;
if (word2[strlen(word2)-1] == '\n')
word2[strlen(word2)-1] = '\0';
if (word3[strlen(word3)-1] == '\n')
word3[strlen(word3)-1] = '\0';
if (fastcmp(word, "NAME"))
{
deh_strlcpy(skincolors[num].name, word3,
sizeof (skincolors[num].name), va("Skincolor %d: name", num));
}
else if (fastcmp(word, "RAMP"))
{
UINT8 i;
tmp = strtok(word2,",");
for (i = 0; i < COLORRAMPSIZE; i++) {
skincolors[num].ramp[i] = (UINT8)get_number(tmp);
if ((tmp = strtok(NULL,",")) == NULL)
break;
}
}
else if (fastcmp(word, "INVCOLOR"))
{
skincolors[num].invcolor = (UINT16)get_number(word2);
}
else if (fastcmp(word, "INVSHADE"))
{
skincolors[num].invshade = get_number(word2)%COLORRAMPSIZE;
}
else if (fastcmp(word, "CHATCOLOR"))
{
skincolors[num].chatcolor = get_number(word2);
}
else if (fastcmp(word, "ACCESSIBLE"))
{
if (num > FIRSTSUPERCOLOR)
skincolors[num].accessible = (boolean)(atoi(word2) || word2[0] == 'T' || word2[0] == 'Y');
}
else
deh_warning("Skincolor %d: unknown word '%s'", num, word);
}
} while (!myfeof(f)); // finish when the line is empty
Z_Free(s);
}
#ifdef HWRENDER
static void readlight(MYFILE *f, INT32 num)
{
@ -1174,7 +1265,7 @@ static void readgametype(MYFILE *f, char *gtname)
// It works down here, though.
{
INT32 numline = 0;
for (i = 0; i < MAXLINELEN-1; i++)
for (i = 0; (size_t)i < sizeof(gtdescription)-1; i++)
{
if (numline < 20 && gtdescription[i] == '\n')
numline++;
@ -1557,7 +1648,7 @@ static void readlevelheader(MYFILE *f, INT32 num)
}
else if (fastcmp(word, "ACT"))
{
if (i >= 0 && i < 20) // 0 for no act number, TTL1 through TTL19
if (i >= 0 && i <= 99) // 0 for no act number
mapheaderinfo[num-1]->actnum = (UINT8)i;
else
deh_warning("Level header %d: invalid act number %d", num, i);
@ -2813,7 +2904,7 @@ static actionpointer_t actionpointers[] =
{{A_ThrownRing}, "A_THROWNRING"},
{{A_SetSolidSteam}, "A_SETSOLIDSTEAM"},
{{A_UnsetSolidSteam}, "A_UNSETSOLIDSTEAM"},
{{A_SignSpin}, "S_SIGNSPIN"},
{{A_SignSpin}, "A_SIGNSPIN"},
{{A_SignPlayer}, "A_SIGNPLAYER"},
{{A_OverlayThink}, "A_OVERLAYTHINK"},
{{A_JetChase}, "A_JETCHASE"},
@ -3952,19 +4043,19 @@ static void readmaincfg(MYFILE *f)
}
else if (fastcmp(word, "REDTEAM"))
{
skincolor_redteam = (UINT8)get_number(word2);
skincolor_redteam = (UINT16)get_number(word2);
}
else if (fastcmp(word, "BLUETEAM"))
{
skincolor_blueteam = (UINT8)get_number(word2);
skincolor_blueteam = (UINT16)get_number(word2);
}
else if (fastcmp(word, "REDRING"))
{
skincolor_redring = (UINT8)get_number(word2);
skincolor_redring = (UINT16)get_number(word2);
}
else if (fastcmp(word, "BLUERING"))
{
skincolor_bluering = (UINT8)get_number(word2);
skincolor_bluering = (UINT16)get_number(word2);
}
else if (fastcmp(word, "INVULNTICS"))
{
@ -4556,6 +4647,18 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile)
ignorelines(f);
}
}
else if (fastcmp(word, "SKINCOLOR") || fastcmp(word, "COLOR"))
{
if (i == 0 && word2[0] != '0') // If word2 isn't a number
i = get_skincolor(word2); // find a skincolor by name
if (i < numskincolors && i >= (INT32)SKINCOLOR_FIRSTFREESLOT)
readskincolor(f, i);
else
{
deh_warning("Skincolor %d out of range (%d - %d)", i, SKINCOLOR_FIRSTFREESLOT, numskincolors-1);
ignorelines(f);
}
}
else if (fastcmp(word, "SPRITE2"))
{
if (i == 0 && word2[0] != '0') // If word2 isn't a number
@ -8999,8 +9102,6 @@ static const char *const ML_LIST[16] = {
"TFERLINE"
};
// This DOES differ from r_draw's Color_Names, unfortunately.
// Also includes Super colors
static const char *COLOR_ENUMS[] = {
"NONE", // SKINCOLOR_NONE,
@ -9436,7 +9537,8 @@ struct {
// SKINCOLOR_ doesn't include these..!
{"MAXSKINCOLORS",MAXSKINCOLORS},
{"MAXTRANSLATIONS",MAXTRANSLATIONS},
{"FIRSTSUPERCOLOR",FIRSTSUPERCOLOR},
{"NUMSUPERCOLORS",NUMSUPERCOLORS},
// Precipitation
{"PRECIP_NONE",PRECIP_NONE},
@ -9487,6 +9589,7 @@ struct {
{"CR_MINECART",CR_MINECART},
{"CR_ROLLOUT",CR_ROLLOUT},
{"CR_PTERABYTE",CR_PTERABYTE},
{"CR_DUSTDEVIL",CR_DUSTDEVIL},
// Ring weapons (ringweapons_t)
// Useful for A_GiveWeapon
@ -9937,6 +10040,26 @@ static statenum_t get_state(const char *word)
return S_NULL;
}
skincolornum_t get_skincolor(const char *word)
{ // Returns the value of SKINCOLOR_ enumerations
skincolornum_t i;
if (*word >= '0' && *word <= '9')
return atoi(word);
if (fastncmp("SKINCOLOR_",word,10))
word += 10; // take off the SKINCOLOR_
for (i = 0; i < NUMCOLORFREESLOTS; i++) {
if (!FREE_SKINCOLORS[i])
break;
if (fastcmp(word, FREE_SKINCOLORS[i]))
return SKINCOLOR_FIRSTFREESLOT+i;
}
for (i = 0; i < SKINCOLOR_FIRSTFREESLOT; i++)
if (fastcmp(word, COLOR_ENUMS[i]))
return i;
deh_warning("Couldn't find skincolor named 'SKINCOLOR_%s'",word);
return SKINCOLOR_GREEN;
}
static spritenum_t get_sprite(const char *word)
{ // Returns the value of SPR_ enumerations
spritenum_t i;
@ -10231,6 +10354,11 @@ static fixed_t find_const(const char **rword)
free(word);
return r;
}
else if (fastncmp("SKINCOLOR_",word,10)) {
r = get_skincolor(word);
free(word);
return r;
}
else if (fastncmp("MT_",word,3)) {
r = get_mobjtype(word);
free(word);
@ -10299,17 +10427,6 @@ static fixed_t find_const(const char **rword)
free(word);
return r;
}
else if (fastncmp("SKINCOLOR_",word,10)) {
char *p = word+10;
for (i = 0; i < MAXTRANSLATIONS; i++)
if (fastcmp(p, COLOR_ENUMS[i])) {
free(word);
return i;
}
const_warning("color",word);
free(word);
return 0;
}
else if (fastncmp("GRADE_",word,6))
{
char *p = word+6;
@ -10370,8 +10487,8 @@ void DEH_Check(void)
if (dehpowers != NUMPOWERS)
I_Error("You forgot to update the Dehacked powers list, you dolt!\n(%d powers defined, versus %s in the Dehacked list)\n", NUMPOWERS, sizeu1(dehpowers));
if (dehcolors != MAXTRANSLATIONS)
I_Error("You forgot to update the Dehacked colors list, you dolt!\n(%d colors defined, versus %s in the Dehacked list)\n", MAXTRANSLATIONS, sizeu1(dehcolors));
if (dehcolors != SKINCOLOR_FIRSTFREESLOT)
I_Error("You forgot to update the Dehacked colors list, you dolt!\n(%d colors defined, versus %s in the Dehacked list)\n", SKINCOLOR_FIRSTFREESLOT, sizeu1(dehcolors));
#endif
}
@ -10479,6 +10596,22 @@ static inline int lib_freeslot(lua_State *L)
if (i == NUMMOBJFREESLOTS)
CONS_Alert(CONS_WARNING, "Ran out of free MobjType slots!\n");
}
else if (fastcmp(type, "SKINCOLOR"))
{
skincolornum_t i;
for (i = 0; i < NUMCOLORFREESLOTS; i++)
if (!FREE_SKINCOLORS[i]) {
CONS_Printf("Skincolor SKINCOLOR_%s allocated.\n",word);
FREE_SKINCOLORS[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL);
strcpy(FREE_SKINCOLORS[i],word);
M_AddMenuColor(numskincolors++);
lua_pushinteger(L, i);
r++;
break;
}
if (i == NUMCOLORFREESLOTS)
CONS_Alert(CONS_WARNING, "Ran out of free skincolor slots!\n");
}
else if (fastcmp(type, "SPR2"))
{
// Search if we already have an SPR2 by that name...
@ -10810,13 +10943,20 @@ static inline int lib_getenum(lua_State *L)
}
else if (fastncmp("SKINCOLOR_",word,10)) {
p = word+10;
for (i = 0; i < MAXTRANSLATIONS; i++)
for (i = 0; i < NUMCOLORFREESLOTS; i++) {
if (!FREE_SKINCOLORS[i])
break;
if (fastcmp(p, FREE_SKINCOLORS[i])) {
lua_pushinteger(L, SKINCOLOR_FIRSTFREESLOT+i);
return 1;
}
}
for (i = 0; i < SKINCOLOR_FIRSTFREESLOT; i++)
if (fastcmp(p, COLOR_ENUMS[i])) {
lua_pushinteger(L, i);
return 1;
}
if (mathlib) return luaL_error(L, "skincolor '%s' could not be found.\n", word);
return 0;
return luaL_error(L, "skincolor '%s' could not be found.\n", word);
}
else if (fastncmp("GRADE_",word,6))
{

View file

@ -61,6 +61,8 @@
#include "../console.h"
#include "../m_menu.h"
#ifdef __GNUG__
#pragma implementation "../i_system.h"
#endif
@ -555,6 +557,7 @@ void I_Error (const char *error, ...)
if (demorecording)
G_CheckDemoStatus();
D_QuitNetGame ();
M_FreePlayerSetupColors();
if (shutdowning)
{
@ -622,6 +625,7 @@ void I_Quit (void)
if (demorecording)
G_CheckDemoStatus();
D_QuitNetGame ();
M_FreePlayerSetupColors();
I_ShutdownMusic();
I_ShutdownSound();
I_ShutdownCD();

View file

@ -218,10 +218,6 @@ typedef struct
#define ZSHIFT 4
extern const UINT8 Color_Index[MAXTRANSLATIONS-1][16];
extern const char *Color_Names[MAXSKINCOLORS + NUMSUPERCOLORS];
extern const UINT8 Color_Opposite[MAXSKINCOLORS - 1][2];
#define NUMMAPS 1035
#endif // __DOOMDATA__

View file

@ -239,6 +239,20 @@ extern char logfilename[1024];
#define PLAYERSMASK (MAXPLAYERS-1)
#define MAXPLAYERNAME 21
#define COLORRAMPSIZE 16
#define MAXCOLORNAME 32
#define NUMCOLORFREESLOTS 1024
typedef struct skincolor_s
{
char name[MAXCOLORNAME+1]; // Skincolor name
UINT8 ramp[COLORRAMPSIZE]; // Colormap ramp
UINT16 invcolor; // Signpost color
UINT8 invshade; // Signpost color shade
UINT16 chatcolor; // Chat color
boolean accessible; // Accessible by the color command + setup menu
} skincolor_t;
typedef enum
{
SKINCOLOR_NONE = 0,
@ -317,12 +331,10 @@ typedef enum
SKINCOLOR_RASPBERRY,
SKINCOLOR_ROSY,
// SKINCOLOR_? - one left before we bump up against 0x39, which isn't a HARD limit anymore but would be excessive
MAXSKINCOLORS,
FIRSTSUPERCOLOR,
// Super special awesome Super flashing colors!
SKINCOLOR_SUPERSILVER1 = MAXSKINCOLORS,
SKINCOLOR_SUPERSILVER1 = FIRSTSUPERCOLOR,
SKINCOLOR_SUPERSILVER2,
SKINCOLOR_SUPERSILVER3,
SKINCOLOR_SUPERSILVER4,
@ -376,9 +388,17 @@ typedef enum
SKINCOLOR_SUPERTAN4,
SKINCOLOR_SUPERTAN5,
MAXTRANSLATIONS,
NUMSUPERCOLORS = ((MAXTRANSLATIONS - MAXSKINCOLORS)/5)
} skincolors_t;
SKINCOLOR_FIRSTFREESLOT,
SKINCOLOR_LASTFREESLOT = SKINCOLOR_FIRSTFREESLOT + NUMCOLORFREESLOTS - 1,
MAXSKINCOLORS,
NUMSUPERCOLORS = ((SKINCOLOR_FIRSTFREESLOT - FIRSTSUPERCOLOR)/5)
} skincolornum_t;
extern UINT16 numskincolors;
extern skincolor_t skincolors[MAXSKINCOLORS];
// State updates, number of tics / second.
// NOTE: used to setup the timer rate, see I_StartupTimer().
@ -565,10 +585,6 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
// None of these that are disabled in the normal build are guaranteed to work perfectly
// Compile them at your own risk!
/// Backwards compatibility with SRB2CB's slope linedef types.
/// \note A simple shim that prints a warning.
#define ESLOPE_TYPESHIM
/// Allows the use of devmode in multiplayer. AKA "fishcake"
//#define NETGAME_DEVMODE

View file

@ -145,7 +145,7 @@ extern INT32 tutorialanalog; // store cv_analog[0] user value
extern boolean looptitle;
// CTF colors.
extern UINT8 skincolor_redteam, skincolor_blueteam, skincolor_redring, skincolor_bluering;
extern UINT16 skincolor_redteam, skincolor_blueteam, skincolor_redring, skincolor_bluering;
extern tic_t countdowntimer;
extern boolean countdowntimeup;
@ -620,6 +620,19 @@ extern mapthing_t *playerstarts[MAXPLAYERS]; // Cooperative
extern mapthing_t *bluectfstarts[MAXPLAYERS]; // CTF
extern mapthing_t *redctfstarts[MAXPLAYERS]; // CTF
#define WAYPOINTSEQUENCESIZE 256
#define NUMWAYPOINTSEQUENCES 256
extern mobj_t *waypoints[NUMWAYPOINTSEQUENCES][WAYPOINTSEQUENCESIZE];
extern UINT16 numwaypoints[NUMWAYPOINTSEQUENCES];
void P_AddWaypoint(UINT8 sequence, UINT8 id, mobj_t *waypoint);
mobj_t *P_GetFirstWaypoint(UINT8 sequence);
mobj_t *P_GetLastWaypoint(UINT8 sequence);
mobj_t *P_GetPreviousWaypoint(mobj_t *current, boolean wrap);
mobj_t *P_GetNextWaypoint(mobj_t *current, boolean wrap);
mobj_t *P_GetClosestWaypoint(UINT8 sequence, mobj_t *mo);
boolean P_IsDegeneratedWaypointSequence(UINT8 sequence);
// =====================================
// Internal parameters, used for engine.
// =====================================

View file

@ -2185,7 +2185,7 @@ void F_EndingDrawer(void)
for (i = 0; i < 7; ++i)
{
UINT8* colormap;
skincolors_t col = SKINCOLOR_GREEN;
skincolornum_t col = SKINCOLOR_GREEN;
switch (i)
{
case 1:

View file

@ -162,7 +162,9 @@ extern wipestyleflags_t wipestyleflags;
// Even my function names are borderline
boolean F_ShouldColormapFade(void);
boolean F_TryColormapFade(UINT8 wipecolor);
#ifndef NOWIPE
void F_DecideWipeStyle(void);
#endif
#define FADECOLORMAPDIV 8
#define FADECOLORMAPROWS (256/FADECOLORMAPDIV)

View file

@ -464,6 +464,7 @@ void F_WipeEndScreen(void)
*/
boolean F_ShouldColormapFade(void)
{
#ifndef NOWIPE
if ((wipestyleflags & (WSF_FADEIN|WSF_FADEOUT)) // only if one of those wipestyleflags are actually set
&& !(wipestyleflags & WSF_CROSSFADE)) // and if not crossfading
{
@ -479,11 +480,13 @@ boolean F_ShouldColormapFade(void)
// Menus
|| gamestate == GS_TIMEATTACK);
}
#endif
return false;
}
/** Decides what wipe style to use.
*/
#ifndef NOWIPE
void F_DecideWipeStyle(void)
{
// Set default wipe style
@ -493,6 +496,7 @@ void F_DecideWipeStyle(void)
if (F_ShouldColormapFade())
wipestyle = WIPESTYLE_COLORMAP;
}
#endif
/** Attempt to run a colormap fade,
provided all the conditionals were properly met.
@ -501,6 +505,7 @@ void F_DecideWipeStyle(void)
*/
boolean F_TryColormapFade(UINT8 wipecolor)
{
#ifndef NOWIPE
if (F_ShouldColormapFade())
{
#ifdef HWRENDER
@ -510,6 +515,7 @@ boolean F_TryColormapFade(UINT8 wipecolor)
return true;
}
else
#endif
{
F_WipeColorFill(wipecolor);
return false;
@ -608,6 +614,7 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu)
tic_t F_GetWipeLength(UINT8 wipetype)
{
#ifdef NOWIPE
(void)wipetype;
return 0;
#else
static char lumpname[10] = "FADEmmss";
@ -634,6 +641,7 @@ tic_t F_GetWipeLength(UINT8 wipetype)
boolean F_WipeExists(UINT8 wipetype)
{
#ifdef NOWIPE
(void)wipetype;
return false;
#else
static char lumpname[10] = "FADEmm00";

View file

@ -68,7 +68,7 @@ static struct {
UINT8 flags; // EZT flags
// EZT_COLOR
UINT8 color, lastcolor;
UINT16 color, lastcolor;
// EZT_SCALE
fixed_t scale, lastscale;
@ -82,7 +82,8 @@ static struct {
// There is no conflict here.
typedef struct demoghost {
UINT8 checksum[16];
UINT8 *buffer, *p, color, fadein;
UINT8 *buffer, *p, fadein;
UINT16 color;
UINT16 version;
mobj_t oldmo, *mo;
struct demoghost *next;
@ -93,7 +94,7 @@ demoghost *ghosts = NULL;
// DEMO RECORDING
//
#define DEMOVERSION 0x000c
#define DEMOVERSION 0x000d
#define DEMOHEADER "\xF0" "SRB2Replay" "\x0F"
#define DF_GHOST 0x01 // This demo contains ghost data too!
@ -165,7 +166,6 @@ void G_LoadMetal(UINT8 **buffer)
void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum)
{
UINT8 ziptic;
(void)playernum;
if (!demo_p || !demo_start)
return;
@ -183,6 +183,7 @@ void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum)
oldcmd.aiming = READINT16(demo_p);
G_CopyTiccmd(cmd, &oldcmd, 1);
players[playernum].angleturn = cmd->angleturn;
if (!(demoflags & DF_GHOST) && *demo_p == DEMOMARKER)
{
@ -280,13 +281,13 @@ void G_GhostAddColor(ghostcolor_t color)
{
if (!demorecording || !(demoflags & DF_GHOST))
return;
if (ghostext.lastcolor == (UINT8)color)
if (ghostext.lastcolor == (UINT16)color)
{
ghostext.flags &= ~EZT_COLOR;
return;
}
ghostext.flags |= EZT_COLOR;
ghostext.color = (UINT8)color;
ghostext.color = (UINT16)color;
}
void G_GhostAddScale(fixed_t scale)
@ -425,7 +426,7 @@ void G_WriteGhostTic(mobj_t *ghost)
WRITEUINT8(demo_p,ghostext.flags);
if (ghostext.flags & EZT_COLOR)
{
WRITEUINT8(demo_p,ghostext.color);
WRITEUINT16(demo_p,ghostext.color);
ghostext.lastcolor = ghostext.color;
}
if (ghostext.flags & EZT_SCALE)
@ -501,7 +502,7 @@ void G_WriteGhostTic(mobj_t *ghost)
WRITEUINT8(demo_p,ghost->player->followmobj->sprite2);
WRITEUINT16(demo_p,ghost->player->followmobj->sprite);
WRITEUINT8(demo_p,(ghost->player->followmobj->frame & FF_FRAMEMASK));
WRITEUINT8(demo_p,ghost->player->followmobj->color);
WRITEUINT16(demo_p,ghost->player->followmobj->color);
*followtic_p = followtic;
}
@ -566,7 +567,7 @@ void G_ConsGhostTic(void)
{ // But wait, there's more!
UINT8 xziptic = READUINT8(demo_p);
if (xziptic & EZT_COLOR)
demo_p++;
demo_p += (demoversion==0x000c) ? 1 : sizeof(UINT16);
if (xziptic & EZT_SCALE)
demo_p += sizeof(fixed_t);
if (xziptic & EZT_HIT)
@ -633,7 +634,7 @@ void G_ConsGhostTic(void)
demo_p++;
demo_p += sizeof(UINT16);
demo_p++;
demo_p++;
demo_p += (demoversion==0x000c) ? 1 : sizeof(UINT16);
}
// Re-synchronise
@ -731,7 +732,7 @@ void G_GhostTicker(void)
xziptic = READUINT8(g->p);
if (xziptic & EZT_COLOR)
{
g->color = READUINT8(g->p);
g->color = (g->version==0x000c) ? READUINT8(g->p) : READUINT16(g->p);
switch(g->color)
{
default:
@ -764,7 +765,7 @@ void G_GhostTicker(void)
if (xziptic & EZT_THOKMASK)
{ // Let's only spawn ONE of these per frame, thanks.
mobj_t *mobj;
INT32 type = -1;
UINT32 type = MT_NULL;
if (g->mo->skin)
{
skin_t *skin = (skin_t *)g->mo->skin;
@ -864,7 +865,7 @@ void G_GhostTicker(void)
g->mo->color += abs( ( (signed)( (unsigned)leveltime >> 1 ) % 9) - 4);
break;
case GHC_INVINCIBLE: // Mario invincibility (P_CheckInvincibilityTimer)
g->mo->color = (UINT8)(SKINCOLOR_RUBY + (leveltime % (MAXSKINCOLORS - SKINCOLOR_RUBY))); // Passes through all saturated colours
g->mo->color = (UINT16)(SKINCOLOR_RUBY + (leveltime % (FIRSTSUPERCOLOR - SKINCOLOR_RUBY))); // Passes through all saturated colours
break;
default:
break;
@ -918,7 +919,7 @@ void G_GhostTicker(void)
follow->sprite = READUINT16(g->p);
follow->frame = (READUINT8(g->p)) | (g->mo->frame & FF_TRANSMASK);
follow->angle = g->mo->angle;
follow->color = READUINT8(g->p);
follow->color = (g->version==0x000c) ? READUINT8(g->p) : READUINT16(g->p);
if (!(followtic & FZT_SPAWNED))
{
@ -996,7 +997,11 @@ void G_ReadMetalTic(mobj_t *metal)
// Read changes from the tic
if (ziptic & GZT_XYZ)
{
P_TeleportMove(metal, READFIXED(metal_p), READFIXED(metal_p), READFIXED(metal_p));
// make sure the values are read in the right order
oldmetal.x = READFIXED(metal_p);
oldmetal.y = READFIXED(metal_p);
oldmetal.z = READFIXED(metal_p);
P_TeleportMove(metal, oldmetal.x, oldmetal.y, oldmetal.z);
oldmetal.x = metal->x;
oldmetal.y = metal->y;
oldmetal.z = metal->z;
@ -1051,7 +1056,7 @@ void G_ReadMetalTic(mobj_t *metal)
if (xziptic & EZT_THOKMASK)
{ // Let's only spawn ONE of these per frame, thanks.
mobj_t *mobj;
INT32 type = -1;
UINT32 type = MT_NULL;
if (metal->skin)
{
skin_t *skin = (skin_t *)metal->skin;
@ -1158,7 +1163,7 @@ void G_ReadMetalTic(mobj_t *metal)
follow->sprite = READUINT16(metal_p);
follow->frame = READUINT32(metal_p); // NOT & FF_FRAMEMASK here, so 32 bits
follow->angle = metal->angle;
follow->color = READUINT8(metal_p);
follow->color = (metalversion==0x000c) ? READUINT8(metal_p) : READUINT16(metal_p);
if (!(followtic & FZT_SPAWNED))
{
@ -1340,7 +1345,7 @@ void G_WriteMetalTic(mobj_t *metal)
WRITEUINT8(demo_p,metal->player->followmobj->sprite2);
WRITEUINT16(demo_p,metal->player->followmobj->sprite);
WRITEUINT32(demo_p,metal->player->followmobj->frame); // NOT & FF_FRAMEMASK here, so 32 bits
WRITEUINT8(demo_p,metal->player->followmobj->color);
WRITEUINT16(demo_p,metal->player->followmobj->color);
*followtic_p = followtic;
}
@ -1394,7 +1399,7 @@ void G_RecordMetal(void)
void G_BeginRecording(void)
{
UINT8 i;
char name[16];
char name[MAXCOLORNAME+1];
player_t *player = &players[consoleplayer];
if (demo_p)
@ -1457,12 +1462,12 @@ void G_BeginRecording(void)
demo_p += 16;
// Color
for (i = 0; i < 16 && cv_playercolor.string[i]; i++)
for (i = 0; i < MAXCOLORNAME && cv_playercolor.string[i]; i++)
name[i] = cv_playercolor.string[i];
for (; i < 16; i++)
for (; i < MAXCOLORNAME; i++)
name[i] = '\0';
M_Memcpy(demo_p,name,16);
demo_p += 16;
M_Memcpy(demo_p,name,MAXCOLORNAME);
demo_p += MAXCOLORNAME;
// Stats
WRITEUINT8(demo_p,player->charability);
@ -1622,7 +1627,7 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
c = READUINT8(p); // SUBVERSION
I_Assert(c == SUBVERSION);
s = READUINT16(p);
I_Assert(s == DEMOVERSION);
I_Assert(s >= 0x000c);
p += 16; // demo checksum
I_Assert(!memcmp(p, "PLAY", 4));
p += 4; // PLAY
@ -1671,6 +1676,7 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
switch(oldversion) // demoversion
{
case DEMOVERSION: // latest always supported
case 0x000c: // all that changed between then and now was longer color name
break;
// too old, cannot support.
default:
@ -1744,15 +1750,15 @@ void G_DoPlayDemo(char *defdemoname)
{
UINT8 i;
lumpnum_t l;
char skin[17],color[17],*n,*pdemoname;
UINT8 version,subversion,charability,charability2,thrustfactor,accelstart,acceleration;
char skin[17],color[MAXCOLORNAME+1],*n,*pdemoname;
UINT8 version,subversion,charability,charability2,thrustfactor,accelstart,acceleration,cnamelen;
pflags_t pflags;
UINT32 randseed, followitem;
fixed_t camerascale,shieldscale,actionspd,mindash,maxdash,normalspeed,runspeed,jumpfactor,height,spinheight;
char msg[1024];
skin[16] = '\0';
color[16] = '\0';
color[MAXCOLORNAME] = '\0';
n = defdemoname+strlen(defdemoname);
while (*n != '/' && *n != '\\' && n != defdemoname)
@ -1810,6 +1816,11 @@ void G_DoPlayDemo(char *defdemoname)
switch(demoversion)
{
case DEMOVERSION: // latest always supported
cnamelen = MAXCOLORNAME;
break;
// all that changed between then and now was longer color name
case 0x000c:
cnamelen = 16;
break;
// too old, cannot support.
default:
@ -1876,8 +1887,8 @@ void G_DoPlayDemo(char *defdemoname)
demo_p += 16;
// Color
M_Memcpy(color,demo_p,16);
demo_p += 16;
M_Memcpy(color,demo_p,cnamelen);
demo_p += cnamelen;
charability = READUINT8(demo_p);
charability2 = READUINT8(demo_p);
@ -1941,7 +1952,9 @@ void G_DoPlayDemo(char *defdemoname)
// Set skin
SetPlayerSkin(0, skin);
#ifdef HAVE_BLUA
LUAh_MapChange(gamemap);
#endif
displayplayer = consoleplayer = 0;
memset(playeringame,0,sizeof(playeringame));
playeringame[0] = true;
@ -1949,8 +1962,9 @@ void G_DoPlayDemo(char *defdemoname)
G_InitNew(false, G_BuildMapName(gamemap), true, true, false);
// Set color
for (i = 0; i < MAXSKINCOLORS; i++)
if (!stricmp(Color_Names[i],color))
players[0].skincolor = skins[players[0].skin].prefcolor;
for (i = 0; i < numskincolors; i++)
if (!stricmp(skincolors[i].name,color))
{
players[0].skincolor = i;
break;
@ -1992,7 +2006,8 @@ void G_AddGhost(char *defdemoname)
{
INT32 i;
lumpnum_t l;
char name[17],skin[17],color[17],*n,*pdemoname,md5[16];
char name[17],skin[17],color[MAXCOLORNAME+1],*n,*pdemoname,md5[16];
UINT8 cnamelen;
demoghost *gh;
UINT8 flags;
UINT8 *buffer,*p;
@ -2047,6 +2062,11 @@ void G_AddGhost(char *defdemoname)
switch(ghostversion)
{
case DEMOVERSION: // latest always supported
cnamelen = MAXCOLORNAME;
break;
// all that changed between then and now was longer color name
case 0x000c:
cnamelen = 16;
break;
// too old, cannot support.
default:
@ -2109,8 +2129,8 @@ void G_AddGhost(char *defdemoname)
p += 16;
// Color
M_Memcpy(color, p,16);
p += 16;
M_Memcpy(color, p,cnamelen);
p += cnamelen;
// Ghosts do not have a player structure to put this in.
p++; // charability
@ -2198,10 +2218,10 @@ void G_AddGhost(char *defdemoname)
// Set color
gh->mo->color = ((skin_t*)gh->mo->skin)->prefcolor;
for (i = 0; i < MAXSKINCOLORS; i++)
if (!stricmp(Color_Names[i],color))
for (i = 0; i < numskincolors; i++)
if (!stricmp(skincolors[i].name,color))
{
gh->mo->color = (UINT8)i;
gh->mo->color = (UINT16)i;
break;
}
gh->oldmo.color = gh->mo->color;
@ -2292,6 +2312,7 @@ void G_DoPlayMetal(void)
switch(metalversion)
{
case DEMOVERSION: // latest always supported
case 0x000c: // all that changed between then and now was longer color name
break;
// too old, cannot support.
default:
@ -2332,6 +2353,38 @@ void G_DoneLevelLoad(void)
===================
*/
// Writes the demo's checksum, or just random garbage if you can't do that for some reason.
static void WriteDemoChecksum(void)
{
UINT8 *p = demobuffer+16; // checksum position
#ifdef NOMD5
UINT8 i;
for (i = 0; i < 16; i++, p++)
*p = P_RandomByte(); // This MD5 was chosen by fair dice roll and most likely < 50% correct.
#else
md5_buffer((char *)p+16, demo_p - (p+16), p); // make a checksum of everything after the checksum in the file.
#endif
}
// Stops recording a demo.
static void G_StopDemoRecording(void)
{
boolean saved = false;
WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker
WriteDemoChecksum();
saved = FIL_WriteFile(va(pandf, srb2home, demoname), demobuffer, demo_p - demobuffer); // finally output the file.
free(demobuffer);
demorecording = false;
if (modeattacking != ATTACKING_RECORD)
{
if (saved)
CONS_Printf(M_GetText("Demo %s recorded\n"), demoname);
else
CONS_Alert(CONS_WARNING, M_GetText("Demo %s not saved\n"), demoname);
}
}
// Stops metal sonic's demo. Separate from other functions because metal + replays can coexist
void G_StopMetalDemo(void)
{
@ -2349,20 +2402,8 @@ ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(boolean kill)
boolean saved = false;
if (demo_p)
{
UINT8 *p = demobuffer+16; // checksum position
if (kill)
WRITEUINT8(demo_p, METALDEATH); // add the metal death marker
else
WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker
#ifdef NOMD5
{
UINT8 i;
for (i = 0; i < 16; i++, p++)
*p = P_RandomByte(); // This MD5 was chosen by fair dice roll and most likely < 50% correct.
}
#else
md5_buffer((char *)p+16, demo_p - (p+16), (void *)p); // make a checksum of everything after the checksum in the file.
#endif
WRITEUINT8(demo_p, (kill) ? METALDEATH : DEMOMARKER); // add the demo end (or metal death) marker
WriteDemoChecksum();
saved = FIL_WriteFile(va("%sMS.LMP", G_BuildMapName(gamemap)), demobuffer, demo_p - demobuffer); // finally output the file.
}
free(demobuffer);
@ -2372,6 +2413,63 @@ ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(boolean kill)
I_Error("Failed to save demo!");
}
// Stops timing a demo.
static void G_StopTimingDemo(void)
{
INT32 demotime;
double f1, f2;
demotime = I_GetTime() - demostarttime;
if (!demotime)
return;
G_StopDemo();
timingdemo = false;
f1 = (double)demotime;
f2 = (double)framecount*TICRATE;
CONS_Printf(M_GetText("timed %u gametics in %d realtics - %u frames\n%f seconds, %f avg fps\n"),
leveltime,demotime,(UINT32)framecount,f1/TICRATE,f2/f1);
// CSV-readable timedemo results, for external parsing
if (timedemo_csv)
{
FILE *f;
const char *csvpath = va("%s"PATHSEP"%s", srb2home, "timedemo.csv");
const char *header = "id,demoname,seconds,avgfps,leveltime,demotime,framecount,ticrate,rendermode,vidmode,vidwidth,vidheight,procbits\n";
const char *rowformat = "\"%s\",\"%s\",%f,%f,%u,%d,%u,%u,%u,%u,%u,%u,%u\n";
boolean headerrow = !FIL_FileExists(csvpath);
UINT8 procbits = 0;
// Bitness
if (sizeof(void*) == 4)
procbits = 32;
else if (sizeof(void*) == 8)
procbits = 64;
f = fopen(csvpath, "a+");
if (f)
{
if (headerrow)
fputs(header, f);
fprintf(f, rowformat,
timedemo_csv_id,timedemo_name,f1/TICRATE,f2/f1,leveltime,demotime,(UINT32)framecount,TICRATE,rendermode,vid.modenum,vid.width,vid.height,procbits);
fclose(f);
CONS_Printf("Timedemo results saved to '%s'\n", csvpath);
}
else
{
// Just print the CSV output to console
CON_LogMessage(header);
CONS_Printf(rowformat,
timedemo_csv_id,timedemo_name,f1/TICRATE,f2/f1,leveltime,demotime,(UINT32)framecount,TICRATE,rendermode,vid.modenum,vid.width,vid.height,procbits);
}
}
if (restorecv_vidwait != cv_vidwait.value)
CV_SetValue(&cv_vidwait, restorecv_vidwait);
D_AdvanceDemo();
}
// reset engine variable set for the demos
// called from stopdemo command, map command, and g_checkdemoStatus.
void G_StopDemo(void)
@ -2394,66 +2492,13 @@ void G_StopDemo(void)
boolean G_CheckDemoStatus(void)
{
boolean saved;
G_FreeGhosts();
// DO NOT end metal sonic demos here
if (timingdemo)
{
INT32 demotime;
double f1, f2;
demotime = I_GetTime() - demostarttime;
if (!demotime)
return true;
G_StopDemo();
timingdemo = false;
f1 = (double)demotime;
f2 = (double)framecount*TICRATE;
CONS_Printf(M_GetText("timed %u gametics in %d realtics - %u frames\n%f seconds, %f avg fps\n"),
leveltime,demotime,(UINT32)framecount,f1/TICRATE,f2/f1);
// CSV-readable timedemo results, for external parsing
if (timedemo_csv)
{
FILE *f;
const char *csvpath = va("%s"PATHSEP"%s", srb2home, "timedemo.csv");
const char *header = "id,demoname,seconds,avgfps,leveltime,demotime,framecount,ticrate,rendermode,vidmode,vidwidth,vidheight,procbits\n";
const char *rowformat = "\"%s\",\"%s\",%f,%f,%u,%d,%u,%u,%u,%u,%u,%u,%u\n";
boolean headerrow = !FIL_FileExists(csvpath);
UINT8 procbits = 0;
// Bitness
if (sizeof(void*) == 4)
procbits = 32;
else if (sizeof(void*) == 8)
procbits = 64;
f = fopen(csvpath, "a+");
if (f)
{
if (headerrow)
fputs(header, f);
fprintf(f, rowformat,
timedemo_csv_id,timedemo_name,f1/TICRATE,f2/f1,leveltime,demotime,(UINT32)framecount,TICRATE,rendermode,vid.modenum,vid.width,vid.height,procbits);
fclose(f);
CONS_Printf("Timedemo results saved to '%s'\n", csvpath);
}
else
{
// Just print the CSV output to console
CON_LogMessage(header);
CONS_Printf(rowformat,
timedemo_csv_id,timedemo_name,f1/TICRATE,f2/f1,leveltime,demotime,(UINT32)framecount,TICRATE,rendermode,vid.modenum,vid.width,vid.height,procbits);
}
}
if (restorecv_vidwait != cv_vidwait.value)
CV_SetValue(&cv_vidwait, restorecv_vidwait);
D_AdvanceDemo();
G_StopTimingDemo();
return true;
}
@ -2473,27 +2518,7 @@ boolean G_CheckDemoStatus(void)
if (demorecording)
{
UINT8 *p = demobuffer+16; // checksum position
#ifdef NOMD5
UINT8 i;
WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker
for (i = 0; i < 16; i++, p++)
*p = P_RandomByte(); // This MD5 was chosen by fair dice roll and most likely < 50% correct.
#else
WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker
md5_buffer((char *)p+16, demo_p - (p+16), p); // make a checksum of everything after the checksum in the file.
#endif
saved = FIL_WriteFile(va(pandf, srb2home, demoname), demobuffer, demo_p - demobuffer); // finally output the file.
free(demobuffer);
demorecording = false;
if (modeattacking != ATTACKING_RECORD)
{
if (saved)
CONS_Printf(M_GetText("Demo %s recorded\n"), demoname);
else
CONS_Alert(CONS_WARNING, M_GetText("Demo %s not saved\n"), demoname);
}
G_StopDemoRecording();
return true;
}

View file

@ -54,7 +54,7 @@ UINT8 ultimatemode = false;
boolean botingame;
UINT8 botskin;
UINT8 botcolor;
UINT16 botcolor;
JoyType_t Joystick;
JoyType_t Joystick2;
@ -135,10 +135,10 @@ INT32 tutorialanalog = 0; // store cv_analog[0] user value
boolean looptitle = false;
UINT8 skincolor_redteam = SKINCOLOR_RED;
UINT8 skincolor_blueteam = SKINCOLOR_BLUE;
UINT8 skincolor_redring = SKINCOLOR_SALMON;
UINT8 skincolor_bluering = SKINCOLOR_CORNFLOWER;
UINT16 skincolor_redteam = SKINCOLOR_RED;
UINT16 skincolor_blueteam = SKINCOLOR_BLUE;
UINT16 skincolor_redring = SKINCOLOR_SALMON;
UINT16 skincolor_bluering = SKINCOLOR_CORNFLOWER;
tic_t countdowntimer = 0;
boolean countdowntimeup = false;
@ -1065,6 +1065,7 @@ static fixed_t forwardmove[2] = {25<<FRACBITS>>16, 50<<FRACBITS>>16};
static fixed_t sidemove[2] = {25<<FRACBITS>>16, 50<<FRACBITS>>16}; // faster!
static fixed_t angleturn[3] = {640, 1280, 320}; // + slow turn
INT16 ticcmd_oldangleturn[2];
boolean ticcmd_centerviewdown[2]; // For simple controls, lock the camera behind the player
mobj_t *ticcmd_ztargetfocus[2]; // Locking onto an object?
void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
@ -1140,7 +1141,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
if (paused || P_AutoPause() || (gamestate == GS_LEVEL && (player->playerstate == PST_REBORN || ((gametyperules & GTR_TAG)
&& (leveltime < hidetime * TICRATE) && (player->pflags & PF_TAGIT)))))
{//@TODO splitscreen player
cmd->angleturn = (INT16)(*myangle >> 16);
cmd->angleturn = ticcmd_oldangleturn[forplayer];
cmd->aiming = G_ClipAimingPitch(myaiming);
return;
}
@ -1361,7 +1362,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
if (controlstyle == CS_SIMPLE && !ticcmd_centerviewdown[forplayer] && !G_RingSlingerGametype())
{
CV_SetValue(&cv_directionchar[forplayer], 2);
*myangle = player->mo->angle;
cmd->angleturn = (INT16)((player->mo->angle - *myangle) >> 16);
*myaiming = 0;
if (cv_cam_lockonboss[forplayer].value)
@ -1430,7 +1431,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
else if (anglediff < -maxturn)
anglediff = -maxturn;
*myangle += anglediff;
cmd->angleturn = (INT16)(cmd->angleturn + (anglediff >> 16));
}
}
}
@ -1567,19 +1568,23 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
B_HandleFlightIndicator(player);
}
else if (player->bot == 2)
*myangle = localangle; // Fix offset angle for P2-controlled Tailsbot when P2's controls are set to non-Legacy
// Fix offset angle for P2-controlled Tailsbot when P2's controls are set to non-Legacy
cmd->angleturn = (INT16)((localangle - *myangle) >> 16);
*myangle += (cmd->angleturn<<16);
if (controlstyle == CS_LMAOGALOG) {
angle_t angle;
if (player->awayviewtics)
cmd->angleturn = (INT16)(player->awayviewmobj->angle >> 16);
angle = player->awayviewmobj->angle;
else
cmd->angleturn = (INT16)(thiscam->angle >> 16);
angle = thiscam->angle;
cmd->angleturn = (INT16)((angle - (ticcmd_oldangleturn[forplayer] << 16)) >> 16);
}
else
{
*myangle += (cmd->angleturn<<16);
cmd->angleturn = (INT16)(*myangle >> 16);
// Adjust camera angle by player input
if (controlstyle == CS_SIMPLE && !forcestrafe && thiscam->chase && !turnheld[forplayer] && !ticcmd_centerviewdown[forplayer] && !player->climbing && player->powers[pw_carry] != CR_MINECART)
{
@ -1589,13 +1594,17 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
{
fixed_t sine = FINESINE((R_PointToAngle2(0, 0, player->rmomx, player->rmomy) - localangle)>>ANGLETOFINESHIFT);
fixed_t factor;
INT16 camadjust;
if ((sine > 0) == (cmd->sidemove > 0))
sine = 0; // Prevent jerking right when braking from going left, or vice versa
factor = min(40, FixedMul(player->speed, abs(sine))*2 / FRACUNIT);
*myangle -= cmd->sidemove * factor * camadjustfactor;
camadjust = (cmd->sidemove * factor * camadjustfactor) >> 16;
*myangle -= camadjust << 16;
cmd->angleturn = (INT16)(cmd->angleturn - camadjust);
}
if (ticcmd_centerviewdown[forplayer] && (cv_cam_lockedinput[forplayer].value || (player->pflags & PF_STARTDASH)))
@ -1632,9 +1641,10 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
{
angle_t controlangle;
INT32 anglediff;
INT16 camadjust;
if ((cmd->forwardmove || cmd->sidemove) && !(player->pflags & PF_SPINNING))
controlangle = (cmd->angleturn<<16) + R_PointToAngle2(0, 0, cmd->forwardmove << FRACBITS, -cmd->sidemove << FRACBITS);
controlangle = *myangle + R_PointToAngle2(0, 0, cmd->forwardmove << FRACBITS, -cmd->sidemove << FRACBITS);
else
controlangle = player->drawangle + drawangleoffset;
@ -1651,7 +1661,10 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
anglediff = FixedMul(anglediff, sine);
}
*myangle += FixedMul(anglediff, camadjustfactor);
camadjust = FixedMul(anglediff, camadjustfactor) >> 16;
*myangle += camadjust << 16;
cmd->angleturn = (INT16)(cmd->angleturn + camadjust);
}
}
}
@ -1665,6 +1678,9 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
LUAh_ViewpointSwitch(player, &players[consoleplayer], true);
displayplayer = consoleplayer;
}
cmd->angleturn = (INT16)(cmd->angleturn + ticcmd_oldangleturn[forplayer]);
ticcmd_oldangleturn[forplayer] = cmd->angleturn;
}
ticcmd_t *G_CopyTiccmd(ticcmd_t* dest, const ticcmd_t* src, const size_t n)
@ -1866,6 +1882,7 @@ void G_StartTitleCard(void)
//
void G_PreLevelTitleCard(void)
{
#ifndef NOWIPE
tic_t starttime = I_GetTime();
tic_t endtime = starttime + (PRELEVELTIME*NEWTICRATERATIO);
tic_t nowtime = starttime;
@ -1888,6 +1905,7 @@ void G_PreLevelTitleCard(void)
}
if (!cv_showhud.value)
wipestyleflags = WSF_CROSSFADE;
#endif
}
static boolean titlecardforreload = false;
@ -2205,11 +2223,16 @@ void G_Ticker(boolean run)
buf = gametic % BACKUPTICS;
// read/write demo and check turbo cheat
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i])
{
G_CopyTiccmd(&players[i].cmd, &netcmds[buf][i], 1);
players[i].angleturn += players[i].cmd.angleturn - players[i].oldrelangleturn;
players[i].oldrelangleturn = players[i].cmd.angleturn;
players[i].cmd.angleturn = players[i].angleturn;
}
}
// do main actions
@ -2377,11 +2400,12 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
fixed_t height;
fixed_t spinheight;
INT32 exiting;
tic_t dashmode;
INT16 numboxes;
INT16 totalring;
UINT8 laps;
UINT8 mare;
UINT8 skincolor;
UINT16 skincolor;
INT32 skin;
UINT32 availabilities;
tic_t jointime;
@ -2392,6 +2416,8 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
SINT8 pity;
INT16 rings;
INT16 spheres;
INT16 playerangleturn;
INT16 oldrelangleturn;
score = players[player].score;
lives = players[player].lives;
@ -2403,6 +2429,8 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
spectator = players[player].spectator;
outofcoop = players[player].outofcoop;
pflags = (players[player].pflags & (PF_FLIPCAM|PF_ANALOGMODE|PF_DIRECTIONCHAR|PF_AUTOBRAKE|PF_TAGIT|PF_GAMETYPEOVER));
playerangleturn = players[player].angleturn;
oldrelangleturn = players[player].oldrelangleturn;
if (!betweenmaps)
pflags |= (players[player].pflags & PF_FINISHED);
@ -2411,6 +2439,8 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
if (!(netgame || multiplayer))
pflags |= (players[player].pflags & (PF_GODMODE|PF_NOCLIP|PF_INVIS));
dashmode = players[player].dashmode;
numboxes = players[player].numboxes;
laps = players[player].laps;
totalring = players[player].totalring;
@ -2474,6 +2504,8 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
p->quittime = quittime;
p->spectator = spectator;
p->outofcoop = outofcoop;
p->angleturn = playerangleturn;
p->oldrelangleturn = oldrelangleturn;
// save player config truth reborn
p->skincolor = skincolor;
@ -2509,6 +2541,8 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
p->spinheight = spinheight;
p->exiting = exiting;
p->dashmode = dashmode;
p->numboxes = numboxes;
p->laps = laps;
p->totalring = totalring;
@ -4475,7 +4509,7 @@ cleanup:
//
void G_DeferedInitNew(boolean pultmode, const char *mapname, INT32 pickedchar, boolean SSSG, boolean FLS)
{
UINT8 color = skins[pickedchar].prefcolor;
UINT16 color = skins[pickedchar].prefcolor;
paused = false;
if (demoplayback)
@ -4629,7 +4663,7 @@ char *G_BuildMapTitle(INT32 mapnum)
{
size_t len = 1;
const char *zonetext = NULL;
const INT32 actnum = mapheaderinfo[mapnum-1]->actnum;
const UINT8 actnum = mapheaderinfo[mapnum-1]->actnum;
len += strlen(mapheaderinfo[mapnum-1]->lvlttl);
if (!(mapheaderinfo[mapnum-1]->levelflags & LF_NOZONE))

View file

@ -93,6 +93,7 @@ typedef enum
// build an internal map name MAPxx from map number
const char *G_BuildMapName(INT32 map);
extern INT16 ticcmd_oldangleturn[2];
extern boolean ticcmd_centerviewdown[2]; // For simple controls, lock the camera behind the player
extern mobj_t *ticcmd_ztargetfocus[2]; // Locking onto an object?
void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer);

View file

@ -57,6 +57,7 @@ extern UINT8 ultimatemode; // was sk_insane
extern gameaction_t gameaction;
extern boolean botingame;
extern UINT8 botskin, botcolor;
extern UINT8 botskin;
extern UINT16 botcolor;
#endif //__G_STATE__

View file

@ -511,7 +511,7 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
// Set fixedheight to the slope's height from our viewpoint, if we have a slope
if (slope)
fixedheight = P_GetZAt(slope, viewx, viewy);
fixedheight = P_GetSlopeZAt(slope, viewx, viewy);
height = FIXED_TO_FLOAT(fixedheight);
@ -657,7 +657,7 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
\
if (slope)\
{\
fixedheight = P_GetZAt(slope, FLOAT_TO_FIXED((vx)), FLOAT_TO_FIXED((vy)));\
fixedheight = P_GetSlopeZAt(slope, FLOAT_TO_FIXED((vx)), FLOAT_TO_FIXED((vy)));\
vert->y = FIXED_TO_FLOAT(fixedheight);\
}\
}
@ -1101,8 +1101,8 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum,
float endpegt, endpegb, endpegmul;
float endheight = 0.0f, endbheight = 0.0f;
// compiler complains when P_GetZAt is used in FLOAT_TO_FIXED directly
// use this as a temp var to store P_GetZAt's return value each time
// compiler complains when P_GetSlopeZAt is used in FLOAT_TO_FIXED directly
// use this as a temp var to store P_GetSlopeZAt's return value each time
fixed_t temp;
fixed_t v1x = FLOAT_TO_FIXED(wallVerts[0].x);
@ -1165,26 +1165,16 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum,
else
solid = false;
if (list[i].slope)
{
temp = P_GetZAt(list[i].slope, v1x, v1y);
height = FIXED_TO_FLOAT(temp);
temp = P_GetZAt(list[i].slope, v2x, v2y);
endheight = FIXED_TO_FLOAT(temp);
}
else
height = endheight = FIXED_TO_FLOAT(list[i].height);
temp = P_GetLightZAt(&list[i], v1x, v1y);
height = FIXED_TO_FLOAT(temp);
temp = P_GetLightZAt(&list[i], v2x, v2y);
endheight = FIXED_TO_FLOAT(temp);
if (solid)
{
if (*list[i].caster->b_slope)
{
temp = P_GetZAt(*list[i].caster->b_slope, v1x, v1y);
bheight = FIXED_TO_FLOAT(temp);
temp = P_GetZAt(*list[i].caster->b_slope, v2x, v2y);
endbheight = FIXED_TO_FLOAT(temp);
}
else
bheight = endbheight = FIXED_TO_FLOAT(*list[i].caster->bottomheight);
temp = P_GetFFloorBottomZAt(list[i].caster, v1x, v1y);
bheight = FIXED_TO_FLOAT(temp);
temp = P_GetFFloorBottomZAt(list[i].caster, v2x, v2y);
endbheight = FIXED_TO_FLOAT(temp);
}
if (endheight >= endtop && height >= top)
@ -1197,15 +1187,10 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum,
if (i + 1 < sector->numlights)
{
if (list[i+1].slope)
{
temp = P_GetZAt(list[i+1].slope, v1x, v1y);
bheight = FIXED_TO_FLOAT(temp);
temp = P_GetZAt(list[i+1].slope, v2x, v2y);
endbheight = FIXED_TO_FLOAT(temp);
}
else
bheight = endbheight = FIXED_TO_FLOAT(list[i+1].height);
temp = P_GetLightZAt(&list[i+1], v1x, v1y);
bheight = FIXED_TO_FLOAT(temp);
temp = P_GetLightZAt(&list[i+1], v2x, v2y);
endbheight = FIXED_TO_FLOAT(temp);
}
else
{
@ -1344,11 +1329,8 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
v2y = FLOAT_TO_FIXED(ve.y);
#define SLOPEPARAMS(slope, end1, end2, normalheight) \
if (slope) { \
end1 = P_GetZAt(slope, v1x, v1y); \
end2 = P_GetZAt(slope, v2x, v2y); \
} else \
end1 = end2 = normalheight;
end1 = P_GetZAt(slope, v1x, v1y, normalheight); \
end2 = P_GetZAt(slope, v2x, v2y, normalheight);
SLOPEPARAMS(gr_frontsector->c_slope, worldtop, worldtopslope, gr_frontsector->ceilingheight)
SLOPEPARAMS(gr_frontsector->f_slope, worldbottom, worldbottomslope, gr_frontsector->floorheight)
@ -1927,10 +1909,10 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
texnum = R_GetTextureNum(sides[newline->sidenum[0]].midtexture);
}
h = *rover->t_slope ? P_GetZAt(*rover->t_slope, v1x, v1y) : *rover->topheight;
hS = *rover->t_slope ? P_GetZAt(*rover->t_slope, v2x, v2y) : *rover->topheight;
l = *rover->b_slope ? P_GetZAt(*rover->b_slope, v1x, v1y) : *rover->bottomheight;
lS = *rover->b_slope ? P_GetZAt(*rover->b_slope, v2x, v2y) : *rover->bottomheight;
h = P_GetFFloorTopZAt (rover, v1x, v1y);
hS = P_GetFFloorTopZAt (rover, v2x, v2y);
l = P_GetFFloorBottomZAt(rover, v1x, v1y);
lS = P_GetFFloorBottomZAt(rover, v2x, v2y);
if (!(*rover->t_slope) && !gr_frontsector->c_slope && !gr_backsector->c_slope && h > highcut)
h = hS = highcut;
if (!(*rover->b_slope) && !gr_frontsector->f_slope && !gr_backsector->f_slope && l < lowcut)
@ -2068,10 +2050,10 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
newline = rover->master->frontsector->lines[0] + linenum;
texnum = R_GetTextureNum(sides[newline->sidenum[0]].midtexture);
}
h = *rover->t_slope ? P_GetZAt(*rover->t_slope, v1x, v1y) : *rover->topheight;
hS = *rover->t_slope ? P_GetZAt(*rover->t_slope, v2x, v2y) : *rover->topheight;
l = *rover->b_slope ? P_GetZAt(*rover->b_slope, v1x, v1y) : *rover->bottomheight;
lS = *rover->b_slope ? P_GetZAt(*rover->b_slope, v2x, v2y) : *rover->bottomheight;
h = P_GetFFloorTopZAt (rover, v1x, v1y);
hS = P_GetFFloorTopZAt (rover, v2x, v2y);
l = P_GetFFloorBottomZAt(rover, v1x, v1y);
lS = P_GetFFloorBottomZAt(rover, v2x, v2y);
if (!(*rover->t_slope) && !gr_frontsector->c_slope && !gr_backsector->c_slope && h > highcut)
h = hS = highcut;
if (!(*rover->b_slope) && !gr_frontsector->f_slope && !gr_backsector->f_slope && l < lowcut)
@ -2189,24 +2171,21 @@ static boolean CheckClip(seg_t * seg, sector_t * afrontsector, sector_t * abacks
v2x = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->x);
v2y = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->y);
#define SLOPEPARAMS(slope, end1, end2, normalheight) \
if (slope) { \
end1 = P_GetZAt(slope, v1x, v1y); \
end2 = P_GetZAt(slope, v2x, v2y); \
} else \
end1 = end2 = normalheight;
end1 = P_GetZAt(slope, v1x, v1y, normalheight); \
end2 = P_GetZAt(slope, v2x, v2y, normalheight);
SLOPEPARAMS(afrontsector->f_slope, frontf1, frontf2, afrontsector->floorheight)
SLOPEPARAMS(afrontsector->f_slope, frontf1, frontf2, afrontsector-> floorheight)
SLOPEPARAMS(afrontsector->c_slope, frontc1, frontc2, afrontsector->ceilingheight)
SLOPEPARAMS( abacksector->f_slope, backf1, backf2, abacksector->floorheight)
SLOPEPARAMS( abacksector->c_slope, backc1, backc2, abacksector->ceilingheight)
SLOPEPARAMS( abacksector->f_slope, backf1, backf2, abacksector-> floorheight)
SLOPEPARAMS( abacksector->c_slope, backc1, backc2, abacksector->ceilingheight)
#undef SLOPEPARAMS
}
else
{
frontf1 = frontf2 = afrontsector->floorheight;
frontf1 = frontf2 = afrontsector-> floorheight;
frontc1 = frontc2 = afrontsector->ceilingheight;
backf1 = backf2 = abacksector->floorheight;
backc1 = backc2 = abacksector->ceilingheight;
backf1 = backf2 = abacksector-> floorheight;
backc1 = backc2 = abacksector->ceilingheight;
}
// properly render skies (consider door "open" if both ceilings are sky)
// same for floors
@ -2740,16 +2719,13 @@ static void HWR_AddLine(seg_t * line)
fixed_t backf1, backf2, backc1, backc2; // back floor ceiling ends
#define SLOPEPARAMS(slope, end1, end2, normalheight) \
if (slope) { \
end1 = P_GetZAt(slope, v1x, v1y); \
end2 = P_GetZAt(slope, v2x, v2y); \
} else \
end1 = end2 = normalheight;
end1 = P_GetZAt(slope, v1x, v1y, normalheight); \
end2 = P_GetZAt(slope, v2x, v2y, normalheight);
SLOPEPARAMS(gr_frontsector->f_slope, frontf1, frontf2, gr_frontsector->floorheight)
SLOPEPARAMS(gr_frontsector->f_slope, frontf1, frontf2, gr_frontsector-> floorheight)
SLOPEPARAMS(gr_frontsector->c_slope, frontc1, frontc2, gr_frontsector->ceilingheight)
SLOPEPARAMS( gr_backsector->f_slope, backf1, backf2, gr_backsector->floorheight)
SLOPEPARAMS( gr_backsector->c_slope, backc1, backc2, gr_backsector->ceilingheight)
SLOPEPARAMS( gr_backsector->f_slope, backf1, backf2, gr_backsector-> floorheight)
SLOPEPARAMS( gr_backsector->c_slope, backc1, backc2, gr_backsector->ceilingheight)
#undef SLOPEPARAMS
// if both ceilings are skies, consider it always "open"
// same for floors
@ -3307,20 +3283,10 @@ static void HWR_Subsector(size_t num)
}
else
{
cullFloorHeight = locFloorHeight = gr_frontsector->floorheight;
cullCeilingHeight = locCeilingHeight = gr_frontsector->ceilingheight;
if (gr_frontsector->f_slope)
{
cullFloorHeight = P_GetZAt(gr_frontsector->f_slope, viewx, viewy);
locFloorHeight = P_GetZAt(gr_frontsector->f_slope, gr_frontsector->soundorg.x, gr_frontsector->soundorg.y);
}
if (gr_frontsector->c_slope)
{
cullCeilingHeight = P_GetZAt(gr_frontsector->c_slope, viewx, viewy);
locCeilingHeight = P_GetZAt(gr_frontsector->c_slope, gr_frontsector->soundorg.x, gr_frontsector->soundorg.y);
}
cullFloorHeight = P_GetSectorFloorZAt (gr_frontsector, viewx, viewy);
cullCeilingHeight = P_GetSectorCeilingZAt(gr_frontsector, viewx, viewy);
locFloorHeight = P_GetSectorFloorZAt (gr_frontsector, gr_frontsector->soundorg.x, gr_frontsector->soundorg.y);
locCeilingHeight = P_GetSectorCeilingZAt(gr_frontsector, gr_frontsector->soundorg.x, gr_frontsector->soundorg.y);
}
// ----- end special tricks -----
@ -3412,13 +3378,8 @@ static void HWR_Subsector(size_t num)
fixed_t cullHeight, centerHeight;
// bottom plane
if (*rover->b_slope)
{
cullHeight = P_GetZAt(*rover->b_slope, viewx, viewy);
centerHeight = P_GetZAt(*rover->b_slope, gr_frontsector->soundorg.x, gr_frontsector->soundorg.y);
}
else
cullHeight = centerHeight = *rover->bottomheight;
cullHeight = P_GetFFloorBottomZAt(rover, viewx, viewy);
centerHeight = P_GetFFloorBottomZAt(rover, gr_frontsector->soundorg.x, gr_frontsector->soundorg.y);
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERPLANES))
continue;
@ -3478,13 +3439,8 @@ static void HWR_Subsector(size_t num)
}
// top plane
if (*rover->t_slope)
{
cullHeight = P_GetZAt(*rover->t_slope, viewx, viewy);
centerHeight = P_GetZAt(*rover->t_slope, gr_frontsector->soundorg.x, gr_frontsector->soundorg.y);
}
else
cullHeight = centerHeight = *rover->topheight;
cullHeight = P_GetFFloorTopZAt(rover, viewx, viewy);
centerHeight = P_GetFFloorTopZAt(rover, gr_frontsector->soundorg.x, gr_frontsector->soundorg.y);
if (centerHeight >= locFloorHeight &&
centerHeight <= locCeilingHeight &&
@ -3883,20 +3839,21 @@ static void HWR_DrawDropShadow(mobj_t *thing, gr_vissprite_t *spr, fixed_t scale
UINT8 lightlevel = 255;
extracolormap_t *colormap = NULL;
UINT8 i;
SINT8 flip = P_MobjFlip(thing);
INT32 light;
fixed_t scalemul;
UINT16 alpha;
fixed_t floordiff;
fixed_t floorz;
fixed_t groundz;
fixed_t slopez;
pslope_t *floorslope;
pslope_t *groundslope;
floorz = R_GetShadowZ(thing, &floorslope);
groundz = R_GetShadowZ(thing, &groundslope);
//if (abs(floorz - gr_viewz) / tz > 4) return; // Prevent stretchy shadows and possible crashes
//if (abs(groundz - gr_viewz) / tz > 4) return; // Prevent stretchy shadows and possible crashes
floordiff = abs(thing->z - floorz);
floordiff = abs((flip < 0 ? thing->height : 0) + thing->z - groundz);
alpha = floordiff / (4*FRACUNIT) + 75;
if (alpha >= 255) return;
@ -3928,18 +3885,18 @@ static void HWR_DrawDropShadow(mobj_t *thing, gr_vissprite_t *spr, fixed_t scale
shadowVerts[0].z = shadowVerts[1].z = fy - offset;
shadowVerts[3].z = shadowVerts[2].z = fy + offset;
if (floorslope)
if (groundslope)
{
for (i = 0; i < 4; i++)
{
slopez = P_GetZAt(floorslope, FLOAT_TO_FIXED(shadowVerts[i].x), FLOAT_TO_FIXED(shadowVerts[i].z));
shadowVerts[i].y = FIXED_TO_FLOAT(slopez) + 0.05f;
slopez = P_GetSlopeZAt(groundslope, FLOAT_TO_FIXED(shadowVerts[i].x), FLOAT_TO_FIXED(shadowVerts[i].z));
shadowVerts[i].y = FIXED_TO_FLOAT(slopez) + flip * 0.05f;
}
}
else
{
for (i = 0; i < 4; i++)
shadowVerts[i].y = FIXED_TO_FLOAT(floorz) + 0.05f;
shadowVerts[i].y = FIXED_TO_FLOAT(groundz) + flip * 0.05f;
}
if (spr->flip)
@ -3967,7 +3924,7 @@ static void HWR_DrawDropShadow(mobj_t *thing, gr_vissprite_t *spr, fixed_t scale
if (thing->subsector->sector->numlights)
{
light = R_GetPlaneLight(thing->subsector->sector, floorz, false); // Always use the light at the top instead of whatever I was doing before
light = R_GetPlaneLight(thing->subsector->sector, groundz, false); // Always use the light at the top instead of whatever I was doing before
if (*thing->subsector->sector->lightlist[light].lightlevel > 255)
lightlevel = 255;
@ -4168,8 +4125,7 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
for (i = 1; i < sector->numlights; i++)
{
fixed_t h = sector->lightlist[i].slope ? P_GetZAt(sector->lightlist[i].slope, spr->mobj->x, spr->mobj->y)
: sector->lightlist[i].height;
fixed_t h = P_GetLightZAt(&sector->lightlist[i], spr->mobj->x, spr->mobj->y);
if (h <= temp)
{
if (!(spr->mobj->frame & FF_FULLBRIGHT))
@ -4194,15 +4150,10 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
if (i + 1 < sector->numlights)
{
if (list[i+1].slope)
{
temp = P_GetZAt(list[i+1].slope, v1x, v1y);
bheight = FIXED_TO_FLOAT(temp);
temp = P_GetZAt(list[i+1].slope, v2x, v2y);
endbheight = FIXED_TO_FLOAT(temp);
}
else
bheight = endbheight = FIXED_TO_FLOAT(list[i+1].height);
temp = P_GetLightZAt(&list[i+1], v1x, v1y);
bheight = FIXED_TO_FLOAT(temp);
temp = P_GetLightZAt(&list[i+1], v2x, v2y);
endbheight = FIXED_TO_FLOAT(temp);
}
else
{

View file

@ -677,12 +677,12 @@ spritemodelfound:
#define SETBRIGHTNESS(brightness,r,g,b) \
brightness = (UINT8)(((1063*(UINT16)(r))/5000) + ((3576*(UINT16)(g))/5000) + ((361*(UINT16)(b))/5000))
static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, GLMipmap_t *grmip, INT32 skinnum, skincolors_t color)
static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, GLMipmap_t *grmip, INT32 skinnum, skincolornum_t color)
{
UINT16 w = gpatch->width, h = gpatch->height;
UINT32 size = w*h;
RGBA_t *image, *blendimage, *cur, blendcolor;
UINT8 translation[16]; // First the color index
UINT16 translation[16]; // First the color index
UINT8 cutoff[16]; // Brightness cutoff before using the next color
UINT8 translen = 0;
UINT8 i;
@ -718,16 +718,16 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch,
if (skinnum == TC_METALSONIC)
color = SKINCOLOR_COBALT;
if (color != SKINCOLOR_NONE)
if (color != SKINCOLOR_NONE && color < numskincolors)
{
UINT8 numdupes = 1;
translation[translen] = Color_Index[color-1][0];
translation[translen] = skincolors[color].ramp[0];
cutoff[translen] = 255;
for (i = 1; i < 16; i++)
{
if (translation[translen] == Color_Index[color-1][i])
if (translation[translen] == skincolors[color].ramp[i])
{
numdupes++;
continue;
@ -741,7 +741,7 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch,
numdupes = 1;
translen++;
translation[translen] = (UINT8)Color_Index[color-1][i];
translation[translen] = (UINT16)skincolors[color].ramp[i];
}
translen++;
@ -1043,7 +1043,7 @@ skippixel:
#undef SETBRIGHTNESS
static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, INT32 skinnum, const UINT8 *colormap, skincolors_t color)
static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, INT32 skinnum, const UINT8 *colormap, skincolornum_t color)
{
// mostly copied from HWR_GetMappedPatch, hence the similarities and comment
GLMipmap_t *grmip, *newmip;
@ -1336,7 +1336,7 @@ boolean HWR_DrawModel(gr_vissprite_t *spr)
else
skinnum = TC_BOSS;
}
else if ((skincolors_t)spr->mobj->color != SKINCOLOR_NONE)
else if ((skincolornum_t)spr->mobj->color != SKINCOLOR_NONE)
{
if (spr->mobj->colorized)
skinnum = TC_RAINBOW;
@ -1356,7 +1356,7 @@ boolean HWR_DrawModel(gr_vissprite_t *spr)
}
// Translation or skin number found
HWR_GetBlendedTexture(gpatch, (GLPatch_t *)md2->blendgrpatch, skinnum, spr->colormap, (skincolors_t)spr->mobj->color);
HWR_GetBlendedTexture(gpatch, (GLPatch_t *)md2->blendgrpatch, skinnum, spr->colormap, (skincolornum_t)spr->mobj->color);
}
else
{

View file

@ -68,7 +68,7 @@ patch_t *nightsnum[10]; // 0-9
// Level title and credits fonts
patch_t *lt_font[LT_FONTSIZE];
patch_t *cred_font[CRED_FONTSIZE];
patch_t *ttlnum[20]; // act numbers (0-19)
patch_t *ttlnum[10]; // act numbers (0-9)
// Name tag fonts
patch_t *ntb_font[NT_FONTSIZE];
@ -243,7 +243,7 @@ void HU_LoadGraphics(void)
tallinfin = (patch_t *)W_CachePatchName("STTINFIN", PU_HUDGFX);
// cache act numbers for level titles
for (i = 0; i < 20; i++)
for (i = 0; i < 10; i++)
{
sprintf(buffer, "TTL%.2d", i);
ttlnum[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
@ -755,113 +755,40 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
}
else
{
const UINT8 color = players[playernum].skincolor;
UINT16 chatcolor = skincolors[players[playernum].skincolor].chatcolor;
cstart = "\x83";
// Follow palette order at r_draw.c Color_Names
switch (color)
{
default:
case SKINCOLOR_WHITE:
case SKINCOLOR_BONE:
case SKINCOLOR_CLOUDY:
case SKINCOLOR_GREY:
case SKINCOLOR_SILVER:
case SKINCOLOR_AETHER:
case SKINCOLOR_SLATE:
cstart = "\x80"; // white
break;
case SKINCOLOR_CARBON:
case SKINCOLOR_JET:
case SKINCOLOR_BLACK:
cstart = "\x86"; // V_GRAYMAP
break;
case SKINCOLOR_PINK:
case SKINCOLOR_RUBY:
case SKINCOLOR_SALMON:
case SKINCOLOR_RED:
case SKINCOLOR_CRIMSON:
case SKINCOLOR_FLAME:
case SKINCOLOR_KETCHUP:
cstart = "\x85"; // V_REDMAP
break;
case SKINCOLOR_YOGURT:
case SKINCOLOR_BROWN:
case SKINCOLOR_BRONZE:
case SKINCOLOR_TAN:
case SKINCOLOR_BEIGE:
case SKINCOLOR_QUAIL:
cstart = "\x8d"; // V_BROWNMAP
break;
case SKINCOLOR_MOSS:
case SKINCOLOR_GREEN:
case SKINCOLOR_FOREST:
case SKINCOLOR_EMERALD:
case SKINCOLOR_MINT:
cstart = "\x83"; // V_GREENMAP
break;
case SKINCOLOR_AZURE:
cstart = "\x8c"; // V_AZUREMAP
break;
case SKINCOLOR_LAVENDER:
case SKINCOLOR_PASTEL:
case SKINCOLOR_PURPLE:
cstart = "\x89"; // V_PURPLEMAP
break;
case SKINCOLOR_PEACHY:
case SKINCOLOR_LILAC:
case SKINCOLOR_PLUM:
case SKINCOLOR_ROSY:
cstart = "\x8e"; // V_ROSYMAP
break;
case SKINCOLOR_SUNSET:
case SKINCOLOR_COPPER:
case SKINCOLOR_APRICOT:
case SKINCOLOR_ORANGE:
case SKINCOLOR_RUST:
cstart = "\x87"; // V_ORANGEMAP
break;
case SKINCOLOR_GOLD:
case SKINCOLOR_SANDY:
case SKINCOLOR_YELLOW:
case SKINCOLOR_OLIVE:
cstart = "\x82"; // V_YELLOWMAP
break;
case SKINCOLOR_LIME:
case SKINCOLOR_PERIDOT:
case SKINCOLOR_APPLE:
cstart = "\x8b"; // V_PERIDOTMAP
break;
case SKINCOLOR_SEAFOAM:
case SKINCOLOR_AQUA:
cstart = "\x8a"; // V_AQUAMAP
break;
case SKINCOLOR_TEAL:
case SKINCOLOR_WAVE:
case SKINCOLOR_CYAN:
case SKINCOLOR_SKY:
case SKINCOLOR_CERULEAN:
case SKINCOLOR_ICY:
case SKINCOLOR_SAPPHIRE:
case SKINCOLOR_VAPOR:
cstart = "\x88"; // V_SKYMAP
break;
case SKINCOLOR_CORNFLOWER:
case SKINCOLOR_BLUE:
case SKINCOLOR_COBALT:
case SKINCOLOR_DUSK:
case SKINCOLOR_BLUEBELL:
cstart = "\x84"; // V_BLUEMAP
break;
case SKINCOLOR_BUBBLEGUM:
case SKINCOLOR_MAGENTA:
case SKINCOLOR_NEON:
case SKINCOLOR_VIOLET:
case SKINCOLOR_RASPBERRY:
cstart = "\x81"; // V_MAGENTAMAP
break;
}
if (!chatcolor || chatcolor%0x1000 || chatcolor>V_INVERTMAP)
cstart = "\x80";
else if (chatcolor == V_MAGENTAMAP)
cstart = "\x81";
else if (chatcolor == V_YELLOWMAP)
cstart = "\x82";
else if (chatcolor == V_GREENMAP)
cstart = "\x83";
else if (chatcolor == V_BLUEMAP)
cstart = "\x84";
else if (chatcolor == V_REDMAP)
cstart = "\x85";
else if (chatcolor == V_GRAYMAP)
cstart = "\x86";
else if (chatcolor == V_ORANGEMAP)
cstart = "\x87";
else if (chatcolor == V_SKYMAP)
cstart = "\x88";
else if (chatcolor == V_PURPLEMAP)
cstart = "\x89";
else if (chatcolor == V_AQUAMAP)
cstart = "\x8a";
else if (chatcolor == V_PERIDOTMAP)
cstart = "\x8b";
else if (chatcolor == V_AZUREMAP)
cstart = "\x8c";
else if (chatcolor == V_BROWNMAP)
cstart = "\x8d";
else if (chatcolor == V_ROSYMAP)
cstart = "\x8e";
else if (chatcolor == V_INVERTMAP)
cstart = "\x8f";
}
prefix = cstart;

View file

@ -85,7 +85,7 @@ extern patch_t *lt_font[LT_FONTSIZE];
extern patch_t *cred_font[CRED_FONTSIZE];
extern patch_t *ntb_font[NT_FONTSIZE];
extern patch_t *nto_font[NT_FONTSIZE];
extern patch_t *ttlnum[20];
extern patch_t *ttlnum[10];
extern patch_t *emeraldpics[3][8];
extern patch_t *rflagico;
extern patch_t *bflagico;

View file

@ -20,6 +20,7 @@
#include "m_misc.h"
#include "z_zone.h"
#include "d_player.h"
#include "v_video.h" // V_*MAP constants
#include "lzf.h"
#ifdef HWRENDER
#include "hardware/hw_light.h"
@ -21589,8 +21590,140 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
#endif
};
skincolor_t skincolors[MAXSKINCOLORS] = {
{"None", {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SKINCOLOR_NONE, 0, 0, false}, // SKINCOLOR_NONE
/** Patches the mobjinfo table and state table.
// Greyscale ranges
{"White", {0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x11}, SKINCOLOR_BLACK, 5, 0, true}, // SKINCOLOR_WHITE
{"Bone", {0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x05, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x11, 0x12}, SKINCOLOR_JET, 7, 0, true}, // SKINCOLOR_BONE
{"Cloudy", {0x02, 0x03, 0x04, 0x05, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14}, SKINCOLOR_CARBON, 7, 0, true}, // SKINCOLOR_CLOUDY
{"Grey", {0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18}, SKINCOLOR_AETHER, 12, 0, true}, // SKINCOLOR_GREY
{"Silver", {0x02, 0x03, 0x05, 0x07, 0x09, 0x0b, 0x0d, 0x0f, 0x11, 0x13, 0x15, 0x17, 0x19, 0x1b, 0x1d, 0x1f}, SKINCOLOR_SLATE, 12, 0, true}, // SKINCOLOR_SILVER
{"Carbon", {0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x16, 0x17, 0x17, 0x19, 0x19, 0x1a, 0x1a, 0x1b, 0x1c, 0x1d}, SKINCOLOR_CLOUDY, 7, V_GRAYMAP, true}, // SKINCOLOR_CARBON
{"Jet", {0x00, 0x05, 0x0a, 0x0f, 0x14, 0x19, 0x1a, 0x1b, 0x1c, 0x1e, 0x1e, 0x1e, 0x1f, 0x1f, 0x1f, 0x1f}, SKINCOLOR_BONE, 7, V_GRAYMAP, true}, // SKINCOLOR_JET
{"Black", {0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1b, 0x1b, 0x1c, 0x1d, 0x1d, 0x1e, 0x1e, 0x1f, 0x1f}, SKINCOLOR_WHITE, 7, V_GRAYMAP, true}, // SKINCOLOR_BLACK
// Desaturated
{"Aether", {0x00, 0x00, 0x01, 0x02, 0x02, 0x03, 0x91, 0x91, 0x91, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xaf}, SKINCOLOR_GREY, 15, 0, true}, // SKINCOLOR_AETHER
{"Slate", {0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0xaa, 0xaa, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xad, 0xae, 0xaf}, SKINCOLOR_SILVER, 12, 0, true}, // SKINCOLOR_SLATE
{"Bluebell", {0x90, 0x91, 0x92, 0x93, 0x94, 0x94, 0x95, 0xac, 0xac, 0xad, 0xad, 0xa8, 0xa8, 0xa9, 0xfd, 0xfe}, SKINCOLOR_COPPER, 4, V_BLUEMAP, true}, // SKINCOLOR_BLUEBELL
{"Pink", {0xd0, 0xd0, 0xd1, 0xd1, 0xd2, 0xd2, 0xd3, 0xd3, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0x2b, 0x2c, 0x2e}, SKINCOLOR_AZURE, 9, V_REDMAP, true}, // SKINCOLOR_PINK
{"Yogurt", {0xd0, 0x30, 0xd8, 0xd9, 0xda, 0xdb, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe3, 0xe6, 0xe8, 0xe9}, SKINCOLOR_RUST, 7, V_BROWNMAP, true}, // SKINCOLOR_YOGURT
{"Brown", {0xdf, 0xe0, 0xe1, 0xe2, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef}, SKINCOLOR_TAN, 2, V_BROWNMAP, true}, // SKINCOLOR_BROWN
{"Bronze", {0xde, 0xe0, 0xe1, 0xe4, 0xe7, 0xe9, 0xeb, 0xec, 0xed, 0xed, 0xed, 0x19, 0x19, 0x1b, 0x1d, 0x1e}, SKINCOLOR_KETCHUP, 0, V_BROWNMAP, true}, // SKINCOLOR_BRONZE
{"Tan", {0x51, 0x51, 0x54, 0x54, 0x55, 0x55, 0x56, 0x56, 0x56, 0x57, 0xf5, 0xf5, 0xf9, 0xf9, 0xed, 0xed}, SKINCOLOR_BROWN, 12, V_BROWNMAP, true}, // SKINCOLOR_TAN
{"Beige", {0x54, 0x55, 0x56, 0x56, 0xf2, 0xf3, 0xf3, 0xf4, 0xf5, 0xf6, 0xf8, 0xf9, 0xfa, 0xfb, 0xed, 0xed}, SKINCOLOR_MOSS, 5, V_BROWNMAP, true}, // SKINCOLOR_BEIGE
{"Moss", {0x58, 0x58, 0x59, 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5b, 0x5c, 0x5d, 0x5d, 0x5e, 0x5e, 0x5f, 0x5f}, SKINCOLOR_BEIGE, 13, V_GREENMAP, true}, // SKINCOLOR_MOSS
{"Azure", {0x90, 0x90, 0x91, 0x91, 0xaa, 0xaa, 0xab, 0xab, 0xab, 0xac, 0xad, 0xad, 0xae, 0xae, 0xaf, 0xaf}, SKINCOLOR_PINK, 5, V_AZUREMAP, true}, // SKINCOLOR_AZURE
{"Lavender", {0xc0, 0xc0, 0xc1, 0xc1, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc4, 0xc5, 0xc5, 0xc6, 0xc6, 0xc7, 0xc7}, SKINCOLOR_GOLD, 4, V_PURPLEMAP, true}, // SKINCOLOR_LAVENDER
// Viv's vivid colours (toast 21/07/17)
{"Ruby", {0xb0, 0xb0, 0xc9, 0xca, 0xcc, 0x26, 0x27, 0x28, 0x29, 0x2a, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xfd}, SKINCOLOR_EMERALD, 10, V_REDMAP, true}, // SKINCOLOR_RUBY
{"Salmon", {0xd0, 0xd0, 0xd1, 0xd2, 0x20, 0x21, 0x24, 0x25, 0x26, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e}, SKINCOLOR_FOREST, 6, V_REDMAP, true}, // SKINCOLOR_SALMON
{"Red", {0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x47, 0x2e, 0x2f}, SKINCOLOR_GREEN, 10, V_REDMAP, true}, // SKINCOLOR_RED
{"Crimson", {0x27, 0x27, 0x28, 0x28, 0x29, 0x2a, 0x2b, 0x2b, 0x2c, 0x2d, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x1f}, SKINCOLOR_ICY, 10, V_REDMAP, true}, // SKINCOLOR_CRIMSON
{"Flame", {0x31, 0x32, 0x33, 0x36, 0x22, 0x22, 0x25, 0x25, 0x25, 0xcd, 0xcf, 0xcf, 0xc5, 0xc5, 0xc7, 0xc7}, SKINCOLOR_PURPLE, 8, V_REDMAP, true}, // SKINCOLOR_FLAME
{"Ketchup", {0x48, 0x49, 0x40, 0x33, 0x34, 0x36, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2b, 0x2c, 0x47, 0x2e, 0x2f}, SKINCOLOR_BRONZE, 8, V_REDMAP, true}, // SKINCOLOR_KETCHUP
{"Peachy", {0xd0, 0x30, 0x31, 0x31, 0x32, 0x32, 0xdc, 0xdc, 0xdc, 0xd3, 0xd4, 0xd4, 0xcc, 0xcd, 0xce, 0xcf}, SKINCOLOR_TEAL, 7, V_ROSYMAP, true}, // SKINCOLOR_PEACHY
{"Quail", {0xd8, 0xd9, 0xdb, 0xdc, 0xde, 0xdf, 0xd5, 0xd5, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0x1d, 0x1f}, SKINCOLOR_WAVE, 5, V_BROWNMAP, true}, // SKINCOLOR_QUAIL
{"Sunset", {0x51, 0x52, 0x40, 0x40, 0x34, 0x36, 0xd5, 0xd5, 0xd6, 0xd7, 0xcf, 0xcf, 0xc6, 0xc6, 0xc7, 0xfe}, SKINCOLOR_SAPPHIRE, 5, V_ORANGEMAP, true}, // SKINCOLOR_SUNSET
{"Copper", {0x58, 0x54, 0x40, 0x34, 0x35, 0x38, 0x3a, 0x3c, 0x3d, 0x2a, 0x2b, 0x2c, 0x2c, 0xba, 0xba, 0xbb}, SKINCOLOR_BLUEBELL, 5, V_ORANGEMAP, true}, // SKINCOLOR_COPPER
{"Apricot", {0x00, 0xd8, 0xd9, 0xda, 0xdb, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e}, SKINCOLOR_CYAN, 4, V_ORANGEMAP, true}, // SKINCOLOR_APRICOT
{"Orange", {0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x2c}, SKINCOLOR_BLUE, 4, V_ORANGEMAP, true}, // SKINCOLOR_ORANGE
{"Rust", {0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3c, 0x3d, 0x3d, 0x3d, 0x3f, 0x2c, 0x2d, 0x47, 0x2e, 0x2f, 0x2f}, SKINCOLOR_YOGURT, 8, V_ORANGEMAP, true}, // SKINCOLOR_RUST
{"Gold", {0x51, 0x51, 0x54, 0x54, 0x41, 0x42, 0x43, 0x43, 0x44, 0x45, 0x46, 0x3f, 0x2d, 0x2e, 0x2f, 0x2f}, SKINCOLOR_LAVENDER, 10, V_YELLOWMAP, true}, // SKINCOLOR_GOLD
{"Sandy", {0x53, 0x40, 0x41, 0x42, 0x43, 0xe6, 0xe9, 0xe9, 0xea, 0xec, 0xec, 0xc6, 0xc6, 0xc7, 0xc7, 0xfe}, SKINCOLOR_SKY, 8, V_YELLOWMAP, true}, // SKINCOLOR_SANDY
{"Yellow", {0x52, 0x53, 0x49, 0x49, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4c, 0x4d, 0x4d, 0x4e, 0x4e, 0x4f, 0xed}, SKINCOLOR_CORNFLOWER, 8, V_YELLOWMAP, true}, // SKINCOLOR_YELLOW
{"Olive", {0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4e, 0xe7, 0xe7, 0xe9, 0xc5, 0xc5, 0xc6, 0xc6, 0xc7, 0xc7, 0xfd}, SKINCOLOR_DUSK, 3, V_YELLOWMAP, true}, // SKINCOLOR_OLIVE
{"Lime", {0x50, 0x51, 0x52, 0x53, 0x48, 0xbc, 0xbd, 0xbe, 0xbe, 0xbf, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f}, SKINCOLOR_MAGENTA, 9, V_PERIDOTMAP, true}, // SKINCOLOR_LIME
{"Peridot", {0x58, 0x58, 0xbc, 0xbc, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbf, 0x5e, 0x5e, 0x5f, 0x5f, 0x77, 0x77}, SKINCOLOR_COBALT, 2, V_PERIDOTMAP, true}, // SKINCOLOR_PERIDOT
{"Apple", {0x49, 0x49, 0xbc, 0xbd, 0xbe, 0xbe, 0xbe, 0x67, 0x69, 0x6a, 0x6b, 0x6b, 0x6c, 0x6d, 0x6d, 0x6d}, SKINCOLOR_RASPBERRY, 13, V_PERIDOTMAP, true}, // SKINCOLOR_APPLE
{"Green", {0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f}, SKINCOLOR_RED, 6, V_GREENMAP, true}, // SKINCOLOR_GREEN
{"Forest", {0x65, 0x66, 0x67, 0x68, 0x69, 0x69, 0x6a, 0x6b, 0x6b, 0x6c, 0x6d, 0x6d, 0x6e, 0x6e, 0x6e, 0x6f}, SKINCOLOR_SALMON, 9, V_GREENMAP, true}, // SKINCOLOR_FOREST
{"Emerald", {0x70, 0x70, 0x71, 0x71, 0x72, 0x72, 0x73, 0x73, 0x73, 0x74, 0x75, 0x75, 0x76, 0x76, 0x77, 0x77}, SKINCOLOR_RUBY, 4, V_GREENMAP, true}, // SKINCOLOR_EMERALD
{"Mint", {0x00, 0x00, 0x58, 0x58, 0x59, 0x62, 0x62, 0x62, 0x64, 0x67, 0x7e, 0x7e, 0x8f, 0x8f, 0x8a, 0x8a}, SKINCOLOR_VIOLET, 5, V_GREENMAP, true}, // SKINCOLOR_MINT
{"Seafoam", {0x01, 0x58, 0x59, 0x5a, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x8f, 0x8f, 0x8a, 0x8a, 0x8a, 0xfd, 0xfd}, SKINCOLOR_PLUM, 6, V_AQUAMAP, true}, // SKINCOLOR_SEAFOAM
{"Aqua", {0x78, 0x79, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c, 0x7d, 0x7e, 0x7e, 0x7f, 0x7f, 0x76, 0x77}, SKINCOLOR_ROSY, 7, V_AQUAMAP, true}, // SKINCOLOR_AQUA
{"Teal", {0x78, 0x78, 0x8c, 0x8c, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x8a, 0x8a, 0x8a, 0x8a}, SKINCOLOR_PEACHY, 7, V_SKYMAP, true}, // SKINCOLOR_TEAL
{"Wave", {0x00, 0x78, 0x78, 0x79, 0x8d, 0x87, 0x88, 0x89, 0x89, 0xae, 0xa8, 0xa8, 0xa9, 0xa9, 0xfd, 0xfd}, SKINCOLOR_QUAIL, 5, V_SKYMAP, true}, // SKINCOLOR_WAVE
{"Cyan", {0x80, 0x81, 0xff, 0xff, 0x83, 0x83, 0x8d, 0x8d, 0x8d, 0x8e, 0x7e, 0x7f, 0x76, 0x76, 0x77, 0x6e}, SKINCOLOR_APRICOT, 6, V_SKYMAP, true}, // SKINCOLOR_CYAN
{"Sky", {0x80, 0x80, 0x81, 0x82, 0x83, 0x83, 0x84, 0x85, 0x85, 0x86, 0x87, 0x88, 0x89, 0x89, 0x8a, 0x8b}, SKINCOLOR_SANDY, 1, V_SKYMAP, true}, // SKINCOLOR_SKY
{"Cerulean", {0x85, 0x86, 0x87, 0x88, 0x88, 0x89, 0x89, 0x89, 0x8a, 0x8a, 0xfd, 0xfd, 0xfd, 0x1f, 0x1f, 0x1f}, SKINCOLOR_NEON, 4, V_SKYMAP, true}, // SKINCOLOR_CERULEAN
{"Icy", {0x00, 0x00, 0x00, 0x00, 0x80, 0x81, 0x83, 0x83, 0x86, 0x87, 0x95, 0x95, 0xad, 0xad, 0xae, 0xaf}, SKINCOLOR_CRIMSON, 0, V_SKYMAP, true}, // SKINCOLOR_ICY
{"Sapphire", {0x80, 0x83, 0x86, 0x87, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xfd, 0xfe}, SKINCOLOR_SUNSET, 5, V_SKYMAP, true}, // SKINCOLOR_SAPPHIRE
{"Cornflower", {0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x9a, 0x9c, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e}, SKINCOLOR_YELLOW, 4, V_BLUEMAP, true}, // SKINCOLOR_CORNFLOWER
{"Blue", {0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xfd, 0xfe}, SKINCOLOR_ORANGE, 5, V_BLUEMAP, true}, // SKINCOLOR_BLUE
{"Cobalt", {0x93, 0x94, 0x95, 0x96, 0x98, 0x9a, 0x9b, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xfd, 0xfd, 0xfe, 0xfe}, SKINCOLOR_PERIDOT, 5, V_BLUEMAP, true}, // SKINCOLOR_COBALT
{"Vapor", {0x80, 0x81, 0x83, 0x86, 0x94, 0x94, 0xa3, 0xa3, 0xa4, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa9, 0xa9}, SKINCOLOR_LILAC, 4, V_SKYMAP, true}, // SKINCOLOR_VAPOR
{"Dusk", {0x92, 0x93, 0x94, 0x94, 0xac, 0xad, 0xad, 0xad, 0xae, 0xae, 0xaf, 0xaf, 0xa9, 0xa9, 0xfd, 0xfd}, SKINCOLOR_OLIVE, 0, V_BLUEMAP, true}, // SKINCOLOR_DUSK
{"Pastel", {0x90, 0x90, 0xa0, 0xa0, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa3, 0xa4, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8}, SKINCOLOR_BUBBLEGUM, 9, V_PURPLEMAP, true}, // SKINCOLOR_PASTEL
{"Purple", {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa6, 0xa7, 0xa7, 0xa8, 0xa8, 0xa9, 0xa9}, SKINCOLOR_FLAME, 7, V_PURPLEMAP, true}, // SKINCOLOR_PURPLE
{"Bubblegum", {0x00, 0xd0, 0xd0, 0xc8, 0xc8, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8}, SKINCOLOR_PASTEL, 8, V_MAGENTAMAP, true}, // SKINCOLOR_BUBBLEGUM
{"Magenta", {0xb3, 0xb3, 0xb4, 0xb5, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xbb}, SKINCOLOR_LIME, 6, V_MAGENTAMAP, true}, // SKINCOLOR_MAGENTA
{"Neon", {0xb3, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xbb, 0xc7, 0xc7, 0x1d, 0x1d, 0x1e}, SKINCOLOR_CERULEAN, 2, V_MAGENTAMAP, true}, // SKINCOLOR_NEON
{"Violet", {0xd0, 0xd1, 0xd2, 0xca, 0xcc, 0xb8, 0xb9, 0xb9, 0xba, 0xa8, 0xa8, 0xa9, 0xa9, 0xfd, 0xfe, 0xfe}, SKINCOLOR_MINT, 6, V_MAGENTAMAP, true}, // SKINCOLOR_VIOLET
{"Lilac", {0x00, 0xd0, 0xd1, 0xd2, 0xd3, 0xc1, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc5, 0xc6, 0xc6, 0xfe, 0x1f}, SKINCOLOR_VAPOR, 4, V_ROSYMAP, true}, // SKINCOLOR_LILAC
{"Plum", {0xc8, 0xd3, 0xd5, 0xd6, 0xd7, 0xce, 0xcf, 0xb9, 0xb9, 0xba, 0xba, 0xa9, 0xa9, 0xa9, 0xfd, 0xfe}, SKINCOLOR_MINT, 7, V_ROSYMAP, true}, // SKINCOLOR_PLUM
{"Raspberry", {0xc8, 0xc9, 0xca, 0xcb, 0xcb, 0xcc, 0xcd, 0xcd, 0xce, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xfe, 0xfe}, SKINCOLOR_APPLE, 15, V_MAGENTAMAP, true}, // SKINCOLOR_RASPBERRY
{"Rosy", {0xfc, 0xc8, 0xc8, 0xc9, 0xc9, 0xca, 0xca, 0xcb, 0xcb, 0xcc, 0xcc, 0xcd, 0xcd, 0xce, 0xce, 0xcf}, SKINCOLOR_AQUA, 1, V_ROSYMAP, true}, // SKINCOLOR_ROSY
// super
{"Super Silver 1", {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x03}, SKINCOLOR_BLACK, 15, 0, false}, // SKINCOLOR_SUPERSILVER1
{"Super Silver 2", {0x00, 0x01, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x07}, SKINCOLOR_BLACK, 6, 0, false}, // SKINCOLOR_SUPERSILVER2
{"Super Silver 3", {0x01, 0x02, 0x02, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x07, 0x09, 0x0b}, SKINCOLOR_BLACK, 5, 0, false}, // SKINCOLOR_SUPERSILVER3
{"Super Silver 4", {0x02, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x07, 0x09, 0x0b, 0x0d, 0x0f, 0x11}, SKINCOLOR_BLACK, 5, V_GRAYMAP, false}, // SKINCOLOR_SUPERSILVER4
{"Super Silver 5", {0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x07, 0x09, 0x0b, 0x0d, 0x0f, 0x11, 0x13}, SKINCOLOR_BLACK, 5, V_GRAYMAP, false}, // SKINCOLOR_SUPERSILVER5
{"Super Red 1", {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0xd0, 0xd1, 0xd1, 0xd2, 0xd2}, SKINCOLOR_CYAN, 15, 0, false}, // SKINCOLOR_SUPERRED1
{"Super Red 2", {0x00, 0x00, 0x00, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1, 0xd2, 0xd2, 0xd2, 0x20, 0x20, 0x21, 0x21}, SKINCOLOR_CYAN, 14, V_ROSYMAP, false}, // SKINCOLOR_SUPERRED2
{"Super Red 3", {0x00, 0x00, 0xd0, 0xd0, 0xd1, 0xd1, 0xd2, 0xd2, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23}, SKINCOLOR_CYAN, 13, V_REDMAP, false}, // SKINCOLOR_SUPERRED3
{"Super Red 4", {0x00, 0xd0, 0xd1, 0xd1, 0xd2, 0xd2, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, 0x24, 0x24}, SKINCOLOR_CYAN, 11, V_REDMAP, false}, // SKINCOLOR_SUPERRED4
{"Super Red 5", {0xd0, 0xd1, 0xd2, 0xd2, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, 0x24, 0x24, 0x25, 0x25}, SKINCOLOR_CYAN, 10, V_REDMAP, false}, // SKINCOLOR_SUPERRED5
{"Super Orange 1", {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x30, 0x31, 0x32, 0x33, 0x34}, SKINCOLOR_SAPPHIRE, 15, 0, false}, // SKINCOLOR_SUPERORANGE1
{"Super Orange 2", {0x00, 0x00, 0x00, 0x00, 0xd0, 0xd0, 0x30, 0x30, 0x31, 0x31, 0x32, 0x32, 0x33, 0x33, 0x34, 0x34}, SKINCOLOR_SAPPHIRE, 12, V_ORANGEMAP, false}, // SKINCOLOR_SUPERORANGE2
{"Super Orange 3", {0x00, 0x00, 0xd0, 0xd0, 0x30, 0x30, 0x31, 0x31, 0x32, 0x32, 0x33, 0x33, 0x34, 0x34, 0x35, 0x35}, SKINCOLOR_SAPPHIRE, 9, V_ORANGEMAP, false}, // SKINCOLOR_SUPERORANGE3
{"Super Orange 4", {0x00, 0xd0, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x44, 0x45, 0x46}, SKINCOLOR_SAPPHIRE, 4, V_ORANGEMAP, false}, // SKINCOLOR_SUPERORANGE4
{"Super Orange 5", {0xd0, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x44, 0x45, 0x46, 0x47}, SKINCOLOR_SAPPHIRE, 3, V_ORANGEMAP, false}, // SKINCOLOR_SUPERORANGE5
{"Super Gold 1", {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x50, 0x51, 0x52, 0x53, 0x48}, SKINCOLOR_CORNFLOWER, 15, 0, false}, // SKINCOLOR_SUPERGOLD1
{"Super Gold 2", {0x00, 0x50, 0x51, 0x52, 0x53, 0x53, 0x48, 0x48, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x40, 0x41}, SKINCOLOR_CORNFLOWER, 9, V_YELLOWMAP, false}, // SKINCOLOR_SUPERGOLD2
{"Super Gold 3", {0x51, 0x52, 0x53, 0x53, 0x48, 0x48, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x40, 0x41, 0x42, 0x43}, SKINCOLOR_CORNFLOWER, 8, V_YELLOWMAP, false}, // SKINCOLOR_SUPERGOLD3
{"Super Gold 4", {0x53, 0x48, 0x48, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46}, SKINCOLOR_CORNFLOWER, 8, V_YELLOWMAP, false}, // SKINCOLOR_SUPERGOLD4
{"Super Gold 5", {0x48, 0x48, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47}, SKINCOLOR_CORNFLOWER, 8, V_YELLOWMAP, false}, // SKINCOLOR_SUPERGOLD5
{"Super Peridot 1", {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x58, 0x58, 0xbc, 0xbc, 0xbc}, SKINCOLOR_COBALT, 15, 0, false}, // SKINCOLOR_SUPERPERIDOT1
{"Super Peridot 2", {0x00, 0x58, 0x58, 0x58, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe}, SKINCOLOR_COBALT, 4, V_PERIDOTMAP, false}, // SKINCOLOR_SUPERPERIDOT2
{"Super Peridot 3", {0x58, 0x58, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbf, 0xbf}, SKINCOLOR_COBALT, 3, V_PERIDOTMAP, false}, // SKINCOLOR_SUPERPERIDOT3
{"Super Peridot 4", {0x58, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbf, 0xbf, 0x5e, 0x5e, 0x5f}, SKINCOLOR_COBALT, 3, V_PERIDOTMAP, false}, // SKINCOLOR_SUPERPERIDOT4
{"Super Peridot 5", {0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbf, 0xbf, 0x5e, 0x5e, 0x5f, 0x77}, SKINCOLOR_COBALT, 3, V_PERIDOTMAP, false}, // SKINCOLOR_SUPERPERIDOT5
{"Super Sky 1", {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x81, 0x82, 0x83, 0x84}, SKINCOLOR_RUST, 15, 0, false}, // SKINCOLOR_SUPERSKY1
{"Super Sky 2", {0x00, 0x80, 0x81, 0x82, 0x83, 0x83, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x86, 0x86}, SKINCOLOR_RUST, 4, V_SKYMAP, false}, // SKINCOLOR_SUPERSKY2
{"Super Sky 3", {0x81, 0x82, 0x83, 0x83, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x86, 0x86, 0x87, 0x87}, SKINCOLOR_RUST, 3, V_SKYMAP, false}, // SKINCOLOR_SUPERSKY3
{"Super Sky 4", {0x83, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x86, 0x86, 0x87, 0x87, 0x88, 0x89, 0x8a}, SKINCOLOR_RUST, 3, V_SKYMAP, false}, // SKINCOLOR_SUPERSKY4
{"Super Sky 5", {0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x86, 0x86, 0x87, 0x87, 0x88, 0x89, 0x8a, 0x8b}, SKINCOLOR_RUST, 3, V_SKYMAP, false}, // SKINCOLOR_SUPERSKY5
{"Super Purple 1", {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90, 0xa0, 0xa0, 0xa1, 0xa2}, SKINCOLOR_EMERALD, 15, 0, false}, // SKINCOLOR_SUPERPURPLE1
{"Super Purple 2", {0x00, 0x90, 0xa0, 0xa0, 0xa1, 0xa1, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa5, 0xa5}, SKINCOLOR_EMERALD, 4, V_PURPLEMAP, false}, // SKINCOLOR_SUPERPURPLE2
{"Super Purple 3", {0xa0, 0xa0, 0xa1, 0xa1, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa5, 0xa5, 0xa6, 0xa6}, SKINCOLOR_EMERALD, 0, V_PURPLEMAP, false}, // SKINCOLOR_SUPERPURPLE3
{"Super Purple 4", {0xa1, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa5, 0xa5, 0xa6, 0xa6, 0xa7, 0xa8, 0xa9}, SKINCOLOR_EMERALD, 0, V_PURPLEMAP, false}, // SKINCOLOR_SUPERPURPLE4
{"Super Purple 5", {0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa5, 0xa5, 0xa6, 0xa6, 0xa7, 0xa8, 0xa9, 0xfd}, SKINCOLOR_EMERALD, 0, V_PURPLEMAP, false}, // SKINCOLOR_SUPERPURPLE5
{"Super Rust 1", {0x00, 0xd0, 0xd0, 0xd0, 0x30, 0x30, 0x31, 0x32, 0x33, 0x37, 0x3a, 0x44, 0x45, 0x46, 0x47, 0x2e}, SKINCOLOR_CYAN, 14, V_ORANGEMAP, false}, // SKINCOLOR_SUPERRUST1
{"Super Rust 2", {0x30, 0x31, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x38, 0x3a, 0x44, 0x45, 0x46, 0x47, 0x47, 0x2e}, SKINCOLOR_CYAN, 10, V_ORANGEMAP, false}, // SKINCOLOR_SUPERRUST2
{"Super Rust 3", {0x31, 0x32, 0x33, 0x34, 0x36, 0x37, 0x38, 0x3a, 0x44, 0x45, 0x45, 0x46, 0x46, 0x47, 0x2e, 0x2e}, SKINCOLOR_CYAN, 9, V_ORANGEMAP, false}, // SKINCOLOR_SUPERRUST3
{"Super Rust 4", {0x48, 0x40, 0x41, 0x42, 0x43, 0x44, 0x44, 0x45, 0x45, 0x46, 0x46, 0x47, 0x47, 0x2e, 0x2e, 0x2e}, SKINCOLOR_CYAN, 8, V_ORANGEMAP, false}, // SKINCOLOR_SUPERRUST4
{"Super Rust 5", {0x41, 0x42, 0x43, 0x43, 0x44, 0x44, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xed, 0xee, 0xee, 0xef, 0xef}, SKINCOLOR_CYAN, 8, V_ORANGEMAP, false}, // SKINCOLOR_SUPERRUST5
{"Super Tan 1", {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x50, 0x51, 0x51, 0x52, 0x52}, SKINCOLOR_BROWN, 14, 0, false}, // SKINCOLOR_SUPERTAN1
{"Super Tan 2", {0x00, 0x50, 0x50, 0x51, 0x51, 0x52, 0x52, 0x52, 0x54, 0x54, 0x54, 0x54, 0x55, 0x56, 0x57, 0xf5}, SKINCOLOR_BROWN, 13, V_BROWNMAP, false}, // SKINCOLOR_SUPERTAN2
{"Super Tan 3", {0x50, 0x51, 0x51, 0x52, 0x52, 0x52, 0x54, 0x54, 0x54, 0x54, 0x55, 0x56, 0x57, 0xf5, 0xf7, 0xf9}, SKINCOLOR_BROWN, 12, V_BROWNMAP, false}, // SKINCOLOR_SUPERTAN3
{"Super Tan 4", {0x51, 0x52, 0x52, 0x52, 0x52, 0x54, 0x54, 0x54, 0x55, 0x56, 0x57, 0xf5, 0xf7, 0xf9, 0xfb, 0xed}, SKINCOLOR_BROWN, 11, V_BROWNMAP, false}, // SKINCOLOR_SUPERTAN4
{"Super Tan 5", {0x52, 0x52, 0x54, 0x54, 0x54, 0x55, 0x56, 0x57, 0xf5, 0xf7, 0xf9, 0xfb, 0xed, 0xee, 0xef, 0xef}, SKINCOLOR_BROWN, 10, V_BROWNMAP, false} // SKINCOLOR_SUPERTAN5
};
/** Patches the mobjinfo, state, and skincolor tables.
* Free slots are emptied out and set to initial values.
*/
void P_PatchInfoTables(void)
@ -21618,6 +21751,11 @@ void P_PatchInfoTables(void)
sprnames[i][0] = '\0'; // i == NUMSPRITES
memset(&states[S_FIRSTFREESLOT], 0, sizeof (state_t) * NUMSTATEFREESLOTS);
memset(&mobjinfo[MT_FIRSTFREESLOT], 0, sizeof (mobjinfo_t) * NUMMOBJFREESLOTS);
memset(&skincolors[SKINCOLOR_FIRSTFREESLOT], 0, sizeof (skincolor_t) * NUMCOLORFREESLOTS);
for (i = SKINCOLOR_FIRSTFREESLOT; i <= SKINCOLOR_LASTFREESLOT; i++) {
skincolors[i].accessible = false;
skincolors[i].name[0] = '\0';
}
for (i = MT_FIRSTFREESLOT; i <= MT_LASTFREESLOT; i++)
mobjinfo[i].doomednum = -1;
}
@ -21626,7 +21764,8 @@ void P_PatchInfoTables(void)
static char *sprnamesbackup;
static state_t *statesbackup;
static mobjinfo_t *mobjinfobackup;
static size_t sprnamesbackupsize, statesbackupsize, mobjinfobackupsize;
static skincolor_t *skincolorsbackup;
static size_t sprnamesbackupsize, statesbackupsize, mobjinfobackupsize, skincolorsbackupsize;
#endif
void P_BackupTables(void)
@ -21636,6 +21775,7 @@ void P_BackupTables(void)
sprnamesbackup = Z_Malloc(sizeof(sprnames), PU_STATIC, NULL);
statesbackup = Z_Malloc(sizeof(states), PU_STATIC, NULL);
mobjinfobackup = Z_Malloc(sizeof(mobjinfo), PU_STATIC, NULL);
skincolorsbackup = Z_Malloc(sizeof(skincolors), PU_STATIC, NULL);
// Sprite names
sprnamesbackupsize = lzf_compress(sprnames, sizeof(sprnames), sprnamesbackup, sizeof(sprnames));
@ -21657,6 +21797,13 @@ void P_BackupTables(void)
mobjinfobackup = Z_Realloc(mobjinfobackup, mobjinfobackupsize, PU_STATIC, NULL);
else
M_Memcpy(mobjinfobackup, mobjinfo, sizeof(mobjinfo));
//Skincolor info
skincolorsbackupsize = lzf_compress(skincolors, sizeof(skincolors), skincolorsbackup, sizeof(skincolors));
if (skincolorsbackupsize > 0)
skincolorsbackup = Z_Realloc(skincolorsbackup, skincolorsbackupsize, PU_STATIC, NULL);
else
M_Memcpy(skincolorsbackup, skincolors, sizeof(skincolors));
#endif
}
@ -21689,5 +21836,13 @@ void P_ResetData(INT32 flags)
else
M_Memcpy(mobjinfo, mobjinfobackup, sizeof(mobjinfobackup));
}
if (flags & 8)
{
if (skincolorsbackupsize > 0)
lzf_decompress(skincolorsbackup, skincolorsbackupsize, skincolors, sizeof(skincolors));
else
M_Memcpy(skincolors, skincolorsbackup, sizeof(skincolorsbackup));
}
#endif
}

View file

@ -14,7 +14,7 @@
#include "fastcmp.h"
#include "p_local.h"
#include "p_setup.h" // So we can have P_SetupLevelSky
#include "p_slopes.h" // P_GetZAt
#include "p_slopes.h" // P_GetSlopeZAt
#include "z_zone.h"
#include "r_main.h"
#include "r_draw.h"
@ -27,6 +27,7 @@
#include "hu_stuff.h" // HU_AddChatText
#include "console.h"
#include "d_netcmd.h" // IsPlayerAdmin
#include "m_menu.h" // Player Setup menu color stuff
#include "lua_script.h"
#include "lua_libs.h"
@ -144,6 +145,8 @@ static const struct {
{META_STATE, "state_t"},
{META_MOBJINFO, "mobjinfo_t"},
{META_SFXINFO, "sfxinfo_t"},
{META_SKINCOLOR, "skincolor_t"},
{META_COLORRAMP, "skincolor_t.ramp"},
{META_SPRITEINFO, "spriteinfo_t"},
{META_PIVOTLIST, "spriteframepivot_t[]"},
{META_FRAMEPIVOT, "spriteframepivot_t"},
@ -257,6 +260,43 @@ static int lib_reserveLuabanks(lua_State *L)
return 1;
}
// M_MENU
//////////////
static int lib_pMoveColorBefore(lua_State *L)
{
UINT16 color = (UINT16)luaL_checkinteger(L, 1);
UINT16 targ = (UINT16)luaL_checkinteger(L, 2);
NOHUD
M_MoveColorBefore(color, targ);
return 0;
}
static int lib_pMoveColorAfter(lua_State *L)
{
UINT16 color = (UINT16)luaL_checkinteger(L, 1);
UINT16 targ = (UINT16)luaL_checkinteger(L, 2);
NOHUD
M_MoveColorAfter(color, targ);
return 0;
}
static int lib_pGetColorBefore(lua_State *L)
{
UINT16 color = (UINT16)luaL_checkinteger(L, 1);
lua_pushinteger(L, M_GetColorBefore(color));
return 1;
}
static int lib_pGetColorAfter(lua_State *L)
{
UINT16 color = (UINT16)luaL_checkinteger(L, 1);
lua_pushinteger(L, M_GetColorAfter(color));
return 1;
}
// M_RANDOM
//////////////
@ -2189,14 +2229,20 @@ static int lib_evStartCrumble(lua_State *L)
static int lib_pGetZAt(lua_State *L)
{
pslope_t *slope = *((pslope_t **)luaL_checkudata(L, 1, META_SLOPE));
fixed_t x = luaL_checkfixed(L, 2);
fixed_t y = luaL_checkfixed(L, 3);
//HUDSAFE
if (!slope)
return LUA_ErrInvalid(L, "pslope_t");
if (lua_isnil(L, 1))
{
fixed_t z = luaL_checkfixed(L, 4);
lua_pushfixed(L, P_GetZAt(NULL, x, y, z));
}
else
{
pslope_t *slope = *((pslope_t **)luaL_checkudata(L, 1, META_SLOPE));
lua_pushfixed(L, P_GetSlopeZAt(slope, x, y));
}
lua_pushfixed(L, P_GetZAt(slope, x, y));
return 1;
}
@ -2387,10 +2433,10 @@ static int lib_rGetColorByName(lua_State *L)
// SKINCOLOR_GREEN > "Green" for example
static int lib_rGetNameByColor(lua_State *L)
{
UINT8 colornum = (UINT8)luaL_checkinteger(L, 1);
if (!colornum || colornum >= MAXSKINCOLORS)
return luaL_error(L, "skincolor %d out of range (1 - %d).", colornum, MAXSKINCOLORS-1);
lua_pushstring(L, Color_Names[colornum]);
UINT16 colornum = (UINT16)luaL_checkinteger(L, 1);
if (!colornum || colornum >= numskincolors)
return luaL_error(L, "skincolor %d out of range (1 - %d).", colornum, numskincolors-1);
lua_pushstring(L, skincolors[colornum].name);
return 1;
}
@ -2463,6 +2509,20 @@ static int lib_sStopSound(lua_State *L)
return 0;
}
static int lib_sStopSoundByID(lua_State *L)
{
void *origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
sfxenum_t sound_id = luaL_checkinteger(L, 2);
//NOHUD
if (!origin)
return LUA_ErrInvalid(L, "mobj_t");
if (sound_id >= NUMSFX)
return luaL_error(L, "sfx %d out of range (0 - %d)", sound_id, NUMSFX-1);
S_StopSoundByID(origin, sound_id);
return 0;
}
static int lib_sChangeMusic(lua_State *L)
{
#ifdef MUSICSLOT_COMPATIBILITY
@ -2883,15 +2943,50 @@ static int lib_gAddGametype(lua_State *L)
return 0;
}
static int Lcheckmapnumber (lua_State *L, int idx, const char *fun)
{
if (ISINLEVEL)
return luaL_optinteger(L, idx, gamemap);
else
{
if (lua_isnoneornil(L, idx))
{
return luaL_error(L,
"%s can only be used without a parameter while in a level.",
fun
);
}
else
return luaL_checkinteger(L, idx);
}
}
static int lib_gBuildMapName(lua_State *L)
{
INT32 map = luaL_optinteger(L, 1, gamemap);
INT32 map = Lcheckmapnumber(L, 1, "G_BuildMapName");
//HUDSAFE
INLEVEL
lua_pushstring(L, G_BuildMapName(map));
return 1;
}
static int lib_gBuildMapTitle(lua_State *L)
{
INT32 map = Lcheckmapnumber(L, 1, "G_BuildMapTitle");
char *name;
if (map < 1 || map > NUMMAPS)
{
return luaL_error(L,
"map number %d out of range (1 - %d)",
map,
NUMMAPS
);
}
name = G_BuildMapTitle(map);
lua_pushstring(L, name);
Z_Free(name);
return 1;
}
static int lib_gDoReborn(lua_State *L)
{
INT32 playernum = luaL_checkinteger(L, 1);
@ -3078,6 +3173,12 @@ static luaL_Reg lib[] = {
{"IsPlayerAdmin", lib_isPlayerAdmin},
{"reserveLuabanks", lib_reserveLuabanks},
// m_menu
{"M_MoveColorAfter",lib_pMoveColorAfter},
{"M_MoveColorBefore",lib_pMoveColorBefore},
{"M_GetColorAfter",lib_pGetColorAfter},
{"M_GetColorBefore",lib_pGetColorBefore},
// m_random
{"P_RandomFixed",lib_pRandomFixed},
{"P_RandomByte",lib_pRandomByte},
@ -3258,6 +3359,7 @@ static luaL_Reg lib[] = {
{"S_StartSound",lib_sStartSound},
{"S_StartSoundAtVolume",lib_sStartSoundAtVolume},
{"S_StopSound",lib_sStopSound},
{"S_StopSoundByID",lib_sStopSoundByID},
{"S_ChangeMusic",lib_sChangeMusic},
{"S_SpeedMusic",lib_sSpeedMusic},
{"S_StopMusic",lib_sStopMusic},
@ -3276,6 +3378,7 @@ static luaL_Reg lib[] = {
// g_game
{"G_AddGametype", lib_gAddGametype},
{"G_BuildMapName",lib_gBuildMapName},
{"G_BuildMapTitle",lib_gBuildMapTitle},
{"G_DoReborn",lib_gDoReborn},
{"G_SetCustomExitVars",lib_gSetCustomExitVars},
{"G_EnoughPlayersFinished",lib_gEnoughPlayersFinished},

File diff suppressed because it is too large Load diff

View file

@ -878,8 +878,8 @@ static int libd_drawNameTag(lua_State *L)
INT32 y;
const char *str;
INT32 flags;
UINT8 basecolor;
UINT8 outlinecolor;
UINT16 basecolor;
UINT16 outlinecolor;
UINT8 *basecolormap = NULL;
UINT8 *outlinecolormap = NULL;
@ -908,8 +908,8 @@ static int libd_drawScaledNameTag(lua_State *L)
const char *str;
INT32 flags;
fixed_t scale;
UINT8 basecolor;
UINT8 outlinecolor;
UINT16 basecolor;
UINT16 outlinecolor;
UINT8 *basecolormap = NULL;
UINT8 *outlinecolormap = NULL;
@ -966,7 +966,7 @@ static int libd_nameTagWidth(lua_State *L)
static int libd_getColormap(lua_State *L)
{
INT32 skinnum = TC_DEFAULT;
skincolors_t color = luaL_optinteger(L, 2, 0);
skincolornum_t color = luaL_optinteger(L, 2, 0);
UINT8* colormap = NULL;
HUDONLY
if (lua_isnoneornil(L, 1))

View file

@ -25,6 +25,9 @@
#include "lua_libs.h"
#include "lua_hud.h" // hud_running errors
extern CV_PossibleValue_t Color_cons_t[MAXSKINCOLORS+1];
extern void R_FlushTranslationColormapCache(void);
boolean LUA_CallAction(const char *action, mobj_t *actor);
state_t *astate;
@ -1465,6 +1468,229 @@ static int lib_luabankslen(lua_State *L)
return 1;
}
////////////////////
// SKINCOLOR INFO //
////////////////////
// Arbitrary skincolors[] table index -> skincolor_t *
static int lib_getSkinColor(lua_State *L)
{
UINT32 i;
lua_remove(L, 1);
i = luaL_checkinteger(L, 1);
if (!i || i >= numskincolors)
return luaL_error(L, "skincolors[] index %d out of range (1 - %d)", i, numskincolors-1);
LUA_PushUserdata(L, &skincolors[i], META_SKINCOLOR);
return 1;
}
//Set the entire c->ramp array
static void setRamp(lua_State *L, skincolor_t* c) {
UINT32 i;
lua_pushnil(L);
for (i=0; i<COLORRAMPSIZE; i++) {
if (lua_objlen(L,-2)<COLORRAMPSIZE) {
luaL_error(L, LUA_QL("skincolor_t") " field 'ramp' must be %d entries long; got %d.", COLORRAMPSIZE, lua_objlen(L,-2));
break;
}
if (lua_next(L, -2) != 0) {
c->ramp[i] = lua_isnumber(L,-1) ? (UINT8)luaL_checkinteger(L,-1) : 120;
lua_pop(L, 1);
} else
c->ramp[i] = 120;
}
lua_pop(L,1);
}
// Lua table full of data -> skincolors[]
static int lib_setSkinColor(lua_State *L)
{
UINT32 j;
skincolor_t *info;
UINT16 cnum; //skincolor num
lua_remove(L, 1); // don't care about skincolors[] userdata.
{
cnum = (UINT16)luaL_checkinteger(L, 1);
if (cnum < SKINCOLOR_FIRSTFREESLOT || cnum >= numskincolors)
return luaL_error(L, "skincolors[] index %d out of range (%d - %d)", cnum, SKINCOLOR_FIRSTFREESLOT, numskincolors-1);
info = &skincolors[cnum]; // get the skincolor to assign to.
}
luaL_checktype(L, 2, LUA_TTABLE); // check that we've been passed a table.
lua_remove(L, 1); // pop skincolor num, don't need it any more.
lua_settop(L, 1); // cut the stack here. the only thing left now is the table of data we're assigning to the skincolor.
if (hud_running)
return luaL_error(L, "Do not alter skincolors in HUD rendering code!");
// clear the skincolor to start with, in case of missing table elements
memset(info,0,sizeof(skincolor_t));
Color_cons_t[cnum].value = cnum;
lua_pushnil(L);
while (lua_next(L, 1)) {
lua_Integer i = 0;
const char *str = NULL;
if (lua_isnumber(L, 2))
i = lua_tointeger(L, 2);
else
str = luaL_checkstring(L, 2);
if (i == 1 || (str && fastcmp(str,"name"))) {
const char* n = luaL_checkstring(L, 3);
strlcpy(info->name, n, MAXCOLORNAME+1);
if (strlen(n) > MAXCOLORNAME)
CONS_Alert(CONS_WARNING, "skincolor_t field 'name' ('%s') longer than %d chars; shortened to %s.\n", n, MAXCOLORNAME, info->name);
} else if (i == 2 || (str && fastcmp(str,"ramp"))) {
if (!lua_istable(L, 3) && luaL_checkudata(L, 3, META_COLORRAMP) == NULL)
return luaL_error(L, LUA_QL("skincolor_t") " field 'ramp' must be a table or array.");
else if (lua_istable(L, 3))
setRamp(L, info);
else
for (j=0; j<COLORRAMPSIZE; j++)
info->ramp[j] = (*((UINT8 **)luaL_checkudata(L, 3, META_COLORRAMP)))[j];
R_FlushTranslationColormapCache();
} else if (i == 3 || (str && fastcmp(str,"invcolor")))
info->invcolor = (UINT16)luaL_checkinteger(L, 3);
else if (i == 4 || (str && fastcmp(str,"invshade")))
info->invshade = (UINT8)luaL_checkinteger(L, 3)%COLORRAMPSIZE;
else if (i == 5 || (str && fastcmp(str,"chatcolor")))
info->chatcolor = (UINT16)luaL_checkinteger(L, 3);
else if (i == 6 || (str && fastcmp(str,"accessible"))) {
boolean v = lua_isboolean(L,3) ? lua_toboolean(L, 3) : true;
if (cnum < FIRSTSUPERCOLOR && v != skincolors[cnum].accessible)
return luaL_error(L, "skincolors[] index %d is a standard color; accessibility changes are prohibited.", i);
else
info->accessible = v;
}
lua_pop(L, 1);
}
return 0;
}
// #skincolors -> numskincolors
static int lib_skincolorslen(lua_State *L)
{
lua_pushinteger(L, numskincolors);
return 1;
}
// skincolor_t *, field -> number
static int skincolor_get(lua_State *L)
{
skincolor_t *info = *((skincolor_t **)luaL_checkudata(L, 1, META_SKINCOLOR));
const char *field = luaL_checkstring(L, 2);
I_Assert(info != NULL);
I_Assert(info >= skincolors);
if (fastcmp(field,"name"))
lua_pushstring(L, info->name);
else if (fastcmp(field,"ramp"))
LUA_PushUserdata(L, info->ramp, META_COLORRAMP);
else if (fastcmp(field,"invcolor"))
lua_pushinteger(L, info->invcolor);
else if (fastcmp(field,"invshade"))
lua_pushinteger(L, info->invshade);
else if (fastcmp(field,"chatcolor"))
lua_pushinteger(L, info->chatcolor);
else if (fastcmp(field,"accessible"))
lua_pushboolean(L, info->accessible);
else
CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; returning nil.\n"), "skincolor_t", field);
return 1;
}
// skincolor_t *, field, number -> skincolors[]
static int skincolor_set(lua_State *L)
{
UINT32 i;
skincolor_t *info = *((skincolor_t **)luaL_checkudata(L, 1, META_SKINCOLOR));
const char *field = luaL_checkstring(L, 2);
I_Assert(info != NULL);
I_Assert(info >= skincolors);
if (info-skincolors < SKINCOLOR_FIRSTFREESLOT || info-skincolors >= numskincolors)
return luaL_error(L, "skincolors[] index %d out of range (%d - %d)", info-skincolors, SKINCOLOR_FIRSTFREESLOT, numskincolors-1);
if (fastcmp(field,"name")) {
const char* n = luaL_checkstring(L, 3);
if (strchr(n, ' ') != NULL)
CONS_Alert(CONS_WARNING, "skincolor_t field 'name' ('%s') contains spaces.\n", n);
strlcpy(info->name, n, MAXCOLORNAME+1);
if (strlen(n) > MAXCOLORNAME)
CONS_Alert(CONS_WARNING, "skincolor_t field 'name' ('%s') longer than %d chars; clipped to %s.\n", n, MAXCOLORNAME, info->name);
} else if (fastcmp(field,"ramp")) {
if (!lua_istable(L, 3) && luaL_checkudata(L, 3, META_COLORRAMP) == NULL)
return luaL_error(L, LUA_QL("skincolor_t") " field 'ramp' must be a table or array.");
else if (lua_istable(L, 3))
setRamp(L, info);
else
for (i=0; i<COLORRAMPSIZE; i++)
info->ramp[i] = (*((UINT8 **)luaL_checkudata(L, 3, META_COLORRAMP)))[i];
R_FlushTranslationColormapCache();
} else if (fastcmp(field,"invcolor"))
info->invcolor = (UINT16)luaL_checkinteger(L, 3);
else if (fastcmp(field,"invshade"))
info->invshade = (UINT8)luaL_checkinteger(L, 3)%COLORRAMPSIZE;
else if (fastcmp(field,"chatcolor"))
info->chatcolor = (UINT16)luaL_checkinteger(L, 3);
else if (fastcmp(field,"accessible"))
info->accessible = lua_isboolean(L,3);
else
CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; returning nil.\n"), "skincolor_t", field);
return 1;
}
// skincolor_t * -> SKINCOLOR_*
static int skincolor_num(lua_State *L)
{
skincolor_t *info = *((skincolor_t **)luaL_checkudata(L, 1, META_SKINCOLOR));
I_Assert(info != NULL);
I_Assert(info >= skincolors);
lua_pushinteger(L, info-skincolors);
return 1;
}
// ramp, n -> ramp[n]
static int colorramp_get(lua_State *L)
{
UINT8 *colorramp = *((UINT8 **)luaL_checkudata(L, 1, META_COLORRAMP));
UINT32 n = luaL_checkinteger(L, 2);
if (n >= COLORRAMPSIZE)
return luaL_error(L, LUA_QL("skincolor_t") " field 'ramp' index %d out of range (0 - %d)", n, COLORRAMPSIZE-1);
lua_pushinteger(L, colorramp[n]);
return 1;
}
// ramp, n, value -> ramp[n] = value
static int colorramp_set(lua_State *L)
{
UINT8 *colorramp = *((UINT8 **)luaL_checkudata(L, 1, META_COLORRAMP));
UINT16 cnum = (UINT16)(((uint8_t*)colorramp - (uint8_t*)(skincolors[0].ramp))/sizeof(skincolor_t));
UINT32 n = luaL_checkinteger(L, 2);
UINT8 i = (UINT8)luaL_checkinteger(L, 3);
if (cnum < SKINCOLOR_FIRSTFREESLOT || cnum >= numskincolors)
return luaL_error(L, "skincolors[] index %d out of range (%d - %d)", cnum, SKINCOLOR_FIRSTFREESLOT, numskincolors-1);
if (n >= COLORRAMPSIZE)
return luaL_error(L, LUA_QL("skincolor_t") " field 'ramp' index %d out of range (0 - %d)", n, COLORRAMPSIZE-1);
if (hud_running)
return luaL_error(L, "Do not alter skincolor_t in HUD rendering code!");
colorramp[n] = i;
R_FlushTranslationColormapCache();
return 0;
}
// #ramp -> COLORRAMPSIZE
static int colorramp_len(lua_State *L)
{
lua_pushinteger(L, COLORRAMPSIZE);
return 1;
}
//////////////////////////////
//
// Now push all these functions into the Lua state!
@ -1502,6 +1728,28 @@ int LUA_InfoLib(lua_State *L)
lua_setfield(L, -2, "__len");
lua_pop(L, 1);
luaL_newmetatable(L, META_SKINCOLOR);
lua_pushcfunction(L, skincolor_get);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, skincolor_set);
lua_setfield(L, -2, "__newindex");
lua_pushcfunction(L, skincolor_num);
lua_setfield(L, -2, "__len");
lua_pop(L, 1);
luaL_newmetatable(L, META_COLORRAMP);
lua_pushcfunction(L, colorramp_get);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, colorramp_set);
lua_setfield(L, -2, "__newindex");
lua_pushcfunction(L, colorramp_len);
lua_setfield(L, -2, "__len");
lua_pop(L,1);
luaL_newmetatable(L, META_SFXINFO);
lua_pushcfunction(L, sfxinfo_get);
lua_setfield(L, -2, "__index");
@ -1605,6 +1853,19 @@ int LUA_InfoLib(lua_State *L)
lua_setmetatable(L, -2);
lua_setglobal(L, "mobjinfo");
lua_newuserdata(L, 0);
lua_createtable(L, 0, 2);
lua_pushcfunction(L, lib_getSkinColor);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, lib_setSkinColor);
lua_setfield(L, -2, "__newindex");
lua_pushcfunction(L, lib_skincolorslen);
lua_setfield(L, -2, "__len");
lua_setmetatable(L, -2);
lua_setglobal(L, "skincolors");
lua_newuserdata(L, 0);
lua_createtable(L, 0, 2);
lua_pushcfunction(L, lib_getSfxInfo);

View file

@ -20,6 +20,8 @@ extern lua_State *gL;
#define META_STATE "STATE_T*"
#define META_MOBJINFO "MOBJINFO_T*"
#define META_SFXINFO "SFXINFO_T*"
#define META_SKINCOLOR "SKINCOLOR_T*"
#define META_COLORRAMP "SKINCOLOR_T*RAMP"
#define META_SPRITEINFO "SPRITEINFO_T*"
#define META_PIVOTLIST "SPRITEFRAMEPIVOT_T[]"
#define META_FRAMEPIVOT "SPRITEFRAMEPIVOT_T*"

View file

@ -113,7 +113,8 @@ static int lib_fixeddiv(lua_State *L)
static int lib_fixedrem(lua_State *L)
{
lua_pushfixed(L, FixedRem(luaL_checkfixed(L, 1), luaL_checkfixed(L, 2)));
LUA_Deprecated(L, "FixedRem(a, b)", "a % b");
lua_pushfixed(L, luaL_checkfixed(L, 1) % luaL_checkfixed(L, 2));
return 1;
}
@ -172,15 +173,14 @@ static int lib_all7emeralds(lua_State *L)
return 1;
}
// Whee, special Lua-exclusive function for making use of Color_Opposite[]
// Returns both color and signpost shade numbers!
static int lib_coloropposite(lua_State *L)
{
UINT8 colornum = (UINT8)luaL_checkinteger(L, 1);
if (!colornum || colornum >= MAXSKINCOLORS)
return luaL_error(L, "skincolor %d out of range (1 - %d).", colornum, MAXSKINCOLORS-1);
lua_pushinteger(L, Color_Opposite[colornum-1][0]); // push color
lua_pushinteger(L, Color_Opposite[colornum-1][1]); // push sign shade index, 0-15
UINT16 colornum = (UINT16)luaL_checkinteger(L, 1);
if (!colornum || colornum >= numskincolors)
return luaL_error(L, "skincolor %d out of range (1 - %d).", colornum, numskincolors-1);
lua_pushinteger(L, skincolors[colornum].invcolor); // push color
lua_pushinteger(L, skincolors[colornum].invshade); // push sign shade index, 0-15
return 2;
}

View file

@ -459,10 +459,8 @@ static int mobj_set(lua_State *L)
return UNIMPLEMENTED;
case mobj_angle:
mo->angle = luaL_checkangle(L, 3);
if (mo->player == &players[consoleplayer])
localangle = mo->angle;
else if (mo->player == &players[secondarydisplayplayer])
localangle2 = mo->angle;
if (mo->player)
P_SetPlayerAngle(mo->player, mo->angle);
break;
case mobj_pitch:
mo->pitch = luaL_checkangle(L, 3);
@ -590,9 +588,9 @@ static int mobj_set(lua_State *L)
}
case mobj_color:
{
UINT8 newcolor = (UINT8)luaL_checkinteger(L,3);
if (newcolor >= MAXTRANSLATIONS)
return luaL_error(L, "mobj.color %d out of range (0 - %d).", newcolor, MAXTRANSLATIONS-1);
UINT16 newcolor = (UINT16)luaL_checkinteger(L,3);
if (newcolor >= numskincolors)
return luaL_error(L, "mobj.color %d out of range (0 - %d).", newcolor, numskincolors-1);
mo->color = newcolor;
break;
}
@ -907,6 +905,15 @@ static int mapthing_set(lua_State *L)
return 0;
}
static int mapthing_num(lua_State *L)
{
mapthing_t *mt = *((mapthing_t **)luaL_checkudata(L, 1, META_MAPTHING));
if (!mt)
return luaL_error(L, "accessed mapthing_t doesn't exist anymore.");
lua_pushinteger(L, mt-mapthings);
return 1;
}
static int lib_iterateMapthings(lua_State *L)
{
size_t i = 0;
@ -987,6 +994,9 @@ int LUA_MobjLib(lua_State *L)
lua_pushcfunction(L, mapthing_set);
lua_setfield(L, -2, "__newindex");
lua_pushcfunction(L, mapthing_num);
lua_setfield(L, -2, "__len");
lua_pop(L,1);
lua_newuserdata(L, 0);

View file

@ -461,9 +461,9 @@ static int player_set(lua_State *L)
plr->flashpal = (UINT16)luaL_checkinteger(L, 3);
else if (fastcmp(field,"skincolor"))
{
UINT8 newcolor = (UINT8)luaL_checkinteger(L,3);
if (newcolor >= MAXSKINCOLORS)
return luaL_error(L, "player.skincolor %d out of range (0 - %d).", newcolor, MAXSKINCOLORS-1);
UINT16 newcolor = (UINT16)luaL_checkinteger(L,3);
if (newcolor >= numskincolors)
return luaL_error(L, "player.skincolor %d out of range (0 - %d).", newcolor, numskincolors-1);
plr->skincolor = newcolor;
}
else if (fastcmp(field,"score"))

View file

@ -78,6 +78,58 @@ FUNCNORETURN static int LUA_Panic(lua_State *L)
#endif
}
#define LEVELS1 12 // size of the first part of the stack
#define LEVELS2 10 // size of the second part of the stack
// Error handler used with pcall() when loading scripts or calling hooks
// Takes a string with the original error message,
// appends the traceback to it, and return the result
int LUA_GetErrorMessage(lua_State *L)
{
int level = 1;
int firstpart = 1; // still before eventual `...'
lua_Debug ar;
lua_pushliteral(L, "\nstack traceback:");
while (lua_getstack(L, level++, &ar))
{
if (level > LEVELS1 && firstpart)
{
// no more than `LEVELS2' more levels?
if (!lua_getstack(L, level + LEVELS2, &ar))
level--; // keep going
else
{
lua_pushliteral(L, "\n ..."); // too many levels
while (lua_getstack(L, level + LEVELS2, &ar)) // find last levels
level++;
}
firstpart = 0;
continue;
}
lua_pushliteral(L, "\n ");
lua_getinfo(L, "Snl", &ar);
lua_pushfstring(L, "%s:", ar.short_src);
if (ar.currentline > 0)
lua_pushfstring(L, "%d:", ar.currentline);
if (*ar.namewhat != '\0') // is there a name?
lua_pushfstring(L, " in function " LUA_QS, ar.name);
else
{
if (*ar.what == 'm') // main?
lua_pushfstring(L, " in main chunk");
else if (*ar.what == 'C' || *ar.what == 't')
lua_pushliteral(L, " ?"); // C function or tail call
else
lua_pushfstring(L, " in function <%s:%d>",
ar.short_src, ar.linedefined);
}
lua_concat(L, lua_gettop(L));
}
lua_concat(L, lua_gettop(L));
return 1;
}
// Moved here from lib_getenum.
int LUA_PushGlobals(lua_State *L, const char *word)
{
@ -413,11 +465,13 @@ static inline void LUA_LoadFile(MYFILE *f, char *name)
lua_lumploading = true; // turn on loading flag
if (luaL_loadbuffer(gL, f->data, f->size, va("@%s",name)) || lua_pcall(gL, 0, 0, 0)) {
lua_pushcfunction(gL, LUA_GetErrorMessage);
if (luaL_loadbuffer(gL, f->data, f->size, va("@%s",name)) || lua_pcall(gL, 0, 0, lua_gettop(gL) - 1)) {
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
lua_pop(gL,1);
}
lua_gc(gL, LUA_GCCOLLECT, 0);
lua_pop(gL, 1); // Pop error handler
lua_lumploading = false; // turn off again
}
@ -759,6 +813,7 @@ enum
ARCH_FFLOOR,
ARCH_SLOPE,
ARCH_MAPHEADER,
ARCH_SKINCOLOR,
ARCH_TEND=0xFF,
};
@ -784,6 +839,7 @@ static const struct {
{META_FFLOOR, ARCH_FFLOOR},
{META_SLOPE, ARCH_SLOPE},
{META_MAPHEADER, ARCH_MAPHEADER},
{META_SKINCOLOR, ARCH_SKINCOLOR},
{NULL, ARCH_NULL}
};
@ -1071,6 +1127,14 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
}
break;
}
case ARCH_SKINCOLOR:
{
skincolor_t *info = *((skincolor_t **)lua_touserdata(gL, myindex));
WRITEUINT8(save_p, ARCH_SKINCOLOR);
WRITEUINT16(save_p, info - skincolors);
break;
}
default:
WRITEUINT8(save_p, ARCH_NULL);
return 2;
@ -1302,6 +1366,9 @@ static UINT8 UnArchiveValue(int TABLESINDEX)
case ARCH_MAPHEADER:
LUA_PushUserdata(gL, mapheaderinfo[READUINT16(save_p)], META_MAPHEADER);
break;
case ARCH_SKINCOLOR:
LUA_PushUserdata(gL, &skincolors[READUINT16(save_p)], META_SKINCOLOR);
break;
case ARCH_TEND:
return 1;
}

View file

@ -39,6 +39,7 @@ void LUA_ClearExtVars(void);
extern boolean lua_lumploading; // is LUA_LoadLump being called?
int LUA_GetErrorMessage(lua_State *L);
void LUA_LoadLump(UINT16 wad, UINT16 lump);
#ifdef LUA_ALLOW_BYTECODE
void LUA_DumpFile(const char *filename);
@ -99,5 +100,8 @@ void COM_Lua_f(void);
// uncomment if you want seg_t/node_t in Lua
// #define HAVE_LUA_SEGS
#define INLEVEL if (gamestate != GS_LEVEL && !titlemapinaction)\
#define ISINLEVEL \
(gamestate == GS_LEVEL || titlemapinaction)
#define INLEVEL if (! ISINLEVEL)\
return luaL_error(L, "This can only be used in a level!");

View file

@ -490,29 +490,28 @@ const UINT8 gifframe_gchead[4] = {0x21,0xF9,0x04,0x04}; // GCE, bytes, packed by
static UINT8 *gifframe_data = NULL;
static size_t gifframe_size = 8192;
//
// GIF_rgbconvert
// converts an RGB frame to a frame with a palette.
//
#ifdef HWRENDER
static void hwrconvert(void)
static void GIF_rgbconvert(UINT8 *linear, UINT8 *scr)
{
UINT8 *linear = HWR_GetScreenshot();
UINT8 *dest = screens[2];
UINT8 r, g, b;
INT32 x, y;
size_t i = 0;
size_t src = 0, dest = 0;
size_t size = (vid.width * vid.height * 3);
InitColorLUT(gif_framepalette);
for (y = 0; y < vid.height; y++)
while (src < size)
{
for (x = 0; x < vid.width; x++, i += 3)
{
r = (UINT8)linear[i];
g = (UINT8)linear[i + 1];
b = (UINT8)linear[i + 2];
dest[(y * vid.width) + x] = colorlookup[r >> SHIFTCOLORBITS][g >> SHIFTCOLORBITS][b >> SHIFTCOLORBITS];
}
r = (UINT8)linear[src];
g = (UINT8)linear[src + 1];
b = (UINT8)linear[src + 2];
scr[dest] = colorlookup[r >> SHIFTCOLORBITS][g >> SHIFTCOLORBITS][b >> SHIFTCOLORBITS];
src += (3 * scrbuf_downscaleamt);
dest += scrbuf_downscaleamt;
}
free(linear);
}
#endif
@ -556,7 +555,11 @@ static void GIF_framewrite(void)
I_ReadScreen(movie_screen);
#ifdef HWRENDER
else if (rendermode == render_opengl)
hwrconvert();
{
UINT8 *linear = HWR_GetScreenshot();
GIF_rgbconvert(linear, movie_screen);
free(linear);
}
#endif
}
else
@ -565,18 +568,20 @@ static void GIF_framewrite(void)
blitw = vid.width;
blith = vid.height;
if (gif_frames == 0)
{
if (rendermode == render_soft)
I_ReadScreen(movie_screen);
#ifdef HWRENDER
else if (rendermode == render_opengl)
{
hwrconvert();
VID_BlitLinearScreen(screens[2], screens[0], vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes);
}
#endif
// Copy the current OpenGL frame into the base screen
if (rendermode == render_opengl)
{
UINT8 *linear = HWR_GetScreenshot();
GIF_rgbconvert(linear, screens[0]);
free(linear);
}
#endif
// Copy the first frame into the movie screen
// OpenGL already does the same above.
if (gif_frames == 0 && rendermode == render_soft)
I_ReadScreen(movie_screen);
movie_screen = screens[0];
}

View file

@ -555,7 +555,8 @@ void Command_Teleport_f(void)
p->mo->flags2 &= ~MF2_OBJECTFLIP;
}
localangle = p->mo->angle = p->drawangle = FixedAngle(mt->angle<<FRACBITS);
p->mo->angle = p->drawangle = FixedAngle(mt->angle<<FRACBITS);
P_SetPlayerAngle(p, p->mo->angle);
}
else // scan the thinkers to find starposts...
{
@ -619,7 +620,8 @@ void Command_Teleport_f(void)
p->mo->flags2 &= ~MF2_OBJECTFLIP;
}
localangle = p->mo->angle = p->drawangle = mo2->angle;
p->mo->angle = p->drawangle = mo2->angle;
P_SetPlayerAngle(p, p->mo->angle);
}
CONS_Printf(M_GetText("Teleporting to checkpoint %d, %d...\n"), starpostnum, starpostpath);
@ -673,7 +675,10 @@ void Command_Teleport_f(void)
i = COM_CheckParm("-ang");
if (i)
localangle = p->drawangle = p->mo->angle = FixedAngle(atoi(COM_Argv(i + 1))<<FRACBITS);
{
p->drawangle = p->mo->angle = FixedAngle(atoi(COM_Argv(i + 1))<<FRACBITS);
P_SetPlayerAngle(p, p->mo->angle);
}
i = COM_CheckParm("-aim");
if (i)
@ -978,7 +983,7 @@ static mobjflag2_t op_oldflags2 = 0;
static UINT32 op_oldeflags = 0;
static fixed_t op_oldmomx = 0, op_oldmomy = 0, op_oldmomz = 0, op_oldheight = 0;
static statenum_t op_oldstate = 0;
static UINT8 op_oldcolor = 0;
static UINT16 op_oldcolor = 0;
//
// Static calculation / common output help
@ -1032,8 +1037,8 @@ static boolean OP_HeightOkay(player_t *player, UINT8 ceiling)
if (ceiling)
{
// Truncate position to match where mapthing would be when spawned
// (this applies to every further P_GetZAt call as well)
fixed_t cheight = sec->c_slope ? P_GetZAt(sec->c_slope, player->mo->x & 0xFFFF0000, player->mo->y & 0xFFFF0000) : sec->ceilingheight;
// (this applies to every further P_GetSlopeZAt call as well)
fixed_t cheight = P_GetSectorCeilingZAt(sec, player->mo->x & 0xFFFF0000, player->mo->y & 0xFFFF0000);
if (((cheight - player->mo->z - player->mo->height)>>FRACBITS) >= (1 << (16-ZSHIFT)))
{
@ -1044,7 +1049,7 @@ static boolean OP_HeightOkay(player_t *player, UINT8 ceiling)
}
else
{
fixed_t fheight = sec->f_slope ? P_GetZAt(sec->f_slope, player->mo->x & 0xFFFF0000, player->mo->y & 0xFFFF0000) : sec->floorheight;
fixed_t fheight = P_GetSectorFloorZAt(sec, player->mo->x & 0xFFFF0000, player->mo->y & 0xFFFF0000);
if (((player->mo->z - fheight)>>FRACBITS) >= (1 << (16-ZSHIFT)))
{
CONS_Printf(M_GetText("Sorry, you're too %s to place this object (max: %d %s).\n"), M_GetText("high"),
@ -1091,12 +1096,12 @@ static mapthing_t *OP_CreateNewMapThing(player_t *player, UINT16 type, boolean c
mt->y = (INT16)(player->mo->y>>FRACBITS);
if (ceiling)
{
fixed_t cheight = sec->c_slope ? P_GetZAt(sec->c_slope, mt->x << FRACBITS, mt->y << FRACBITS) : sec->ceilingheight;
fixed_t cheight = P_GetSectorCeilingZAt(sec, mt->x << FRACBITS, mt->y << FRACBITS);
mt->z = (UINT16)((cheight - player->mo->z - player->mo->height)>>FRACBITS);
}
else
{
fixed_t fheight = sec->f_slope ? P_GetZAt(sec->f_slope, mt->x << FRACBITS, mt->y << FRACBITS) : sec->floorheight;
fixed_t fheight = P_GetSectorFloorZAt(sec, mt->x << FRACBITS, mt->y << FRACBITS);
mt->z = (UINT16)((player->mo->z - fheight)>>FRACBITS);
}
mt->angle = (INT16)(FixedInt(AngleFixed(player->mo->angle)));
@ -1342,12 +1347,12 @@ void OP_ObjectplaceMovement(player_t *player)
if (!!(mobjinfo[op_currentthing].flags & MF_SPAWNCEILING) ^ !!(cv_opflags.value & MTF_OBJECTFLIP))
{
fixed_t cheight = sec->c_slope ? P_GetZAt(sec->c_slope, player->mo->x & 0xFFFF0000, player->mo->y & 0xFFFF0000) : sec->ceilingheight;
fixed_t cheight = P_GetSectorCeilingZAt(sec, player->mo->x & 0xFFFF0000, player->mo->y & 0xFFFF0000);
op_displayflags = (UINT16)((cheight - player->mo->z - mobjinfo[op_currentthing].height)>>FRACBITS);
}
else
{
fixed_t fheight = sec->f_slope ? P_GetZAt(sec->f_slope, player->mo->x & 0xFFFF0000, player->mo->y & 0xFFFF0000) : sec->floorheight;
fixed_t fheight = P_GetSectorFloorZAt(sec, player->mo->x & 0xFFFF0000, player->mo->y & 0xFFFF0000);
op_displayflags = (UINT16)((player->mo->z - fheight)>>FRACBITS);
}
op_displayflags <<= ZSHIFT;

View file

@ -523,9 +523,9 @@ emblem_t *M_GetLevelEmblems(INT32 mapnum)
return NULL;
}
skincolors_t M_GetEmblemColor(emblem_t *em)
skincolornum_t M_GetEmblemColor(emblem_t *em)
{
if (!em || em->color >= MAXSKINCOLORS)
if (!em || em->color >= numskincolors)
return SKINCOLOR_NONE;
return em->color;
}
@ -549,9 +549,9 @@ const char *M_GetEmblemPatch(emblem_t *em, boolean big)
return pnamebuf;
}
skincolors_t M_GetExtraEmblemColor(extraemblem_t *em)
skincolornum_t M_GetExtraEmblemColor(extraemblem_t *em)
{
if (!em || em->color >= MAXSKINCOLORS)
if (!em || em->color >= numskincolors)
return SKINCOLOR_NONE;
return em->color;
}

View file

@ -90,7 +90,7 @@ typedef struct
INT16 tag; ///< Tag of emblem mapthing
INT16 level; ///< Level on which this emblem can be found.
UINT8 sprite; ///< emblem sprite to use, 0 - 25
UINT8 color; ///< skincolor to use
UINT16 color; ///< skincolor to use
INT32 var; ///< If needed, specifies information on the target amount to achieve (or target skin)
char hint[110]; ///< Hint for emblem hints menu
UINT8 collected; ///< Do you have this emblem?
@ -102,7 +102,7 @@ typedef struct
UINT8 conditionset; ///< Condition set that awards this emblem.
UINT8 showconditionset; ///< Condition set that shows this emblem.
UINT8 sprite; ///< emblem sprite to use, 0 - 25
UINT8 color; ///< skincolor to use
UINT16 color; ///< skincolor to use
UINT8 collected; ///< Do you have this emblem?
} extraemblem_t;
@ -172,9 +172,9 @@ INT32 M_CountEmblems(void);
// Emblem shit
emblem_t *M_GetLevelEmblems(INT32 mapnum);
skincolors_t M_GetEmblemColor(emblem_t *em);
skincolornum_t M_GetEmblemColor(emblem_t *em);
const char *M_GetEmblemPatch(emblem_t *em, boolean big);
skincolors_t M_GetExtraEmblemColor(extraemblem_t *em);
skincolornum_t M_GetExtraEmblemColor(extraemblem_t *em);
const char *M_GetExtraEmblemPatch(extraemblem_t *em, boolean big);
// If you're looking to compare stats for unlocks or what not, use these

View file

@ -204,18 +204,6 @@ FUNCMATH FUNCINLINE static ATTRINLINE fixed_t FixedDiv(fixed_t a, fixed_t b)
return FixedDiv2(a, b);
}
/** \brief The FixedRem function
\param x fixed_t number
\param y fixed_t number
\return remainder of dividing x by y
*/
FUNCMATH FUNCINLINE static ATTRINLINE fixed_t FixedRem(fixed_t x, fixed_t y)
{
return x % y;
}
/** \brief The FixedSqrt function
\param x fixed_t number

View file

@ -882,7 +882,8 @@ static menuitem_t SP_NightsAttackLevelSelectMenu[] =
static menuitem_t SP_NightsAttackMenu[] =
{
{IT_STRING|IT_KEYHANDLER, NULL, "Level Select...", &M_HandleTimeAttackLevelSelect, 52},
{IT_STRING|IT_CVAR, NULL, "Show Records For", &cv_dummymares, 62},
{IT_STRING|IT_CVAR, NULL, "Character", &cv_chooseskin, 62},
{IT_STRING|IT_CVAR, NULL, "Show Records For", &cv_dummymares, 72},
{IT_DISABLED, NULL, "Guest Option...", &SP_NightsGuestReplayDef, 100},
{IT_DISABLED, NULL, "Replay...", &SP_NightsReplayDef, 110},
@ -893,6 +894,7 @@ static menuitem_t SP_NightsAttackMenu[] =
enum
{
nalevel,
nachar,
narecords,
naguest,
@ -5186,7 +5188,7 @@ static boolean M_PrepareLevelPlatter(INT32 gt, boolean nextmappick)
{
if (M_CanShowLevelOnPlatter(mapnum, gt))
{
const INT32 actnum = mapheaderinfo[mapnum]->actnum;
const UINT8 actnum = mapheaderinfo[mapnum]->actnum;
const boolean headingisname = (fastcmp(mapheaderinfo[mapnum]->selectheading, mapheaderinfo[mapnum]->lvlttl));
const boolean wide = (mapheaderinfo[mapnum]->menuflags & LF2_WIDEICON);
@ -7543,7 +7545,7 @@ static void M_DrawSoundTest(void)
{
frame[1] = (2-st_time);
frame[2] = ((cv_soundtest.value - 1) % 9);
frame[3] += (((cv_soundtest.value - 1) / 9) % (MAXSKINCOLORS - frame[3]));
frame[3] += (((cv_soundtest.value - 1) / 9) % (FIRSTSUPERCOLOR - frame[3]));
if (st_time < 2)
st_time++;
}
@ -8211,13 +8213,13 @@ static void M_DrawLoadGameData(void)
{
if (charskin->prefoppositecolor)
{
col = charskin->prefoppositecolor - 1;
col = Color_Index[col][Color_Opposite[Color_Opposite[col][0] - 1][1]];
col = charskin->prefoppositecolor;
col = skincolors[col].ramp[skincolors[skincolors[col].invcolor].invshade];
}
else
{
col = charskin->prefcolor - 1;
col = Color_Index[Color_Opposite[col][0]-1][Color_Opposite[col][1]];
col = charskin->prefcolor;
col = skincolors[skincolors[col].invcolor].ramp[skincolors[col].invshade];
}
}
@ -9053,7 +9055,7 @@ static void M_DrawSetupChoosePlayerMenu(void)
skin_t *charskin = &skins[0];
INT32 skinnum = 0;
UINT8 col;
UINT16 col;
UINT8 *colormap = NULL;
INT32 prev = -1, next = -1;
@ -9092,10 +9094,10 @@ static void M_DrawSetupChoosePlayerMenu(void)
// Use the opposite of the character's skincolor
col = description[char_on].oppositecolor;
if (!col)
col = Color_Opposite[charskin->prefcolor - 1][0];
col = skincolors[charskin->prefcolor].invcolor;
// Make the translation colormap
colormap = R_GetTranslationColormap(TC_DEFAULT, col, 0);
colormap = R_GetTranslationColormap(TC_DEFAULT, col, GTC_CACHE);
// Don't render the title map
hidetitlemap = true;
@ -9143,8 +9145,8 @@ static void M_DrawSetupChoosePlayerMenu(void)
INT32 ox, oxsh = FixedInt(FixedMul(BASEVIDWIDTH*FRACUNIT, FixedDiv(char_scroll, 128*FRACUNIT))), txsh;
patch_t *curpatch = NULL, *prevpatch = NULL, *nextpatch = NULL;
const char *curtext = NULL, *prevtext = NULL, *nexttext = NULL;
UINT8 curtextcolor = 0, prevtextcolor = 0, nexttextcolor = 0;
UINT8 curoutlinecolor = 0, prevoutlinecolor = 0, nextoutlinecolor = 0;
UINT16 curtextcolor = 0, prevtextcolor = 0, nexttextcolor = 0;
UINT16 curoutlinecolor = 0, prevoutlinecolor = 0, nextoutlinecolor = 0;
// Name tag
curtext = description[char_on].displayname;
@ -9155,7 +9157,7 @@ static void M_DrawSetupChoosePlayerMenu(void)
if (!curtextcolor)
curtextcolor = charskin->prefcolor;
if (!curoutlinecolor)
curoutlinecolor = Color_Opposite[charskin->prefcolor - 1][0];
curoutlinecolor = col = skincolors[charskin->prefcolor].invcolor;
txsh = oxsh;
ox = 8 + SHORT((description[char_on].charpic)->width)/2;
@ -9171,8 +9173,8 @@ static void M_DrawSetupChoosePlayerMenu(void)
{
V_DrawNameTag(
x, y, V_CENTERNAMETAG, FRACUNIT,
R_GetTranslationColormap(TC_DEFAULT, curtextcolor, 0),
R_GetTranslationColormap(TC_DEFAULT, curoutlinecolor, 0),
R_GetTranslationColormap(TC_DEFAULT, curtextcolor, GTC_CACHE),
R_GetTranslationColormap(TC_DEFAULT, curoutlinecolor, GTC_CACHE),
curtext
);
}
@ -9194,7 +9196,7 @@ static void M_DrawSetupChoosePlayerMenu(void)
if (!prevtextcolor)
prevtextcolor = charskin->prefcolor;
if (!prevoutlinecolor)
prevoutlinecolor = Color_Opposite[charskin->prefcolor - 1][0];
prevoutlinecolor = col = skincolors[charskin->prefcolor].invcolor;
x = (ox - txsh) - w;
if (prevpatch)
@ -9204,8 +9206,8 @@ static void M_DrawSetupChoosePlayerMenu(void)
{
V_DrawNameTag(
x, y, V_CENTERNAMETAG, FRACUNIT,
R_GetTranslationColormap(TC_DEFAULT, prevtextcolor, 0),
R_GetTranslationColormap(TC_DEFAULT, prevoutlinecolor, 0),
R_GetTranslationColormap(TC_DEFAULT, prevtextcolor, GTC_CACHE),
R_GetTranslationColormap(TC_DEFAULT, prevoutlinecolor, GTC_CACHE),
prevtext
);
}
@ -9224,7 +9226,7 @@ static void M_DrawSetupChoosePlayerMenu(void)
if (!nexttextcolor)
nexttextcolor = charskin->prefcolor;
if (!nextoutlinecolor)
nextoutlinecolor = Color_Opposite[charskin->prefcolor - 1][0];
nextoutlinecolor = col = skincolors[charskin->prefcolor].invcolor;
x = (ox - txsh) + w;
if (nextpatch)
@ -9234,8 +9236,8 @@ static void M_DrawSetupChoosePlayerMenu(void)
{
V_DrawNameTag(
x, y, V_CENTERNAMETAG, FRACUNIT,
R_GetTranslationColormap(TC_DEFAULT, nexttextcolor, 0),
R_GetTranslationColormap(TC_DEFAULT, nextoutlinecolor, 0),
R_GetTranslationColormap(TC_DEFAULT, nexttextcolor, GTC_CACHE),
R_GetTranslationColormap(TC_DEFAULT, nextoutlinecolor, GTC_CACHE),
nexttext
);
}
@ -11074,15 +11076,15 @@ static UINT8 multi_spr2;
// this is set before entering the MultiPlayer setup menu,
// for either player 1 or 2
static char setupm_name[MAXPLAYERNAME+1];
static player_t *setupm_player;
static consvar_t *setupm_cvskin;
static consvar_t *setupm_cvcolor;
static consvar_t *setupm_cvname;
static consvar_t *setupm_cvdefaultskin;
static consvar_t *setupm_cvdefaultcolor;
static INT32 setupm_fakeskin;
static INT32 setupm_fakecolor;
static char setupm_name[MAXPLAYERNAME+1];
static player_t *setupm_player;
static consvar_t *setupm_cvskin;
static consvar_t *setupm_cvcolor;
static consvar_t *setupm_cvname;
static consvar_t *setupm_cvdefaultskin;
static consvar_t *setupm_cvdefaultcolor;
static INT32 setupm_fakeskin;
static menucolor_t *setupm_fakecolor;
static void M_DrawSetupMultiPlayerMenu(void)
{
@ -11149,11 +11151,11 @@ static void M_DrawSetupMultiPlayerMenu(void)
sprdef = &skins[setupm_fakeskin].sprites[multi_spr2];
if (!setupm_fakecolor || !sprdef->numframes) // should never happen but hey, who knows
if (!setupm_fakecolor->color || !sprdef->numframes) // should never happen but hey, who knows
goto faildraw;
// ok, draw player sprite for sure now
colormap = R_GetTranslationColormap(setupm_fakeskin, setupm_fakecolor, 0);
colormap = R_GetTranslationColormap(setupm_fakeskin, setupm_fakecolor->color, 0);
if (multi_frame >= sprdef->numframes)
multi_frame = 0;
@ -11199,11 +11201,11 @@ colordraw:
// draw color string
V_DrawRightAlignedString(BASEVIDWIDTH - x, y,
((MP_PlayerSetupMenu[2].status & IT_TYPE) == IT_SPACE ? V_TRANSLUCENT : 0)|(itemOn == 2 ? V_YELLOWMAP : 0)|V_ALLOWLOWERCASE,
Color_Names[setupm_fakecolor]);
skincolors[setupm_fakecolor->color].name);
if (itemOn == 2 && (MP_PlayerSetupMenu[2].status & IT_TYPE) != IT_SPACE)
{
V_DrawCharacter(BASEVIDWIDTH - x - 10 - V_StringWidth(Color_Names[setupm_fakecolor], V_ALLOWLOWERCASE) - (skullAnimCounter/5), y,
V_DrawCharacter(BASEVIDWIDTH - x - 10 - V_StringWidth(skincolors[setupm_fakecolor->color].name, V_ALLOWLOWERCASE) - (skullAnimCounter/5), y,
'\x1C' | V_YELLOWMAP, false);
V_DrawCharacter(BASEVIDWIDTH - x + 2 + (skullAnimCounter/5), y,
'\x1D' | V_YELLOWMAP, false);
@ -11213,25 +11215,39 @@ colordraw:
#define indexwidth 8
{
const INT32 colwidth = (282-charw)/(2*indexwidth);
INT32 i = -colwidth;
INT16 col = setupm_fakecolor - colwidth;
INT32 w = indexwidth;
const INT32 numcolors = (282-charw)/(2*indexwidth); // Number of colors per side
INT32 w = indexwidth; // Width of a singular color block
menucolor_t *mc = setupm_fakecolor->prev; // Last accessed color
UINT8 h;
INT16 i;
while (col < 1)
col += MAXSKINCOLORS-1;
while (i <= colwidth)
{
if (!(i++))
w = charw;
else
w = indexwidth;
// Draw color in the middle
x += numcolors*w;
for (h = 0; h < 16; h++)
V_DrawFill(x, y+h, charw, 1, skincolors[setupm_fakecolor->color].ramp[h]);
//Draw colors from middle to left
for (i=0; i<numcolors; i++) {
x -= w;
// Find accessible color before this one
while (!skincolors[mc->color].accessible)
mc = mc->prev;
for (h = 0; h < 16; h++)
V_DrawFill(x, y+h, w, 1, Color_Index[col-1][h]);
if (++col >= MAXSKINCOLORS)
col -= MAXSKINCOLORS-1;
V_DrawFill(x, y+h, w, 1, skincolors[mc->color].ramp[h]);
mc = mc->prev;
}
// Draw colors from middle to right
mc = setupm_fakecolor->next;
x += numcolors*w + charw;
for (i=0; i<numcolors; i++) {
// Find accessible color after this one
while (!skincolors[mc->color].accessible)
mc = mc->next;
for (h = 0; h < 16; h++)
V_DrawFill(x, y+h, w, 1, skincolors[mc->color].ramp[h]);
x += w;
mc = mc->next;
}
}
#undef charw
@ -11242,7 +11258,7 @@ colordraw:
V_DrawString(x, y,
((R_SkinAvailable(setupm_cvdefaultskin->string) != setupm_fakeskin
|| setupm_cvdefaultcolor->value != setupm_fakecolor)
|| setupm_cvdefaultcolor->value != setupm_fakecolor->color)
? 0
: V_TRANSLUCENT)
| ((itemOn == 3) ? V_YELLOWMAP : 0),
@ -11290,19 +11306,19 @@ static void M_HandleSetupMultiPlayer(INT32 choice)
else if (itemOn == 2) // player color
{
S_StartSound(NULL,sfx_menu1); // Tails
setupm_fakecolor--;
setupm_fakecolor = setupm_fakecolor->prev;
}
break;
case KEY_ENTER:
if (itemOn == 3
&& (R_SkinAvailable(setupm_cvdefaultskin->string) != setupm_fakeskin
|| setupm_cvdefaultcolor->value != setupm_fakecolor))
|| setupm_cvdefaultcolor->value != setupm_fakecolor->color))
{
S_StartSound(NULL,sfx_strpst);
// you know what? always putting these in the buffer won't hurt anything.
COM_BufAddText (va("%s \"%s\"\n",setupm_cvdefaultskin->name,skins[setupm_fakeskin].name));
COM_BufAddText (va("%s %d\n",setupm_cvdefaultcolor->name,setupm_fakecolor));
COM_BufAddText (va("%s %d\n",setupm_cvdefaultcolor->name,setupm_fakecolor->color));
break;
}
/* FALLTHRU */
@ -11323,7 +11339,7 @@ static void M_HandleSetupMultiPlayer(INT32 choice)
else if (itemOn == 2) // player color
{
S_StartSound(NULL,sfx_menu1); // Tails
setupm_fakecolor++;
setupm_fakecolor = setupm_fakecolor->next;
}
break;
@ -11339,11 +11355,13 @@ static void M_HandleSetupMultiPlayer(INT32 choice)
}
else if (itemOn == 2)
{
UINT8 col = skins[setupm_fakeskin].prefcolor;
if (setupm_fakecolor != col)
UINT16 col = skins[setupm_fakeskin].prefcolor;
if ((setupm_fakecolor->color != col) && skincolors[col].accessible)
{
S_StartSound(NULL,sfx_menu1); // Tails
setupm_fakecolor = col;
for (setupm_fakecolor=menucolorhead;;setupm_fakecolor=setupm_fakecolor->next)
if (setupm_fakecolor->color == col || setupm_fakecolor == menucolortail)
break;
}
}
break;
@ -11371,10 +11389,14 @@ static void M_HandleSetupMultiPlayer(INT32 choice)
}
// check color
if (setupm_fakecolor < 1)
setupm_fakecolor = MAXSKINCOLORS-1;
if (setupm_fakecolor > MAXSKINCOLORS-1)
setupm_fakecolor = 1;
if (itemOn == 2 && !skincolors[setupm_fakecolor->color].accessible) {
if (choice == KEY_LEFTARROW)
while (!skincolors[setupm_fakecolor->color].accessible)
setupm_fakecolor = setupm_fakecolor->prev;
else if (choice == KEY_RIGHTARROW || choice == KEY_ENTER)
while (!skincolors[setupm_fakecolor->color].accessible)
setupm_fakecolor = setupm_fakecolor->next;
}
if (exitmenu)
{
@ -11406,7 +11428,10 @@ static void M_SetupMultiPlayer(INT32 choice)
setupm_fakeskin = R_SkinAvailable(setupm_cvskin->string);
if (setupm_fakeskin == -1)
setupm_fakeskin = 0;
setupm_fakecolor = setupm_cvcolor->value;
for (setupm_fakecolor=menucolorhead;;setupm_fakecolor=setupm_fakecolor->next)
if (setupm_fakecolor->color == setupm_cvcolor->value || setupm_fakecolor == menucolortail)
break;
// disable skin changes if we can't actually change skins
if (!CanChangeSkin(consoleplayer))
@ -11447,7 +11472,10 @@ static void M_SetupMultiPlayer2(INT32 choice)
setupm_fakeskin = R_SkinAvailable(setupm_cvskin->string);
if (setupm_fakeskin == -1)
setupm_fakeskin = 0;
setupm_fakecolor = setupm_cvcolor->value;
for (setupm_fakecolor=menucolorhead;;setupm_fakecolor=setupm_fakecolor->next)
if (setupm_fakecolor->color == setupm_cvcolor->value || setupm_fakecolor == menucolortail)
break;
// disable skin changes if we can't actually change skins
if (splitscreen && !CanChangeSkin(secondarydisplayplayer))
@ -11479,12 +11507,181 @@ static boolean M_QuitMultiPlayerMenu(void)
setupm_name[l] =0;
COM_BufAddText (va("%s \"%s\"\n",setupm_cvname->name,setupm_name));
}
// you know what? always putting these in the buffer won't hurt anything.
COM_BufAddText (va("%s \"%s\"\n",setupm_cvskin->name,skins[setupm_fakeskin].name));
COM_BufAddText (va("%s %d\n",setupm_cvcolor->name,setupm_fakecolor));
// send color if changed
if (setupm_fakecolor->color != setupm_cvcolor->value)
COM_BufAddText (va("%s %d\n",setupm_cvcolor->name,setupm_fakecolor->color));
return true;
}
void M_AddMenuColor(UINT16 color) {
menucolor_t *c;
if (color >= numskincolors) {
CONS_Printf("M_AddMenuColor: color %d does not exist.",color);
return;
}
c = (menucolor_t *)malloc(sizeof(menucolor_t));
c->color = color;
if (menucolorhead == NULL) {
c->next = c;
c->prev = c;
menucolorhead = c;
menucolortail = c;
} else {
c->next = menucolorhead;
c->prev = menucolortail;
menucolortail->next = c;
menucolorhead->prev = c;
menucolortail = c;
}
}
void M_MoveColorBefore(UINT16 color, UINT16 targ) {
menucolor_t *look, *c = NULL, *t = NULL;
if (color == targ)
return;
if (color >= numskincolors) {
CONS_Printf("M_MoveColorBefore: color %d does not exist.",color);
return;
}
if (targ >= numskincolors) {
CONS_Printf("M_MoveColorBefore: target color %d does not exist.",targ);
return;
}
for (look=menucolorhead;;look=look->next) {
if (look->color == color)
c = look;
else if (look->color == targ)
t = look;
if (c != NULL && t != NULL)
break;
if (look==menucolortail)
return;
}
if (c == t->prev)
return;
if (t==menucolorhead)
menucolorhead = c;
if (c==menucolortail)
menucolortail = c->prev;
c->prev->next = c->next;
c->next->prev = c->prev;
c->prev = t->prev;
c->next = t;
t->prev->next = c;
t->prev = c;
}
void M_MoveColorAfter(UINT16 color, UINT16 targ) {
menucolor_t *look, *c = NULL, *t = NULL;
if (color == targ)
return;
if (color >= numskincolors) {
CONS_Printf("M_MoveColorAfter: color %d does not exist.\n",color);
return;
}
if (targ >= numskincolors) {
CONS_Printf("M_MoveColorAfter: target color %d does not exist.\n",targ);
return;
}
for (look=menucolorhead;;look=look->next) {
if (look->color == color)
c = look;
else if (look->color == targ)
t = look;
if (c != NULL && t != NULL)
break;
if (look==menucolortail)
return;
}
if (t == c->prev)
return;
if (t==menucolortail)
menucolortail = c;
else if (c==menucolortail)
menucolortail = c->prev;
c->prev->next = c->next;
c->next->prev = c->prev;
c->next = t->next;
c->prev = t;
t->next->prev = c;
t->next = c;
}
UINT16 M_GetColorBefore(UINT16 color) {
menucolor_t *look;
if (color >= numskincolors) {
CONS_Printf("M_GetColorBefore: color %d does not exist.\n",color);
return 0;
}
for (look=menucolorhead;;look=look->next) {
if (look->color == color)
return look->prev->color;
if (look==menucolortail)
return 0;
}
}
UINT16 M_GetColorAfter(UINT16 color) {
menucolor_t *look;
if (color >= numskincolors) {
CONS_Printf("M_GetColorAfter: color %d does not exist.\n",color);
return 0;
}
for (look=menucolorhead;;look=look->next) {
if (look->color == color)
return look->next->color;
if (look==menucolortail)
return 0;
}
}
void M_InitPlayerSetupColors(void) {
UINT8 i;
numskincolors = SKINCOLOR_FIRSTFREESLOT;
menucolorhead = menucolortail = NULL;
for (i=0; i<numskincolors; i++)
M_AddMenuColor(i);
}
void M_FreePlayerSetupColors(void) {
menucolor_t *look = menucolorhead, *tmp;
if (menucolorhead==NULL)
return;
while (true) {
if (look != menucolortail) {
tmp = look;
look = look->next;
free(tmp);
} else {
free(look);
return;
}
}
menucolorhead = menucolortail = NULL;
}
// =================
// DATA OPTIONS MENU
// =================

View file

@ -355,11 +355,11 @@ typedef struct
// new character select
char displayname[SKINNAMESIZE+1];
SINT8 skinnum[2];
UINT8 oppositecolor;
UINT16 oppositecolor;
char nametag[8];
patch_t *namepic;
UINT8 tagtextcolor;
UINT8 tagoutlinecolor;
UINT16 tagtextcolor;
UINT16 tagoutlinecolor;
} description_t;
// level select platter
@ -443,6 +443,23 @@ void Addons_option_Onchange(void);
// Moviemode menu updating
void Moviemode_option_Onchange(void);
// Player Setup menu colors linked list
typedef struct menucolor_s {
struct menucolor_s *next;
struct menucolor_s *prev;
UINT16 color;
} menucolor_t;
extern menucolor_t *menucolorhead, *menucolortail;
void M_AddMenuColor(UINT16 color);
void M_MoveColorBefore(UINT16 color, UINT16 targ);
void M_MoveColorAfter(UINT16 color, UINT16 targ);
UINT16 M_GetColorBefore(UINT16 color);
UINT16 M_GetColorAfter(UINT16 color);
void M_InitPlayerSetupColors(void);
void M_FreePlayerSetupColors(void);
// These defines make it a little easier to make menus
#define DEFAULTMENUSTYLE(id, header, source, prev, x, y)\
{\

View file

@ -5106,13 +5106,13 @@ void A_SignPlayer(mobj_t *actor)
INT32 locvar2 = var2;
skin_t *skin = NULL;
mobj_t *ov;
UINT8 facecolor, signcolor = (UINT8)locvar2;
UINT16 facecolor, signcolor = (UINT16)locvar2;
UINT32 signframe = states[actor->info->raisestate].frame;
if (LUA_CallAction("A_SignPlayer", actor))
return;
if (actor->tracer == NULL || locvar1 < -3 || locvar1 >= numskins || signcolor >= MAXTRANSLATIONS)
if (actor->tracer == NULL || locvar1 < -3 || locvar1 >= numskins || signcolor >= numskincolors)
return;
// if no face overlay, spawn one
@ -5143,7 +5143,7 @@ void A_SignPlayer(mobj_t *actor)
else if ((actor->target->player->skincolor == skin->prefcolor) && (skin->prefoppositecolor)) // Set it as the skin's preferred oppositecolor?
signcolor = skin->prefoppositecolor;
else if (actor->target->player->skincolor) // Set the sign to be an appropriate background color for this player's skincolor.
signcolor = Color_Opposite[actor->target->player->skincolor - 1][0];
signcolor = skincolors[actor->target->player->skincolor].invcolor;
else
signcolor = SKINCOLOR_NONE;
}
@ -5181,7 +5181,7 @@ void A_SignPlayer(mobj_t *actor)
else if (skin->prefoppositecolor)
signcolor = skin->prefoppositecolor;
else if (facecolor)
signcolor = Color_Opposite[facecolor - 1][0];
signcolor = skincolors[facecolor].invcolor;
}
if (skin)
@ -5212,19 +5212,8 @@ void A_SignPlayer(mobj_t *actor)
}
actor->tracer->color = signcolor;
/*
If you're here from the comment above Color_Opposite,
the following line is the one which is dependent on the
array being symmetrical. It gets the opposite of the
opposite of your desired colour just so it can get the
brightness frame for the End Sign. It's not a great
design choice, but it's constant time array access and
the idea that the colours should be OPPOSITES is kind
of in the name. If you have a better idea, feel free
to let me know. ~toast 2016/07/20
*/
if (signcolor && signcolor < MAXSKINCOLORS)
signframe += (15 - Color_Opposite[Color_Opposite[signcolor - 1][0] - 1][1]);
if (signcolor && signcolor < numskincolors)
signframe += (15 - skincolors[signcolor].invshade);
actor->tracer->frame = signframe;
}
@ -8804,10 +8793,10 @@ void A_ChangeColorRelative(mobj_t *actor)
{
// Have you ever seen anything so hideous?
if (actor->target)
actor->color = (UINT8)(actor->color + actor->target->color);
actor->color = (UINT16)(actor->color + actor->target->color);
}
else
actor->color = (UINT8)(actor->color + locvar2);
actor->color = (UINT16)(actor->color + locvar2);
}
// Function: A_ChangeColorAbsolute
@ -8831,7 +8820,7 @@ void A_ChangeColorAbsolute(mobj_t *actor)
actor->color = actor->target->color;
}
else
actor->color = (UINT8)locvar2;
actor->color = (UINT16)locvar2;
}
// Function: A_Dye
@ -8850,21 +8839,21 @@ void A_Dye(mobj_t *actor)
UINT8 color = (UINT8)locvar2;
if (LUA_CallAction("A_Dye", actor))
return;
if (color >= MAXTRANSLATIONS)
if (color >= numskincolors)
return;
if (!color)
target->colorized = false;
else
target->colorized = true;
// What if it's a player?
if (target->player)
{
target->player->powers[pw_dye] = color;
return;
}
target->color = color;
}
@ -9707,6 +9696,9 @@ void A_SplitShot(mobj_t *actor)
if (LUA_CallAction("A_SplitShot", actor))
return;
if (!actor->target)
return;
A_FaceTarget(actor);
{
const angle_t an = (actor->angle + ANGLE_90) >> ANGLETOFINESHIFT;
@ -12700,8 +12692,8 @@ void A_Boss5FindWaypoint(mobj_t *actor)
else // locvar1 == 0
{
fixed_t hackoffset = P_MobjFlip(actor)*56*FRACUNIT;
INT32 numwaypoints = 0;
mobj_t **waypoints;
INT32 numfangwaypoints = 0;
mobj_t **fangwaypoints;
INT32 key;
actor->z += hackoffset;
@ -12726,7 +12718,7 @@ void A_Boss5FindWaypoint(mobj_t *actor)
continue;
if (!P_CheckSight(actor, mapthings[i].mobj))
continue;
numwaypoints++;
numfangwaypoints++;
}
// players also count as waypoints apparently
@ -12748,11 +12740,11 @@ void A_Boss5FindWaypoint(mobj_t *actor)
continue;
if (!P_CheckSight(actor, players[i].mo))
continue;
numwaypoints++;
numfangwaypoints++;
}
}
if (!numwaypoints)
if (!numfangwaypoints)
{
// restore z position
actor->z -= hackoffset;
@ -12760,8 +12752,8 @@ void A_Boss5FindWaypoint(mobj_t *actor)
}
// allocate the table and reset count to zero
waypoints = Z_Calloc(sizeof(*waypoints)*numwaypoints, PU_STATIC, NULL);
numwaypoints = 0;
fangwaypoints = Z_Calloc(sizeof(*waypoints)*numfangwaypoints, PU_STATIC, NULL);
numfangwaypoints = 0;
// now find them again and add them to the table!
for (i = 0; i < nummapthings; i++)
@ -12786,7 +12778,7 @@ void A_Boss5FindWaypoint(mobj_t *actor)
}
if (!P_CheckSight(actor, mapthings[i].mobj))
continue;
waypoints[numwaypoints++] = mapthings[i].mobj;
fangwaypoints[numfangwaypoints++] = mapthings[i].mobj;
}
if (actor->extravalue2 > 1)
@ -12807,25 +12799,25 @@ void A_Boss5FindWaypoint(mobj_t *actor)
continue;
if (!P_CheckSight(actor, players[i].mo))
continue;
waypoints[numwaypoints++] = players[i].mo;
fangwaypoints[numfangwaypoints++] = players[i].mo;
}
}
// restore z position
actor->z -= hackoffset;
if (!numwaypoints)
if (!numfangwaypoints)
{
Z_Free(waypoints); // free table
Z_Free(fangwaypoints); // free table
goto nowaypoints; // ???
}
key = P_RandomKey(numwaypoints);
key = P_RandomKey(numfangwaypoints);
P_SetTarget(&actor->tracer, waypoints[key]);
P_SetTarget(&actor->tracer, fangwaypoints[key]);
if (actor->tracer->type == MT_FANGWAYPOINT)
actor->tracer->reactiontime = numwaypoints/4; // Monster Iestyn: is this how it should be? I count center waypoints as waypoints unlike the original Lua script
Z_Free(waypoints); // free table
actor->tracer->reactiontime = numfangwaypoints/4; // Monster Iestyn: is this how it should be? I count center waypoints as waypoints unlike the original Lua script
Z_Free(fangwaypoints); // free table
}
// now face the tracer you just set!
@ -13369,8 +13361,9 @@ static boolean PIT_DustDevilLaunch(mobj_t *thing)
P_ResetPlayer(player);
A_PlayActiveSound(dustdevil);
}
player->powers[pw_carry] = CR_DUSTDEVIL;
player->powers[pw_nocontrol] = 2;
player->drawangle += ANG20;
P_SetTarget(&thing->tracer, dustdevil);
P_SetPlayerMobjState(thing, S_PLAY_PAIN);
if (dist > dragamount)
@ -13390,7 +13383,9 @@ static boolean PIT_DustDevilLaunch(mobj_t *thing)
P_ResetPlayer(player);
thing->z = dustdevil->z + dustdevil->height;
thrust = 20 * FRACUNIT;
player->powers[pw_carry] = CR_NONE;
player->powers[pw_nocontrol] = 0;
P_SetTarget(&thing->tracer, NULL);
S_StartSound(thing, sfx_wdjump);
P_SetPlayerMobjState(thing, S_PLAY_FALL);
}

View file

@ -696,10 +696,20 @@ void T_BounceCheese(bouncecheese_t *bouncer)
return;
}
T_MovePlane(bouncer->sector, bouncer->speed/2, bouncer->sector->ceilingheight -
70*FRACUNIT, false, true, -1); // move ceiling
T_MovePlane(bouncer->sector, bouncer->speed/2, bouncer->sector->floorheight - 70*FRACUNIT,
false, false, -1); // move floor
if (bouncer->speed >= 0) // move floor first to fix height desync and any bizarre bugs following that
{
T_MovePlane(bouncer->sector, bouncer->speed/2, bouncer->sector->floorheight - 70*FRACUNIT,
false, false, -1); // move floor
T_MovePlane(bouncer->sector, bouncer->speed/2, bouncer->sector->ceilingheight -
70*FRACUNIT, false, true, -1); // move ceiling
}
else
{
T_MovePlane(bouncer->sector, bouncer->speed/2, bouncer->sector->ceilingheight -
70*FRACUNIT, false, true, -1); // move ceiling
T_MovePlane(bouncer->sector, bouncer->speed/2, bouncer->sector->floorheight - 70*FRACUNIT,
false, false, -1); // move floor
}
bouncer->sector->floorspeed = -bouncer->speed/2;
bouncer->sector->ceilspeed = 42;
@ -2231,9 +2241,9 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover)
{
mobj_t *spawned = NULL;
if (*rover->t_slope)
topz = P_GetZAt(*rover->t_slope, a, b) - (spacing>>1);
topz = P_GetSlopeZAt(*rover->t_slope, a, b) - (spacing>>1);
if (*rover->b_slope)
bottomz = P_GetZAt(*rover->b_slope, a, b);
bottomz = P_GetSlopeZAt(*rover->b_slope, a, b);
for (c = topz; c > bottomz; c -= spacing)
{

View file

@ -1143,10 +1143,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
toucher->angle = special->angle;
if (player == &players[consoleplayer])
localangle = toucher->angle;
else if (player == &players[secondarydisplayplayer])
localangle2 = toucher->angle;
P_SetPlayerAngle(player, toucher->angle);
P_ResetPlayer(player);
@ -1564,10 +1561,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
#if 0 // camera redirection - deemed unnecessary
toucher->angle = special->angle;
if (player == &players[consoleplayer])
localangle = toucher->angle;
else if (player == &players[secondarydisplayplayer])
localangle2 = toucher->angle;
P_SetPlayerAngle(player, toucher->angle);
#endif
S_StartSound(toucher, special->info->attacksound); // home run

View file

@ -138,6 +138,10 @@ void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor);
void P_ResetPlayer(player_t *player);
boolean P_PlayerCanDamage(player_t *player, mobj_t *thing);
boolean P_IsLocalPlayer(player_t *player);
void P_SetPlayerAngle(player_t *player, angle_t angle);
angle_t P_GetLocalAngle(player_t *player);
void P_SetLocalAngle(player_t *player, angle_t angle);
void P_ForceLocalAngle(player_t *player, angle_t angle);
boolean P_IsObjectInGoop(mobj_t *mo);
boolean P_IsObjectOnGround(mobj_t *mo);

View file

@ -372,12 +372,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
object->angle = object->player->drawangle = spring->angle;
if (!demoplayback || P_ControlStyle(object->player) == CS_LMAOGALOG)
{
if (object->player == &players[consoleplayer])
localangle = spring->angle;
else if (object->player == &players[secondarydisplayplayer])
localangle2 = spring->angle;
}
P_SetPlayerAngle(object->player, spring->angle);
}
if (object->player->pflags & PF_GLIDING)
@ -1310,12 +1305,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
thing->angle = tmthing->angle;
if (!demoplayback || P_ControlStyle(thing->player) == CS_LMAOGALOG)
{
if (thing->player == &players[consoleplayer])
localangle = thing->angle;
else if (thing->player == &players[secondarydisplayplayer])
localangle2 = thing->angle;
}
P_SetPlayerAngle(thing->player, thing->angle);
return true;
}
@ -3202,102 +3192,83 @@ isblocking:
static boolean P_IsClimbingValid(player_t *player, angle_t angle)
{
fixed_t platx, platy;
subsector_t *glidesector;
sector_t *glidesector;
fixed_t floorz, ceilingz;
mobj_t *mo = player->mo;
ffloor_t *rover;
platx = P_ReturnThrustX(player->mo, angle, player->mo->radius + FixedMul(8*FRACUNIT, player->mo->scale));
platy = P_ReturnThrustY(player->mo, angle, player->mo->radius + FixedMul(8*FRACUNIT, player->mo->scale));
platx = P_ReturnThrustX(mo, angle, mo->radius + FixedMul(8*FRACUNIT, mo->scale));
platy = P_ReturnThrustY(mo, angle, mo->radius + FixedMul(8*FRACUNIT, mo->scale));
glidesector = R_PointInSubsector(player->mo->x + platx, player->mo->y + platy);
glidesector = R_PointInSubsector(mo->x + platx, mo->y + platy)->sector;
floorz = glidesector->sector->f_slope ? P_GetZAt(glidesector->sector->f_slope, player->mo->x, player->mo->y) : glidesector->sector->floorheight;
ceilingz = glidesector->sector->c_slope ? P_GetZAt(glidesector->sector->c_slope, player->mo->x, player->mo->y) : glidesector->sector->ceilingheight;
floorz = P_GetSectorFloorZAt (glidesector, mo->x, mo->y);
ceilingz = P_GetSectorCeilingZAt(glidesector, mo->x, mo->y);
if (glidesector->sector != player->mo->subsector->sector)
if (glidesector != mo->subsector->sector)
{
boolean floorclimb = false;
fixed_t topheight, bottomheight;
if (glidesector->sector->ffloors)
for (rover = glidesector->ffloors; rover; rover = rover->next)
{
ffloor_t *rover;
for (rover = glidesector->sector->ffloors; rover; rover = rover->next)
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER))
continue;
topheight = P_GetFFloorTopZAt (rover, mo->x, mo->y);
bottomheight = P_GetFFloorBottomZAt(rover, mo->x, mo->y);
floorclimb = true;
if (mo->eflags & MFE_VERTICALFLIP)
{
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER))
continue;
topheight = *rover->topheight;
bottomheight = *rover->bottomheight;
if (*rover->t_slope)
topheight = P_GetZAt(*rover->t_slope, player->mo->x, player->mo->y);
if (*rover->b_slope)
bottomheight = P_GetZAt(*rover->b_slope, player->mo->x, player->mo->y);
floorclimb = true;
if (player->mo->eflags & MFE_VERTICALFLIP)
{
if ((topheight < player->mo->z + player->mo->height) && ((player->mo->z + player->mo->height + player->mo->momz) < topheight))
{
floorclimb = true;
}
if (topheight < player->mo->z) // Waaaay below the ledge.
{
floorclimb = false;
}
if (bottomheight > player->mo->z + player->mo->height - FixedMul(16*FRACUNIT,player->mo->scale))
{
floorclimb = false;
}
}
else
{
if ((bottomheight > player->mo->z) && ((player->mo->z - player->mo->momz) > bottomheight))
{
floorclimb = true;
}
if (bottomheight > player->mo->z + player->mo->height) // Waaaay below the ledge.
{
floorclimb = false;
}
if (topheight < player->mo->z + FixedMul(16*FRACUNIT,player->mo->scale))
{
floorclimb = false;
}
}
if (floorclimb)
break;
if ((topheight < mo->z + mo->height) && ((mo->z + mo->height + mo->momz) < topheight))
floorclimb = true;
if (topheight < mo->z) // Waaaay below the ledge.
floorclimb = false;
if (bottomheight > mo->z + mo->height - FixedMul(16*FRACUNIT,mo->scale))
floorclimb = false;
}
else
{
if ((bottomheight > mo->z) && ((mo->z - mo->momz) > bottomheight))
floorclimb = true;
if (bottomheight > mo->z + mo->height) // Waaaay below the ledge.
floorclimb = false;
if (topheight < mo->z + FixedMul(16*FRACUNIT,mo->scale))
floorclimb = false;
}
if (floorclimb)
break;
}
if (player->mo->eflags & MFE_VERTICALFLIP)
if (mo->eflags & MFE_VERTICALFLIP)
{
if ((floorz <= player->mo->z + player->mo->height)
&& ((player->mo->z + player->mo->height - player->mo->momz) <= floorz))
if ((floorz <= mo->z + mo->height)
&& ((mo->z + mo->height - mo->momz) <= floorz))
floorclimb = true;
if ((floorz > player->mo->z)
&& glidesector->sector->floorpic == skyflatnum)
if ((floorz > mo->z)
&& glidesector->floorpic == skyflatnum)
return false;
if ((player->mo->z + player->mo->height - FixedMul(16*FRACUNIT,player->mo->scale) > ceilingz)
|| (player->mo->z + player->mo->height <= floorz))
if ((mo->z + mo->height - FixedMul(16*FRACUNIT,mo->scale) > ceilingz)
|| (mo->z + mo->height <= floorz))
floorclimb = true;
}
else
{
if ((ceilingz >= player->mo->z)
&& ((player->mo->z - player->mo->momz) >= ceilingz))
if ((ceilingz >= mo->z)
&& ((mo->z - mo->momz) >= ceilingz))
floorclimb = true;
if ((ceilingz < player->mo->z+player->mo->height)
&& glidesector->sector->ceilingpic == skyflatnum)
if ((ceilingz < mo->z+mo->height)
&& glidesector->ceilingpic == skyflatnum)
return false;
if ((player->mo->z + FixedMul(16*FRACUNIT,player->mo->scale) < floorz)
|| (player->mo->z >= ceilingz))
if ((mo->z + FixedMul(16*FRACUNIT,mo->scale) < floorz)
|| (mo->z >= ceilingz))
floorclimb = true;
}
@ -3310,9 +3281,123 @@ static boolean P_IsClimbingValid(player_t *player, angle_t angle)
return false;
}
//
// PTR_SlideTraverse
//
static boolean PTR_LineIsBlocking(line_t *li)
{
// one-sided linedefs are always solid to sliding movement.
if (!li->backsector)
return !P_PointOnLineSide(slidemo->x, slidemo->y, li);
if (!(slidemo->flags & MF_MISSILE))
{
if (li->flags & ML_IMPASSIBLE)
return true;
if ((slidemo->flags & (MF_ENEMY|MF_BOSS)) && li->flags & ML_BLOCKMONSTERS)
return true;
}
// set openrange, opentop, openbottom
P_LineOpening(li, slidemo);
if (openrange < slidemo->height)
return true; // doesn't fit
if (opentop - slidemo->z < slidemo->height)
return true; // mobj is too high
if (openbottom - slidemo->z > FixedMul(MAXSTEPMOVE, slidemo->scale))
return true; // too big a step up
return false;
}
static void PTR_GlideClimbTraverse(line_t *li)
{
line_t *checkline = li;
ffloor_t *rover;
fixed_t topheight, bottomheight;
boolean fofline = false;
sector_t *checksector = (li->backsector && !P_PointOnLineSide(slidemo->x, slidemo->y, li)) ? li->backsector : li->frontsector;
if (checksector->ffloors)
{
for (rover = checksector->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER) || (rover->flags & FF_BUSTUP))
continue;
topheight = P_GetFFloorTopZAt (rover, slidemo->x, slidemo->y);
bottomheight = P_GetFFloorBottomZAt(rover, slidemo->x, slidemo->y);
if (topheight < slidemo->z)
continue;
if (bottomheight > slidemo->z + slidemo->height)
continue;
// Got this far, so I guess it's climbable. // TODO: Climbing check, also, better method to do this?
if (rover->master->flags & ML_TFERLINE)
{
size_t linenum = li-checksector->lines[0];
checkline = rover->master->frontsector->lines[0] + linenum;
fofline = true;
}
break;
}
}
// see about climbing on the wall
if (!(checkline->flags & ML_NOCLIMB) && checkline->special != HORIZONSPECIAL)
{
boolean canclimb;
angle_t climbangle, climbline;
INT32 whichside = P_PointOnLineSide(slidemo->x, slidemo->y, li);
climbangle = climbline = R_PointToAngle2(li->v1->x, li->v1->y, li->v2->x, li->v2->y);
if (whichside) // on second side?
climbline += ANGLE_180;
climbangle += (ANGLE_90 * (whichside ? -1 : 1));
canclimb = (li->backsector ? P_IsClimbingValid(slidemo->player, climbangle) : true);
if (((!slidemo->player->climbing && abs((signed)(slidemo->angle - ANGLE_90 - climbline)) < ANGLE_45)
|| (slidemo->player->climbing == 1 && abs((signed)(slidemo->angle - climbline)) < ANGLE_135))
&& canclimb)
{
slidemo->angle = climbangle;
/*if (!demoplayback || P_ControlStyle(slidemo->player) == CS_LMAOGALOG)
P_SetPlayerAngle(slidemo->player, slidemo->angle);*/
if (!slidemo->player->climbing)
{
S_StartSound(slidemo->player->mo, sfx_s3k4a);
slidemo->player->climbing = 5;
}
slidemo->player->pflags &= ~(PF_GLIDING|PF_SPINNING|PF_JUMPED|PF_NOJUMPDAMAGE|PF_THOKKED);
slidemo->player->glidetime = 0;
slidemo->player->secondjump = 0;
if (slidemo->player->climbing > 1)
slidemo->momz = slidemo->momx = slidemo->momy = 0;
if (fofline)
whichside = 0;
if (!whichside)
{
slidemo->player->lastsidehit = checkline->sidenum[whichside];
slidemo->player->lastlinehit = (INT16)(checkline - lines);
}
P_Thrust(slidemo, slidemo->angle, FixedMul(5*FRACUNIT, slidemo->scale));
}
}
}
static boolean PTR_SlideTraverse(intercept_t *in)
{
line_t *li;
@ -3321,151 +3406,20 @@ static boolean PTR_SlideTraverse(intercept_t *in)
li = in->d.line;
// one-sided linedefs are always solid to sliding movement.
// one-sided linedef
if (!li->backsector)
{
if (P_PointOnLineSide(slidemo->x, slidemo->y, li))
return true; // don't hit the back side
goto isblocking;
}
if (!PTR_LineIsBlocking(li))
return true;
if (!(slidemo->flags & MF_MISSILE))
{
if (li->flags & ML_IMPASSIBLE)
goto isblocking;
if ((slidemo->flags & (MF_ENEMY|MF_BOSS)) && li->flags & ML_BLOCKMONSTERS)
goto isblocking;
}
// set openrange, opentop, openbottom
P_LineOpening(li, slidemo);
if (openrange < slidemo->height)
goto isblocking; // doesn't fit
if (opentop - slidemo->z < slidemo->height)
goto isblocking; // mobj is too high
if (openbottom - slidemo->z > FixedMul(MAXSTEPMOVE, slidemo->scale))
goto isblocking; // too big a step up
// this line doesn't block movement
return true;
// the line does block movement,
// the line blocks movement,
// see if it is closer than best so far
isblocking:
if (li->polyobj && slidemo->player)
{
if ((li->polyobj->lines[0]->backsector->flags & SF_TRIGGERSPECIAL_TOUCH) && !(li->polyobj->flags & POF_NOSPECIALS))
P_ProcessSpecialSector(slidemo->player, slidemo->subsector->sector, li->polyobj->lines[0]->backsector);
}
if (slidemo->player && (slidemo->player->pflags & PF_GLIDING || slidemo->player->climbing)
&& slidemo->player->charability == CA_GLIDEANDCLIMB)
{
line_t *checkline = li;
sector_t *checksector;
ffloor_t *rover;
fixed_t topheight, bottomheight;
boolean fofline = false;
INT32 side = P_PointOnLineSide(slidemo->x, slidemo->y, li);
if (!side && li->backsector)
checksector = li->backsector;
else
checksector = li->frontsector;
if (checksector->ffloors)
{
for (rover = checksector->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER) || (rover->flags & FF_BUSTUP))
continue;
topheight = *rover->topheight;
bottomheight = *rover->bottomheight;
if (*rover->t_slope)
topheight = P_GetZAt(*rover->t_slope, slidemo->x, slidemo->y);
if (*rover->b_slope)
bottomheight = P_GetZAt(*rover->b_slope, slidemo->x, slidemo->y);
if (topheight < slidemo->z)
continue;
if (bottomheight > slidemo->z + slidemo->height)
continue;
// Got this far, so I guess it's climbable. // TODO: Climbing check, also, better method to do this?
if (rover->master->flags & ML_TFERLINE)
{
size_t linenum = li-checksector->lines[0];
checkline = rover->master->frontsector->lines[0] + linenum;
fofline = true;
}
break;
}
}
// see about climbing on the wall
if (!(checkline->flags & ML_NOCLIMB) && checkline->special != HORIZONSPECIAL)
{
boolean canclimb;
angle_t climbangle, climbline;
INT32 whichside = P_PointOnLineSide(slidemo->x, slidemo->y, li);
climbangle = climbline = R_PointToAngle2(li->v1->x, li->v1->y, li->v2->x, li->v2->y);
if (whichside) // on second side?
climbline += ANGLE_180;
climbangle += (ANGLE_90 * (whichside ? -1 : 1));
canclimb = (li->backsector ? P_IsClimbingValid(slidemo->player, climbangle) : true);
if (((!slidemo->player->climbing && abs((signed)(slidemo->angle - ANGLE_90 - climbline)) < ANGLE_45)
|| (slidemo->player->climbing == 1 && abs((signed)(slidemo->angle - climbline)) < ANGLE_135))
&& canclimb)
{
slidemo->angle = climbangle;
/*if (!demoplayback || P_ControlStyle(slidemo->player) == CS_LMAOGALOG)
{
if (slidemo->player == &players[consoleplayer])
localangle = slidemo->angle;
else if (slidemo->player == &players[secondarydisplayplayer])
localangle2 = slidemo->angle;
}*/
if (!slidemo->player->climbing)
{
S_StartSound(slidemo->player->mo, sfx_s3k4a);
slidemo->player->climbing = 5;
}
slidemo->player->pflags &= ~(PF_GLIDING|PF_SPINNING|PF_JUMPED|PF_NOJUMPDAMAGE|PF_THOKKED);
slidemo->player->glidetime = 0;
slidemo->player->secondjump = 0;
if (slidemo->player->climbing > 1)
slidemo->momz = slidemo->momx = slidemo->momy = 0;
if (fofline)
whichside = 0;
if (!whichside)
{
slidemo->player->lastsidehit = checkline->sidenum[whichside];
slidemo->player->lastlinehit = (INT16)(checkline - lines);
}
P_Thrust(slidemo, slidemo->angle, FixedMul(5*FRACUNIT, slidemo->scale));
}
}
}
if (slidemo->player && slidemo->player->charability == CA_GLIDEANDCLIMB
&& (slidemo->player->pflags & PF_GLIDING || slidemo->player->climbing))
PTR_GlideClimbTraverse(li);
if (in->frac < bestslidefrac && (!slidemo->player || !slidemo->player->climbing))
{
@ -3596,9 +3550,7 @@ static void P_CheckLavaWall(mobj_t *mo, sector_t *sec)
if (rover->master->flags & ML_BLOCKMONSTERS)
continue;
topheight = *rover->t_slope ?
P_GetZAt(*rover->t_slope, mo->x, mo->y) :
*rover->topheight;
topheight = P_GetFFloorTopZAt(rover, mo->x, mo->y);
if (mo->eflags & MFE_VERTICALFLIP)
{
@ -3611,9 +3563,7 @@ static void P_CheckLavaWall(mobj_t *mo, sector_t *sec)
continue;
}
bottomheight = *rover->b_slope ?
P_GetZAt(*rover->b_slope, mo->x, mo->y) :
*rover->bottomheight;
bottomheight = P_GetFFloorBottomZAt(rover, mo->x, mo->y);
if (mo->eflags & MFE_VERTICALFLIP)
{
@ -4199,11 +4149,8 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush)
topheight = *rover->topheight;
bottomheight = *rover->bottomheight;
/*if (rover->t_slope)
topheight = P_GetZAt(rover->t_slope, thing->x, thing->y);
if (rover->b_slope)
bottomheight = P_GetZAt(rover->b_slope, thing->x, thing->y);*/
//topheight = P_GetFFloorTopZAt (rover, thing->x, thing->y);
//bottomheight = P_GetFFloorBottomZAt(rover, thing->x, thing->y);
delta1 = thing->z - (bottomheight + topheight)/2;
delta2 = thingtop - (bottomheight + topheight)/2;
@ -4980,10 +4927,7 @@ void P_MapEnd(void)
fixed_t P_FloorzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height)
{
sector_t *sec = R_PointInSubsector(x, y)->sector;
fixed_t floorz = sec->floorheight;
if (sec->f_slope)
floorz = P_GetZAt(sec->f_slope, x, y);
fixed_t floorz = P_GetSectorFloorZAt(sec, x, y);
// Intercept the stupid 'fall through 3dfloors' bug Tails 03-17-2002
if (sec->ffloors)
@ -5000,13 +4944,8 @@ fixed_t P_FloorzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height)
if ((!(rover->flags & FF_SOLID || rover->flags & FF_QUICKSAND) || (rover->flags & FF_SWIMMABLE)))
continue;
topheight = *rover->topheight;
bottomheight = *rover->bottomheight;
if (*rover->t_slope)
topheight = P_GetZAt(*rover->t_slope, x, y);
if (*rover->b_slope)
bottomheight = P_GetZAt(*rover->b_slope, x, y);
topheight = P_GetFFloorTopZAt (rover, x, y);
bottomheight = P_GetFFloorBottomZAt(rover, x, y);
if (rover->flags & FF_QUICKSAND)
{

View file

@ -303,45 +303,33 @@ void P_CameraLineOpening(line_t *linedef)
// If you can see through it, why not move the camera through it too?
if (front->camsec >= 0)
{
frontfloor = sectors[front->camsec].floorheight;
frontceiling = sectors[front->camsec].ceilingheight;
if (sectors[front->camsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope)
frontfloor = P_GetZAt(sectors[front->camsec].f_slope, camera.x, camera.y);
if (sectors[front->camsec].c_slope)
frontceiling = P_GetZAt(sectors[front->camsec].c_slope, camera.x, camera.y);
// SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope)
frontfloor = P_GetSectorFloorZAt (&sectors[front->camsec], camera.x, camera.y);
frontceiling = P_GetSectorCeilingZAt(&sectors[front->camsec], camera.x, camera.y);
}
else if (front->heightsec >= 0)
{
frontfloor = sectors[front->heightsec].floorheight;
frontceiling = sectors[front->heightsec].ceilingheight;
if (sectors[front->heightsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope)
frontfloor = P_GetZAt(sectors[front->heightsec].f_slope, camera.x, camera.y);
if (sectors[front->heightsec].c_slope)
frontceiling = P_GetZAt(sectors[front->heightsec].c_slope, camera.x, camera.y);
// SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope)
frontfloor = P_GetSectorFloorZAt (&sectors[front->heightsec], camera.x, camera.y);
frontceiling = P_GetSectorCeilingZAt(&sectors[front->heightsec], camera.x, camera.y);
}
else
{
frontfloor = P_CameraGetFloorZ(mapcampointer, front, tmx, tmy, linedef);
frontfloor = P_CameraGetFloorZ (mapcampointer, front, tmx, tmy, linedef);
frontceiling = P_CameraGetCeilingZ(mapcampointer, front, tmx, tmy, linedef);
}
if (back->camsec >= 0)
{
backfloor = sectors[back->camsec].floorheight;
backceiling = sectors[back->camsec].ceilingheight;
if (sectors[back->camsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope)
frontfloor = P_GetZAt(sectors[back->camsec].f_slope, camera.x, camera.y);
if (sectors[back->camsec].c_slope)
frontceiling = P_GetZAt(sectors[back->camsec].c_slope, camera.x, camera.y);
// SRB2CBTODO: ESLOPE (sectors[back->heightsec].f_slope)
backfloor = P_GetSectorFloorZAt (&sectors[back->camsec], camera.x, camera.y);
backceiling = P_GetSectorCeilingZAt(&sectors[back->camsec], camera.x, camera.y);
}
else if (back->heightsec >= 0)
{
backfloor = sectors[back->heightsec].floorheight;
backceiling = sectors[back->heightsec].ceilingheight;
if (sectors[back->heightsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope)
frontfloor = P_GetZAt(sectors[back->heightsec].f_slope, camera.x, camera.y);
if (sectors[back->heightsec].c_slope)
frontceiling = P_GetZAt(sectors[back->heightsec].c_slope, camera.x, camera.y);
// SRB2CBTODO: ESLOPE (sectors[back->heightsec].f_slope)
backfloor = P_GetSectorFloorZAt (&sectors[back->heightsec], camera.x, camera.y);
backceiling = P_GetSectorCeilingZAt(&sectors[back->heightsec], camera.x, camera.y);
}
else
{

View file

@ -436,7 +436,7 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
mobj->sprite2 = spr2;
mobj->frame = frame|(st->frame&~FF_FRAMEMASK);
if (mobj->color >= MAXSKINCOLORS && mobj->color < MAXTRANSLATIONS) // Super colours? Super bright!
if (mobj->color >= FIRSTSUPERCOLOR && mobj->color < numskincolors) // Super colours? Super bright!
mobj->frame |= FF_FULLBRIGHT;
}
// Regular sprites
@ -926,13 +926,8 @@ boolean P_InsideANonSolidFFloor(mobj_t *mobj, ffloor_t *rover)
|| ((rover->flags & FF_BLOCKOTHERS) && !mobj->player)))
return false;
topheight = *rover->topheight;
bottomheight = *rover->bottomheight;
if (*rover->t_slope)
topheight = P_GetZAt(*rover->t_slope, mobj->x, mobj->y);
if (*rover->b_slope)
bottomheight = P_GetZAt(*rover->b_slope, mobj->x, mobj->y);
topheight = P_GetFFloorTopZAt (rover, mobj->x, mobj->y);
bottomheight = P_GetFFloorBottomZAt(rover, mobj->x, mobj->y);
if (mobj->z > topheight)
return false;
@ -963,12 +958,12 @@ static fixed_t HighestOnLine(fixed_t radius, fixed_t x, fixed_t y, line_t *line,
/*CONS_Printf("BEFORE: v1 = %f %f %f\n",
FIXED_TO_FLOAT(v1.x),
FIXED_TO_FLOAT(v1.y),
FIXED_TO_FLOAT(P_GetZAt(slope, v1.x, v1.y))
FIXED_TO_FLOAT(P_GetSlopeZAt(slope, v1.x, v1.y))
);
CONS_Printf(" v2 = %f %f %f\n",
FIXED_TO_FLOAT(v2.x),
FIXED_TO_FLOAT(v2.y),
FIXED_TO_FLOAT(P_GetZAt(slope, v2.x, v2.y))
FIXED_TO_FLOAT(P_GetSlopeZAt(slope, v2.x, v2.y))
);*/
if (abs(v1.x-x) > radius) {
@ -1026,24 +1021,24 @@ static fixed_t HighestOnLine(fixed_t radius, fixed_t x, fixed_t y, line_t *line,
/*CONS_Printf("AFTER: v1 = %f %f %f\n",
FIXED_TO_FLOAT(v1.x),
FIXED_TO_FLOAT(v1.y),
FIXED_TO_FLOAT(P_GetZAt(slope, v1.x, v1.y))
FIXED_TO_FLOAT(P_GetSlopeZAt(slope, v1.x, v1.y))
);
CONS_Printf(" v2 = %f %f %f\n",
FIXED_TO_FLOAT(v2.x),
FIXED_TO_FLOAT(v2.y),
FIXED_TO_FLOAT(P_GetZAt(slope, v2.x, v2.y))
FIXED_TO_FLOAT(P_GetSlopeZAt(slope, v2.x, v2.y))
);*/
// Return the higher of the two points
if (actuallylowest)
return min(
P_GetZAt(slope, v1.x, v1.y),
P_GetZAt(slope, v2.x, v2.y)
P_GetSlopeZAt(slope, v1.x, v1.y),
P_GetSlopeZAt(slope, v2.x, v2.y)
);
else
return max(
P_GetZAt(slope, v1.x, v1.y),
P_GetZAt(slope, v2.x, v2.y)
P_GetSlopeZAt(slope, v1.x, v1.y),
P_GetSlopeZAt(slope, v2.x, v2.y)
);
}
@ -1077,7 +1072,7 @@ fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t
// If the highest point is in the sector, then we have it easy! Just get the Z at that point
if (R_PointInSubsector(testx, testy)->sector == (boundsec ? boundsec : sector))
return P_GetZAt(slope, testx, testy);
return P_GetSlopeZAt(slope, testx, testy);
// If boundsec is set, we're looking for specials. In that case, iterate over every line in this sector to find the TRUE highest/lowest point
if (perfect) {
@ -1117,7 +1112,7 @@ fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t
// If we're just testing for base sector location (no collision line), just go for the center's spot...
// It'll get fixed when we test for collision anyway, and the final result can't be lower than this
if (line == NULL)
return P_GetZAt(slope, x, y);
return P_GetSlopeZAt(slope, x, y);
return HighestOnLine(mobj->radius, x, y, line, slope, lowest);
} else // Well, that makes it easy. Just get the floor height
@ -1154,7 +1149,7 @@ fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed
// If the highest point is in the sector, then we have it easy! Just get the Z at that point
if (R_PointInSubsector(testx, testy)->sector == (boundsec ? boundsec : sector))
return P_GetZAt(slope, testx, testy);
return P_GetSlopeZAt(slope, testx, testy);
// If boundsec is set, we're looking for specials. In that case, iterate over every line in this sector to find the TRUE highest/lowest point
if (perfect) {
@ -1194,7 +1189,7 @@ fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed
// If we're just testing for base sector location (no collision line), just go for the center's spot...
// It'll get fixed when we test for collision anyway, and the final result can't be lower than this
if (line == NULL)
return P_GetZAt(slope, x, y);
return P_GetSlopeZAt(slope, x, y);
return HighestOnLine(mobj->radius, x, y, line, slope, lowest);
} else // Well, that makes it easy. Just get the ceiling height
@ -1232,7 +1227,7 @@ fixed_t P_CameraFloorZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, fix
// If the highest point is in the sector, then we have it easy! Just get the Z at that point
if (R_PointInSubsector(testx, testy)->sector == (boundsec ? boundsec : sector))
return P_GetZAt(slope, testx, testy);
return P_GetSlopeZAt(slope, testx, testy);
// If boundsec is set, we're looking for specials. In that case, iterate over every line in this sector to find the TRUE highest/lowest point
if (perfect) {
@ -1272,7 +1267,7 @@ fixed_t P_CameraFloorZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, fix
// If we're just testing for base sector location (no collision line), just go for the center's spot...
// It'll get fixed when we test for collision anyway, and the final result can't be lower than this
if (line == NULL)
return P_GetZAt(slope, x, y);
return P_GetSlopeZAt(slope, x, y);
return HighestOnLine(mobj->radius, x, y, line, slope, lowest);
} else // Well, that makes it easy. Just get the floor height
@ -1309,7 +1304,7 @@ fixed_t P_CameraCeilingZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, f
// If the highest point is in the sector, then we have it easy! Just get the Z at that point
if (R_PointInSubsector(testx, testy)->sector == (boundsec ? boundsec : sector))
return P_GetZAt(slope, testx, testy);
return P_GetSlopeZAt(slope, testx, testy);
// If boundsec is set, we're looking for specials. In that case, iterate over every line in this sector to find the TRUE highest/lowest point
if (perfect) {
@ -1349,7 +1344,7 @@ fixed_t P_CameraCeilingZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, f
// If we're just testing for base sector location (no collision line), just go for the center's spot...
// It'll get fixed when we test for collision anyway, and the final result can't be lower than this
if (line == NULL)
return P_GetZAt(slope, x, y);
return P_GetSlopeZAt(slope, x, y);
return HighestOnLine(mobj->radius, x, y, line, slope, lowest);
} else // Well, that makes it easy. Just get the ceiling height
@ -1674,70 +1669,74 @@ static void P_PushableCheckBustables(mobj_t *mo)
for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next)
{
ffloor_t *rover;
fixed_t topheight, bottomheight;
if (!node->m_sector)
break;
if (node->m_sector->ffloors)
if (!node->m_sector->ffloors)
continue;
for (rover = node->m_sector->ffloors; rover; rover = rover->next)
{
ffloor_t *rover;
fixed_t topheight, bottomheight;
if (!(rover->flags & FF_EXISTS))
continue;
for (rover = node->m_sector->ffloors; rover; rover = rover->next)
if (!(rover->flags & FF_BUSTUP))
continue;
// Needs ML_EFFECT4 flag for pushables to break it
if (!(rover->master->flags & ML_EFFECT4))
continue;
if (rover->master->frontsector->crumblestate != CRUMBLE_NONE)
continue;
topheight = P_GetFOFTopZ(mo, node->m_sector, rover, mo->x, mo->y, NULL);
bottomheight = P_GetFOFBottomZ(mo, node->m_sector, rover, mo->x, mo->y, NULL);
// Height checks
if (rover->flags & FF_SHATTERBOTTOM)
{
if (!(rover->flags & FF_EXISTS)) continue;
if (mo->z + mo->momz + mo->height < bottomheight)
continue;
if (!(rover->flags & FF_BUSTUP)) continue;
// Needs ML_EFFECT4 flag for pushables to break it
if (!(rover->master->flags & ML_EFFECT4)) continue;
if (rover->master->frontsector->crumblestate == CRUMBLE_NONE)
{
topheight = P_GetFOFTopZ(mo, node->m_sector, rover, mo->x, mo->y, NULL);
bottomheight = P_GetFOFBottomZ(mo, node->m_sector, rover, mo->x, mo->y, NULL);
// Height checks
if (rover->flags & FF_SHATTERBOTTOM)
{
if (mo->z+mo->momz + mo->height < bottomheight)
continue;
if (mo->z+mo->height > bottomheight)
continue;
}
else if (rover->flags & FF_SPINBUST)
{
if (mo->z+mo->momz > topheight)
continue;
if (mo->z+mo->height < bottomheight)
continue;
}
else if (rover->flags & FF_SHATTER)
{
if (mo->z+mo->momz > topheight)
continue;
if (mo->z+mo->momz + mo->height < bottomheight)
continue;
}
else
{
if (mo->z >= topheight)
continue;
if (mo->z+mo->height < bottomheight)
continue;
}
EV_CrumbleChain(NULL, rover); // node->m_sector
// Run a linedef executor??
if (rover->master->flags & ML_EFFECT5)
P_LinedefExecute((INT16)(P_AproxDistance(rover->master->dx, rover->master->dy)>>FRACBITS), mo, node->m_sector);
goto bustupdone;
}
if (mo->z + mo->height > bottomheight)
continue;
}
else if (rover->flags & FF_SPINBUST)
{
if (mo->z + mo->momz > topheight)
continue;
if (mo->z + mo->height < bottomheight)
continue;
}
else if (rover->flags & FF_SHATTER)
{
if (mo->z + mo->momz > topheight)
continue;
if (mo->z + mo->momz + mo->height < bottomheight)
continue;
}
else
{
if (mo->z >= topheight)
continue;
if (mo->z + mo->height < bottomheight)
continue;
}
EV_CrumbleChain(NULL, rover); // node->m_sector
// Run a linedef executor??
if (rover->master->flags & ML_EFFECT5)
P_LinedefExecute((INT16)(P_AproxDistance(rover->master->dx, rover->master->dy)>>FRACBITS), mo, node->m_sector);
goto bustupdone;
}
}
bustupdone:
@ -1772,7 +1771,7 @@ void P_XYMovement(mobj_t *mo)
fixed_t oldx, oldy; // reducing bobbing/momentum on ice when up against walls
boolean moved;
pslope_t *oldslope = NULL;
vector3_t slopemom;
vector3_t slopemom = {0,0,0};
fixed_t predictedz = 0;
I_Assert(mo != NULL);
@ -2798,6 +2797,93 @@ static boolean P_ZMovement(mobj_t *mo)
return true;
}
// Check for "Mario" blocks to hit and bounce them
static void P_CheckMarioBlocks(mobj_t *mo)
{
msecnode_t *node;
if (netgame && mo->player->spectator)
return;
for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next)
{
ffloor_t *rover;
if (!node->m_sector->ffloors)
continue;
for (rover = node->m_sector->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS))
continue;
if (!(rover->flags & FF_MARIO))
continue;
if (mo->eflags & MFE_VERTICALFLIP)
continue; // if you were flipped, your head isn't actually hitting your ceilingz is it?
if (*rover->bottomheight != mo->ceilingz)
continue;
if (rover->flags & FF_SHATTERBOTTOM) // Brick block!
EV_CrumbleChain(node->m_sector, rover);
else // Question block!
EV_MarioBlock(rover, node->m_sector, mo);
}
}
}
// Check if we're on a polyobject that triggers a linedef executor.
static boolean P_PlayerPolyObjectZMovement(mobj_t *mo)
{
msecnode_t *node;
boolean stopmovecut = false;
for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next)
{
sector_t *sec = node->m_sector;
subsector_t *newsubsec;
size_t i;
for (i = 0; i < numsubsectors; i++)
{
polyobj_t *po;
sector_t *polysec;
newsubsec = &subsectors[i];
if (newsubsec->sector != sec)
continue;
for (po = newsubsec->polyList; po; po = (polyobj_t *)(po->link.next))
{
if (!(po->flags & POF_SOLID))
continue;
if (!P_MobjInsidePolyobj(po, mo))
continue;
polysec = po->lines[0]->backsector;
// Moving polyobjects should act like conveyors if the player lands on one. (I.E. none of the momentum cut thing below) -Red
if ((mo->z == polysec->ceilingheight || mo->z + mo->height == polysec->floorheight) && po->thinker)
stopmovecut = true;
if (!(po->flags & POF_LDEXEC))
continue;
if (mo->z != polysec->ceilingheight)
continue;
// We're landing on a PO, so check for a linedef executor.
P_LinedefExecute(po->triggertag, mo, NULL);
}
}
}
return stopmovecut;
}
static void P_PlayerZMovement(mobj_t *mo)
{
boolean onground;
@ -2894,64 +2980,10 @@ static void P_PlayerZMovement(mobj_t *mo)
mo->eflags |= MFE_JUSTHITFLOOR; // Spin Attack
clipmomz = P_PlayerHitFloor(mo->player, true);
if (!P_PlayerPolyObjectZMovement(mo))
{
// Check if we're on a polyobject
// that triggers a linedef executor.
msecnode_t *node;
boolean stopmovecut = false;
for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next)
{
sector_t *sec = node->m_sector;
subsector_t *newsubsec;
size_t i;
for (i = 0; i < numsubsectors; i++)
{
newsubsec = &subsectors[i];
if (newsubsec->sector != sec)
continue;
if (newsubsec->polyList)
{
polyobj_t *po = newsubsec->polyList;
sector_t *polysec;
while(po)
{
if (!P_MobjInsidePolyobj(po, mo) || !(po->flags & POF_SOLID))
{
po = (polyobj_t *)(po->link.next);
continue;
}
// We're inside it! Yess...
polysec = po->lines[0]->backsector;
// Moving polyobjects should act like conveyors if the player lands on one. (I.E. none of the momentum cut thing below) -Red
if ((mo->z == polysec->ceilingheight || mo->z+mo->height == polysec->floorheight) && po->thinker)
stopmovecut = true;
if (!(po->flags & POF_LDEXEC))
{
po = (polyobj_t *)(po->link.next);
continue;
}
if (mo->z == polysec->ceilingheight)
{
// We're landing on a PO, so check for a linedef executor.
P_LinedefExecute(po->triggertag, mo, NULL);
}
po = (polyobj_t *)(po->link.next);
}
}
}
}
if (!stopmovecut)
// Cut momentum in half when you hit the ground and
// aren't pressing any controls.
if (!(mo->player->cmd.forwardmove || mo->player->cmd.sidemove) && !mo->player->cmomx && !mo->player->cmomy && !(mo->player->pflags & PF_SPINNING))
@ -2961,8 +2993,6 @@ static void P_PlayerZMovement(mobj_t *mo)
}
}
clipmomz = P_PlayerHitFloor(mo->player, true);
if (!(mo->player->pflags & PF_SPINNING) && mo->player->powers[pw_carry] != CR_NIGHTSMODE)
mo->player->pflags &= ~PF_STARTDASH;
@ -3017,39 +3047,10 @@ nightsdone:
}
}
// Check for "Mario" blocks to hit and bounce them
if (P_MobjFlip(mo)*mo->momz > 0)
{
msecnode_t *node;
if (CheckForMarioBlocks && !(netgame && mo->player->spectator)) // Only let the player punch
{
// Search the touching sectors, from side-to-side...
for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next)
{
ffloor_t *rover;
if (!node->m_sector->ffloors)
continue;
for (rover = node->m_sector->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS))
continue;
// Come on, it's time to go...
if (rover->flags & FF_MARIO
&& !(mo->eflags & MFE_VERTICALFLIP) // if you were flipped, your head isn't actually hitting your ceilingz is it?
&& *rover->bottomheight == mo->ceilingz) // The player's head hit the bottom!
{
// DO THE MARIO!
if (rover->flags & FF_SHATTERBOTTOM) // Brick block!
EV_CrumbleChain(node->m_sector, rover);
else // Question block!
EV_MarioBlock(rover, node->m_sector, mo);
}
}
} // Ugly ugly billions of braces! Argh!
}
if (CheckForMarioBlocks)
P_CheckMarioBlocks(mo);
// hit the ceiling
if (mariomode)
@ -3208,9 +3209,7 @@ static boolean P_SceneryZMovement(mobj_t *mo)
//
boolean P_CanRunOnWater(player_t *player, ffloor_t *rover)
{
fixed_t topheight = *rover->t_slope ?
P_GetZAt(*rover->t_slope, player->mo->x, player->mo->y) :
*rover->topheight;
fixed_t topheight = P_GetFFloorTopZAt(rover, player->mo->x, player->mo->y);
if (!player->powers[pw_carry] && !player->homing
&& ((player->powers[pw_super] || player->charflags & SF_RUNONWATER || player->dashmode >= DASHMODE_THRESHOLD) && player->mo->ceilingz-topheight >= player->mo->height)
@ -3253,14 +3252,8 @@ void P_MobjCheckWater(mobj_t *mobj)
|| ((rover->flags & FF_BLOCKOTHERS) && !mobj->player)))
continue;
topheight = *rover->topheight;
bottomheight = *rover->bottomheight;
if (*rover->t_slope)
topheight = P_GetZAt(*rover->t_slope, mobj->x, mobj->y);
if (*rover->b_slope)
bottomheight = P_GetZAt(*rover->b_slope, mobj->x, mobj->y);
topheight = P_GetFFloorTopZAt (rover, mobj->x, mobj->y);
bottomheight = P_GetFFloorBottomZAt(rover, mobj->x, mobj->y);
if (mobj->eflags & MFE_VERTICALFLIP)
{
@ -3507,14 +3500,8 @@ static void P_SceneryCheckWater(mobj_t *mobj)
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_SWIMMABLE) || rover->flags & FF_BLOCKOTHERS)
continue;
topheight = *rover->topheight;
bottomheight = *rover->bottomheight;
if (*rover->t_slope)
topheight = P_GetZAt(*rover->t_slope, mobj->x, mobj->y);
if (*rover->b_slope)
bottomheight = P_GetZAt(*rover->b_slope, mobj->x, mobj->y);
topheight = P_GetFFloorTopZAt (rover, mobj->x, mobj->y);
bottomheight = P_GetFFloorBottomZAt(rover, mobj->x, mobj->y);
if (topheight <= mobj->z
|| bottomheight > (mobj->z + (mobj->height>>1)))
@ -3559,13 +3546,9 @@ static boolean P_CameraCheckHeat(camera_t *thiscam)
if (!(rover->flags & FF_EXISTS))
continue;
if (halfheight >= (*rover->t_slope ?
P_GetZAt(*rover->t_slope, thiscam->x, thiscam->y) :
*rover->topheight))
if (halfheight >= P_GetFFloorTopZAt(rover, thiscam->x, thiscam->y))
continue;
if (halfheight <= (*rover->b_slope ?
P_GetZAt(*rover->b_slope, thiscam->x, thiscam->y) :
*rover->bottomheight))
if (halfheight <= P_GetFFloorBottomZAt(rover, thiscam->x, thiscam->y))
continue;
if (P_FindSpecialLineFromTag(13, rover->master->frontsector->tag, -1) != -1)
@ -3593,13 +3576,9 @@ static boolean P_CameraCheckWater(camera_t *thiscam)
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_SWIMMABLE) || rover->flags & FF_BLOCKOTHERS)
continue;
if (halfheight >= (*rover->t_slope ?
P_GetZAt(*rover->t_slope, thiscam->x, thiscam->y) :
*rover->topheight))
if (halfheight >= P_GetFFloorTopZAt(rover, thiscam->x, thiscam->y))
continue;
if (halfheight <= (
*rover->b_slope ? P_GetZAt(*rover->b_slope, thiscam->x, thiscam->y) :
*rover->bottomheight))
if (halfheight <= P_GetFFloorBottomZAt(rover, thiscam->x, thiscam->y))
continue;
return true;
@ -3775,13 +3754,114 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled
return false;
}
//
// P_PlayerMobjThinker
//
static void P_PlayerMobjThinker(mobj_t *mobj)
static void P_CheckCrumblingPlatforms(mobj_t *mobj)
{
msecnode_t *node;
if (netgame && mobj->player->spectator)
return;
for (node = mobj->touching_sectorlist; node; node = node->m_sectorlist_next)
{
ffloor_t *rover;
for (rover = node->m_sector->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS))
continue;
if (!(rover->flags & FF_CRUMBLE))
continue;
if (mobj->eflags & MFE_VERTICALFLIP)
{
if (P_GetSpecialBottomZ(mobj, sectors + rover->secnum, node->m_sector) != mobj->z + mobj->height)
continue;
}
else
{
if (P_GetSpecialTopZ(mobj, sectors + rover->secnum, node->m_sector) != mobj->z)
continue;
}
EV_StartCrumble(rover->master->frontsector, rover, (rover->flags & FF_FLOATBOB), mobj->player, rover->alpha, !(rover->flags & FF_NORETURN));
}
}
}
static boolean P_MobjTouchesSectorWithWater(mobj_t *mobj)
{
msecnode_t *node;
for (node = mobj->touching_sectorlist; node; node = node->m_sectorlist_next)
{
ffloor_t *rover;
if (!node->m_sector->ffloors)
continue;
for (rover = node->m_sector->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS))
continue;
if (!(rover->flags & FF_SWIMMABLE))
continue;
return true;
}
}
return false;
}
// Check for floating water platforms and bounce them
static void P_CheckFloatbobPlatforms(mobj_t *mobj)
{
msecnode_t *node;
// Can't land on anything if you're not moving downwards
if (P_MobjFlip(mobj)*mobj->momz >= 0)
return;
if (!P_MobjTouchesSectorWithWater(mobj))
return;
for (node = mobj->touching_sectorlist; node; node = node->m_sectorlist_next)
{
ffloor_t *rover;
if (!node->m_sector->ffloors)
continue;
for (rover = node->m_sector->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS))
continue;
if (!(rover->flags & FF_FLOATBOB))
continue;
if (mobj->eflags & MFE_VERTICALFLIP)
{
if (abs(*rover->bottomheight - (mobj->z + mobj->height)) > abs(mobj->momz))
continue;
}
else
{
if (abs(*rover->topheight - mobj->z) > abs(mobj->momz))
continue;
}
// Initiate a 'bouncy' elevator function which slowly diminishes.
EV_BounceSector(rover->master->frontsector, -mobj->momz, rover->master);
}
}
}
static void P_PlayerMobjThinker(mobj_t *mobj)
{
I_Assert(mobj != NULL);
I_Assert(mobj->player != NULL);
I_Assert(!P_MobjWasRemoved(mobj));
@ -3834,77 +3914,10 @@ static void P_PlayerMobjThinker(mobj_t *mobj)
else
P_TryMove(mobj, mobj->x, mobj->y, true);
if (!(netgame && mobj->player->spectator))
{
// Crumbling platforms
for (node = mobj->touching_sectorlist; node; node = node->m_sectorlist_next)
{
fixed_t topheight, bottomheight;
ffloor_t *rover;
P_CheckCrumblingPlatforms(mobj);
for (rover = node->m_sector->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_CRUMBLE))
continue;
topheight = P_GetSpecialTopZ(mobj, sectors + rover->secnum, node->m_sector);
bottomheight = P_GetSpecialBottomZ(mobj, sectors + rover->secnum, node->m_sector);
if ((topheight == mobj->z && !(mobj->eflags & MFE_VERTICALFLIP))
|| (bottomheight == mobj->z + mobj->height && mobj->eflags & MFE_VERTICALFLIP)) // You nut.
EV_StartCrumble(rover->master->frontsector, rover, (rover->flags & FF_FLOATBOB), mobj->player, rover->alpha, !(rover->flags & FF_NORETURN));
}
}
}
// Check for floating water platforms and bounce them
if (CheckForFloatBob && P_MobjFlip(mobj)*mobj->momz < 0)
{
boolean thereiswater = false;
for (node = mobj->touching_sectorlist; node; node = node->m_sectorlist_next)
{
if (node->m_sector->ffloors)
{
ffloor_t *rover;
// Get water boundaries first
for (rover = node->m_sector->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS))
continue;
if (rover->flags & FF_SWIMMABLE) // Is there water?
{
thereiswater = true;
break;
}
}
}
}
if (thereiswater)
{
for (node = mobj->touching_sectorlist; node; node = node->m_sectorlist_next)
{
if (node->m_sector->ffloors)
{
ffloor_t *rover;
for (rover = node->m_sector->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_FLOATBOB))
continue;
if ((!(mobj->eflags & MFE_VERTICALFLIP) && abs(*rover->topheight-mobj->z) <= abs(mobj->momz)) // The player is landing on the cheese!
|| (mobj->eflags & MFE_VERTICALFLIP && abs(*rover->bottomheight-(mobj->z+mobj->height)) <= abs(mobj->momz)))
{
// Initiate a 'bouncy' elevator function
// which slowly diminishes.
EV_BounceSector(rover->master->frontsector, -mobj->momz, rover->master);
}
}
}
}
} // Ugly ugly billions of braces! Argh!
}
if (CheckForFloatBob)
P_CheckFloatbobPlatforms(mobj);
// always do the gravity bit now, that's simpler
// BUT CheckPosition only if wasn't done before.
@ -3947,9 +3960,7 @@ static void CalculatePrecipFloor(precipmobj_t *mobj)
mobjsecsubsec = mobj->subsector->sector;
else
return;
mobj->floorz = mobjsecsubsec->f_slope ?
P_GetZAt(mobjsecsubsec->f_slope, mobj->x, mobj->y) :
mobjsecsubsec->floorheight;
mobj->floorz = P_GetSectorFloorZAt(mobjsecsubsec, mobj->x, mobj->y);
if (mobjsecsubsec->ffloors)
{
ffloor_t *rover;
@ -3964,11 +3975,7 @@ static void CalculatePrecipFloor(precipmobj_t *mobj)
if (!(rover->flags & FF_BLOCKOTHERS) && !(rover->flags & FF_SWIMMABLE))
continue;
if (*rover->t_slope)
topheight = P_GetZAt(*rover->t_slope, mobj->x, mobj->y);
else
topheight = *rover->topheight;
topheight = P_GetFFloorTopZAt(rover, mobj->x, mobj->y);
if (topheight > mobj->floorz)
mobj->floorz = topheight;
}
@ -9460,7 +9467,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
case MT_BOSSFLYPOINT:
return false;
case MT_NIGHTSCORE:
mobj->color = (UINT8)(leveltime % SKINCOLOR_WHITE);
mobj->color = (UINT16)(leveltime % SKINCOLOR_WHITE);
break;
case MT_JETFUME1:
if (!P_JetFume1Think(mobj))
@ -10495,12 +10502,8 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
// Make sure scale matches destscale immediately when spawned
P_SetScale(mobj, mobj->destscale);
mobj->floorz = mobj->subsector->sector->f_slope ?
P_GetZAt(mobj->subsector->sector->f_slope, x, y) :
mobj->subsector->sector->floorheight;
mobj->ceilingz = mobj->subsector->sector->c_slope ?
P_GetZAt(mobj->subsector->sector->c_slope, x, y) :
mobj->subsector->sector->ceilingheight;
mobj->floorz = P_GetSectorFloorZAt (mobj->subsector->sector, x, y);
mobj->ceilingz = P_GetSectorCeilingZAt(mobj->subsector->sector, x, y);
mobj->floorrover = NULL;
mobj->ceilingrover = NULL;
@ -10671,7 +10674,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
break;
case MT_EGGROBO1:
mobj->movecount = P_RandomKey(13);
mobj->color = SKINCOLOR_RUBY + P_RandomKey(MAXSKINCOLORS - SKINCOLOR_RUBY);
mobj->color = SKINCOLOR_RUBY + P_RandomKey(numskincolors - SKINCOLOR_RUBY);
break;
case MT_HIVEELEMENTAL:
mobj->extravalue1 = 5;
@ -10853,12 +10856,8 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype
// set subsector and/or block links
P_SetPrecipitationThingPosition(mobj);
mobj->floorz = starting_floorz = mobj->subsector->sector->f_slope ?
P_GetZAt(mobj->subsector->sector->f_slope, x, y) :
mobj->subsector->sector->floorheight;
mobj->ceilingz = mobj->subsector->sector->c_slope ?
P_GetZAt(mobj->subsector->sector->c_slope, x, y) :
mobj->subsector->sector->ceilingheight;
mobj->floorz = starting_floorz = P_GetSectorFloorZAt (mobj->subsector->sector, x, y);
mobj->ceilingz = P_GetSectorCeilingZAt(mobj->subsector->sector, x, y);
mobj->floorrover = NULL;
mobj->ceilingrover = NULL;
@ -11389,6 +11388,14 @@ void P_SpawnPlayer(INT32 playernum)
p->realtime = leveltime;
p->followitem = skins[p->skin].followitem;
// Make sure player's stats are reset if they were in dashmode!
if (p->dashmode)
{
p->dashmode = 0;
p->normalspeed = skins[p->skin].normalspeed;
p->jumpfactor = skins[p->skin].jumpfactor;
}
//awayview stuff
p->awayviewmobj = NULL;
p->awayviewtics = 0;
@ -11427,10 +11434,7 @@ void P_AfterPlayerSpawn(INT32 playernum)
player_t *p = &players[playernum];
mobj_t *mobj = p->mo;
if (playernum == consoleplayer)
localangle = mobj->angle;
else if (playernum == secondarydisplayplayer)
localangle2 = mobj->angle;
P_SetPlayerAngle(p, mobj->angle);
p->viewheight = 41*p->height/48;
@ -11447,7 +11451,6 @@ void P_AfterPlayerSpawn(INT32 playernum)
HU_Start();
}
SV_SpawnPlayer(playernum, mobj->x, mobj->y, mobj->angle);
p->drawangle = mobj->angle;
if (camera.chase)
@ -11493,12 +11496,8 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing)
// set Z height
sector = R_PointInSubsector(x, y)->sector;
floor = sector->f_slope ?
P_GetZAt(sector->f_slope, x, y) :
sector->floorheight;
ceiling = sector->c_slope ?
P_GetZAt(sector->c_slope, x, y) :
sector->ceilingheight;
floor = P_GetSectorFloorZAt (sector, x, y);
ceiling = P_GetSectorCeilingZAt(sector, x, y);
ceilingspawn = ceiling - mobjinfo[MT_PLAYER].height;
if (mthing)
@ -11568,12 +11567,8 @@ void P_MovePlayerToStarpost(INT32 playernum)
P_SetThingPosition(mobj);
sector = R_PointInSubsector(mobj->x, mobj->y)->sector;
floor = sector->f_slope ?
P_GetZAt(sector->f_slope, mobj->x, mobj->y) :
sector->floorheight;
ceiling = sector->c_slope ?
P_GetZAt(sector->c_slope, mobj->x, mobj->y) :
sector->ceilingheight;
floor = P_GetSectorFloorZAt (sector, mobj->x, mobj->y);
ceiling = P_GetSectorCeilingZAt(sector, mobj->x, mobj->y);
z = p->starpostz << FRACBITS;
@ -11622,11 +11617,9 @@ fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const fixed_t x, const f
// Establish height.
if (flip)
return (ss->sector->c_slope ? P_GetZAt(ss->sector->c_slope, x, y) : ss->sector->ceilingheight)
- FixedMul(scale, offset + mobjinfo[mobjtype].height);
return P_GetSectorCeilingZAt(ss->sector, x, y) - FixedMul(scale, offset + mobjinfo[mobjtype].height);
else
return (ss->sector->f_slope ? P_GetZAt(ss->sector->f_slope, x, y) : ss->sector->floorheight)
+ FixedMul(scale, offset);
return P_GetSectorFloorZAt(ss->sector, x, y) + FixedMul(scale, offset);
}
fixed_t P_GetMapThingSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* mthing, const fixed_t x, const fixed_t y)
@ -11965,7 +11958,7 @@ static boolean P_SetupEmblem(mapthing_t *mthing, mobj_t *mobj)
{
INT32 j;
emblem_t* emblem = M_GetLevelEmblems(gamemap);
skincolors_t emcolor;
skincolornum_t emcolor;
while (emblem)
{
@ -11988,7 +11981,7 @@ static boolean P_SetupEmblem(mapthing_t *mthing, mobj_t *mobj)
mobj->health = j + 1;
emcolor = M_GetEmblemColor(&emblemlocations[j]); // workaround for compiler complaint about bad function casting
mobj->color = (UINT8)emcolor;
mobj->color = (UINT16)emcolor;
if (emblemlocations[j].collected
|| (emblemlocations[j].type == ET_SKIN && emblemlocations[j].var != players[0].skin))
@ -12633,7 +12626,7 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean
break;
case MT_BALLOON:
if (mthing->angle > 0)
mobj->color = ((mthing->angle - 1) % (MAXSKINCOLORS - 1)) + 1;
mobj->color = ((mthing->angle - 1) % (numskincolors - 1)) + 1;
break;
#define makesoftwarecorona(mo, h) \
corona = P_SpawnMobjFromMobj(mo, 0, 0, h<<FRACBITS, MT_PARTICLE);\
@ -12733,9 +12726,14 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean
mobj->threshold = min(mthing->extrainfo, 7);
break;
case MT_TUBEWAYPOINT:
mobj->health = mthing->angle & 255;
mobj->threshold = mthing->angle >> 8;
{
UINT8 sequence = mthing->angle >> 8;
UINT8 id = mthing->angle & 255;
mobj->health = id;
mobj->threshold = sequence;
P_AddWaypoint(sequence, id, mobj);
break;
}
case MT_IDEYAANCHOR:
mobj->health = mthing->extrainfo;
break;

View file

@ -312,7 +312,7 @@ typedef struct mobj_s
void *skin; // overrides 'sprite' when non-NULL (for player bodies to 'remember' the skin)
// Player and mobj sprites in multiplayer modes are modified
// using an internal color lookup table for re-indexing.
UINT8 color; // This replaces MF_TRANSLATION. Use 0 for default (no translation).
UINT16 color; // This replaces MF_TRANSLATION. Use 0 for default (no translation).
// Interaction info, by BLOCKMAP.
// Links in blocks (if needed).

View file

@ -231,6 +231,9 @@ static void Polyobj_GetInfo(polyobj_t *po, line_t *line)
/*if (line->args[3] & TMPF_DONTCLIPPLANES)
po->flags &= ~POF_CLIPPLANES;*/
if (lines[i].flags & ML_EFFECT6)
po->flags |= POF_SPLAT;
if (line->args[3] & TMPF_EXECUTOR) // Has a linedef executor
po->flags |= POF_LDEXEC;
@ -1032,7 +1035,7 @@ static boolean Polyobj_moveXY(polyobj_t *po, fixed_t x, fixed_t y, boolean check
// The formula for this can be found here:
// http://www.inversereality.org/tutorials/graphics%20programming/2dtransformations.html
// It is, of course, just a vector-matrix multiplication.
static inline void Polyobj_rotatePoint(vertex_t *v, const vertex_t *c, angle_t ang)
static inline void Polyobj_rotatePoint(vertex_t *v, const vector2_t *c, angle_t ang)
{
vertex_t tmp = *v;
@ -1085,7 +1088,7 @@ static void Polyobj_rotateLine(line_t *ld)
}
// Causes objects resting on top of the rotating polyobject to 'ride' with its movement.
static void Polyobj_rotateThings(polyobj_t *po, vertex_t origin, angle_t delta, UINT8 turnthings)
static void Polyobj_rotateThings(polyobj_t *po, vector2_t origin, angle_t delta, UINT8 turnthings)
{
static INT32 pomovecount = 10000;
INT32 x, y;
@ -1149,10 +1152,7 @@ static void Polyobj_rotateThings(polyobj_t *po, vertex_t origin, angle_t delta,
if (turnthings == 2 || (turnthings == 1 && !mo->player)) {
mo->angle += delta;
if (mo->player == &players[consoleplayer])
localangle += delta;
else if (mo->player == &players[secondarydisplayplayer])
localangle2 += delta;
P_SetPlayerAngle(mo->player, (angle_t)(mo->player->angleturn << 16) + delta);
}
}
}
@ -1165,7 +1165,7 @@ static boolean Polyobj_rotate(polyobj_t *po, angle_t delta, UINT8 turnthings, bo
{
size_t i;
angle_t angle;
vertex_t origin;
vector2_t origin;
INT32 hitflags = 0;
// don't move bad polyobjects
@ -1561,17 +1561,39 @@ void T_PolyObjMove(polymove_t *th)
}
}
static void T_MovePolyObj(polyobj_t *po, fixed_t distx, fixed_t disty, fixed_t distz)
{
polyobj_t *child;
INT32 start;
Polyobj_moveXY(po, distx, disty, true);
// TODO: use T_MovePlane
po->lines[0]->backsector->floorheight += distz;
po->lines[0]->backsector->ceilingheight += distz;
// Sal: Remember to check your sectors!
// Monster Iestyn: we only need to bother with the back sector, now that P_CheckSector automatically checks the blockmap
// updating objects in the front one too just added teleporting to ground bugs
P_CheckSector(po->lines[0]->backsector, (boolean)(po->damage));
// Apply action to mirroring polyobjects as well
start = 0;
while ((child = Polyobj_GetChild(po, &start)))
{
if (child->isBad)
continue;
Polyobj_moveXY(child, distx, disty, true);
// TODO: use T_MovePlane
child->lines[0]->backsector->floorheight += distz;
child->lines[0]->backsector->ceilingheight += distz;
P_CheckSector(child->lines[0]->backsector, (boolean)(child->damage));
}
}
void T_PolyObjWaypoint(polywaypoint_t *th)
{
mobj_t *mo2;
mobj_t *target = NULL;
mobj_t *waypoint = NULL;
thinker_t *wp;
fixed_t adjustx, adjusty, adjustz;
fixed_t momx, momy, momz, dist;
INT32 start;
polyobj_t *po = Polyobj_GetForNum(th->polyObjNum);
polyobj_t *oldpo = po;
fixed_t speed = th->speed;
if (!po)
#ifdef RANGECHECK
@ -1585,31 +1607,10 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
#endif
// check for displacement due to override and reattach when possible
if (po->thinker == NULL)
if (!po->thinker)
po->thinker = &th->thinker;
/*
// Find out target first.
// We redo this each tic to make savegame compatibility easier.
for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next)
{
if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)wp;
if (mo2->type != MT_TUBEWAYPOINT)
continue;
if (mo2->threshold == th->sequence && mo2->health == th->pointnum)
{
target = mo2;
break;
}
}
*/
target = th->target;
target = waypoints[th->sequence][th->pointnum];
if (!target)
{
@ -1617,240 +1618,93 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
return;
}
// Compensate for position offset
adjustx = po->centerPt.x + th->diffx;
adjusty = po->centerPt.y + th->diffy;
adjustz = po->lines[0]->backsector->floorheight + (po->lines[0]->backsector->ceilingheight - po->lines[0]->backsector->floorheight)/2 + th->diffz;
dist = P_AproxDistance(P_AproxDistance(target->x - adjustx, target->y - adjusty), target->z - adjustz);
if (dist < 1)
dist = 1;
momx = FixedMul(FixedDiv(target->x - adjustx, dist), (th->speed));
momy = FixedMul(FixedDiv(target->y - adjusty, dist), (th->speed));
momz = FixedMul(FixedDiv(target->z - adjustz, dist), (th->speed));
// Calculate the distance between the polyobject and the waypoint
// 'dist' already equals this.
// Will the polyobject be FURTHER away if the momx/momy/momz is added to
// its current coordinates, or closer? (shift down to fracunits to avoid approximation errors)
if (dist>>FRACBITS <= P_AproxDistance(P_AproxDistance(target->x - adjustx - momx, target->y - adjusty - momy), target->z - adjustz - momz)>>FRACBITS)
// Move along the waypoint sequence until speed for the current tic is exhausted
while (speed > 0)
{
// If further away, set XYZ of polyobject to waypoint location
fixed_t amtx, amty, amtz;
fixed_t diffz;
amtx = (target->x - th->diffx) - po->centerPt.x;
amty = (target->y - th->diffy) - po->centerPt.y;
Polyobj_moveXY(po, amtx, amty, true);
// TODO: use T_MovePlane
amtz = (po->lines[0]->backsector->ceilingheight - po->lines[0]->backsector->floorheight)/2;
diffz = po->lines[0]->backsector->floorheight - (target->z - amtz);
po->lines[0]->backsector->floorheight = target->z - amtz;
po->lines[0]->backsector->ceilingheight = target->z + amtz;
// Sal: Remember to check your sectors!
// Monster Iestyn: we only need to bother with the back sector, now that P_CheckSector automatically checks the blockmap
// updating objects in the front one too just added teleporting to ground bugs
P_CheckSector(po->lines[0]->backsector, (boolean)(po->damage));
// Apply action to mirroring polyobjects as well
start = 0;
while ((po = Polyobj_GetChild(oldpo, &start)))
mobj_t *waypoint = NULL;
fixed_t pox, poy, poz;
fixed_t distx, disty, distz, dist;
// Current position of polyobject
pox = po->centerPt.x;
poy = po->centerPt.y;
poz = (po->lines[0]->backsector->floorheight + po->lines[0]->backsector->ceilingheight)/2;
// Calculate the distance between the polyobject and the waypoint
distx = target->x - pox;
disty = target->y - poy;
distz = target->z - poz;
dist = P_AproxDistance(P_AproxDistance(distx, disty), distz);
if (dist < 1)
dist = 1;
// Will the polyobject overshoot its target?
if (speed < dist)
{
if (po->isBad)
continue;
// No. Move towards waypoint
fixed_t momx, momy, momz;
Polyobj_moveXY(po, amtx, amty, true);
// TODO: use T_MovePlane
po->lines[0]->backsector->floorheight += diffz; // move up/down by same amount as the parent did
po->lines[0]->backsector->ceilingheight += diffz;
// Sal: Remember to check your sectors!
// Monster Iestyn: we only need to bother with the back sector, now that P_CheckSector automatically checks the blockmap
// updating objects in the front one too just added teleporting to ground bugs
P_CheckSector(po->lines[0]->backsector, (boolean)(po->damage));
}
po = oldpo;
if (!th->stophere)
{
CONS_Debug(DBG_POLYOBJ, "Looking for next waypoint...\n");
// Find next waypoint
for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next)
{
if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)wp;
if (mo2->type != MT_TUBEWAYPOINT)
continue;
if (mo2->threshold != th->sequence)
continue;
if (th->direction == -1)
{
if (mo2->health == target->health - 1)
{
waypoint = mo2;
break;
}
}
else
{
if (mo2->health == target->health + 1)
{
waypoint = mo2;
break;
}
}
}
if (!waypoint && th->wrap) // If specified, wrap waypoints
{
if (!th->continuous)
{
th->wrap = 0;
th->stophere = true;
}
for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next)
{
if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)wp;
if (mo2->type != MT_TUBEWAYPOINT)
continue;
if (mo2->threshold != th->sequence)
continue;
if (th->direction == -1)
{
if (waypoint == NULL)
waypoint = mo2;
else if (mo2->health > waypoint->health)
waypoint = mo2;
}
else
{
if (mo2->health == 0)
{
waypoint = mo2;
break;
}
}
}
}
else if (!waypoint && th->comeback) // Come back to the start
{
th->direction = -th->direction;
if (!th->continuous)
th->comeback = false;
for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next)
{
if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)wp;
if (mo2->type != MT_TUBEWAYPOINT)
continue;
if (mo2->threshold != th->sequence)
continue;
if (th->direction == -1)
{
if (mo2->health == target->health - 1)
{
waypoint = mo2;
break;
}
}
else
{
if (mo2->health == target->health + 1)
{
waypoint = mo2;
break;
}
}
}
}
}
if (waypoint)
{
CONS_Debug(DBG_POLYOBJ, "Found waypoint (sequence %d, number %d).\n", waypoint->threshold, waypoint->health);
target = waypoint;
th->pointnum = target->health;
// Set the mobj as your target! -- Monster Iestyn 27/12/19
P_SetTarget(&th->target, target);
// calculate MOMX/MOMY/MOMZ for next waypoint
// change slope
dist = P_AproxDistance(P_AproxDistance(target->x - adjustx, target->y - adjusty), target->z - adjustz);
if (dist < 1)
dist = 1;
momx = FixedMul(FixedDiv(target->x - adjustx, dist), (th->speed));
momy = FixedMul(FixedDiv(target->y - adjusty, dist), (th->speed));
momz = FixedMul(FixedDiv(target->z - adjustz, dist), (th->speed));
momx = FixedMul(FixedDiv(target->x - pox, dist), speed);
momy = FixedMul(FixedDiv(target->y - poy, dist), speed);
momz = FixedMul(FixedDiv(target->z - poz, dist), speed);
T_MovePolyObj(po, momx, momy, momz);
return;
}
else
{
momx = momy = momz = 0;
// Yes. Teleport to waypoint and look for the next one
T_MovePolyObj(po, distx, disty, distz);
if (!th->stophere)
CONS_Debug(DBG_POLYOBJ, "Next waypoint not found!\n");
{
CONS_Debug(DBG_POLYOBJ, "Looking for next waypoint...\n");
waypoint = (th->direction == -1) ? P_GetPreviousWaypoint(target, false) : P_GetNextWaypoint(target, false);
if (po->thinker == &th->thinker)
po->thinker = NULL;
if (!waypoint && th->returnbehavior == PWR_WRAP) // If specified, wrap waypoints
{
if (!th->continuous)
{
th->returnbehavior = PWR_STOP;
th->stophere = true;
}
P_RemoveThinker(&th->thinker);
return;
waypoint = (th->direction == -1) ? P_GetLastWaypoint(th->sequence) : P_GetFirstWaypoint(th->sequence);
}
else if (!waypoint && th->returnbehavior == PWR_COMEBACK) // Come back to the start
{
th->direction = -th->direction;
if (!th->continuous)
th->returnbehavior = PWR_STOP;
waypoint = (th->direction == -1) ? P_GetPreviousWaypoint(target, false) : P_GetNextWaypoint(target, false);
}
}
if (waypoint)
{
CONS_Debug(DBG_POLYOBJ, "Found waypoint (sequence %d, number %d).\n", waypoint->threshold, waypoint->health);
target = waypoint;
th->pointnum = target->health;
// Calculate remaining speed
speed -= dist;
}
else
{
if (!th->stophere)
CONS_Debug(DBG_POLYOBJ, "Next waypoint not found!\n");
if (po->thinker == &th->thinker)
po->thinker = NULL;
P_RemoveThinker(&th->thinker);
return;
}
}
}
else
{
// momx/momy/momz already equals the right speed
}
// Move the polyobject
Polyobj_moveXY(po, momx, momy, true);
// TODO: use T_MovePlane
po->lines[0]->backsector->floorheight += momz;
po->lines[0]->backsector->ceilingheight += momz;
// Sal: Remember to check your sectors!
// Monster Iestyn: we only need to bother with the back sector, now that P_CheckSector automatically checks the blockmap
// updating objects in the front one too just added teleporting to ground bugs
P_CheckSector(po->lines[0]->backsector, (boolean)(po->damage));
// Apply action to mirroring polyobjects as well
start = 0;
while ((po = Polyobj_GetChild(oldpo, &start)))
{
if (po->isBad)
continue;
Polyobj_moveXY(po, momx, momy, true);
// TODO: use T_MovePlane
po->lines[0]->backsector->floorheight += momz;
po->lines[0]->backsector->ceilingheight += momz;
// Sal: Remember to check your sectors!
// Monster Iestyn: we only need to bother with the back sector, now that P_CheckSector automatically checks the blockmap
// updating objects in the front one too just added teleporting to ground bugs
P_CheckSector(po->lines[0]->backsector, (boolean)(po->damage));
}
}
void T_PolyDoorSlide(polyslidedoor_t *th)
@ -2268,11 +2122,7 @@ boolean EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
{
polyobj_t *po;
polywaypoint_t *th;
mobj_t *mo2;
mobj_t *first = NULL;
mobj_t *last = NULL;
mobj_t *target = NULL;
thinker_t *wp;
if (!(po = Polyobj_GetForNum(pwdata->polyObjNum)))
{
@ -2296,56 +2146,16 @@ boolean EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
// set fields
th->polyObjNum = pwdata->polyObjNum;
th->speed = pwdata->speed;
th->sequence = pwdata->sequence; // Used to specify sequence #
if (pwdata->reverse)
th->direction = -1;
else
th->direction = 1;
th->sequence = pwdata->sequence;
th->direction = (pwdata->flags & PWF_REVERSE) ? -1 : 1;
th->comeback = pwdata->comeback;
th->continuous = pwdata->continuous;
th->wrap = pwdata->wrap;
th->returnbehavior = pwdata->returnbehavior;
if (pwdata->flags & PWF_LOOP)
th->continuous = true;
th->stophere = false;
// Find the first waypoint we need to use
for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next)
{
if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)wp;
if (mo2->type != MT_TUBEWAYPOINT)
continue;
if (mo2->threshold != th->sequence)
continue;
if (th->direction == -1) // highest waypoint #
{
if (mo2->health == 0)
last = mo2;
else
{
if (first == NULL)
first = mo2;
else if (mo2->health > first->health)
first = mo2;
}
}
else // waypoint 0
{
if (mo2->health == 0)
first = mo2;
else
{
if (last == NULL)
last = mo2;
else if (mo2->health > last->health)
last = mo2;
}
}
}
first = (th->direction == -1) ? P_GetLastWaypoint(th->sequence) : P_GetFirstWaypoint(th->sequence);
if (!first)
{
@ -2355,77 +2165,16 @@ boolean EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
return false;
}
// Hotfix to not crash on single-waypoint sequences -Red
if (!last)
last = first;
// Set diffx, diffy, diffz
// Put these at 0 for now...might not be needed after all.
th->diffx = 0;//first->x - po->centerPt.x;
th->diffy = 0;//first->y - po->centerPt.y;
th->diffz = 0;//first->z - (po->lines[0]->backsector->floorheight + (po->lines[0]->backsector->ceilingheight - po->lines[0]->backsector->floorheight)/2);
if (last->x == po->centerPt.x
&& last->y == po->centerPt.y
&& last->z == (po->lines[0]->backsector->floorheight + (po->lines[0]->backsector->ceilingheight - po->lines[0]->backsector->floorheight)/2))
// Sanity check: If all waypoints are in the same location,
// don't allow the movement to be continuous so we don't get stuck in an infinite loop.
if (th->continuous && P_IsDegeneratedWaypointSequence(th->sequence))
{
// Already at the destination point...
if (!th->wrap)
{
po->thinker = NULL;
P_RemoveThinker(&th->thinker);
}
CONS_Debug(DBG_POLYOBJ, "EV_DoPolyObjWaypoint: All waypoints are in the same location!\n");
th->continuous = false;
}
// Find the actual target movement waypoint
target = first;
/*for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next)
{
if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
th->pointnum = first->health;
mo2 = (mobj_t *)wp;
if (mo2->type != MT_TUBEWAYPOINT)
continue;
if (mo2->threshold != th->sequence)
continue;
if (th->direction == -1) // highest waypoint #
{
if (mo2->health == first->health - 1)
{
target = mo2;
break;
}
}
else // waypoint 0
{
if (mo2->health == first->health + 1)
{
target = mo2;
break;
}
}
}*/
if (!target)
{
CONS_Debug(DBG_POLYOBJ, "EV_DoPolyObjWaypoint: Missing target waypoint!\n");
po->thinker = NULL;
P_RemoveThinker(&th->thinker);
return false;
}
// Set pointnum
th->pointnum = target->health;
th->target = NULL; // set to NULL first so the below doesn't go wrong
// Set the mobj as your target! -- Monster Iestyn 27/12/19
P_SetTarget(&th->target, target);
// We don't deal with the mirror crap here, we'll
// handle that in the T_Thinker function.
return true;
}

View file

@ -36,7 +36,7 @@ typedef enum
POF_SOLID = 0x3, ///< Clips things.
POF_TESTHEIGHT = 0x4, ///< Test line collision with heights
POF_RENDERSIDES = 0x8, ///< Renders the sides.
POF_RENDERTOP = 0x10, ///< Renders the top..
POF_RENDERTOP = 0x10, ///< Renders the top.
POF_RENDERBOTTOM = 0x20, ///< Renders the bottom.
POF_RENDERPLANES = 0x30, ///< Renders top and bottom.
POF_RENDERALL = 0x38, ///< Renders everything.
@ -47,6 +47,7 @@ typedef enum
POF_LDEXEC = 0x400, ///< This PO triggers a linedef executor.
POF_ONESIDE = 0x800, ///< Only use the first side of the linedef.
POF_NOSPECIALS = 0x1000, ///< Don't apply sector specials.
POF_SPLAT = 0x2000, ///< Use splat flat renderer (treat cyan pixels as invisible).
} polyobjflags_e;
typedef enum
@ -150,26 +151,26 @@ typedef struct polymove_s
UINT32 angle; // angle along which to move
} polymove_t;
// PolyObject waypoint movement return behavior
typedef enum
{
PWR_STOP, // Stop after reaching last waypoint
PWR_WRAP, // Wrap back to first waypoint
PWR_COMEBACK, // Repeat sequence in reverse
} polywaypointreturn_e;
typedef struct polywaypoint_s
{
thinker_t thinker; // must be first
INT32 polyObjNum; // numeric id of polyobject
INT32 speed; // resultant velocity
INT32 sequence; // waypoint sequence #
INT32 pointnum; // waypoint #
INT32 direction; // 1 for normal, -1 for backwards
UINT8 comeback; // reverses and comes back when the end is reached
UINT8 wrap; // Wrap around waypoints
UINT8 continuous; // continuously move - used with COMEBACK or WRAP
UINT8 stophere; // Will stop after it reaches the next waypoint
// Difference between location of PO and location of waypoint (offset)
fixed_t diffx;
fixed_t diffy;
fixed_t diffz;
mobj_t *target; // next waypoint mobj
INT32 polyObjNum; // numeric id of polyobject
INT32 speed; // resultant velocity
INT32 sequence; // waypoint sequence #
INT32 pointnum; // waypoint #
INT32 direction; // 1 for normal, -1 for backwards
UINT8 returnbehavior; // behavior after reaching the last waypoint
UINT8 continuous; // continuously move - used with PWR_WRAP or PWR_COMEBACK
UINT8 stophere; // Will stop after it reaches the next waypoint
} polywaypoint_t;
typedef struct polyslidedoor_s
@ -264,15 +265,19 @@ typedef struct polymovedata_s
UINT8 overRide; // if true, will override any action on the object
} polymovedata_t;
typedef enum
{
PWF_REVERSE = 1, // Move through waypoints in reverse order
PWF_LOOP = 1<<1, // Loop movement (used with PWR_WRAP or PWR_COMEBACK)
} polywaypointflags_e;
typedef struct polywaypointdata_s
{
INT32 polyObjNum; // numeric id of polyobject to affect
INT32 sequence; // waypoint sequence #
fixed_t speed; // linear speed
UINT8 reverse; // if true, will go in reverse waypoint order
UINT8 comeback; // reverses and comes back when the end is reached
UINT8 wrap; // Wrap around waypoints
UINT8 continuous; // continuously move - used with COMEBACK or WRAP
INT32 polyObjNum; // numeric id of polyobject to affect
INT32 sequence; // waypoint sequence #
fixed_t speed; // linear speed
UINT8 returnbehavior; // behavior after reaching the last waypoint
UINT8 flags; // PWF_ flags
} polywaypointdata_t;
// polyobject door types

View file

@ -103,6 +103,8 @@ static void P_NetArchivePlayers(void)
// no longer send ticcmds, player name, skin, or color
WRITEINT16(save_p, players[i].angleturn);
WRITEINT16(save_p, players[i].oldrelangleturn);
WRITEANGLE(save_p, players[i].aiming);
WRITEANGLE(save_p, players[i].drawangle);
WRITEANGLE(save_p, players[i].viewrollangle);
@ -311,6 +313,8 @@ static void P_NetUnArchivePlayers(void)
// sending player names, skin and color should not be necessary at all!
// (that data is handled in the server config now)
players[i].angleturn = READINT16(save_p);
players[i].oldrelangleturn = READINT16(save_p);
players[i].aiming = READANGLE(save_p);
players[i].drawangle = READANGLE(save_p);
players[i].viewrollangle = READANGLE(save_p);
@ -717,6 +721,34 @@ static void P_NetUnArchiveColormaps(void)
net_colormaps = NULL;
}
static void P_NetArchiveWaypoints(void)
{
INT32 i, j;
for (i = 0; i < NUMWAYPOINTSEQUENCES; i++)
{
WRITEUINT16(save_p, numwaypoints[i]);
for (j = 0; j < numwaypoints[i]; j++)
WRITEUINT32(save_p, waypoints[i][j] ? waypoints[i][j]->mobjnum : 0);
}
}
static void P_NetUnArchiveWaypoints(void)
{
INT32 i, j;
UINT32 mobjnum;
for (i = 0; i < NUMWAYPOINTSEQUENCES; i++)
{
numwaypoints[i] = READUINT16(save_p);
for (j = 0; j < numwaypoints[i]; j++)
{
mobjnum = READUINT32(save_p);
waypoints[i][j] = (mobjnum == 0) ? NULL : P_FindNewPosition(mobjnum);
}
}
}
///
/// World Archiving
///
@ -1692,7 +1724,7 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
if (diff2 & MD2_SKIN)
WRITEUINT8(save_p, (UINT8)((skin_t *)mobj->skin - skins));
if (diff2 & MD2_COLOR)
WRITEUINT8(save_p, mobj->color);
WRITEUINT16(save_p, mobj->color);
if (diff2 & MD2_EXTVAL1)
WRITEINT32(save_p, mobj->extravalue1);
if (diff2 & MD2_EXTVAL2)
@ -1987,8 +2019,7 @@ static void SaveLaserThinker(const thinker_t *th, const UINT8 type)
{
const laserthink_t *ht = (const void *)th;
WRITEUINT8(save_p, type);
WRITEUINT32(save_p, SaveSector(ht->sector));
WRITEUINT32(save_p, SaveSector(ht->sec));
WRITEINT16(save_p, ht->tag);
WRITEUINT32(save_p, SaveLine(ht->sourceline));
WRITEUINT8(save_p, ht->nobosses);
}
@ -2095,6 +2126,7 @@ static inline void SavePolyrotatetThinker(const thinker_t *th, const UINT8 type)
WRITEINT32(save_p, ht->polyObjNum);
WRITEINT32(save_p, ht->speed);
WRITEINT32(save_p, ht->distance);
WRITEUINT8(save_p, ht->turnobjs);
}
static void SavePolymoveThinker(const thinker_t *th, const UINT8 type)
@ -2118,14 +2150,9 @@ static void SavePolywaypointThinker(const thinker_t *th, UINT8 type)
WRITEINT32(save_p, ht->sequence);
WRITEINT32(save_p, ht->pointnum);
WRITEINT32(save_p, ht->direction);
WRITEUINT8(save_p, ht->comeback);
WRITEUINT8(save_p, ht->wrap);
WRITEUINT8(save_p, ht->returnbehavior);
WRITEUINT8(save_p, ht->continuous);
WRITEUINT8(save_p, ht->stophere);
WRITEFIXED(save_p, ht->diffx);
WRITEFIXED(save_p, ht->diffy);
WRITEFIXED(save_p, ht->diffz);
WRITEUINT32(save_p, SaveMobjnum(ht->target));
}
static void SavePolyslidedoorThinker(const thinker_t *th, const UINT8 type)
@ -2656,11 +2683,6 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
i = READUINT8(save_p);
mobj->player = &players[i];
mobj->player->mo = mobj;
// added for angle prediction
if (consoleplayer == i)
localangle = mobj->angle;
if (secondarydisplayplayer == i)
localangle2 = mobj->angle;
}
if (diff & MD_MOVEDIR)
mobj->movedir = READANGLE(save_p);
@ -2709,7 +2731,7 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
if (diff2 & MD2_SKIN)
mobj->skin = &skins[READUINT8(save_p)];
if (diff2 & MD2_COLOR)
mobj->color = READUINT8(save_p);
mobj->color = READUINT16(save_p);
if (diff2 & MD2_EXTVAL1)
mobj->extravalue1 = READINT32(save_p);
if (diff2 & MD2_EXTVAL2)
@ -3098,16 +3120,10 @@ static thinker_t* LoadPusherThinker(actionf_p1 thinker)
static inline thinker_t* LoadLaserThinker(actionf_p1 thinker)
{
laserthink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ffloor_t *rover = NULL;
ht->thinker.function.acp1 = thinker;
ht->sector = LoadSector(READUINT32(save_p));
ht->sec = LoadSector(READUINT32(save_p));
ht->tag = READINT16(save_p);
ht->sourceline = LoadLine(READUINT32(save_p));
ht->nobosses = READUINT8(save_p);
for (rover = ht->sector->ffloors; rover; rover = rover->next)
if (rover->secnum == (size_t)(ht->sec - sectors)
&& rover->master == ht->sourceline)
ht->ffloor = rover;
return &ht->thinker;
}
@ -3242,6 +3258,7 @@ static inline thinker_t* LoadPolyrotatetThinker(actionf_p1 thinker)
ht->polyObjNum = READINT32(save_p);
ht->speed = READINT32(save_p);
ht->distance = READINT32(save_p);
ht->turnobjs = READUINT8(save_p);
return &ht->thinker;
}
@ -3267,14 +3284,9 @@ static inline thinker_t* LoadPolywaypointThinker(actionf_p1 thinker)
ht->sequence = READINT32(save_p);
ht->pointnum = READINT32(save_p);
ht->direction = READINT32(save_p);
ht->comeback = READUINT8(save_p);
ht->wrap = READUINT8(save_p);
ht->returnbehavior = READUINT8(save_p);
ht->continuous = READUINT8(save_p);
ht->stophere = READUINT8(save_p);
ht->diffx = READFIXED(save_p);
ht->diffy = READFIXED(save_p);
ht->diffz = READFIXED(save_p);
ht->target = LoadMobj(READUINT32(save_p));
return &ht->thinker;
}
@ -3521,7 +3533,6 @@ static void P_NetUnArchiveThinkers(void)
case tc_polywaypoint:
th = LoadPolywaypointThinker((actionf_p1)T_PolyObjWaypoint);
restoreNum = true;
break;
case tc_polyslidedoor:
@ -3581,7 +3592,6 @@ static void P_NetUnArchiveThinkers(void)
if (restoreNum)
{
executor_t *delay = NULL;
polywaypoint_t *polywp = NULL;
UINT32 mobjnum;
for (currentthinker = thlist[THINK_MAIN].next; currentthinker != &thlist[THINK_MAIN]; currentthinker = currentthinker->next)
{
@ -3592,15 +3602,6 @@ static void P_NetUnArchiveThinkers(void)
continue;
delay->caller = P_FindNewPosition(mobjnum);
}
for (currentthinker = thlist[THINK_POLYOBJ].next; currentthinker != &thlist[THINK_POLYOBJ]; currentthinker = currentthinker->next)
{
if (currentthinker->function.acp1 != (actionf_p1)T_PolyObjWaypoint)
continue;
polywp = (void *)currentthinker;
if (!(mobjnum = (UINT32)(size_t)polywp->target))
continue;
polywp->target = P_FindNewPosition(mobjnum);
}
}
}
@ -4173,6 +4174,7 @@ void P_SaveNetGame(void)
P_NetArchiveThinkers();
P_NetArchiveSpecials();
P_NetArchiveColormaps();
P_NetArchiveWaypoints();
}
LUA_Archive();
@ -4211,6 +4213,7 @@ boolean P_LoadNetGame(void)
P_NetUnArchiveThinkers();
P_NetUnArchiveSpecials();
P_NetUnArchiveColormaps();
P_NetUnArchiveWaypoints();
P_RelinkPointers();
P_FinishMobjs();
}

View file

@ -145,6 +145,133 @@ mapthing_t *playerstarts[MAXPLAYERS];
mapthing_t *bluectfstarts[MAXPLAYERS];
mapthing_t *redctfstarts[MAXPLAYERS];
// Maintain waypoints
mobj_t *waypoints[NUMWAYPOINTSEQUENCES][WAYPOINTSEQUENCESIZE];
UINT16 numwaypoints[NUMWAYPOINTSEQUENCES];
void P_AddWaypoint(UINT8 sequence, UINT8 id, mobj_t *waypoint)
{
waypoints[sequence][id] = waypoint;
if (id >= numwaypoints[sequence])
numwaypoints[sequence] = id + 1;
}
static void P_ResetWaypoints(void)
{
UINT16 sequence, id;
for (sequence = 0; sequence < NUMWAYPOINTSEQUENCES; sequence++)
{
for (id = 0; id < numwaypoints[sequence]; id++)
waypoints[sequence][id] = NULL;
numwaypoints[sequence] = 0;
}
}
mobj_t *P_GetFirstWaypoint(UINT8 sequence)
{
return waypoints[sequence][0];
}
mobj_t *P_GetLastWaypoint(UINT8 sequence)
{
return waypoints[sequence][numwaypoints[sequence] - 1];
}
mobj_t *P_GetPreviousWaypoint(mobj_t *current, boolean wrap)
{
UINT8 sequence = current->threshold;
UINT8 id = current->health;
if (id == 0)
{
if (!wrap)
return NULL;
id = numwaypoints[sequence] - 1;
}
else
id--;
return waypoints[sequence][id];
}
mobj_t *P_GetNextWaypoint(mobj_t *current, boolean wrap)
{
UINT8 sequence = current->threshold;
UINT8 id = current->health;
if (id == numwaypoints[sequence] - 1)
{
if (!wrap)
return NULL;
id = 0;
}
else
id++;
return waypoints[sequence][id];
}
mobj_t *P_GetClosestWaypoint(UINT8 sequence, mobj_t *mo)
{
UINT8 wp;
mobj_t *mo2, *result = NULL;
fixed_t bestdist = 0;
fixed_t curdist;
for (wp = 0; wp < numwaypoints[sequence]; wp++)
{
mo2 = waypoints[sequence][wp];
if (!mo2)
continue;
curdist = P_AproxDistance(P_AproxDistance(mo->x - mo2->x, mo->y - mo2->y), mo->z - mo2->z);
if (result && curdist > bestdist)
continue;
result = mo2;
bestdist = curdist;
}
return result;
}
// Return true if all waypoints are in the same location
boolean P_IsDegeneratedWaypointSequence(UINT8 sequence)
{
mobj_t *first, *waypoint;
UINT8 wp;
if (numwaypoints[sequence] <= 1)
return true;
first = waypoints[sequence][0];
for (wp = 1; wp < numwaypoints[sequence]; wp++)
{
waypoint = waypoints[sequence][wp];
if (!waypoint)
continue;
if (waypoint->x != first->x)
return false;
if (waypoint->y != first->y)
return false;
if (waypoint->z != first->z)
return false;
}
return true;
}
/** Logs an error about a map being corrupt, then terminate.
* This allows reporting highly technical errors for usefulness, without
* confusing a novice map designer who simply needs to run ZenNode.
@ -3986,6 +4113,8 @@ boolean P_LoadLevel(boolean fromnetsave)
P_ResetSpawnpoints();
P_ResetWaypoints();
P_MapStart();
if (!P_LoadMapFromFile())

View file

@ -259,10 +259,10 @@ static boolean P_CrossSubsector(size_t num, register los_t *los)
fracx = los->strace.x + FixedMul(los->strace.dx, frac);
fracy = los->strace.y + FixedMul(los->strace.dy, frac);
// calculate sector heights
frontf = (front->f_slope) ? P_GetZAt(front->f_slope, fracx, fracy) : front->floorheight;
frontc = (front->c_slope) ? P_GetZAt(front->c_slope, fracx, fracy) : front->ceilingheight;
backf = (back->f_slope) ? P_GetZAt(back->f_slope, fracx, fracy) : back->floorheight;
backc = (back->c_slope) ? P_GetZAt(back->c_slope, fracx, fracy) : back->ceilingheight;
frontf = P_GetSectorFloorZAt (front, fracx, fracy);
frontc = P_GetSectorCeilingZAt(front, fracx, fracy);
backf = P_GetSectorFloorZAt (back , fracx, fracy);
backc = P_GetSectorCeilingZAt(back , fracx, fracy);
// crosses a two sided line
// no wall to block sight with?
if (frontf == backf && frontc == backc
@ -312,10 +312,10 @@ static boolean P_CrossSubsector(size_t num, register los_t *los)
continue;
}
topz = (*rover->t_slope) ? P_GetZAt(*rover->t_slope, fracx, fracy) : *rover->topheight;
bottomz = (*rover->b_slope) ? P_GetZAt(*rover->b_slope, fracx, fracy) : *rover->bottomheight;
topslope = FixedDiv(topz - los->sightzstart , frac);
bottomslope = FixedDiv(bottomz - los->sightzstart , frac);
topz = P_GetFFloorTopZAt (rover, fracx, fracy);
bottomz = P_GetFFloorBottomZAt(rover, fracx, fracy);
topslope = FixedDiv( topz - los->sightzstart, frac);
bottomslope = FixedDiv(bottomz - los->sightzstart, frac);
if (topslope >= los->topslope && bottomslope <= los->bottomslope)
return false; // view completely blocked
}
@ -328,10 +328,10 @@ static boolean P_CrossSubsector(size_t num, register los_t *los)
continue;
}
topz = (*rover->t_slope) ? P_GetZAt(*rover->t_slope, fracx, fracy) : *rover->topheight;
bottomz = (*rover->b_slope) ? P_GetZAt(*rover->b_slope, fracx, fracy) : *rover->bottomheight;
topslope = FixedDiv(topz - los->sightzstart , frac);
bottomslope = FixedDiv(bottomz - los->sightzstart , frac);
topz = P_GetFFloorTopZAt (rover, fracx, fracy);
bottomz = P_GetFFloorBottomZAt(rover, fracx, fracy);
topslope = FixedDiv( topz - los->sightzstart, frac);
bottomslope = FixedDiv(bottomz - los->sightzstart, frac);
if (topslope >= los->topslope && bottomslope <= los->bottomslope)
return false; // view completely blocked
}
@ -457,21 +457,10 @@ boolean P_CheckSight(mobj_t *t1, mobj_t *t2)
continue;
}
if (*rover->t_slope)
{
topz1 = P_GetZAt(*rover->t_slope, t1->x, t1->y);
topz2 = P_GetZAt(*rover->t_slope, t2->x, t2->y);
}
else
topz1 = topz2 = *rover->topheight;
if (*rover->b_slope)
{
bottomz1 = P_GetZAt(*rover->b_slope, t1->x, t1->y);
bottomz2 = P_GetZAt(*rover->b_slope, t2->x, t2->y);
}
else
bottomz1 = bottomz2 = *rover->bottomheight;
topz1 = P_GetFFloorTopZAt (rover, t1->x, t1->y);
topz2 = P_GetFFloorTopZAt (rover, t2->x, t2->y);
bottomz1 = P_GetFFloorBottomZAt(rover, t1->x, t1->y);
bottomz2 = P_GetFFloorBottomZAt(rover, t2->x, t2->y);
// Check for blocking floors here.
if ((los.sightzstart < bottomz1 && t2->z >= topz2)

View file

@ -680,17 +680,49 @@ void P_SpawnSlopes(const boolean fromsave) {
// Various utilities related to slopes
//
//
// P_GetZAt
//
// Returns the height of the sloped plane at (x, y) as a fixed_t
//
fixed_t P_GetZAt(pslope_t *slope, fixed_t x, fixed_t y)
fixed_t P_GetSlopeZAt(const pslope_t *slope, fixed_t x, fixed_t y)
{
fixed_t dist = FixedMul(x - slope->o.x, slope->d.x) +
FixedMul(y - slope->o.y, slope->d.y);
fixed_t dist = FixedMul(x - slope->o.x, slope->d.x) +
FixedMul(y - slope->o.y, slope->d.y);
return slope->o.z + FixedMul(dist, slope->zdelta);
return slope->o.z + FixedMul(dist, slope->zdelta);
}
// Like P_GetSlopeZAt but falls back to z if slope is NULL
fixed_t P_GetZAt(const pslope_t *slope, fixed_t x, fixed_t y, fixed_t z)
{
return slope ? P_GetSlopeZAt(slope, x, y) : z;
}
// Returns the height of the sector floor at (x, y)
fixed_t P_GetSectorFloorZAt(const sector_t *sector, fixed_t x, fixed_t y)
{
return sector->f_slope ? P_GetSlopeZAt(sector->f_slope, x, y) : sector->floorheight;
}
// Returns the height of the sector ceiling at (x, y)
fixed_t P_GetSectorCeilingZAt(const sector_t *sector, fixed_t x, fixed_t y)
{
return sector->c_slope ? P_GetSlopeZAt(sector->c_slope, x, y) : sector->ceilingheight;
}
// Returns the height of the FOF top at (x, y)
fixed_t P_GetFFloorTopZAt(const ffloor_t *ffloor, fixed_t x, fixed_t y)
{
return *ffloor->t_slope ? P_GetSlopeZAt(*ffloor->t_slope, x, y) : *ffloor->topheight;
}
// Returns the height of the FOF bottom at (x, y)
fixed_t P_GetFFloorBottomZAt(const ffloor_t *ffloor, fixed_t x, fixed_t y)
{
return *ffloor->b_slope ? P_GetSlopeZAt(*ffloor->b_slope, x, y) : *ffloor->bottomheight;
}
// Returns the height of the light list at (x, y)
fixed_t P_GetLightZAt(const lightlist_t *light, fixed_t x, fixed_t y)
{
return light->slope ? P_GetSlopeZAt(light->slope, x, y) : light->height;
}

View file

@ -62,7 +62,21 @@ void P_CopySectorSlope(line_t *line);
pslope_t *P_SlopeById(UINT16 id);
// Returns the height of the sloped plane at (x, y) as a fixed_t
fixed_t P_GetZAt(pslope_t *slope, fixed_t x, fixed_t y);
fixed_t P_GetSlopeZAt(const pslope_t *slope, fixed_t x, fixed_t y);
// Like P_GetSlopeZAt but falls back to z if slope is NULL
fixed_t P_GetZAt(const pslope_t *slope, fixed_t x, fixed_t y, fixed_t z);
// Returns the height of the sector at (x, y)
fixed_t P_GetSectorFloorZAt (const sector_t *sector, fixed_t x, fixed_t y);
fixed_t P_GetSectorCeilingZAt(const sector_t *sector, fixed_t x, fixed_t y);
// Returns the height of the FOF at (x, y)
fixed_t P_GetFFloorTopZAt (const ffloor_t *ffloor, fixed_t x, fixed_t y);
fixed_t P_GetFFloorBottomZAt(const ffloor_t *ffloor, fixed_t x, fixed_t y);
// Returns the height of the light list at (x, y)
fixed_t P_GetLightZAt(const lightlist_t *light, fixed_t x, fixed_t y);
// Lots of physics-based bullshit
void P_QuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope);

View file

@ -1276,10 +1276,21 @@ static boolean PolyWaypoint(line_t *line)
pwd.polyObjNum = line->tag;
pwd.speed = sides[line->sidenum[0]].textureoffset / 8;
pwd.sequence = sides[line->sidenum[0]].rowoffset >> FRACBITS; // Sequence #
pwd.reverse = (line->flags & ML_EFFECT1) == ML_EFFECT1; // Reverse?
pwd.comeback = (line->flags & ML_EFFECT2) == ML_EFFECT2; // Return when reaching end?
pwd.wrap = (line->flags & ML_EFFECT3) == ML_EFFECT3; // Wrap around waypoints
pwd.continuous = (line->flags & ML_EFFECT4) == ML_EFFECT4; // Continuously move - used with COMEBACK or WRAP
// Behavior after reaching the last waypoint?
if (line->flags & ML_EFFECT3)
pwd.returnbehavior = PWR_WRAP; // Wrap back to first waypoint
else if (line->flags & ML_EFFECT2)
pwd.returnbehavior = PWR_COMEBACK; // Go through sequence in reverse
else
pwd.returnbehavior = PWR_STOP; // Stop
// Flags
pwd.flags = 0;
if (line->flags & ML_EFFECT1)
pwd.flags |= PWF_REVERSE;
if (line->flags & ML_EFFECT4)
pwd.flags |= PWF_LOOP;
return EV_DoPolyObjWaypoint(&pwd);
}
@ -3962,7 +3973,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
if (mo)
{
if (color < 0 || color >= MAXTRANSLATIONS)
if (color < 0 || color >= numskincolors)
return;
var1 = 0;
@ -4610,12 +4621,7 @@ DoneSection2:
player->mo->angle = player->drawangle = lineangle;
if (!demoplayback || P_ControlStyle(player) == CS_LMAOGALOG)
{
if (player == &players[consoleplayer])
localangle = player->mo->angle;
else if (player == &players[secondarydisplayplayer])
localangle2 = player->mo->angle;
}
P_SetPlayerAngle(player, player->mo->angle);
if (!(lines[i].flags & ML_EFFECT4))
{
@ -4818,9 +4824,7 @@ DoneSection2:
INT32 sequence;
fixed_t speed;
INT32 lineindex;
thinker_t *th;
mobj_t *waypoint = NULL;
mobj_t *mo2;
angle_t an;
if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT && player->powers[pw_carry] == CR_ZOOMTUBE)
@ -4845,25 +4849,7 @@ DoneSection2:
break;
}
// scan the thinkers
// to find the first waypoint
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th;
if (mo2->type != MT_TUBEWAYPOINT)
continue;
if (mo2->threshold != sequence)
continue;
if (mo2->health != 0)
continue;
waypoint = mo2;
break;
}
waypoint = P_GetFirstWaypoint(sequence);
if (!waypoint)
{
@ -4900,9 +4886,7 @@ DoneSection2:
INT32 sequence;
fixed_t speed;
INT32 lineindex;
thinker_t *th;
mobj_t *waypoint = NULL;
mobj_t *mo2;
angle_t an;
if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT && player->powers[pw_carry] == CR_ZOOMTUBE)
@ -4927,25 +4911,7 @@ DoneSection2:
break;
}
// scan the thinkers
// to find the last waypoint
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th;
if (mo2->type != MT_TUBEWAYPOINT)
continue;
if (mo2->threshold != sequence)
continue;
if (!waypoint)
waypoint = mo2;
else if (mo2->health > waypoint->health)
waypoint = mo2;
}
waypoint = P_GetLastWaypoint(sequence);
if (!waypoint)
{
@ -5027,14 +4993,11 @@ DoneSection2:
INT32 sequence;
fixed_t speed;
INT32 lineindex;
thinker_t *th;
mobj_t *waypointmid = NULL;
mobj_t *waypointhigh = NULL;
mobj_t *waypointlow = NULL;
mobj_t *mo2;
mobj_t *closest = NULL;
vector3_t p, line[2], resulthigh, resultlow;
mobj_t *highest = NULL;
if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT && player->powers[pw_carry] == CR_ROPEHANG)
break;
@ -5080,98 +5043,16 @@ DoneSection2:
// Determine the closest spot on the line between the three waypoints
// Put player at that location.
// scan the thinkers
// to find the first waypoint
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
waypointmid = P_GetClosestWaypoint(sequence, player->mo);
mo2 = (mobj_t *)th;
if (mo2->type != MT_TUBEWAYPOINT)
continue;
if (mo2->threshold != sequence)
continue;
if (!highest)
highest = mo2;
else if (mo2->health > highest->health) // Find the highest waypoint # in case we wrap
highest = mo2;
if (closest && P_AproxDistance(P_AproxDistance(player->mo->x-mo2->x, player->mo->y-mo2->y),
player->mo->z-mo2->z) > P_AproxDistance(P_AproxDistance(player->mo->x-closest->x,
player->mo->y-closest->y), player->mo->z-closest->z))
continue;
// Found a target
closest = mo2;
}
waypointmid = closest;
closest = NULL;
if (waypointmid == NULL)
if (!waypointmid)
{
CONS_Debug(DBG_GAMELOGIC, "ERROR: WAYPOINT(S) IN SEQUENCE %d NOT FOUND.\n", sequence);
break;
}
// Find waypoint before this one (waypointlow)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th;
if (mo2->type != MT_TUBEWAYPOINT)
continue;
if (mo2->threshold != sequence)
continue;
if (waypointmid->health == 0)
{
if (mo2->health != highest->health)
continue;
}
else if (mo2->health != waypointmid->health - 1)
continue;
// Found a target
waypointlow = mo2;
break;
}
// Find waypoint after this one (waypointhigh)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th;
if (mo2->type != MT_TUBEWAYPOINT)
continue;
if (mo2->threshold != sequence)
continue;
if (waypointmid->health == highest->health)
{
if (mo2->health != 0)
continue;
}
else if (mo2->health != waypointmid->health + 1)
continue;
// Found a target
waypointhigh = mo2;
break;
}
waypointlow = P_GetPreviousWaypoint(waypointmid, true);
waypointhigh = P_GetNextWaypoint(waypointmid, true);
CONS_Debug(DBG_GAMELOGIC, "WaypointMid: %d; WaypointLow: %d; WaypointHigh: %d\n",
waypointmid->health, waypointlow ? waypointlow->health : -1, waypointhigh ? waypointhigh->health : -1);
@ -5218,6 +5099,7 @@ DoneSection2:
if (lines[lineindex].flags & ML_EFFECT1) // Don't wrap
{
mobj_t *highest = P_GetLastWaypoint(sequence);
highest->flags |= MF_SLIDEME;
}
@ -5229,7 +5111,7 @@ DoneSection2:
player->mo->y = resulthigh.y;
player->mo->z = resulthigh.z - P_GetPlayerHeight(player);
}
else if ((lines[lineindex].flags & ML_EFFECT1) && waypointmid->health == highest->health)
else if ((lines[lineindex].flags & ML_EFFECT1) && waypointmid->health == numwaypoints[sequence] - 1)
{
closest = waypointmid;
player->mo->x = resultlow.x;
@ -6154,92 +6036,83 @@ static inline void P_AddCameraScanner(sector_t *sourcesec, sector_t *actionsecto
elevator->distance = FixedInt(AngleFixed(angle));
}
static const ffloortype_e laserflags = FF_EXISTS|FF_RENDERALL|FF_NOSHADE|FF_EXTRA|FF_CUTEXTRA|FF_TRANSLUCENT;
/** Flashes a laser block.
*
* \param flash Thinker structure for this laser.
* \sa EV_AddLaserThinker
* \sa P_AddLaserThinker
* \author SSNTails <http://www.ssntails.org>
*/
void T_LaserFlash(laserthink_t *flash)
{
msecnode_t *node;
mobj_t *thing;
sector_t *sourcesec;
ffloor_t *fflr = flash->ffloor;
sector_t *sector = flash->sector;
INT32 s;
ffloor_t *fflr;
sector_t *sector;
sector_t *sourcesec = flash->sourceline->frontsector;
fixed_t top, bottom;
if (!fflr || !(fflr->flags & FF_EXISTS))
return;
if (leveltime & 2)
//fflr->flags |= FF_RENDERALL;
fflr->alpha = 0xB0;
else
//fflr->flags &= ~FF_RENDERALL;
fflr->alpha = 0x90;
sourcesec = fflr->master->frontsector; // Less to type!
top = (*fflr->t_slope) ? P_GetZAt(*fflr->t_slope, sector->soundorg.x, sector->soundorg.y)
: *fflr->topheight;
bottom = (*fflr->b_slope) ? P_GetZAt(*fflr->b_slope, sector->soundorg.x, sector->soundorg.y)
: *fflr->bottomheight;
sector->soundorg.z = (top + bottom)/2;
S_StartSound(&sector->soundorg, sfx_laser);
// Seek out objects to DESTROY! MUAHAHHAHAHAA!!!*cough*
for (node = sector->touching_thinglist; node && node->m_thing; node = node->m_thinglist_next)
for (s = -1; (s = P_FindSectorFromTag(flash->tag, s)) >= 0 ;)
{
thing = node->m_thing;
sector = &sectors[s];
for (fflr = sector->ffloors; fflr; fflr = fflr->next)
{
if (fflr->master != flash->sourceline)
continue;
if (flash->nobosses && thing->flags & MF_BOSS)
continue; // Don't hurt bosses
if (!(fflr->flags & FF_EXISTS))
break;
// Don't endlessly kill egg guard shields (or anything else for that matter)
if (thing->health <= 0)
continue;
if (leveltime & 2)
//fflr->flags |= FF_RENDERALL;
fflr->alpha = 0xB0;
else
//fflr->flags &= ~FF_RENDERALL;
fflr->alpha = 0x90;
top = P_GetSpecialTopZ(thing, sourcesec, sector);
bottom = P_GetSpecialBottomZ(thing, sourcesec, sector);
top = P_GetFFloorTopZAt (fflr, sector->soundorg.x, sector->soundorg.y);
bottom = P_GetFFloorBottomZAt(fflr, sector->soundorg.x, sector->soundorg.y);
sector->soundorg.z = (top + bottom)/2;
S_StartSound(&sector->soundorg, sfx_laser);
if (thing->z >= top
|| thing->z + thing->height <= bottom)
continue;
// Seek out objects to DESTROY! MUAHAHHAHAHAA!!!*cough*
for (node = sector->touching_thinglist; node && node->m_thing; node = node->m_thinglist_next)
{
thing = node->m_thing;
if (thing->flags & MF_SHOOTABLE)
P_DamageMobj(thing, NULL, NULL, 1, 0);
else if (thing->type == MT_EGGSHIELD)
P_KillMobj(thing, NULL, NULL, 0);
if (flash->nobosses && thing->flags & MF_BOSS)
continue; // Don't hurt bosses
// Don't endlessly kill egg guard shields (or anything else for that matter)
if (thing->health <= 0)
continue;
top = P_GetSpecialTopZ(thing, sourcesec, sector);
bottom = P_GetSpecialBottomZ(thing, sourcesec, sector);
if (thing->z >= top
|| thing->z + thing->height <= bottom)
continue;
if (thing->flags & MF_SHOOTABLE)
P_DamageMobj(thing, NULL, NULL, 1, 0);
else if (thing->type == MT_EGGSHIELD)
P_KillMobj(thing, NULL, NULL, 0);
}
break;
}
}
}
/** Adds a laser thinker to a 3Dfloor.
*
* \param fflr 3Dfloor to turn into a laser block.
* \param sector Target sector.
* \param secthkiners Lists of thinkers sorted by sector. May be NULL.
* \sa T_LaserFlash
* \author SSNTails <http://www.ssntails.org>
*/
static inline void EV_AddLaserThinker(sector_t *sec, sector_t *sec2, line_t *line, thinkerlist_t *secthinkers, boolean nobosses)
static inline void P_AddLaserThinker(INT16 tag, line_t *line, boolean nobosses)
{
laserthink_t *flash;
ffloor_t *fflr = P_AddFakeFloor(sec, sec2, line, laserflags, secthinkers);
if (!fflr)
return;
flash = Z_Calloc(sizeof (*flash), PU_LEVSPEC, NULL);
laserthink_t *flash = Z_Calloc(sizeof (*flash), PU_LEVSPEC, NULL);
P_AddThinker(THINK_MAIN, &flash->thinker);
flash->thinker.function.acp1 = (actionf_p1)T_LaserFlash;
flash->ffloor = fflr;
flash->sector = sec; // For finding mobjs
flash->sec = sec2;
flash->tag = tag;
flash->sourceline = line;
flash->nobosses = nobosses;
}
@ -7004,14 +6877,8 @@ void P_SpawnSpecials(boolean fromnetsave)
fixed_t crushspeed = (lines[i].flags & ML_EFFECT5) ? lines[i].dy >> 3 : 10*FRACUNIT;
fixed_t retractspeed = (lines[i].flags & ML_EFFECT5) ? lines[i].dx >> 3 : 2*FRACUNIT;
UINT16 sound = (lines[i].flags & ML_EFFECT4) ? sides[lines[i].sidenum[0]].textureoffset >> FRACBITS : sfx_thwomp;
sec = sides[*lines[i].sidenum].sector - sectors;
for (s = -1; (s = P_FindSectorFromTag(lines[i].tag, s)) >= 0 ;)
{
P_AddThwompThinker(&sectors[sec], lines[i].tag, &lines[i], crushspeed, retractspeed, sound);
P_AddFakeFloor(&sectors[s], &sectors[sec], lines + i,
FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers);
}
P_AddThwompThinker(lines[i].frontsector, lines[i].tag, &lines[i], crushspeed, retractspeed, sound);
P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers);
break;
}
@ -7052,11 +6919,8 @@ void P_SpawnSpecials(boolean fromnetsave)
break;
case 258: // Laser block
sec = sides[*lines[i].sidenum].sector - sectors;
// No longer totally disrupts netgames
for (s = -1; (s = P_FindSectorFromTag(lines[i].tag, s)) >= 0 ;)
EV_AddLaserThinker(&sectors[s], &sectors[sec], lines + i, secthinkers, !!(lines[i].flags & ML_EFFECT1));
P_AddLaserThinker(lines[i].tag, lines + i, !!(lines[i].flags & ML_EFFECT1));
P_AddFakeFloorsByLine(i, FF_EXISTS|FF_RENDERALL|FF_NOSHADE|FF_EXTRA|FF_CUTEXTRA|FF_TRANSLUCENT, secthinkers);
break;
case 259: // Custom FOF
@ -7213,6 +7077,9 @@ void P_SpawnSpecials(boolean fromnetsave)
// 503 is used for a scroller
// 504 is used for a scroller
// 505 is used for a scroller
// 506 is used for a scroller
// 507 is used for a scroller
// 508 is used for a scroller
// 510 is used for a scroller
// 511 is used for a scroller
// 512 is used for a scroller
@ -7753,7 +7620,20 @@ static void P_SpawnScrollers(void)
case 502:
for (s = -1; (s = P_FindLineFromTag(l->tag, s)) >= 0 ;)
if (s != (INT32)i)
Add_Scroller(sc_side, dx, dy, control, lines[s].sidenum[0], accel, 0);
{
if (l->flags & ML_EFFECT2) // use texture offsets instead
{
dx = sides[l->sidenum[0]].textureoffset;
dy = sides[l->sidenum[0]].rowoffset;
}
if (l->flags & ML_EFFECT3)
{
if (lines[s].sidenum[1] != 0xffff)
Add_Scroller(sc_side, dx, dy, control, lines[s].sidenum[1], accel, 0);
}
else
Add_Scroller(sc_side, dx, dy, control, lines[s].sidenum[0], accel, 0);
}
break;
case 505:
@ -7767,7 +7647,25 @@ static void P_SpawnScrollers(void)
if (s != 0xffff)
Add_Scroller(sc_side, -sides[s].textureoffset, sides[s].rowoffset, -1, lines[i].sidenum[0], accel, 0);
else
CONS_Debug(DBG_GAMELOGIC, "Line special 506 (line #%s) missing 2nd side!\n", sizeu1(i));
CONS_Debug(DBG_GAMELOGIC, "Line special 506 (line #%s) missing back side!\n", sizeu1(i));
break;
case 507:
s = lines[i].sidenum[0];
if (lines[i].sidenum[1] != 0xffff)
Add_Scroller(sc_side, -sides[s].textureoffset, sides[s].rowoffset, -1, lines[i].sidenum[1], accel, 0);
else
CONS_Debug(DBG_GAMELOGIC, "Line special 507 (line #%s) missing back side!\n", sizeu1(i));
break;
case 508:
s = lines[i].sidenum[1];
if (s != 0xffff)
Add_Scroller(sc_side, -sides[s].textureoffset, sides[s].rowoffset, -1, s, accel, 0);
else
CONS_Debug(DBG_GAMELOGIC, "Line special 508 (line #%s) missing back side!\n", sizeu1(i));
break;
case 500: // scroll first side
@ -7836,10 +7734,7 @@ void T_Disappear(disappear_t *d)
if (!(lines[d->sourceline].flags & ML_NOCLIMB))
{
if (*rover->t_slope)
sectors[s].soundorg.z = P_GetZAt(*rover->t_slope, sectors[s].soundorg.x, sectors[s].soundorg.y);
else
sectors[s].soundorg.z = *rover->topheight;
sectors[s].soundorg.z = P_GetFFloorTopZAt(rover, sectors[s].soundorg.x, sectors[s].soundorg.y);
S_StartSound(&sectors[s].soundorg, sfx_appear);
}
}
@ -9040,24 +8935,12 @@ void T_Pusher(pusher_t *p)
if (!demoplayback || P_ControlStyle(thing->player) == CS_LMAOGALOG)
{
if (thing->player == &players[consoleplayer])
{
if (thing->angle - localangle > ANGLE_180)
localangle -= (localangle - thing->angle) / 8;
else
localangle += (thing->angle - localangle) / 8;
}
else if (thing->player == &players[secondarydisplayplayer])
{
if (thing->angle - localangle2 > ANGLE_180)
localangle2 -= (localangle2 - thing->angle) / 8;
else
localangle2 += (thing->angle - localangle2) / 8;
}
/*if (thing->player == &players[consoleplayer])
localangle = thing->angle;
else if (thing->player == &players[secondarydisplayplayer])
localangle2 = thing->angle;*/
angle_t angle = thing->player->angleturn << 16;
if (thing->angle - angle > ANGLE_180)
P_SetPlayerAngle(thing->player, angle - (angle - thing->angle) / 8);
else
P_SetPlayerAngle(thing->player, angle + (thing->angle - angle) / 8);
//P_SetPlayerAngle(thing->player, thing->angle);
}
}

View file

@ -104,9 +104,7 @@ typedef struct
typedef struct
{
thinker_t thinker; ///< Thinker structure for laser.
ffloor_t *ffloor; ///< 3Dfloor that is a laser.
sector_t *sector; ///< Sector in which the effect takes place.
sector_t *sec;
INT16 tag;
line_t *sourceline;
UINT8 nobosses;
} laserthink_t;

View file

@ -63,10 +63,7 @@ void P_MixUp(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle,
thing->reactiontime = TICRATE/2; // don't move for about half a second
// absolute angle position
if (thing == players[consoleplayer].mo)
localangle = angle;
if (thing == players[secondarydisplayplayer].mo)
localangle2 = angle;
P_SetPlayerAngle(thing->player, angle);
// move chasecam at new player location
if (splitscreen && camera2.chase
@ -165,10 +162,7 @@ boolean P_Teleport(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle
thing->player->drawangle += (angle - thing->angle);
// absolute angle position
if (thing->player == &players[consoleplayer])
localangle = angle;
if (thing->player == &players[secondarydisplayplayer])
localangle2 = angle;
P_SetPlayerAngle(thing->player, angle);
// move chasecam at new player location
if (splitscreen && camera2.chase && thing->player == &players[secondarydisplayplayer])

View file

@ -770,7 +770,9 @@ void P_PreTicker(INT32 frames)
memcpy(&temptic, &players[i].cmd, sizeof(ticcmd_t));
memset(&players[i].cmd, 0, sizeof(ticcmd_t));
// correct angle on spawn...
players[i].cmd.angleturn = temptic.angleturn;
players[i].angleturn += temptic.angleturn - players[i].oldrelangleturn;
players[i].oldrelangleturn = temptic.angleturn;
players[i].cmd.angleturn = players[i].angleturn;
P_PlayerThink(&players[i]);

File diff suppressed because it is too large Load diff

View file

@ -495,16 +495,13 @@ static void R_AddLine(seg_t *line)
fixed_t frontf1,frontf2, frontc1, frontc2; // front floor/ceiling ends
fixed_t backf1, backf2, backc1, backc2; // back floor ceiling ends
#define SLOPEPARAMS(slope, end1, end2, normalheight) \
if (slope) { \
end1 = P_GetZAt(slope, line->v1->x, line->v1->y); \
end2 = P_GetZAt(slope, line->v2->x, line->v2->y); \
} else \
end1 = end2 = normalheight;
end1 = P_GetZAt(slope, line->v1->x, line->v1->y, normalheight); \
end2 = P_GetZAt(slope, line->v2->x, line->v2->y, normalheight);
SLOPEPARAMS(frontsector->f_slope, frontf1, frontf2, frontsector->floorheight)
SLOPEPARAMS(frontsector->f_slope, frontf1, frontf2, frontsector-> floorheight)
SLOPEPARAMS(frontsector->c_slope, frontc1, frontc2, frontsector->ceilingheight)
SLOPEPARAMS( backsector->f_slope, backf1, backf2, backsector->floorheight)
SLOPEPARAMS( backsector->c_slope, backc1, backc2, backsector->ceilingheight)
SLOPEPARAMS( backsector->f_slope, backf1, backf2, backsector-> floorheight)
SLOPEPARAMS( backsector->c_slope, backc1, backc2, backsector->ceilingheight)
#undef SLOPEPARAMS
// if both ceilings are skies, consider it always "open"
// same for floors
@ -851,13 +848,8 @@ static void R_Subsector(size_t num)
floorcolormap = ceilingcolormap = frontsector->extra_colormap;
floorcenterz = frontsector->f_slope ?
P_GetZAt(frontsector->f_slope, frontsector->soundorg.x, frontsector->soundorg.y) :
frontsector->floorheight;
ceilingcenterz = frontsector->c_slope ?
P_GetZAt(frontsector->c_slope, frontsector->soundorg.x, frontsector->soundorg.y) :
frontsector->ceilingheight;
floorcenterz = P_GetSectorFloorZAt (frontsector, frontsector->soundorg.x, frontsector->soundorg.y);
ceilingcenterz = P_GetSectorCeilingZAt(frontsector, frontsector->soundorg.x, frontsector->soundorg.y);
// Check and prep all 3D floors. Set the sector floor/ceiling light levels and colormaps.
if (frontsector->ffloors)
@ -883,7 +875,7 @@ static void R_Subsector(size_t num)
sub->sector->extra_colormap = frontsector->extra_colormap;
if ((frontsector->f_slope ? P_GetZAt(frontsector->f_slope, viewx, viewy) : frontsector->floorheight) < viewz
if (P_GetSectorFloorZAt(frontsector, viewx, viewy) < viewz
|| frontsector->floorpic == skyflatnum
|| (frontsector->heightsec != -1 && sectors[frontsector->heightsec].ceilingpic == skyflatnum))
{
@ -893,7 +885,7 @@ static void R_Subsector(size_t num)
else
floorplane = NULL;
if ((frontsector->c_slope ? P_GetZAt(frontsector->c_slope, viewx, viewy) : frontsector->ceilingheight) > viewz
if (P_GetSectorCeilingZAt(frontsector, viewx, viewy) > viewz
|| frontsector->ceilingpic == skyflatnum
|| (frontsector->heightsec != -1 && sectors[frontsector->heightsec].floorpic == skyflatnum))
{
@ -930,13 +922,9 @@ static void R_Subsector(size_t num)
ffloor[numffloors].plane = NULL;
ffloor[numffloors].polyobj = NULL;
heightcheck = *rover->b_slope ?
P_GetZAt(*rover->b_slope, viewx, viewy) :
*rover->bottomheight;
heightcheck = P_GetFFloorBottomZAt(rover, viewx, viewy);
planecenterz = *rover->b_slope ?
P_GetZAt(*rover->b_slope, frontsector->soundorg.x, frontsector->soundorg.y) :
*rover->bottomheight;
planecenterz = P_GetFFloorBottomZAt(rover, frontsector->soundorg.x, frontsector->soundorg.y);
if (planecenterz <= ceilingcenterz
&& planecenterz >= floorcenterz
&& ((viewz < heightcheck && (rover->flags & FF_BOTHPLANES || !(rover->flags & FF_INVERTPLANES)))
@ -964,13 +952,9 @@ static void R_Subsector(size_t num)
ffloor[numffloors].plane = NULL;
ffloor[numffloors].polyobj = NULL;
heightcheck = *rover->t_slope ?
P_GetZAt(*rover->t_slope, viewx, viewy) :
*rover->topheight;
heightcheck = P_GetFFloorTopZAt(rover, viewx, viewy);
planecenterz = *rover->t_slope ?
P_GetZAt(*rover->t_slope, frontsector->soundorg.x, frontsector->soundorg.y) :
*rover->topheight;
planecenterz = P_GetFFloorTopZAt(rover, frontsector->soundorg.x, frontsector->soundorg.y);
if (planecenterz >= floorcenterz
&& planecenterz <= ceilingcenterz
&& ((viewz > heightcheck && (rover->flags & FF_BOTHPLANES || !(rover->flags & FF_INVERTPLANES)))
@ -1133,7 +1117,7 @@ void R_Prep3DFloors(sector_t *sector)
else
memset(sector->lightlist, 0, sizeof (lightlist_t) * count);
heighttest = sector->c_slope ? P_GetZAt(sector->c_slope, sector->soundorg.x, sector->soundorg.y) : sector->ceilingheight;
heighttest = P_GetSectorCeilingZAt(sector, sector->soundorg.x, sector->soundorg.y);
sector->lightlist[0].height = heighttest + 1;
sector->lightlist[0].slope = sector->c_slope;
@ -1154,7 +1138,7 @@ void R_Prep3DFloors(sector_t *sector)
&& !(rover->flags & FF_CUTLEVEL) && !(rover->flags & FF_CUTSPRITES)))
continue;
heighttest = *rover->t_slope ? P_GetZAt(*rover->t_slope, sector->soundorg.x, sector->soundorg.y) : *rover->topheight;
heighttest = P_GetFFloorTopZAt(rover, sector->soundorg.x, sector->soundorg.y);
if (heighttest > bestheight && heighttest < maxheight)
{
@ -1164,7 +1148,7 @@ void R_Prep3DFloors(sector_t *sector)
continue;
}
if (rover->flags & FF_DOUBLESHADOW) {
heighttest = *rover->b_slope ? P_GetZAt(*rover->b_slope, sector->soundorg.x, sector->soundorg.y) : *rover->bottomheight;
heighttest = P_GetFFloorBottomZAt(rover, sector->soundorg.x, sector->soundorg.y);
if (heighttest > bestheight
&& heighttest < maxheight)
@ -1206,7 +1190,7 @@ void R_Prep3DFloors(sector_t *sector)
if (best->flags & FF_DOUBLESHADOW)
{
heighttest = *best->b_slope ? P_GetZAt(*best->b_slope, sector->soundorg.x, sector->soundorg.y) : *best->bottomheight;
heighttest = P_GetFFloorBottomZAt(best, sector->soundorg.x, sector->soundorg.y);
if (bestheight == heighttest) ///TODO: do this in a more efficient way -Red
{
sector->lightlist[i].lightlevel = sector->lightlist[best->lastlight].lightlevel;

View file

@ -135,318 +135,6 @@ UINT32 nflatxshift, nflatyshift, nflatshiftup, nflatmask;
static UINT8** translationtablecache[MAXSKINS + 7] = {NULL};
const UINT8 Color_Index[MAXTRANSLATIONS-1][16] = {
// {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, // SKINCOLOR_NONE
// Greyscale ranges
{0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x11}, // SKINCOLOR_WHITE
{0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x05, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x11, 0x12}, // SKINCOLOR_BONE
{0x02, 0x03, 0x04, 0x05, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14}, // SKINCOLOR_CLOUDY
{0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18}, // SKINCOLOR_GREY
{0x02, 0x03, 0x05, 0x07, 0x09, 0x0b, 0x0d, 0x0f, 0x11, 0x13, 0x15, 0x17, 0x19, 0x1b, 0x1d, 0x1f}, // SKINCOLOR_SILVER
{0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x16, 0x17, 0x17, 0x19, 0x19, 0x1a, 0x1a, 0x1b, 0x1c, 0x1d}, // SKINCOLOR_CARBON
{0x00, 0x05, 0x0a, 0x0f, 0x14, 0x19, 0x1a, 0x1b, 0x1c, 0x1e, 0x1e, 0x1e, 0x1f, 0x1f, 0x1f, 0x1f}, // SKINCOLOR_JET
{0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1b, 0x1b, 0x1c, 0x1d, 0x1d, 0x1e, 0x1e, 0x1f, 0x1f}, // SKINCOLOR_BLACK
// Desaturated
{0x00, 0x00, 0x01, 0x02, 0x02, 0x03, 0x91, 0x91, 0x91, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xaf}, // SKINCOLOR_AETHER
{0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0xaa, 0xaa, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xad, 0xae, 0xaf}, // SKINCOLOR_SLATE
{0x90, 0x91, 0x92, 0x93, 0x94, 0x94, 0x95, 0xac, 0xac, 0xad, 0xad, 0xa8, 0xa8, 0xa9, 0xfd, 0xfe}, // SKINCOLOR_BLUEBELL
{0xd0, 0xd0, 0xd1, 0xd1, 0xd2, 0xd2, 0xd3, 0xd3, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0x2b, 0x2c, 0x2e}, // SKINCOLOR_PINK
{0xd0, 0x30, 0xd8, 0xd9, 0xda, 0xdb, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe3, 0xe6, 0xe8, 0xe9}, // SKINCOLOR_YOGURT
{0xdf, 0xe0, 0xe1, 0xe2, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef}, // SKINCOLOR_BROWN
{0xde, 0xe0, 0xe1, 0xe4, 0xe7, 0xe9, 0xeb, 0xec, 0xed, 0xed, 0xed, 0x19, 0x19, 0x1b, 0x1d, 0x1e}, // SKINCOLOR_BRONZE
{0x51, 0x51, 0x54, 0x54, 0x55, 0x55, 0x56, 0x56, 0x56, 0x57, 0xf5, 0xf5, 0xf9, 0xf9, 0xed, 0xed}, // SKINCOLOR_TAN
{0x54, 0x55, 0x56, 0x56, 0xf2, 0xf3, 0xf3, 0xf4, 0xf5, 0xf6, 0xf8, 0xf9, 0xfa, 0xfb, 0xed, 0xed}, // SKINCOLOR_BEIGE
{0x58, 0x58, 0x59, 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5b, 0x5c, 0x5d, 0x5d, 0x5e, 0x5e, 0x5f, 0x5f}, // SKINCOLOR_MOSS
{0x90, 0x90, 0x91, 0x91, 0xaa, 0xaa, 0xab, 0xab, 0xab, 0xac, 0xad, 0xad, 0xae, 0xae, 0xaf, 0xaf}, // SKINCOLOR_AZURE
{0xc0, 0xc0, 0xc1, 0xc1, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc4, 0xc5, 0xc5, 0xc6, 0xc6, 0xc7, 0xc7}, // SKINCOLOR_LAVENDER
// Viv's vivid colours (toast 21/07/17)
{0xb0, 0xb0, 0xc9, 0xca, 0xcc, 0x26, 0x27, 0x28, 0x29, 0x2a, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xfd}, // SKINCOLOR_RUBY
{0xd0, 0xd0, 0xd1, 0xd2, 0x20, 0x21, 0x24, 0x25, 0x26, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e}, // SKINCOLOR_SALMON
{0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x47, 0x2e, 0x2f}, // SKINCOLOR_RED
{0x27, 0x27, 0x28, 0x28, 0x29, 0x2a, 0x2b, 0x2b, 0x2c, 0x2d, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x1f}, // SKINCOLOR_CRIMSON
{0x31, 0x32, 0x33, 0x36, 0x22, 0x22, 0x25, 0x25, 0x25, 0xcd, 0xcf, 0xcf, 0xc5, 0xc5, 0xc7, 0xc7}, // SKINCOLOR_FLAME
{0x48, 0x49, 0x40, 0x33, 0x34, 0x36, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2b, 0x2c, 0x47, 0x2e, 0x2f}, // SKINCOLOR_KETCHUP
{0xd0, 0x30, 0x31, 0x31, 0x32, 0x32, 0xdc, 0xdc, 0xdc, 0xd3, 0xd4, 0xd4, 0xcc, 0xcd, 0xce, 0xcf}, // SKINCOLOR_PEACHY
{0xd8, 0xd9, 0xdb, 0xdc, 0xde, 0xdf, 0xd5, 0xd5, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0x1d, 0x1f}, // SKINCOLOR_QUAIL
{0x51, 0x52, 0x40, 0x40, 0x34, 0x36, 0xd5, 0xd5, 0xd6, 0xd7, 0xcf, 0xcf, 0xc6, 0xc6, 0xc7, 0xfe}, // SKINCOLOR_SUNSET
{0x58, 0x54, 0x40, 0x34, 0x35, 0x38, 0x3a, 0x3c, 0x3d, 0x2a, 0x2b, 0x2c, 0x2c, 0xba, 0xba, 0xbb}, // SKINCOLOR_COPPER
{0x00, 0xd8, 0xd9, 0xda, 0xdb, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e}, // SKINCOLOR_APRICOT
{0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x2c}, // SKINCOLOR_ORANGE
{0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3c, 0x3d, 0x3d, 0x3d, 0x3f, 0x2c, 0x2d, 0x47, 0x2e, 0x2f, 0x2f}, // SKINCOLOR_RUST
{0x51, 0x51, 0x54, 0x54, 0x41, 0x42, 0x43, 0x43, 0x44, 0x45, 0x46, 0x3f, 0x2d, 0x2e, 0x2f, 0x2f}, // SKINCOLOR_GOLD
{0x53, 0x40, 0x41, 0x42, 0x43, 0xe6, 0xe9, 0xe9, 0xea, 0xec, 0xec, 0xc6, 0xc6, 0xc7, 0xc7, 0xfe}, // SKINCOLOR_SANDY
{0x52, 0x53, 0x49, 0x49, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4c, 0x4d, 0x4d, 0x4e, 0x4e, 0x4f, 0xed}, // SKINCOLOR_YELLOW
{0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4e, 0xe7, 0xe7, 0xe9, 0xc5, 0xc5, 0xc6, 0xc6, 0xc7, 0xc7, 0xfd}, // SKINCOLOR_OLIVE
{0x50, 0x51, 0x52, 0x53, 0x48, 0xbc, 0xbd, 0xbe, 0xbe, 0xbf, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f}, // SKINCOLOR_LIME
{0x58, 0x58, 0xbc, 0xbc, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbf, 0x5e, 0x5e, 0x5f, 0x5f, 0x77, 0x77}, // SKINCOLOR_PERIDOT
{0x49, 0x49, 0xbc, 0xbd, 0xbe, 0xbe, 0xbe, 0x67, 0x69, 0x6a, 0x6b, 0x6b, 0x6c, 0x6d, 0x6d, 0x6d}, // SKINCOLOR_APPLE
{0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f}, // SKINCOLOR_GREEN
{0x65, 0x66, 0x67, 0x68, 0x69, 0x69, 0x6a, 0x6b, 0x6b, 0x6c, 0x6d, 0x6d, 0x6e, 0x6e, 0x6e, 0x6f}, // SKINCOLOR_FOREST
{0x70, 0x70, 0x71, 0x71, 0x72, 0x72, 0x73, 0x73, 0x73, 0x74, 0x75, 0x75, 0x76, 0x76, 0x77, 0x77}, // SKINCOLOR_EMERALD
{0x00, 0x00, 0x58, 0x58, 0x59, 0x62, 0x62, 0x62, 0x64, 0x67, 0x7e, 0x7e, 0x8f, 0x8f, 0x8a, 0x8a}, // SKINCOLOR_MINT
{0x01, 0x58, 0x59, 0x5a, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x8f, 0x8f, 0x8a, 0x8a, 0x8a, 0xfd, 0xfd}, // SKINCOLOR_SEAFOAM
{0x78, 0x79, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c, 0x7d, 0x7e, 0x7e, 0x7f, 0x7f, 0x76, 0x77}, // SKINCOLOR_AQUA
{0x78, 0x78, 0x8c, 0x8c, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x8a, 0x8a, 0x8a, 0x8a}, // SKINCOLOR_TEAL
{0x00, 0x78, 0x78, 0x79, 0x8d, 0x87, 0x88, 0x89, 0x89, 0xae, 0xa8, 0xa8, 0xa9, 0xa9, 0xfd, 0xfd}, // SKINCOLOR_WAVE
{0x80, 0x81, 0xff, 0xff, 0x83, 0x83, 0x8d, 0x8d, 0x8d, 0x8e, 0x7e, 0x7f, 0x76, 0x76, 0x77, 0x6e}, // SKINCOLOR_CYAN
{0x80, 0x80, 0x81, 0x82, 0x83, 0x83, 0x84, 0x85, 0x85, 0x86, 0x87, 0x88, 0x89, 0x89, 0x8a, 0x8b}, // SKINCOLOR_SKY
{0x85, 0x86, 0x87, 0x88, 0x88, 0x89, 0x89, 0x89, 0x8a, 0x8a, 0xfd, 0xfd, 0xfd, 0x1f, 0x1f, 0x1f}, // SKINCOLOR_CERULEAN
{0x00, 0x00, 0x00, 0x00, 0x80, 0x81, 0x83, 0x83, 0x86, 0x87, 0x95, 0x95, 0xad, 0xad, 0xae, 0xaf}, // SKINCOLOR_ICY
{0x80, 0x83, 0x86, 0x87, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xfd, 0xfe}, // SKINCOLOR_SAPPHIRE
{0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x9a, 0x9c, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e}, // SKINCOLOR_CORNFLOWER
{0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xfd, 0xfe}, // SKINCOLOR_BLUE
{0x93, 0x94, 0x95, 0x96, 0x98, 0x9a, 0x9b, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xfd, 0xfd, 0xfe, 0xfe}, // SKINCOLOR_COBALT
{0x80, 0x81, 0x83, 0x86, 0x94, 0x94, 0xa3, 0xa3, 0xa4, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa9, 0xa9}, // SKINCOLOR_VAPOR
{0x92, 0x93, 0x94, 0x94, 0xac, 0xad, 0xad, 0xad, 0xae, 0xae, 0xaf, 0xaf, 0xa9, 0xa9, 0xfd, 0xfd}, // SKINCOLOR_DUSK
{0x90, 0x90, 0xa0, 0xa0, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa3, 0xa4, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8}, // SKINCOLOR_PASTEL
{0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa6, 0xa7, 0xa7, 0xa8, 0xa8, 0xa9, 0xa9}, // SKINCOLOR_PURPLE
{0x00, 0xd0, 0xd0, 0xc8, 0xc8, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8}, // SKINCOLOR_BUBBLEGUM
{0xb3, 0xb3, 0xb4, 0xb5, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xbb}, // SKINCOLOR_MAGENTA
{0xb3, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xbb, 0xc7, 0xc7, 0x1d, 0x1d, 0x1e}, // SKINCOLOR_NEON
{0xd0, 0xd1, 0xd2, 0xca, 0xcc, 0xb8, 0xb9, 0xb9, 0xba, 0xa8, 0xa8, 0xa9, 0xa9, 0xfd, 0xfe, 0xfe}, // SKINCOLOR_VIOLET
{0x00, 0xd0, 0xd1, 0xd2, 0xd3, 0xc1, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc5, 0xc6, 0xc6, 0xfe, 0x1f}, // SKINCOLOR_LILAC
{0xc8, 0xd3, 0xd5, 0xd6, 0xd7, 0xce, 0xcf, 0xb9, 0xb9, 0xba, 0xba, 0xa9, 0xa9, 0xa9, 0xfd, 0xfe}, // SKINCOLOR_PLUM
{0xc8, 0xc9, 0xca, 0xcb, 0xcb, 0xcc, 0xcd, 0xcd, 0xce, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xfe, 0xfe}, // SKINCOLOR_RASPBERRY
{0xfc, 0xc8, 0xc8, 0xc9, 0xc9, 0xca, 0xca, 0xcb, 0xcb, 0xcc, 0xcc, 0xcd, 0xcd, 0xce, 0xce, 0xcf}, // SKINCOLOR_ROSY
// {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, // SKINCOLOR_?
// super
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x03}, // SKINCOLOR_SUPERSILVER1
{0x00, 0x01, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x07}, // SKINCOLOR_SUPERSILVER2
{0x01, 0x02, 0x02, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x07, 0x09, 0x0b}, // SKINCOLOR_SUPERSILVER3
{0x02, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x07, 0x09, 0x0b, 0x0d, 0x0f, 0x11}, // SKINCOLOR_SUPERSILVER4
{0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x07, 0x09, 0x0b, 0x0d, 0x0f, 0x11, 0x13}, // SKINCOLOR_SUPERSILVER5
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0xd0, 0xd1, 0xd1, 0xd2, 0xd2}, // SKINCOLOR_SUPERRED1
{0x00, 0x00, 0x00, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1, 0xd2, 0xd2, 0xd2, 0x20, 0x20, 0x21, 0x21}, // SKINCOLOR_SUPERRED2
{0x00, 0x00, 0xd0, 0xd0, 0xd1, 0xd1, 0xd2, 0xd2, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23}, // SKINCOLOR_SUPERRED3
{0x00, 0xd0, 0xd1, 0xd1, 0xd2, 0xd2, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, 0x24, 0x24}, // SKINCOLOR_SUPERRED4
{0xd0, 0xd1, 0xd2, 0xd2, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, 0x24, 0x24, 0x25, 0x25}, // SKINCOLOR_SUPERRED5
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x30, 0x31, 0x32, 0x33, 0x34}, // SKINCOLOR_SUPERORANGE1
{0x00, 0x00, 0x00, 0x00, 0xd0, 0xd0, 0x30, 0x30, 0x31, 0x31, 0x32, 0x32, 0x33, 0x33, 0x34, 0x34}, // SKINCOLOR_SUPERORANGE2
{0x00, 0x00, 0xd0, 0xd0, 0x30, 0x30, 0x31, 0x31, 0x32, 0x32, 0x33, 0x33, 0x34, 0x34, 0x35, 0x35}, // SKINCOLOR_SUPERORANGE3
{0x00, 0xd0, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x44, 0x45, 0x46}, // SKINCOLOR_SUPERORANGE4
{0xd0, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x44, 0x45, 0x46, 0x47}, // SKINCOLOR_SUPERORANGE5
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x50, 0x51, 0x52, 0x53, 0x48, 0x48, 0x48}, // SKINCOLOR_SUPERGOLD1
{0x00, 0x50, 0x51, 0x52, 0x53, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x40, 0x41, 0x41, 0x41}, // SKINCOLOR_SUPERGOLD2
{0x51, 0x52, 0x53, 0x53, 0x48, 0x49, 0x49, 0x49, 0x49, 0x49, 0x40, 0x41, 0x42, 0x43, 0x43, 0x43}, // SKINCOLOR_SUPERGOLD3
{0x53, 0x48, 0x48, 0x49, 0x49, 0x49, 0x49, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x46, 0x46}, // SKINCOLOR_SUPERGOLD4
{0x48, 0x48, 0x49, 0x49, 0x49, 0x40, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x47, 0x47}, // SKINCOLOR_SUPERGOLD5
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x58, 0x58, 0xbc, 0xbc, 0xbc}, // SKINCOLOR_SUPERPERIDOT1
{0x00, 0x58, 0x58, 0x58, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe}, // SKINCOLOR_SUPERPERIDOT2
{0x58, 0x58, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbf, 0xbf}, // SKINCOLOR_SUPERPERIDOT3
{0x58, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbf, 0xbf, 0x5e, 0x5e, 0x5f}, // SKINCOLOR_SUPERPERIDOT4
{0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbf, 0xbf, 0x5e, 0x5e, 0x5f, 0x77}, // SKINCOLOR_SUPERPERIDOT5
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x81, 0x82, 0x83, 0x84}, // SKINCOLOR_SUPERSKY1
{0x00, 0x80, 0x81, 0x82, 0x83, 0x83, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x86, 0x86}, // SKINCOLOR_SUPERSKY2
{0x81, 0x82, 0x83, 0x83, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x86, 0x86, 0x87, 0x87}, // SKINCOLOR_SUPERSKY3
{0x83, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x86, 0x86, 0x87, 0x87, 0x88, 0x89, 0x8a}, // SKINCOLOR_SUPERSKY4
{0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x86, 0x86, 0x87, 0x87, 0x88, 0x89, 0x8a, 0x8b}, // SKINCOLOR_SUPERSKY5
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90, 0xa0, 0xa0, 0xa1, 0xa2}, // SKINCOLOR_SUPERPURPLE1
{0x00, 0x90, 0xa0, 0xa0, 0xa1, 0xa1, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa5, 0xa5}, // SKINCOLOR_SUPERPURPLE2
{0xa0, 0xa0, 0xa1, 0xa1, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa5, 0xa5, 0xa6, 0xa6}, // SKINCOLOR_SUPERPURPLE3
{0xa1, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa5, 0xa5, 0xa6, 0xa6, 0xa7, 0xa8, 0xa9}, // SKINCOLOR_SUPERPURPLE4
{0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa5, 0xa5, 0xa6, 0xa6, 0xa7, 0xa8, 0xa9, 0xfd}, // SKINCOLOR_SUPERPURPLE5
{0x00, 0xd0, 0xd0, 0xd0, 0x30, 0x30, 0x31, 0x32, 0x33, 0x37, 0x3a, 0x44, 0x45, 0x46, 0x47, 0x2e}, // SKINCOLOR_SUPERRUST1
{0x30, 0x31, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x38, 0x3a, 0x44, 0x45, 0x46, 0x47, 0x47, 0x2e}, // SKINCOLOR_SUPERRUST2
{0x31, 0x32, 0x33, 0x34, 0x36, 0x37, 0x38, 0x3a, 0x44, 0x45, 0x45, 0x46, 0x46, 0x47, 0x2e, 0x2e}, // SKINCOLOR_SUPERRUST3
{0x48, 0x40, 0x41, 0x42, 0x43, 0x44, 0x44, 0x45, 0x45, 0x46, 0x46, 0x47, 0x47, 0x2e, 0x2e, 0x2e}, // SKINCOLOR_SUPERRUST4
{0x41, 0x42, 0x43, 0x43, 0x44, 0x44, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xed, 0xee, 0xee, 0xef, 0xef}, // SKINCOLOR_SUPERRUST5
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x50, 0x51, 0x51, 0x52, 0x52}, // SKINCOLOR_SUPERTAN1
{0x00, 0x50, 0x50, 0x51, 0x51, 0x52, 0x52, 0x52, 0x54, 0x54, 0x54, 0x54, 0x55, 0x56, 0x57, 0xf5}, // SKINCOLOR_SUPERTAN2
{0x50, 0x51, 0x51, 0x52, 0x52, 0x52, 0x54, 0x54, 0x54, 0x54, 0x55, 0x56, 0x57, 0xf5, 0xf7, 0xf9}, // SKINCOLOR_SUPERTAN3
{0x51, 0x52, 0x52, 0x52, 0x52, 0x54, 0x54, 0x54, 0x55, 0x56, 0x57, 0xf5, 0xf7, 0xf9, 0xfb, 0xed}, // SKINCOLOR_SUPERTAN4
{0x52, 0x52, 0x54, 0x54, 0x54, 0x55, 0x56, 0x57, 0xf5, 0xf7, 0xf9, 0xfb, 0xed, 0xee, 0xef, 0xef} // SKINCOLOR_SUPERTAN5
};
// See also the enum skincolors_t
// TODO Callum: Can this be translated?
const char *Color_Names[MAXSKINCOLORS + NUMSUPERCOLORS] =
{
"None", // SKINCOLOR_NONE,
// Greyscale ranges
"White", // SKINCOLOR_WHITE,
"Bone", // SKINCOLOR_BONE,
"Cloudy", // SKINCOLOR_CLOUDY,
"Grey", // SKINCOLOR_GREY,
"Silver", // SKINCOLOR_SILVER,
"Carbon", // SKINCOLOR_CARBON,
"Jet", // SKINCOLOR_JET,
"Black", // SKINCOLOR_BLACK,
// Desaturated
"Aether", // SKINCOLOR_AETHER,
"Slate", // SKINCOLOR_SLATE,
"Bluebell", // SKINCOLOR_BLUEBELL,
"Pink", // SKINCOLOR_PINK,
"Yogurt", // SKINCOLOR_YOGURT,
"Brown", // SKINCOLOR_BROWN,
"Bronze", // SKINCOLOR_BRONZE,
"Tan", // SKINCOLOR_TAN,
"Beige", // SKINCOLOR_BEIGE,
"Moss", // SKINCOLOR_MOSS,
"Azure", // SKINCOLOR_AZURE,
"Lavender", // SKINCOLOR_LAVENDER,
// Viv's vivid colours (toast 21/07/17)
"Ruby", // SKINCOLOR_RUBY,
"Salmon", // SKINCOLOR_SALMON,
"Red", // SKINCOLOR_RED,
"Crimson", // SKINCOLOR_CRIMSON,
"Flame", // SKINCOLOR_FLAME,
"Ketchup", // SKINCOLOR_KETCHUP,
"Peachy", // SKINCOLOR_PEACHY,
"Quail", // SKINCOLOR_QUAIL,
"Sunset", // SKINCOLOR_SUNSET,
"Copper", // SKINCOLOR_COPPER,
"Apricot", // SKINCOLOR_APRICOT,
"Orange", // SKINCOLOR_ORANGE,
"Rust", // SKINCOLOR_RUST,
"Gold", // SKINCOLOR_GOLD,
"Sandy", // SKINCOLOR_SANDY,
"Yellow", // SKINCOLOR_YELLOW,
"Olive", // SKINCOLOR_OLIVE,
"Lime", // SKINCOLOR_LIME,
"Peridot", // SKINCOLOR_PERIDOT,
"Apple", // SKINCOLOR_APPLE,
"Green", // SKINCOLOR_GREEN,
"Forest", // SKINCOLOR_FOREST,
"Emerald", // SKINCOLOR_EMERALD,
"Mint", // SKINCOLOR_MINT,
"Seafoam", // SKINCOLOR_SEAFOAM,
"Aqua", // SKINCOLOR_AQUA,
"Teal", // SKINCOLOR_TEAL,
"Wave", // SKINCOLOR_WAVE,
"Cyan", // SKINCOLOR_CYAN,
"Sky", // SKINCOLOR_SKY,
"Cerulean", // SKINCOLOR_CERULEAN,
"Icy", // SKINCOLOR_ICY,
"Sapphire", // SKINCOLOR_SAPPHIRE,
"Cornflower", // SKINCOLOR_CORNFLOWER,
"Blue", // SKINCOLOR_BLUE,
"Cobalt", // SKINCOLOR_COBALT,
"Vapor", // SKINCOLOR_VAPOR,
"Dusk", // SKINCOLOR_DUSK,
"Pastel", // SKINCOLOR_PASTEL,
"Purple", // SKINCOLOR_PURPLE,
"Bubblegum", // SKINCOLOR_BUBBLEGUM,
"Magenta", // SKINCOLOR_MAGENTA,
"Neon", // SKINCOLOR_NEON,
"Violet", // SKINCOLOR_VIOLET,
"Lilac", // SKINCOLOR_LILAC,
"Plum", // SKINCOLOR_PLUM,
"Raspberry", // SKINCOLOR_RASPBERRY,
"Rosy", // SKINCOLOR_ROSY,
// Super behaves by different rules (one name per 5 colours), and will be accessed exclusively via R_GetSuperColorByName instead of R_GetColorByName.
"Silver", // SKINCOLOR_SUPERSILVER1,
"Red", // SKINCOLOR_SUPERRED1,
"Orange", // SKINCOLOR_SUPERORANGE1,
"Gold", // SKINCOLOR_SUPERGOLD1,
"Peridot", // SKINCOLOR_SUPERPERIDOT1,
"Sky", // SKINCOLOR_SUPERSKY1,
"Purple", // SKINCOLOR_SUPERPURPLE1,
"Rust", // SKINCOLOR_SUPERRUST1,
"Tan" // SKINCOLOR_SUPERTAN1,
};
/*
A word of warning: If the following array is non-symmetrical,
A_SignPlayer's prefoppositecolor behaviour will break.
*/
// [0] = opposite skin color,
// [1] = shade index used by signpost, 0-15 (actual sprite frame is 15 minus this value)
const UINT8 Color_Opposite[MAXSKINCOLORS - 1][2] =
{
// {SKINCOLOR_NONE, 8}, // SKINCOLOR_NONE
// Greyscale ranges
{SKINCOLOR_BLACK, 5}, // SKINCOLOR_WHITE,
{SKINCOLOR_JET, 7}, // SKINCOLOR_BONE,
{SKINCOLOR_CARBON, 7}, // SKINCOLOR_CLOUDY,
{SKINCOLOR_AETHER, 12}, // SKINCOLOR_GREY,
{SKINCOLOR_SLATE, 12}, // SKINCOLOR_SILVER,
{SKINCOLOR_CLOUDY, 7}, // SKINCOLOR_CARBON,
{SKINCOLOR_BONE, 7}, // SKINCOLOR_JET,
{SKINCOLOR_WHITE, 7}, // SKINCOLOR_BLACK,
// Desaturated
{SKINCOLOR_GREY, 15}, // SKINCOLOR_AETHER,
{SKINCOLOR_SILVER, 12}, // SKINCOLOR_SLATE,
{SKINCOLOR_COPPER, 4}, // SKINCOLOR_BLUEBELL,
{SKINCOLOR_AZURE, 9}, // SKINCOLOR_PINK,
{SKINCOLOR_RUST, 7}, // SKINCOLOR_YOGURT,
{SKINCOLOR_TAN, 2}, // SKINCOLOR_BROWN,
{SKINCOLOR_KETCHUP, 0}, // SKINCOLOR_BRONZE,
{SKINCOLOR_BROWN, 12}, // SKINCOLOR_TAN,
{SKINCOLOR_MOSS, 5}, // SKINCOLOR_BEIGE,
{SKINCOLOR_BEIGE, 13}, // SKINCOLOR_MOSS,
{SKINCOLOR_PINK, 5}, // SKINCOLOR_AZURE,
{SKINCOLOR_GOLD, 4}, // SKINCOLOR_LAVENDER,
// Viv's vivid colours (toast 21/07/17)
{SKINCOLOR_EMERALD, 10}, // SKINCOLOR_RUBY,
{SKINCOLOR_FOREST, 6}, // SKINCOLOR_SALMON,
{SKINCOLOR_GREEN, 10}, // SKINCOLOR_RED,
{SKINCOLOR_ICY, 10}, // SKINCOLOR_CRIMSON,
{SKINCOLOR_PURPLE, 8}, // SKINCOLOR_FLAME,
{SKINCOLOR_BRONZE, 8}, // SKINCOLOR_KETCHUP,
{SKINCOLOR_TEAL, 7}, // SKINCOLOR_PEACHY,
{SKINCOLOR_WAVE, 5}, // SKINCOLOR_QUAIL,
{SKINCOLOR_SAPPHIRE, 5}, // SKINCOLOR_SUNSET,
{SKINCOLOR_BLUEBELL, 5}, // SKINCOLOR_COPPER
{SKINCOLOR_CYAN, 4}, // SKINCOLOR_APRICOT,
{SKINCOLOR_BLUE, 4}, // SKINCOLOR_ORANGE,
{SKINCOLOR_YOGURT, 8}, // SKINCOLOR_RUST,
{SKINCOLOR_LAVENDER, 10}, // SKINCOLOR_GOLD,
{SKINCOLOR_SKY, 8}, // SKINCOLOR_SANDY,
{SKINCOLOR_CORNFLOWER, 8}, // SKINCOLOR_YELLOW,
{SKINCOLOR_DUSK, 3}, // SKINCOLOR_OLIVE,
{SKINCOLOR_MAGENTA, 9}, // SKINCOLOR_LIME,
{SKINCOLOR_COBALT, 2}, // SKINCOLOR_PERIDOT,
{SKINCOLOR_RASPBERRY, 13}, // SKINCOLOR_APPLE,
{SKINCOLOR_RED, 6}, // SKINCOLOR_GREEN,
{SKINCOLOR_SALMON, 9}, // SKINCOLOR_FOREST,
{SKINCOLOR_RUBY, 4}, // SKINCOLOR_EMERALD,
{SKINCOLOR_VIOLET, 5}, // SKINCOLOR_MINT,
{SKINCOLOR_PLUM, 6}, // SKINCOLOR_SEAFOAM,
{SKINCOLOR_ROSY, 7}, // SKINCOLOR_AQUA,
{SKINCOLOR_PEACHY, 7}, // SKINCOLOR_TEAL,
{SKINCOLOR_QUAIL, 5}, // SKINCOLOR_WAVE,
{SKINCOLOR_APRICOT, 6}, // SKINCOLOR_CYAN,
{SKINCOLOR_SANDY, 1}, // SKINCOLOR_SKY,
{SKINCOLOR_NEON, 4}, // SKINCOLOR_CERULEAN,
{SKINCOLOR_CRIMSON, 0}, // SKINCOLOR_ICY,
{SKINCOLOR_SUNSET, 5}, // SKINCOLOR_SAPPHIRE,
{SKINCOLOR_YELLOW, 4}, // SKINCOLOR_CORNFLOWER,
{SKINCOLOR_ORANGE, 5}, // SKINCOLOR_BLUE,
{SKINCOLOR_PERIDOT, 5}, // SKINCOLOR_COBALT,
{SKINCOLOR_LILAC, 4}, // SKINCOLOR_VAPOR,
{SKINCOLOR_OLIVE, 0}, // SKINCOLOR_DUSK,
{SKINCOLOR_BUBBLEGUM, 9}, // SKINCOLOR_PASTEL,
{SKINCOLOR_FLAME, 7}, // SKINCOLOR_PURPLE,
{SKINCOLOR_PASTEL, 8}, // SKINCOLOR_BUBBLEGUM,
{SKINCOLOR_LIME, 6}, // SKINCOLOR_MAGENTA,
{SKINCOLOR_CERULEAN, 2}, // SKINCOLOR_NEON,
{SKINCOLOR_MINT, 6}, // SKINCOLOR_VIOLET,
{SKINCOLOR_VAPOR, 4}, // SKINCOLOR_LILAC,
{SKINCOLOR_MINT, 7}, // SKINCOLOR_PLUM,
{SKINCOLOR_APPLE, 13}, // SKINCOLOR_RASPBERRY
{SKINCOLOR_AQUA, 1} // SKINCOLOR_ROSY,
};
CV_PossibleValue_t Color_cons_t[MAXSKINCOLORS+1];
/** \brief The R_InitTranslationTables
@ -496,7 +184,7 @@ void R_InitTranslationTables(void)
\param dest_colormap colormap to populate
\param skincolor translation color
*/
static void R_RainbowColormap(UINT8 *dest_colormap, UINT8 skincolor)
static void R_RainbowColormap(UINT8 *dest_colormap, UINT16 skincolor)
{
INT32 i;
RGBA_t color;
@ -509,7 +197,7 @@ static void R_RainbowColormap(UINT8 *dest_colormap, UINT8 skincolor)
// first generate the brightness of all the colours of that skincolour
for (i = 0; i < 16; i++)
{
color = V_GetColor(Color_Index[skincolor-1][i]);
color = V_GetColor(skincolors[skincolor].ramp[i]);
SETBRIGHTNESS(colorbrightnesses[i], color.s.red, color.s.green, color.s.blue);
}
@ -530,7 +218,7 @@ static void R_RainbowColormap(UINT8 *dest_colormap, UINT8 skincolor)
if (temp < brightdif)
{
brightdif = (UINT16)temp;
dest_colormap[i] = Color_Index[skincolor-1][j];
dest_colormap[i] = skincolors[skincolor].ramp[j];
}
}
}
@ -538,7 +226,7 @@ static void R_RainbowColormap(UINT8 *dest_colormap, UINT8 skincolor)
#undef SETBRIGHTNESS
static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, UINT8 color)
static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, UINT16 color)
{
INT32 i, starttranscolor, skinramplength;
@ -551,7 +239,7 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U
memset(dest_colormap, 0, NUM_PALETTE_ENTRIES * sizeof(UINT8));
return;
case TC_RAINBOW:
if (color >= MAXTRANSLATIONS)
if (color >= numskincolors)
I_Error("Invalid skin color #%hu.", (UINT16)color);
if (color != SKINCOLOR_NONE)
{
@ -560,11 +248,11 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U
}
break;
case TC_BLINK:
if (color >= MAXTRANSLATIONS)
if (color >= numskincolors)
I_Error("Invalid skin color #%hu.", (UINT16)color);
if (color != SKINCOLOR_NONE)
{
memset(dest_colormap, Color_Index[color-1][3], NUM_PALETTE_ENTRIES * sizeof(UINT8));
memset(dest_colormap, skincolors[color].ramp[3], NUM_PALETTE_ENTRIES * sizeof(UINT8));
return;
}
break;
@ -585,11 +273,11 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U
{
for (i = 0; i < 6; i++)
{
dest_colormap[Color_Index[SKINCOLOR_BLUE-1][12-i]] = Color_Index[SKINCOLOR_BLUE-1][i];
dest_colormap[skincolors[SKINCOLOR_BLUE].ramp[12-i]] = skincolors[SKINCOLOR_BLUE].ramp[i];
}
dest_colormap[159] = dest_colormap[253] = dest_colormap[254] = 0;
for (i = 0; i < 16; i++)
dest_colormap[96+i] = dest_colormap[Color_Index[SKINCOLOR_COBALT-1][i]];
dest_colormap[96+i] = dest_colormap[skincolors[SKINCOLOR_COBALT].ramp[i]];
}
else if (skinnum == TC_DASHMODE) // This is a long one, because MotorRoach basically hand-picked the indices
{
@ -634,7 +322,7 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U
return;
}
if (color >= MAXTRANSLATIONS)
if (color >= numskincolors)
I_Error("Invalid skin color #%hu.", (UINT16)color);
starttranscolor = (skinnum != TC_DEFAULT) ? skins[skinnum].starttranscolor : DEFAULT_STARTTRANSCOLOR;
@ -658,7 +346,7 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U
// Build the translated ramp
for (i = 0; i < skinramplength; i++)
dest_colormap[starttranscolor + i] = (UINT8)Color_Index[color-1][i];
dest_colormap[starttranscolor + i] = (UINT8)skincolors[color].ramp[i];
}
@ -670,7 +358,7 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U
\return Colormap. If not cached, caller should Z_Free.
*/
UINT8* R_GetTranslationColormap(INT32 skinnum, skincolors_t color, UINT8 flags)
UINT8* R_GetTranslationColormap(INT32 skinnum, skincolornum_t color, UINT8 flags)
{
UINT8* ret;
INT32 skintableindex;
@ -693,7 +381,7 @@ UINT8* R_GetTranslationColormap(INT32 skinnum, skincolors_t color, UINT8 flags)
// Allocate table for skin if necessary
if (!translationtablecache[skintableindex])
translationtablecache[skintableindex] = Z_Calloc(MAXTRANSLATIONS * sizeof(UINT8**), PU_STATIC, NULL);
translationtablecache[skintableindex] = Z_Calloc(MAXSKINCOLORS * sizeof(UINT8**), PU_STATIC, NULL);
// Get colormap
ret = translationtablecache[skintableindex][color];
@ -728,29 +416,32 @@ void R_FlushTranslationColormapCache(void)
for (i = 0; i < (INT32)(sizeof(translationtablecache) / sizeof(translationtablecache[0])); i++)
if (translationtablecache[i])
memset(translationtablecache[i], 0, MAXTRANSLATIONS * sizeof(UINT8**));
memset(translationtablecache[i], 0, MAXSKINCOLORS * sizeof(UINT8**));
}
UINT8 R_GetColorByName(const char *name)
UINT16 R_GetColorByName(const char *name)
{
UINT8 color = (UINT8)atoi(name);
if (color > 0 && color < MAXSKINCOLORS)
UINT16 color = (UINT16)atoi(name);
if (color > 0 && color < numskincolors)
return color;
for (color = 1; color < MAXSKINCOLORS; color++)
if (!stricmp(Color_Names[color], name))
for (color = 1; color < numskincolors; color++)
if (!stricmp(skincolors[color].name, name))
return color;
return SKINCOLOR_GREEN;
}
UINT8 R_GetSuperColorByName(const char *name)
UINT16 R_GetSuperColorByName(const char *name)
{
UINT8 color; /* = (UINT8)atoi(name); -- This isn't relevant to S_SKIN, which is the only way it's accessible right now. Let's simplify things.
if (color > MAXSKINCOLORS && color < MAXTRANSLATIONS && !((color - MAXSKINCOLORS) % 5))
return color;*/
for (color = 0; color < NUMSUPERCOLORS; color++)
if (!stricmp(Color_Names[color + MAXSKINCOLORS], name))
return ((color*5) + MAXSKINCOLORS);
return SKINCOLOR_SUPERGOLD1;
UINT16 i, color = SKINCOLOR_SUPERGOLD1;
char *realname = Z_Malloc(MAXCOLORNAME+1, PU_STATIC, NULL);
snprintf(realname, MAXCOLORNAME+1, "Super %s 1", name);
for (i = 1; i < numskincolors; i++)
if (!stricmp(skincolors[i].name, realname)) {
color = i;
break;
}
Z_Free(realname);
return color;
}
// ==========================================================================

View file

@ -112,10 +112,10 @@ extern lumpnum_t viewborderlump[8];
// Initialize color translation tables, for player rendering etc.
void R_InitTranslationTables(void);
UINT8* R_GetTranslationColormap(INT32 skinnum, skincolors_t color, UINT8 flags);
UINT8* R_GetTranslationColormap(INT32 skinnum, skincolornum_t color, UINT8 flags);
void R_FlushTranslationColormapCache(void);
UINT8 R_GetColorByName(const char *name);
UINT8 R_GetSuperColorByName(const char *name);
UINT16 R_GetColorByName(const char *name);
UINT16 R_GetSuperColorByName(const char *name);
// Custom player skin translation
void R_InitViewBuffer(INT32 width, INT32 height);

View file

@ -1388,7 +1388,7 @@ void R_RenderPlayerView(player_t *player)
else
{
portalclipstart = 0;
portalclipend = viewwidth-1;
portalclipend = viewwidth;
R_ClearClipSegs();
}
R_ClearDrawSegs();

View file

@ -833,15 +833,15 @@ static void R_SlopeVectors(visplane_t *pl, INT32 i, float fudge)
floatv3_t p, m, n;
float ang;
float vx, vy, vz;
// compiler complains when P_GetZAt is used in FLOAT_TO_FIXED directly
// use this as a temp var to store P_GetZAt's return value each time
// compiler complains when P_GetSlopeZAt is used in FLOAT_TO_FIXED directly
// use this as a temp var to store P_GetSlopeZAt's return value each time
fixed_t temp;
vx = FIXED_TO_FLOAT(pl->viewx+xoffs);
vy = FIXED_TO_FLOAT(pl->viewy-yoffs);
vz = FIXED_TO_FLOAT(pl->viewz);
temp = P_GetZAt(pl->slope, pl->viewx, pl->viewy);
temp = P_GetSlopeZAt(pl->slope, pl->viewx, pl->viewy);
zeroheight = FIXED_TO_FLOAT(temp);
// p is the texture origin in view space
@ -850,7 +850,7 @@ static void R_SlopeVectors(visplane_t *pl, INT32 i, float fudge)
ang = ANG2RAD(ANGLE_270 - pl->viewangle);
p.x = vx * cos(ang) - vy * sin(ang);
p.z = vx * sin(ang) + vy * cos(ang);
temp = P_GetZAt(pl->slope, -xoffs, yoffs);
temp = P_GetSlopeZAt(pl->slope, -xoffs, yoffs);
p.y = FIXED_TO_FLOAT(temp) - vz;
// m is the v direction vector in view space
@ -863,9 +863,9 @@ static void R_SlopeVectors(visplane_t *pl, INT32 i, float fudge)
n.z = -cos(ang);
ang = ANG2RAD(pl->plangle);
temp = P_GetZAt(pl->slope, pl->viewx + FLOAT_TO_FIXED(sin(ang)), pl->viewy + FLOAT_TO_FIXED(cos(ang)));
temp = P_GetSlopeZAt(pl->slope, pl->viewx + FLOAT_TO_FIXED(sin(ang)), pl->viewy + FLOAT_TO_FIXED(cos(ang)));
m.y = FIXED_TO_FLOAT(temp) - zeroheight;
temp = P_GetZAt(pl->slope, pl->viewx + FLOAT_TO_FIXED(cos(ang)), pl->viewy - FLOAT_TO_FIXED(sin(ang)));
temp = P_GetSlopeZAt(pl->slope, pl->viewx + FLOAT_TO_FIXED(cos(ang)), pl->viewy - FLOAT_TO_FIXED(sin(ang)));
n.y = FIXED_TO_FLOAT(temp) - zeroheight;
if (ds_powersoftwo)
@ -943,23 +943,23 @@ void R_DrawSinglePlane(visplane_t *pl)
#endif
spanfunc = spanfuncs[BASEDRAWFUNC];
if (pl->polyobj && pl->polyobj->translucency != 0)
if (pl->polyobj)
{
spanfunctype = SPANDRAWFUNC_TRANS;
// Hacked up support for alpha value in software mode Tails 09-24-2002 (sidenote: ported to polys 10-15-2014, there was no time travel involved -Red)
if (pl->polyobj->translucency >= 10)
return; // Don't even draw it
else if (pl->polyobj->translucency > 0)
{
spanfunctype = (pl->polyobj->flags & POF_SPLAT) ? SPANDRAWFUNC_TRANSSPLAT : SPANDRAWFUNC_TRANS;
ds_transmap = transtables + ((pl->polyobj->translucency-1)<<FF_TRANSSHIFT);
else // Opaque, but allow transparent flat pixels
}
else if (pl->polyobj->flags & POF_SPLAT) // Opaque, but allow transparent flat pixels
spanfunctype = SPANDRAWFUNC_SPLAT;
if ((spanfunctype == SPANDRAWFUNC_SPLAT) || (pl->extra_colormap && (pl->extra_colormap->flags & CMF_FOG)))
if (pl->polyobj->translucency == 0 || (pl->extra_colormap && (pl->extra_colormap->flags & CMF_FOG)))
light = (pl->lightlevel >> LIGHTSEGSHIFT);
else
light = LIGHTLEVELS-1;
}
else
{
@ -984,7 +984,7 @@ void R_DrawSinglePlane(visplane_t *pl)
if (pl->ffloor->flags & FF_TRANSLUCENT)
{
spanfunctype = SPANDRAWFUNC_TRANS;
spanfunctype = (pl->ffloor->master->flags & ML_EFFECT6) ? SPANDRAWFUNC_TRANSSPLAT : SPANDRAWFUNC_TRANS;
// Hacked up support for alpha value in software mode Tails 09-24-2002
if (pl->ffloor->alpha < 12)
@ -1177,7 +1177,7 @@ void R_DrawSinglePlane(visplane_t *pl)
if (itswater)
{
INT32 i;
fixed_t plheight = abs(P_GetZAt(pl->slope, pl->viewx, pl->viewy) - pl->viewz);
fixed_t plheight = abs(P_GetSlopeZAt(pl->slope, pl->viewx, pl->viewy) - pl->viewz);
fixed_t rxoffs = xoffs;
fixed_t ryoffs = yoffs;

View file

@ -374,16 +374,13 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
fixed_t leftheight, rightheight;
light = &frontsector->lightlist[i];
rlight = &dc_lightlist[i];
if (light->slope) {
leftheight = P_GetZAt(light->slope, ds->leftpos.x, ds->leftpos.y);
rightheight = P_GetZAt(light->slope, ds->rightpos.x, ds->rightpos.y);
} else
leftheight = rightheight = light->height;
leftheight = P_GetLightZAt(light, ds-> leftpos.x, ds-> leftpos.y);
rightheight = P_GetLightZAt(light, ds->rightpos.x, ds->rightpos.y);
leftheight -= viewz;
leftheight -= viewz;
rightheight -= viewz;
rlight->height = (centeryfrac) - FixedMul(leftheight, ds->scale1);
rlight->height = (centeryfrac) - FixedMul(leftheight , ds->scale1);
rlight->heightstep = (centeryfrac) - FixedMul(rightheight, ds->scale2);
rlight->heightstep = (rlight->heightstep-rlight->height)/(range);
//if (x1 > ds->x1)
@ -797,11 +794,8 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
rlight = &dc_lightlist[p];
#define SLOPEPARAMS(slope, end1, end2, normalheight) \
if (slope) { \
end1 = P_GetZAt(slope, ds->leftpos.x, ds->leftpos.y); \
end2 = P_GetZAt(slope, ds->rightpos.x, ds->rightpos.y); \
} else \
end1 = end2 = normalheight;
end1 = P_GetZAt(slope, ds-> leftpos.x, ds-> leftpos.y, normalheight); \
end2 = P_GetZAt(slope, ds->rightpos.x, ds->rightpos.y, normalheight);
SLOPEPARAMS(light->slope, leftheight, rightheight, light->height)
SLOPEPARAMS(*pfloor->b_slope, pfloorleft, pfloorright, *pfloor->bottomheight)
@ -814,8 +808,8 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
if (leftheight > pfloorleft && rightheight > pfloorright && i+1 < dc_numlights)
{
lightlist_t *nextlight = &frontsector->lightlist[i+1];
if ((nextlight->slope ? P_GetZAt(nextlight->slope, ds->leftpos.x, ds->leftpos.y) : nextlight->height) > pfloorleft
&& (nextlight->slope ? P_GetZAt(nextlight->slope, ds->rightpos.x, ds->rightpos.y) : nextlight->height) > pfloorright)
if (P_GetZAt(nextlight->slope, ds-> leftpos.x, ds-> leftpos.y, nextlight->height) > pfloorleft
&& P_GetZAt(nextlight->slope, ds->rightpos.x, ds->rightpos.y, nextlight->height) > pfloorright)
continue;
}
@ -911,15 +905,9 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
dc_texheight = textureheight[texnum]>>FRACBITS;
// calculate both left ends
if (*pfloor->t_slope)
left_top = P_GetZAt(*pfloor->t_slope, ds->leftpos.x, ds->leftpos.y) - viewz;
else
left_top = *pfloor->topheight - viewz;
left_top = P_GetFFloorTopZAt (pfloor, ds->leftpos.x, ds->leftpos.y) - viewz;
left_bottom = P_GetFFloorBottomZAt(pfloor, ds->leftpos.x, ds->leftpos.y) - viewz;
if (*pfloor->b_slope)
left_bottom = P_GetZAt(*pfloor->b_slope, ds->leftpos.x, ds->leftpos.y) - viewz;
else
left_bottom = *pfloor->bottomheight - viewz;
skewslope = *pfloor->t_slope; // skew using top slope by default
if (newline)
{
@ -995,15 +983,8 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
fixed_t right_top, right_bottom;
// calculate right ends now
if (*pfloor->t_slope)
right_top = P_GetZAt(*pfloor->t_slope, ds->rightpos.x, ds->rightpos.y) - viewz;
else
right_top = *pfloor->topheight - viewz;
if (*pfloor->b_slope)
right_bottom = P_GetZAt(*pfloor->b_slope, ds->rightpos.x, ds->rightpos.y) - viewz;
else
right_bottom = *pfloor->bottomheight - viewz;
right_top = P_GetFFloorTopZAt (pfloor, ds->rightpos.x, ds->rightpos.y) - viewz;
right_bottom = P_GetFFloorBottomZAt(pfloor, ds->rightpos.x, ds->rightpos.y) - viewz;
// using INT64 to avoid 32bit overflow
top_frac = (INT64)centeryfrac - (((INT64)left_top * ds->scale1) >> FRACBITS);
@ -1785,11 +1766,8 @@ void R_StoreWallRange(INT32 start, INT32 stop)
#define SLOPEPARAMS(slope, end1, end2, normalheight) \
if (slope) { \
end1 = P_GetZAt(slope, segleft.x, segleft.y); \
end2 = P_GetZAt(slope, segright.x, segright.y); \
} else \
end1 = end2 = normalheight;
end1 = P_GetZAt(slope, segleft.x, segleft.y, normalheight); \
end2 = P_GetZAt(slope, segright.x, segright.y, normalheight);
SLOPEPARAMS(frontsector->c_slope, worldtop, worldtopslope, frontsector->ceilingheight)
SLOPEPARAMS(frontsector->f_slope, worldbottom, worldbottomslope, frontsector->floorheight)
@ -1818,12 +1796,8 @@ void R_StoreWallRange(INT32 start, INT32 stop)
if (ffloor[i].polyobj && (!ds_p->curline->polyseg || ffloor[i].polyobj != ds_p->curline->polyseg))
continue;
if (ffloor[i].slope) {
ffloor[i].f_pos = P_GetZAt(ffloor[i].slope, segleft.x, segleft.y) - viewz;
ffloor[i].f_pos_slope = P_GetZAt(ffloor[i].slope, segright.x, segright.y) - viewz;
}
else
ffloor[i].f_pos_slope = ffloor[i].f_pos = ffloor[i].height - viewz;
ffloor[i].f_pos = P_GetZAt(ffloor[i].slope, segleft .x, segleft .y, ffloor[i].height) - viewz;
ffloor[i].f_pos_slope = P_GetZAt(ffloor[i].slope, segright.x, segright.y, ffloor[i].height) - viewz;
}
}
@ -1916,12 +1890,12 @@ void R_StoreWallRange(INT32 start, INT32 stop)
if (worldbottomslope > worldlowslope || worldbottom > worldlow)
{
ds_p->silhouette = SIL_BOTTOM;
if ((backsector->f_slope ? P_GetZAt(backsector->f_slope, viewx, viewy) : backsector->floorheight) > viewz)
if (P_GetSectorFloorZAt(backsector, viewx, viewy) > viewz)
ds_p->bsilheight = INT32_MAX;
else
ds_p->bsilheight = (frontsector->f_slope ? INT32_MAX : frontsector->floorheight);
}
else if ((backsector->f_slope ? P_GetZAt(backsector->f_slope, viewx, viewy) : backsector->floorheight) > viewz)
else if (P_GetSectorFloorZAt(backsector, viewx, viewy) > viewz)
{
ds_p->silhouette = SIL_BOTTOM;
ds_p->bsilheight = INT32_MAX;
@ -1934,12 +1908,12 @@ void R_StoreWallRange(INT32 start, INT32 stop)
if (worldtopslope < worldhighslope || worldtop < worldhigh)
{
ds_p->silhouette |= SIL_TOP;
if ((backsector->c_slope ? P_GetZAt(backsector->c_slope, viewx, viewy) : backsector->ceilingheight) < viewz)
if (P_GetSectorCeilingZAt(backsector, viewx, viewy) < viewz)
ds_p->tsilheight = INT32_MIN;
else
ds_p->tsilheight = (frontsector->c_slope ? INT32_MIN : frontsector->ceilingheight);
}
else if ((backsector->c_slope ? P_GetZAt(backsector->c_slope, viewx, viewy) : backsector->ceilingheight) < viewz)
else if (P_GetSectorCeilingZAt(backsector, viewx, viewy) < viewz)
{
ds_p->silhouette |= SIL_TOP;
ds_p->tsilheight = INT32_MIN;
@ -2270,10 +2244,10 @@ void R_StoreWallRange(INT32 start, INT32 stop)
continue;
// Oy vey.
if ( ((*rover->t_slope ? P_GetZAt(*rover->t_slope, segleft .x, segleft .y) : *rover-> topheight) <= worldbottom + viewz
&& (*rover->t_slope ? P_GetZAt(*rover->t_slope, segright.x, segright.y) : *rover-> topheight) <= worldbottomslope + viewz)
||((*rover->b_slope ? P_GetZAt(*rover->b_slope, segleft .x, segleft .y) : *rover->bottomheight) >= worldtop + viewz
&& (*rover->b_slope ? P_GetZAt(*rover->b_slope, segright.x, segright.y) : *rover->bottomheight) >= worldtopslope + viewz))
if ( ((P_GetFFloorTopZAt (rover, segleft .x, segleft .y)) <= worldbottom + viewz
&& (P_GetFFloorTopZAt (rover, segright.x, segright.y)) <= worldbottomslope + viewz)
||((P_GetFFloorBottomZAt(rover, segleft .x, segleft .y)) >= worldtop + viewz
&& (P_GetFFloorBottomZAt(rover, segright.x, segright.y)) >= worldtopslope + viewz))
continue;
ds_p->thicksides[i] = rover;
@ -2291,16 +2265,16 @@ void R_StoreWallRange(INT32 start, INT32 stop)
if (rover->norender == leveltime)
continue;
// Oy vey.
if ( ((*rover->t_slope ? P_GetZAt(*rover->t_slope, segleft .x, segleft .y) : *rover-> topheight) <= worldbottom + viewz
&& (*rover->t_slope ? P_GetZAt(*rover->t_slope, segright.x, segright.y) : *rover-> topheight) <= worldbottomslope + viewz)
||((*rover->b_slope ? P_GetZAt(*rover->b_slope, segleft .x, segleft .y) : *rover->bottomheight) >= worldtop + viewz
&& (*rover->b_slope ? P_GetZAt(*rover->b_slope, segright.x, segright.y) : *rover->bottomheight) >= worldtopslope + viewz))
if ( (P_GetFFloorTopZAt (rover, segleft .x, segleft .y) <= worldbottom + viewz
&& P_GetFFloorTopZAt (rover, segright.x, segright.y) <= worldbottomslope + viewz)
||(P_GetFFloorBottomZAt(rover, segleft .x, segleft .y) >= worldtop + viewz
&& P_GetFFloorBottomZAt(rover, segright.x, segright.y) >= worldtopslope + viewz))
continue;
if ( ((*rover->t_slope ? P_GetZAt(*rover->t_slope, segleft .x, segleft .y) : *rover-> topheight) <= worldlow + viewz
&& (*rover->t_slope ? P_GetZAt(*rover->t_slope, segright.x, segright.y) : *rover-> topheight) <= worldlowslope + viewz)
||((*rover->b_slope ? P_GetZAt(*rover->b_slope, segleft .x, segleft .y) : *rover->bottomheight) >= worldhigh + viewz
&& (*rover->b_slope ? P_GetZAt(*rover->b_slope, segright.x, segright.y) : *rover->bottomheight) >= worldhighslope + viewz))
if ( (P_GetFFloorTopZAt (rover, segleft .x, segleft .y) <= worldlow + viewz
&& P_GetFFloorTopZAt (rover, segright.x, segright.y) <= worldlowslope + viewz)
||(P_GetFFloorBottomZAt(rover, segleft .x, segleft .y) >= worldhigh + viewz
&& P_GetFFloorBottomZAt(rover, segright.x, segright.y) >= worldhighslope + viewz))
continue;
ds_p->thicksides[i] = rover;
@ -2423,17 +2397,13 @@ void R_StoreWallRange(INT32 start, INT32 stop)
// and doesn't need to be marked.
if (frontsector->heightsec == -1)
{
if (frontsector->floorpic != skyflatnum && (frontsector->f_slope ?
P_GetZAt(frontsector->f_slope, viewx, viewy) :
frontsector->floorheight) >= viewz)
if (frontsector->floorpic != skyflatnum && P_GetSectorFloorZAt(frontsector, viewx, viewy) >= viewz)
{
// above view plane
markfloor = false;
}
if (frontsector->ceilingpic != skyflatnum && (frontsector->c_slope ?
P_GetZAt(frontsector->c_slope, viewx, viewy) :
frontsector->ceilingheight) <= viewz)
if (frontsector->ceilingpic != skyflatnum && P_GetSectorCeilingZAt(frontsector, viewx, viewy) <= viewz)
{
// below view plane
markceiling = false;
@ -2485,14 +2455,12 @@ void R_StoreWallRange(INT32 start, INT32 stop)
light = &frontsector->lightlist[i];
rlight = &dc_lightlist[p];
if (light->slope) {
leftheight = P_GetZAt(light->slope, segleft.x, segleft.y);
rightheight = P_GetZAt(light->slope, segright.x, segright.y);
leftheight = P_GetLightZAt(light, segleft.x, segleft.y);
rightheight = P_GetLightZAt(light, segright.x, segright.y);
if (light->slope)
// Flag sector as having slopes
frontsector->hasslope = true;
} else
leftheight = rightheight = light->height;
leftheight -= viewz;
rightheight -= viewz;
@ -2516,19 +2484,17 @@ void R_StoreWallRange(INT32 start, INT32 stop)
if (light->caster && light->caster->flags & FF_CUTSOLIDS)
{
if (*light->caster->b_slope) {
leftheight = P_GetZAt(*light->caster->b_slope, segleft.x, segleft.y);
rightheight = P_GetZAt(*light->caster->b_slope, segright.x, segright.y);
leftheight = P_GetFFloorBottomZAt(light->caster, segleft.x, segleft.y);
rightheight = P_GetFFloorBottomZAt(light->caster, segright.x, segright.y);
if (*light->caster->b_slope)
// Flag sector as having slopes
frontsector->hasslope = true;
} else
leftheight = rightheight = *light->caster->bottomheight;
leftheight -= viewz;
leftheight -= viewz;
rightheight -= viewz;
leftheight >>= 4;
leftheight >>= 4;
rightheight >>= 4;
rlight->botheight = (centeryfrac>>4) - FixedMul(leftheight, rw_scale);
@ -2612,9 +2578,9 @@ void R_StoreWallRange(INT32 start, INT32 stop)
if (*rover->b_slope || *rover->t_slope)
backsector->hasslope = true;
roverleft = (*rover->b_slope ? P_GetZAt(*rover->b_slope, segleft.x, segleft.y) : *rover->bottomheight) - viewz;
roverright = (*rover->b_slope ? P_GetZAt(*rover->b_slope, segright.x, segright.y) : *rover->bottomheight) - viewz;
planevistest = (*rover->b_slope ? P_GetZAt(*rover->b_slope, viewx, viewy) : *rover->bottomheight);
roverleft = P_GetFFloorBottomZAt(rover, segleft .x, segleft .y) - viewz;
roverright = P_GetFFloorBottomZAt(rover, segright.x, segright.y) - viewz;
planevistest = P_GetFFloorBottomZAt(rover, viewx, viewy);
if ((roverleft>>4 <= worldhigh || roverright>>4 <= worldhighslope) &&
(roverleft>>4 >= worldlow || roverright>>4 >= worldlowslope) &&
@ -2635,9 +2601,9 @@ void R_StoreWallRange(INT32 start, INT32 stop)
if (i >= MAXFFLOORS)
break;
roverleft = (*rover->t_slope ? P_GetZAt(*rover->t_slope, segleft.x, segleft.y) : *rover->topheight) - viewz;
roverright = (*rover->t_slope ? P_GetZAt(*rover->t_slope, segright.x, segright.y) : *rover->topheight) - viewz;
planevistest = (*rover->t_slope ? P_GetZAt(*rover->t_slope, viewx, viewy) : *rover->topheight);
roverleft = P_GetFFloorTopZAt(rover, segleft .x, segleft .y) - viewz;
roverright = P_GetFFloorTopZAt(rover, segright.x, segright.y) - viewz;
planevistest = P_GetFFloorTopZAt(rover, viewx, viewy);
if ((roverleft>>4 <= worldhigh || roverright>>4 <= worldhighslope) &&
(roverleft>>4 >= worldlow || roverright>>4 >= worldlowslope) &&
@ -2669,9 +2635,9 @@ void R_StoreWallRange(INT32 start, INT32 stop)
if (*rover->b_slope || *rover->t_slope)
frontsector->hasslope = true;
roverleft = (*rover->b_slope ? P_GetZAt(*rover->b_slope, segleft.x, segleft.y) : *rover->bottomheight) - viewz;
roverright = (*rover->b_slope ? P_GetZAt(*rover->b_slope, segright.x, segright.y) : *rover->bottomheight) - viewz;
planevistest = (*rover->b_slope ? P_GetZAt(*rover->b_slope, viewx, viewy) : *rover->bottomheight);
roverleft = P_GetFFloorBottomZAt(rover, segleft .x, segleft .y) - viewz;
roverright = P_GetFFloorBottomZAt(rover, segright.x, segright.y) - viewz;
planevistest = P_GetFFloorBottomZAt(rover, viewx, viewy);
if ((roverleft>>4 <= worldhigh || roverright>>4 <= worldhighslope) &&
(roverleft>>4 >= worldlow || roverright>>4 >= worldlowslope) &&
@ -2692,9 +2658,9 @@ void R_StoreWallRange(INT32 start, INT32 stop)
if (i >= MAXFFLOORS)
break;
roverleft = (*rover->t_slope ? P_GetZAt(*rover->t_slope, segleft.x, segleft.y) : *rover->topheight) - viewz;
roverright = (*rover->t_slope ? P_GetZAt(*rover->t_slope, segright.x, segright.y) : *rover->topheight) - viewz;
planevistest = (*rover->t_slope ? P_GetZAt(*rover->t_slope, viewx, viewy) : *rover->topheight);
roverleft = P_GetFFloorTopZAt(rover, segleft .x, segleft .y) - viewz;
roverright = P_GetFFloorTopZAt(rover, segright.x, segright.y) - viewz;
planevistest = P_GetFFloorTopZAt(rover, viewx, viewy);
if ((roverleft>>4 <= worldhigh || roverright>>4 <= worldhighslope) &&
(roverleft>>4 >= worldlow || roverright>>4 >= worldlowslope) &&

View file

@ -248,7 +248,7 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum)
{
player_t *player = &players[playernum];
skin_t *skin = &skins[skinnum];
UINT8 newcolor = 0;
UINT16 newcolor = 0;
if (skinnum >= 0 && skinnum < numskins && R_SkinUsable(playernum, skinnum)) // Make sure it exists!
{

View file

@ -65,9 +65,9 @@ typedef struct
// Definable color translation table
UINT8 starttranscolor;
UINT8 prefcolor;
UINT8 supercolor;
UINT8 prefoppositecolor; // if 0 use tables instead
UINT16 prefcolor;
UINT16 supercolor;
UINT16 prefoppositecolor; // if 0 use tables instead
fixed_t highresscale; // scale of highres, default is 0.5
UINT8 contspeed; // continue screen animation speed

View file

@ -1019,13 +1019,12 @@ static void R_SplitSprite(vissprite_t *sprite)
for (i = 1; i < sector->numlights; i++)
{
fixed_t testheight = sector->lightlist[i].height;
fixed_t testheight;
if (!(sector->lightlist[i].caster->flags & FF_CUTSPRITES))
continue;
if (sector->lightlist[i].slope)
testheight = P_GetZAt(sector->lightlist[i].slope, sprite->gx, sprite->gy);
testheight = P_GetLightZAt(&sector->lightlist[i], sprite->gx, sprite->gy);
if (testheight >= sprite->gzt)
continue;
@ -1097,25 +1096,29 @@ static void R_SplitSprite(vissprite_t *sprite)
//
fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope)
{
fixed_t z, floorz = INT32_MIN;
pslope_t *slope, *floorslope = NULL;
boolean isflipped = thing->eflags & MFE_VERTICALFLIP;
fixed_t z, groundz = isflipped ? INT32_MAX : INT32_MIN;
pslope_t *slope, *groundslope = NULL;
msecnode_t *node;
sector_t *sector;
ffloor_t *rover;
#define CHECKZ (isflipped ? z > thing->z+thing->height/2 && z < groundz : z < thing->z+thing->height/2 && z > groundz)
for (node = thing->touching_sectorlist; node; node = node->m_sectorlist_next)
{
sector = node->m_sector;
slope = (sector->heightsec != -1) ? NULL : sector->f_slope;
z = slope ? P_GetZAt(slope, thing->x, thing->y) : (
(sector->heightsec != -1) ? sectors[sector->heightsec].floorheight : sector->floorheight
);
slope = sector->heightsec != -1 ? NULL : (isflipped ? sector->c_slope : sector->f_slope);
if (z < thing->z+thing->height/2 && z > floorz)
if (sector->heightsec != -1)
z = isflipped ? sectors[sector->heightsec].ceilingheight : sectors[sector->heightsec].floorheight;
else
z = isflipped ? P_GetSectorCeilingZAt(sector, thing->x, thing->y) : P_GetSectorFloorZAt(sector, thing->x, thing->y);
if CHECKZ
{
floorz = z;
floorslope = slope;
groundz = z;
groundslope = slope;
}
if (sector->ffloors)
@ -1124,23 +1127,25 @@ fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope)
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERPLANES) || (rover->alpha < 90 && !(rover->flags & FF_SWIMMABLE)))
continue;
z = *rover->t_slope ? P_GetZAt(*rover->t_slope, thing->x, thing->y) : *rover->topheight;
if (z < thing->z+thing->height/2 && z > floorz)
z = isflipped ? P_GetFFloorBottomZAt(rover, thing->x, thing->y) : P_GetFFloorTopZAt(rover, thing->x, thing->y);
if CHECKZ
{
floorz = z;
floorslope = *rover->t_slope;
groundz = z;
groundslope = isflipped ? *rover->b_slope : *rover->t_slope;
}
}
}
if (thing->floorz > floorz + (!floorslope ? 0 : FixedMul(abs(floorslope->zdelta), thing->radius*3/2)))
if (isflipped ? (thing->ceilingz < groundz - (!groundslope ? 0 : FixedMul(abs(groundslope->zdelta), thing->radius*3/2)))
: (thing->floorz > groundz + (!groundslope ? 0 : FixedMul(abs(groundslope->zdelta), thing->radius*3/2))))
{
floorz = thing->floorz;
floorslope = NULL;
groundz = isflipped ? thing->ceilingz : thing->floorz;
groundslope = NULL;
}
#if 0 // Unfortunately, this drops CEZ2 down to sub-17 FPS on my i7.
// Check polyobjects and see if floorz needs to be altered, for rings only because they don't update floorz
// NOTE: this section was not updated to reflect reverse gravity support
// Check polyobjects and see if groundz needs to be altered, for rings only because they don't update floorz
if (thing->type == MT_RING)
{
INT32 xl, xh, yl, yh, bx, by;
@ -1185,10 +1190,10 @@ fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope)
// We're inside it! Yess...
z = po->lines[0]->backsector->ceilingheight;
if (z < thing->z+thing->height/2 && z > floorz)
if (z < thing->z+thing->height/2 && z > groundz)
{
floorz = z;
floorslope = NULL;
groundz = z;
groundslope = NULL;
}
}
plink = (polymaplink_t *)(plink->link.next);
@ -1198,9 +1203,10 @@ fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope)
#endif
if (shadowslope != NULL)
*shadowslope = floorslope;
*shadowslope = groundslope;
return floorz;
return groundz;
#undef CHECKZ
}
static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, fixed_t tx, fixed_t tz)
@ -1211,14 +1217,15 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale,
INT32 light = 0;
fixed_t scalemul; UINT8 trans;
fixed_t floordiff;
fixed_t floorz;
pslope_t *floorslope;
fixed_t groundz;
pslope_t *groundslope;
boolean isflipped = thing->eflags & MFE_VERTICALFLIP;
floorz = R_GetShadowZ(thing, &floorslope);
groundz = R_GetShadowZ(thing, &groundslope);
if (abs(floorz-viewz)/tz > 4) return; // Prevent stretchy shadows and possible crashes
if (abs(groundz-viewz)/tz > 4) return; // Prevent stretchy shadows and possible crashes
floordiff = abs(thing->z - floorz);
floordiff = abs((isflipped ? thing->height : 0) + thing->z - groundz);
trans = floordiff / (100*FRACUNIT) + 3;
if (trans >= 9) return;
@ -1229,23 +1236,23 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale,
xscale = FixedDiv(projection, tz);
yscale = FixedDiv(projectiony, tz);
shadowxscale = FixedMul(thing->radius*2, scalemul);
shadowyscale = FixedMul(FixedMul(thing->radius*2, scalemul), FixedDiv(abs(floorz - viewz), tz));
shadowyscale = FixedMul(FixedMul(thing->radius*2, scalemul), FixedDiv(abs(groundz - viewz), tz));
shadowyscale = min(shadowyscale, shadowxscale) / SHORT(patch->height);
shadowxscale /= SHORT(patch->width);
shadowskew = 0;
if (floorslope)
if (groundslope)
{
// haha let's try some dumb stuff
fixed_t xslope, zslope;
angle_t sloperelang = (R_PointToAngle(thing->x, thing->y) - floorslope->xydirection) >> ANGLETOFINESHIFT;
angle_t sloperelang = (R_PointToAngle(thing->x, thing->y) - groundslope->xydirection) >> ANGLETOFINESHIFT;
xslope = FixedMul(FINESINE(sloperelang), floorslope->zdelta);
zslope = FixedMul(FINECOSINE(sloperelang), floorslope->zdelta);
xslope = FixedMul(FINESINE(sloperelang), groundslope->zdelta);
zslope = FixedMul(FINECOSINE(sloperelang), groundslope->zdelta);
//CONS_Printf("Shadow is sloped by %d %d\n", xslope, zslope);
if (viewz < floorz)
if (viewz < groundz)
shadowyscale += FixedMul(FixedMul(thing->radius*2 / SHORT(patch->height), scalemul), zslope);
else
shadowyscale -= FixedMul(FixedMul(thing->radius*2 / SHORT(patch->height), scalemul), zslope);
@ -1270,7 +1277,7 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale,
shadow->heightsec = vis->heightsec;
shadow->thingheight = FRACUNIT;
shadow->pz = floorz;
shadow->pz = groundz + (isflipped ? -shadow->thingheight : 0);
shadow->pzt = shadow->pz + shadow->thingheight;
shadow->mobjflags = 0;
@ -1278,7 +1285,7 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale,
shadow->dispoffset = vis->dispoffset - 5;
shadow->gx = thing->x;
shadow->gy = thing->y;
shadow->gzt = shadow->pz + SHORT(patch->height) * shadowyscale / 2;
shadow->gzt = (isflipped ? shadow->pzt : shadow->pz) + SHORT(patch->height) * shadowyscale / 2;
shadow->gz = shadow->gzt - SHORT(patch->height) * shadowyscale;
shadow->texturemid = FixedMul(thing->scale, FixedDiv(shadow->gzt - viewz, shadowyscale));
if (thing->skin && ((skin_t *)thing->skin)->flags & SF_HIRES)
@ -1316,8 +1323,7 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale,
// R_GetPlaneLight won't work on sloped lights!
for (lightnum = 1; lightnum < thing->subsector->sector->numlights; lightnum++) {
fixed_t h = thing->subsector->sector->lightlist[lightnum].slope ? P_GetZAt(thing->subsector->sector->lightlist[lightnum].slope, thing->x, thing->y)
: thing->subsector->sector->lightlist[lightnum].height;
fixed_t h = P_GetLightZAt(&thing->subsector->sector->lightlist[lightnum], thing->x, thing->y);
if (h <= shadow->gzt) {
light = lightnum - 1;
break;
@ -1346,7 +1352,6 @@ static void R_ProjectSprite(mobj_t *thing)
{
mobj_t *oldthing = thing;
fixed_t tr_x, tr_y;
fixed_t gxt, gyt;
fixed_t tx, tz;
fixed_t xscale, yscale, sortscale; //added : 02-02-98 : aaargll..if I were a math-guy!!!
@ -1359,7 +1364,7 @@ static void R_ProjectSprite(mobj_t *thing)
#endif
size_t lump;
size_t rot;
size_t frame, rot;
UINT16 flip;
boolean vflip = (!(thing->eflags & MFE_VERTICALFLIP) != !(thing->frame & FF_VERTICALFLIP));
@ -1399,21 +1404,16 @@ static void R_ProjectSprite(mobj_t *thing)
tr_x = thing->x - viewx;
tr_y = thing->y - viewy;
gxt = FixedMul(tr_x, viewcos);
gyt = -FixedMul(tr_y, viewsin);
tz = gxt-gyt;
tz = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); // near/far distance
// thing is behind view plane?
if (!papersprite && (tz < FixedMul(MINZ, this_scale))) // papersprite clipping is handled later
return;
gxt = -FixedMul(tr_x, viewsin);
gyt = FixedMul(tr_y, viewcos);
basetx = tx = -(gyt + gxt);
basetx = tx = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos); // sideways distance
// too far off the side?
if (!papersprite && abs(tx) > tz<<2) // papersprite clipping is handled later
if (!papersprite && abs(tx) > FixedMul(tz, fovtan)<<2) // papersprite clipping is handled later
return;
// aspect ratio stuff
@ -1426,7 +1426,7 @@ static void R_ProjectSprite(mobj_t *thing)
I_Error("R_ProjectSprite: invalid sprite number %d ", thing->sprite);
#endif
rot = thing->frame&FF_FRAMEMASK;
frame = thing->frame&FF_FRAMEMASK;
//Fab : 02-08-98: 'skin' override spritedef currently used for skin
if (thing->skin && thing->sprite == SPR_PLAY)
@ -1435,15 +1435,15 @@ static void R_ProjectSprite(mobj_t *thing)
#ifdef ROTSPRITE
sprinfo = &((skin_t *)thing->skin)->sprinfo[thing->sprite2];
#endif
if (rot >= sprdef->numframes) {
CONS_Alert(CONS_ERROR, M_GetText("R_ProjectSprite: invalid skins[\"%s\"].sprites[%sSPR2_%s] frame %s\n"), ((skin_t *)thing->skin)->name, ((thing->sprite2 & FF_SPR2SUPER) ? "FF_SPR2SUPER|": ""), spr2names[(thing->sprite2 & ~FF_SPR2SUPER)], sizeu5(rot));
if (frame >= sprdef->numframes) {
CONS_Alert(CONS_ERROR, M_GetText("R_ProjectSprite: invalid skins[\"%s\"].sprites[%sSPR2_%s] frame %s\n"), ((skin_t *)thing->skin)->name, ((thing->sprite2 & FF_SPR2SUPER) ? "FF_SPR2SUPER|": ""), spr2names[(thing->sprite2 & ~FF_SPR2SUPER)], sizeu5(frame));
thing->sprite = states[S_UNKNOWN].sprite;
thing->frame = states[S_UNKNOWN].frame;
sprdef = &sprites[thing->sprite];
#ifdef ROTSPRITE
sprinfo = NULL;
#endif
rot = thing->frame&FF_FRAMEMASK;
frame = thing->frame&FF_FRAMEMASK;
}
}
else
@ -1453,10 +1453,10 @@ static void R_ProjectSprite(mobj_t *thing)
sprinfo = NULL;
#endif
if (rot >= sprdef->numframes)
if (frame >= sprdef->numframes)
{
CONS_Alert(CONS_ERROR, M_GetText("R_ProjectSprite: invalid sprite frame %s/%s for %s\n"),
sizeu1(rot), sizeu2(sprdef->numframes), sprnames[thing->sprite]);
sizeu1(frame), sizeu2(sprdef->numframes), sprnames[thing->sprite]);
if (thing->sprite == thing->state->sprite && thing->frame == thing->state->frame)
{
thing->state->sprite = states[S_UNKNOWN].sprite;
@ -1465,11 +1465,11 @@ static void R_ProjectSprite(mobj_t *thing)
thing->sprite = states[S_UNKNOWN].sprite;
thing->frame = states[S_UNKNOWN].frame;
sprdef = &sprites[thing->sprite];
rot = thing->frame&FF_FRAMEMASK;
frame = thing->frame&FF_FRAMEMASK;
}
}
sprframe = &sprdef->spriteframes[rot];
sprframe = &sprdef->spriteframes[frame];
#ifdef PARANOIA
if (!sprframe)
@ -1523,7 +1523,7 @@ static void R_ProjectSprite(mobj_t *thing)
{
rollangle = R_GetRollAngle(thing->rollangle);
if (!(sprframe->rotsprite.cached & (1<<rot)))
R_CacheRotSprite(thing->sprite, (thing->frame & FF_FRAMEMASK), sprinfo, sprframe, rot, flip);
R_CacheRotSprite(thing->sprite, frame, sprinfo, sprframe, rot, flip);
rotsprite = sprframe->rotsprite.patch[rot][rollangle];
if (rotsprite != NULL)
{
@ -1561,17 +1561,9 @@ static void R_ProjectSprite(mobj_t *thing)
tr_x += FixedMul(offset, cosmul);
tr_y += FixedMul(offset, sinmul);
gxt = FixedMul(tr_x, viewcos);
gyt = -FixedMul(tr_y, viewsin);
tz = gxt-gyt;
yscale = FixedDiv(projectiony, tz);
//if (yscale < 64) return; // Fix some funky visuals
tz = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin);
gxt = -FixedMul(tr_x, viewsin);
gyt = FixedMul(tr_y, viewcos);
tx = -(gyt + gxt);
xscale = FixedDiv(projection, tz);
x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS;
tx = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos);
// Get paperoffset (offset) and paperoffset (distance)
paperoffset = -FixedMul(tr_x, cosmul) - FixedMul(tr_y, sinmul);
@ -1585,17 +1577,9 @@ static void R_ProjectSprite(mobj_t *thing)
tr_x += FixedMul(offset2, cosmul);
tr_y += FixedMul(offset2, sinmul);
gxt = FixedMul(tr_x, viewcos);
gyt = -FixedMul(tr_y, viewsin);
tz2 = gxt-gyt;
yscale2 = FixedDiv(projectiony, tz2);
//if (yscale2 < 64) return; // ditto
tz2 = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin);
gxt = -FixedMul(tr_x, viewsin);
gyt = FixedMul(tr_y, viewcos);
tx2 = -(gyt + gxt);
xscale2 = FixedDiv(projection, tz2);
x2 = ((centerxfrac + FixedMul(tx2,xscale2))>>FRACBITS);
tx2 = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos);
if (max(tz, tz2) < FixedMul(MINZ, this_scale)) // non-papersprite clipping is handled earlier
return;
@ -1606,24 +1590,31 @@ static void R_ProjectSprite(mobj_t *thing)
fixed_t div = FixedDiv(tz2-tz, FixedMul(MINZ, this_scale)-tz);
tx += FixedDiv(tx2-tx, div);
tz = FixedMul(MINZ, this_scale);
yscale = FixedDiv(projectiony, tz);
xscale = FixedDiv(projection, tz);
x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS;
}
else if (tz2 < FixedMul(MINZ, this_scale))
{
fixed_t div = FixedDiv(tz-tz2, FixedMul(MINZ, this_scale)-tz2);
tx2 += FixedDiv(tx-tx2, div);
tz2 = FixedMul(MINZ, this_scale);
yscale2 = FixedDiv(projectiony, tz2);
xscale2 = FixedDiv(projection, tz2);
x2 = (centerxfrac + FixedMul(tx2,xscale2))>>FRACBITS;
}
if (tx2 < -(FixedMul(tz2, fovtan)<<2) || tx > FixedMul(tz, fovtan)<<2) // too far off the side?
return;
yscale = FixedDiv(projectiony, tz);
xscale = FixedDiv(projection, tz);
x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS;
// off the right side?
if (x1 > viewwidth)
return;
yscale2 = FixedDiv(projectiony, tz2);
xscale2 = FixedDiv(projection, tz2);
x2 = (centerxfrac + FixedMul(tx2,xscale2))>>FRACBITS;
// off the left side
if (x2 < 0)
return;
@ -1670,9 +1661,7 @@ static void R_ProjectSprite(mobj_t *thing)
tr_x = thing->x - viewx;
tr_y = thing->y - viewy;
gxt = FixedMul(tr_x, viewcos);
gyt = -FixedMul(tr_y, viewsin);
tz = gxt-gyt;
tz = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin);
linkscale = FixedDiv(projectiony, tz);
if (tz < FixedMul(MINZ, this_scale))
@ -1688,7 +1677,7 @@ static void R_ProjectSprite(mobj_t *thing)
// PORTAL SPRITE CLIPPING
if (portalrender && portalclipline)
{
if (x2 < portalclipstart || x1 > portalclipend)
if (x2 < portalclipstart || x1 >= portalclipend)
return;
if (P_PointOnLineSide(thing->x, thing->y, portalclipline) != 0)
@ -1723,8 +1712,7 @@ static void R_ProjectSprite(mobj_t *thing)
// R_GetPlaneLight won't work on sloped lights!
for (lightnum = 1; lightnum < thing->subsector->sector->numlights; lightnum++) {
fixed_t h = thing->subsector->sector->lightlist[lightnum].slope ? P_GetZAt(thing->subsector->sector->lightlist[lightnum].slope, thing->x, thing->y)
: thing->subsector->sector->lightlist[lightnum].height;
fixed_t h = P_GetLightZAt(&thing->subsector->sector->lightlist[lightnum], thing->x, thing->y);
if (h <= gzt) {
light = lightnum - 1;
break;
@ -1873,7 +1861,6 @@ static void R_ProjectSprite(mobj_t *thing)
static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
{
fixed_t tr_x, tr_y;
fixed_t gxt, gyt;
fixed_t tx, tz;
fixed_t xscale, yscale; //added : 02-02-98 : aaargll..if I were a math-guy!!!
@ -1894,21 +1881,16 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
tr_x = thing->x - viewx;
tr_y = thing->y - viewy;
gxt = FixedMul(tr_x, viewcos);
gyt = -FixedMul(tr_y, viewsin);
tz = gxt - gyt;
tz = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); // near/far distance
// thing is behind view plane?
if (tz < MINZ)
return;
gxt = -FixedMul(tr_x, viewsin);
gyt = FixedMul(tr_y, viewcos);
tx = -(gyt + gxt);
tx = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos); // sideways distance
// too far off the side?
if (abs(tx) > tz<<2)
if (abs(tx) > FixedMul(tz, fovtan)<<2)
return;
// aspect ratio stuff :
@ -1958,7 +1940,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
// PORTAL SPRITE CLIPPING
if (portalrender && portalclipline)
{
if (x2 < portalclipstart || x1 > portalclipend)
if (x2 < portalclipstart || x1 >= portalclipend)
return;
if (P_PointOnLineSide(thing->x, thing->y, portalclipline) != 0)
@ -2377,12 +2359,8 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps
continue;
// Effective height may be different for each comparison in the case of slopes
if (r2->plane->slope) {
planeobjectz = P_GetZAt(r2->plane->slope, rover->gx, rover->gy);
planecameraz = P_GetZAt(r2->plane->slope, viewx, viewy);
}
else
planeobjectz = planecameraz = r2->plane->height;
planeobjectz = P_GetZAt(r2->plane->slope, rover->gx, rover->gy, r2->plane->height);
planecameraz = P_GetZAt(r2->plane->slope, viewx, viewy, r2->plane->height);
if (rover->mobjflags & MF_NOCLIPHEIGHT)
{
@ -2440,19 +2418,10 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps
if (scale <= rover->sortscale)
continue;
if (*r2->ffloor->t_slope) {
topplaneobjectz = P_GetZAt(*r2->ffloor->t_slope, rover->gx, rover->gy);
topplanecameraz = P_GetZAt(*r2->ffloor->t_slope, viewx, viewy);
}
else
topplaneobjectz = topplanecameraz = *r2->ffloor->topheight;
if (*r2->ffloor->b_slope) {
botplaneobjectz = P_GetZAt(*r2->ffloor->b_slope, rover->gx, rover->gy);
botplanecameraz = P_GetZAt(*r2->ffloor->b_slope, viewx, viewy);
}
else
botplaneobjectz = botplanecameraz = *r2->ffloor->bottomheight;
topplaneobjectz = P_GetFFloorTopZAt (r2->ffloor, rover->gx, rover->gy);
topplanecameraz = P_GetFFloorTopZAt (r2->ffloor, viewx, viewy);
botplaneobjectz = P_GetFFloorBottomZAt(r2->ffloor, rover->gx, rover->gy);
botplanecameraz = P_GetFFloorBottomZAt(r2->ffloor, viewx, viewy);
if ((topplanecameraz > viewz && botplanecameraz < viewz) ||
(topplanecameraz < viewz && rover->gzt < topplaneobjectz) ||

View file

@ -338,6 +338,7 @@
<ClCompile Include="..\blua\lfunc.c" />
<ClCompile Include="..\blua\lgc.c" />
<ClCompile Include="..\blua\linit.c" />
<ClCompile Include="..\blua\liolib.c" />
<ClCompile Include="..\blua\llex.c" />
<ClCompile Include="..\blua\lmem.c" />
<ClCompile Include="..\blua\lobject.c" />

View file

@ -534,6 +534,9 @@
<ClCompile Include="..\blua\linit.c">
<Filter>BLUA</Filter>
</ClCompile>
<ClCompile Include="..\blua\liolib.c">
<Filter>BLUA</Filter>
</ClCompile>
<ClCompile Include="..\blua\llex.c">
<Filter>BLUA</Filter>
</ClCompile>

View file

@ -103,6 +103,93 @@ static inline VOID MakeCodeWritable(VOID)
}
#endif
#ifdef LOGMESSAGES
static void InitLogging(void)
{
const char *logdir = NULL;
time_t my_time;
struct tm * timeinfo;
const char *format;
const char *reldir;
int left;
boolean fileabs;
#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON)
const char *link;
#endif
logdir = D_Home();
my_time = time(NULL);
timeinfo = localtime(&my_time);
if (M_CheckParm("-logfile") && M_IsNextParm())
{
format = M_GetNextParm();
fileabs = M_IsPathAbsolute(format);
}
else
{
format = "log-%Y-%m-%d_%H-%M-%S.txt";
fileabs = false;
}
if (fileabs)
{
strftime(logfilename, sizeof logfilename, format, timeinfo);
}
else
{
if (M_CheckParm("-logdir") && M_IsNextParm())
reldir = M_GetNextParm();
else
reldir = "logs";
if (M_IsPathAbsolute(reldir))
{
left = snprintf(logfilename, sizeof logfilename,
"%s"PATHSEP, reldir);
}
else
#ifdef DEFAULTDIR
if (logdir)
{
left = snprintf(logfilename, sizeof logfilename,
"%s"PATHSEP DEFAULTDIR PATHSEP"%s"PATHSEP, logdir, reldir);
}
else
#endif/*DEFAULTDIR*/
{
left = snprintf(logfilename, sizeof logfilename,
"."PATHSEP"%s"PATHSEP, reldir);
}
strftime(&logfilename[left], sizeof logfilename - left,
format, timeinfo);
}
M_MkdirEachUntil(logfilename,
M_PathParts(logdir) - 1,
M_PathParts(logfilename) - 1, 0755);
#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON)
logstream = fopen(logfilename, "w");
#ifdef DEFAULTDIR
if (logdir)
link = va("%s/"DEFAULTDIR"/latest-log.txt", logdir);
else
#endif/*DEFAULTDIR*/
link = "latest-log.txt";
unlink(link);
if (symlink(logfilename, link) == -1)
{
I_OutputMsg("Error symlinking latest-log.txt: %s\n", strerror(errno));
}
#else/*defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON)*/
logstream = fopen("latest-log.txt", "wt+");
#endif/*defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON)*/
}
#endif
/** \brief The main function
@ -121,7 +208,6 @@ int SDL_main(int argc, char **argv)
int main(int argc, char **argv)
#endif
{
const char *logdir = NULL;
myargc = argc;
myargv = argv; /// \todo pull out path to exe from this string
@ -135,90 +221,9 @@ int main(int argc, char **argv)
#ifdef LOGMESSAGES
if (!M_CheckParm("-nolog"))
{
time_t my_time;
struct tm * timeinfo;
const char *format;
const char *reldir;
int left;
boolean fileabs;
#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON)
const char *link;
#endif
logdir = D_Home();
my_time = time(NULL);
timeinfo = localtime(&my_time);
if (M_CheckParm("-logfile") && M_IsNextParm())
{
format = M_GetNextParm();
fileabs = M_IsPathAbsolute(format);
}
else
{
format = "log-%Y-%m-%d_%H-%M-%S.txt";
fileabs = false;
}
if (fileabs)
{
strftime(logfilename, sizeof logfilename, format, timeinfo);
}
else
{
if (M_CheckParm("-logdir") && M_IsNextParm())
reldir = M_GetNextParm();
else
reldir = "logs";
if (M_IsPathAbsolute(reldir))
{
left = snprintf(logfilename, sizeof logfilename,
"%s"PATHSEP, reldir);
}
else
#ifdef DEFAULTDIR
if (logdir)
{
left = snprintf(logfilename, sizeof logfilename,
"%s"PATHSEP DEFAULTDIR PATHSEP"%s"PATHSEP, logdir, reldir);
}
else
#endif/*DEFAULTDIR*/
{
left = snprintf(logfilename, sizeof logfilename,
"."PATHSEP"%s"PATHSEP, reldir);
}
InitLogging();
#endif/*LOGMESSAGES*/
strftime(&logfilename[left], sizeof logfilename - left,
format, timeinfo);
}
M_MkdirEachUntil(logfilename,
M_PathParts(logdir) - 1,
M_PathParts(logfilename) - 1, 0755);
#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON)
logstream = fopen(logfilename, "w");
#ifdef DEFAULTDIR
if (logdir)
link = va("%s/"DEFAULTDIR"/latest-log.txt", logdir);
else
#endif/*DEFAULTDIR*/
link = "latest-log.txt";
unlink(link);
if (symlink(logfilename, link) == -1)
{
I_OutputMsg("Error symlinking latest-log.txt: %s\n", strerror(errno));
}
#else/*defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON)*/
logstream = fopen("latest-log.txt", "wt+");
#endif/*defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON)*/
}
//I_OutputMsg("I_StartupSystem() ...\n");
I_StartupSystem();
#if defined (_WIN32)

View file

@ -178,6 +178,8 @@ static char returnWadPath[256];
#include "../m_argv.h"
#include "../m_menu.h"
#ifdef MAC_ALERT
#include "macosx/mac_alert.h"
#endif
@ -2293,6 +2295,7 @@ void I_Quit(void)
G_StopMetalRecording(false);
D_QuitNetGame();
M_FreePlayerSetupColors();
I_ShutdownMusic();
I_ShutdownSound();
I_ShutdownCD();
@ -2409,6 +2412,7 @@ void I_Error(const char *error, ...)
G_StopMetalRecording(false);
D_QuitNetGame();
M_FreePlayerSetupColors();
I_ShutdownMusic();
I_ShutdownSound();
I_ShutdownCD();

View file

@ -217,7 +217,6 @@ static void SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen, SDL_bool
else
{
Impl_CreateWindow(fullscreen);
Impl_SetWindowIcon();
wasfullscreen = fullscreen;
SDL_SetWindowSize(window, width, height);
if (fullscreen)
@ -374,7 +373,8 @@ static boolean IgnoreMouse(void)
return !M_MouseNeeded();
if (paused || con_destlines || chat_on)
return true;
if (gamestate != GS_LEVEL && gamestate != GS_INTERMISSION && gamestate != GS_CUTSCENE)
if (gamestate != GS_LEVEL && gamestate != GS_INTERMISSION &&
gamestate != GS_CONTINUING && gamestate != GS_CUTSCENE)
return true;
return false;
}
@ -1632,12 +1632,15 @@ static SDL_bool Impl_CreateWindow(SDL_bool fullscreen)
window = SDL_CreateWindow("SRB2 "VERSIONSTRING, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
realwidth, realheight, flags);
if (window == NULL)
{
CONS_Printf(M_GetText("Couldn't create window: %s\n"), SDL_GetError());
return SDL_FALSE;
}
Impl_SetWindowIcon();
return Impl_CreateContext();
}
@ -1654,12 +1657,8 @@ static void Impl_SetWindowName(const char *title)
static void Impl_SetWindowIcon(void)
{
if (window == NULL || icoSurface == NULL)
{
return;
}
//SDL2STUB(); // Monster Iestyn: why is this stubbed?
SDL_SetWindowIcon(window, icoSurface);
if (window && icoSurface)
SDL_SetWindowIcon(window, icoSurface);
}
static void Impl_VideoSetupSDLBuffer(void)
@ -1766,6 +1765,11 @@ void I_StartupGraphics(void)
VID_StartupOpenGL();
#endif
// Window icon
#ifdef HAVE_IMAGE
icoSurface = IMG_ReadXPMFromArray(SDL_icon_xpm);
#endif
// Fury: we do window initialization after GL setup to allow
// SDL_GL_LoadLibrary to work well on Windows
@ -1784,11 +1788,6 @@ void I_StartupGraphics(void)
#ifdef HAVE_TTF
I_ShutdownTTF();
#endif
// Window icon
#ifdef HAVE_IMAGE
icoSurface = IMG_ReadXPMFromArray(SDL_icon_xpm);
#endif
Impl_SetWindowIcon();
VID_SetMode(VID_GetModeForSize(BASEVIDWIDTH, BASEVIDHEIGHT));

View file

@ -456,7 +456,7 @@ boolean st_overlay;
//
// Supports different colors! woo!
static void ST_DrawNightsOverlayNum(fixed_t x /* right border */, fixed_t y, fixed_t s, INT32 a,
UINT32 num, patch_t **numpat, skincolors_t colornum)
UINT32 num, patch_t **numpat, skincolornum_t colornum)
{
fixed_t w = SHORT(numpat[0]->width)*s;
const UINT8 *colormap;
@ -992,7 +992,7 @@ static void ST_drawLivesArea(void)
static void ST_drawInput(void)
{
const INT32 accent = V_SNAPTOLEFT|V_SNAPTOBOTTOM|(stplyr->skincolor ? Color_Index[stplyr->skincolor-1][4] : 0);
const INT32 accent = V_SNAPTOLEFT|V_SNAPTOBOTTOM|(stplyr->skincolor ? skincolors[stplyr->skincolor].ramp[4] : 0);
INT32 col;
UINT8 offs;
@ -1325,7 +1325,7 @@ void ST_drawTitleCard(void)
{
char *lvlttl = mapheaderinfo[gamemap-1]->lvlttl;
char *subttl = mapheaderinfo[gamemap-1]->subttl;
INT32 actnum = mapheaderinfo[gamemap-1]->actnum;
UINT8 actnum = mapheaderinfo[gamemap-1]->actnum;
INT32 lvlttlxpos, ttlnumxpos, zonexpos;
INT32 subttlxpos = BASEVIDWIDTH/2;
INT32 ttlscroll = FixedInt(lt_scroll);
@ -1382,7 +1382,12 @@ void ST_drawTitleCard(void)
if (actnum)
{
if (!splitscreen)
V_DrawMappedPatch(ttlnumxpos + ttlscroll, 104 - ttlscroll, 0, actpat, colormap);
{
if (actnum > 9) // slightly offset the act diamond for two-digit act numbers
V_DrawMappedPatch(ttlnumxpos + (V_LevelActNumWidth(actnum)/4) + ttlscroll, 104 - ttlscroll, 0, actpat, colormap);
else
V_DrawMappedPatch(ttlnumxpos + ttlscroll, 104 - ttlscroll, 0, actpat, colormap);
}
V_DrawLevelActNum(ttlnumxpos + ttlscroll, 104, V_PERPLAYER, actnum);
}
@ -1695,14 +1700,14 @@ static void ST_drawNightsRecords(void)
// 2.0-1: [21:42] <+Rob> Beige - Lavender - Steel Blue - Peach - Orange - Purple - Silver - Yellow - Pink - Red - Blue - Green - Cyan - Gold
/*#define NUMLINKCOLORS 14
static skincolors_t linkColor[NUMLINKCOLORS] =
static skincolornum_t linkColor[NUMLINKCOLORS] =
{SKINCOLOR_BEIGE, SKINCOLOR_LAVENDER, SKINCOLOR_AZURE, SKINCOLOR_PEACH, SKINCOLOR_ORANGE,
SKINCOLOR_MAGENTA, SKINCOLOR_SILVER, SKINCOLOR_SUPERGOLD4, SKINCOLOR_PINK, SKINCOLOR_RED,
SKINCOLOR_BLUE, SKINCOLOR_GREEN, SKINCOLOR_CYAN, SKINCOLOR_GOLD};*/
// 2.2 indev list: (unix time 1470866042) <Rob> Emerald, Aqua, Cyan, Blue, Pastel, Purple, Magenta, Rosy, Red, Orange, Gold, Yellow, Peridot
/*#define NUMLINKCOLORS 13
static skincolors_t linkColor[NUMLINKCOLORS] =
static skincolornum_t linkColor[NUMLINKCOLORS] =
{SKINCOLOR_EMERALD, SKINCOLOR_AQUA, SKINCOLOR_CYAN, SKINCOLOR_BLUE, SKINCOLOR_PASTEL,
SKINCOLOR_PURPLE, SKINCOLOR_MAGENTA, SKINCOLOR_ROSY, SKINCOLOR_RED, SKINCOLOR_ORANGE,
SKINCOLOR_GOLD, SKINCOLOR_YELLOW, SKINCOLOR_PERIDOT};*/
@ -1711,7 +1716,7 @@ static skincolors_t linkColor[NUMLINKCOLORS] =
// [20:00:25] <baldobo> Also Icy for the link freeze text color
// [20:04:03] <baldobo> I would start it on lime
/*#define NUMLINKCOLORS 18
static skincolors_t linkColor[NUMLINKCOLORS] =
static skincolornum_t linkColor[NUMLINKCOLORS] =
{SKINCOLOR_LIME, SKINCOLOR_EMERALD, SKINCOLOR_AQUA, SKINCOLOR_CYAN, SKINCOLOR_SKY,
SKINCOLOR_SAPPHIRE, SKINCOLOR_PASTEL, SKINCOLOR_PURPLE, SKINCOLOR_BUBBLEGUM, SKINCOLOR_MAGENTA,
SKINCOLOR_ROSY, SKINCOLOR_RUBY, SKINCOLOR_RED, SKINCOLOR_FLAME, SKINCOLOR_SUNSET,
@ -1719,7 +1724,7 @@ static skincolors_t linkColor[NUMLINKCOLORS] =
// 2.2+ list for real this time: https://wiki.srb2.org/wiki/User:Rob/Sandbox (check history around 31/10/17, spoopy)
#define NUMLINKCOLORS 12
static skincolors_t linkColor[2][NUMLINKCOLORS] = {
static skincolornum_t linkColor[2][NUMLINKCOLORS] = {
{SKINCOLOR_EMERALD, SKINCOLOR_AQUA, SKINCOLOR_SKY, SKINCOLOR_BLUE, SKINCOLOR_PURPLE, SKINCOLOR_MAGENTA,
SKINCOLOR_ROSY, SKINCOLOR_RED, SKINCOLOR_ORANGE, SKINCOLOR_GOLD, SKINCOLOR_YELLOW, SKINCOLOR_PERIDOT},
{SKINCOLOR_SEAFOAM, SKINCOLOR_CYAN, SKINCOLOR_WAVE, SKINCOLOR_SAPPHIRE, SKINCOLOR_VAPOR, SKINCOLOR_BUBBLEGUM,
@ -1730,7 +1735,7 @@ static void ST_drawNiGHTSLink(void)
static INT32 prevsel[2] = {0, 0}, prevtime[2] = {0, 0};
const UINT8 q = ((splitscreen && stplyr == &players[secondarydisplayplayer]) ? 1 : 0);
INT32 sel = ((stplyr->linkcount-1) / 5) % NUMLINKCOLORS, aflag = V_PERPLAYER, mag = ((stplyr->linkcount-1 >= 300) ? 1 : 0);
skincolors_t colornum;
skincolornum_t colornum;
fixed_t x, y, scale;
if (sel != prevsel[q])

View file

@ -72,7 +72,7 @@ static FUNCMATH angle_t AngleAdj(const fixed_t fa, const fixed_t wf,
const angle_t adj = 0x77;
const boolean fan = fa < 0;
const fixed_t sl = FixedDiv(fa, wf*2);
const fixed_t lb = FixedRem(fa, wf*2);
const fixed_t lb = fa % (wf*2);
const fixed_t lo = (wf*2)-lb;
if (ra == 0)

View file

@ -1040,7 +1040,7 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_
// V_DrawContinueIcon
// Draw a mini player! If we can, that is. Otherwise we draw a star.
//
void V_DrawContinueIcon(INT32 x, INT32 y, INT32 flags, INT32 skinnum, UINT8 skincolor)
void V_DrawContinueIcon(INT32 x, INT32 y, INT32 flags, INT32 skinnum, UINT16 skincolor)
{
if (skinnum >= 0 && skinnum < numskins && skins[skinnum].sprites[SPR2_XTRA].numframes > XTRA_CONTINUE)
{
@ -2952,13 +2952,19 @@ void V_DrawPaddedTallNum(INT32 x, INT32 y, INT32 flags, INT32 num, INT32 digits)
}
// Draw an act number for a level title
// Todo: actually draw two-digit numbers as two act num patches
void V_DrawLevelActNum(INT32 x, INT32 y, INT32 flags, INT32 num)
void V_DrawLevelActNum(INT32 x, INT32 y, INT32 flags, UINT8 num)
{
if (num < 0 || num > 19)
if (num > 99)
return; // not supported
V_DrawScaledPatch(x, y, flags, ttlnum[num]);
while (num > 0)
{
if (num > 9) // if there are two digits, draw second digit first
V_DrawScaledPatch(x + (V_LevelActNumWidth(num) - V_LevelActNumWidth(num%10)), y, flags, ttlnum[num%10]);
else
V_DrawScaledPatch(x, y, flags, ttlnum[num]);
num = num/10;
}
}
// Write a string using the credit font
@ -3339,13 +3345,21 @@ INT32 V_LevelNameHeight(const char *string)
}
// For ST_drawTitleCard
// Returns the width of the act num patch
INT32 V_LevelActNumWidth(INT32 num)
// Returns the width of the act num patch(es)
INT16 V_LevelActNumWidth(UINT8 num)
{
if (num < 0 || num > 19)
return 0; // not a valid number
INT16 result = 0;
return SHORT(ttlnum[num]->width);
if (num == 0)
result = SHORT(ttlnum[num]->width);
while (num > 0 && num <= 99)
{
result = result + SHORT(ttlnum[num%10]->width);
num = num/10;
}
return result;
}
//
@ -3696,7 +3710,7 @@ void V_Init(void)
#ifdef DEBUG
CONS_Debug(DBG_RENDER, "V_Init done:\n");
for (i = 0; i < NUMSCREENS+1; i++)
for (i = 0; i < NUMSCREENS; i++)
CONS_Debug(DBG_RENDER, " screens[%d] = %x\n", i, screens[i]);
#endif
}

View file

@ -160,7 +160,7 @@ void V_CubeApply(UINT8 *red, UINT8 *green, UINT8 *blue);
void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 scrn, patch_t *patch, const UINT8 *colormap);
void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_t *patch, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h);
void V_DrawContinueIcon(INT32 x, INT32 y, INT32 flags, INT32 skinnum, UINT8 skincolor);
void V_DrawContinueIcon(INT32 x, INT32 y, INT32 flags, INT32 skinnum, UINT16 skincolor);
// Draw a linear block of pixels into the view buffer.
void V_DrawBlock(INT32 x, INT32 y, INT32 scrn, INT32 width, INT32 height, const UINT8 *src);
@ -238,12 +238,12 @@ void V_DrawRightAlignedSmallThinStringAtFixed(fixed_t x, fixed_t y, INT32 option
// Draw tall nums, used for menu, HUD, intermission
void V_DrawTallNum(INT32 x, INT32 y, INT32 flags, INT32 num);
void V_DrawPaddedTallNum(INT32 x, INT32 y, INT32 flags, INT32 num, INT32 digits);
void V_DrawLevelActNum(INT32 x, INT32 y, INT32 flags, INT32 num);
void V_DrawLevelActNum(INT32 x, INT32 y, INT32 flags, UINT8 num);
// Find string width from lt_font chars
INT32 V_LevelNameWidth(const char *string);
INT32 V_LevelNameHeight(const char *string);
INT32 V_LevelActNumWidth(INT32 num); // act number width
INT16 V_LevelActNumWidth(UINT8 num); // act number width
void V_DrawCreditString(fixed_t x, fixed_t y, INT32 option, const char *string);
INT32 V_CreditStringWidth(const char *string);

View file

@ -643,37 +643,28 @@ int WINAPI WinMain (HINSTANCE hInstance,
int nCmdShow)
{
int Result = -1;
#if 0
// Win95 and NT <4 don't have this, so link at runtime.
p_IsDebuggerPresent pfnIsDebuggerPresent = (p_IsDebuggerPresent)GetProcAddress(GetModuleHandleA("kernel32.dll"),"IsDebuggerPresent");
#endif
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
UNREFERENCED_PARAMETER(nCmdShow);
#if 0
#ifdef BUGTRAP
// Try BugTrap first.
if((!pfnIsDebuggerPresent || !pfnIsDebuggerPresent()) && InitBugTrap())
Result = HandledWinMain(hInstance);
else
{
#endif
// Try Dr MinGW's exception handler.
if (!pfnIsDebuggerPresent || !pfnIsDebuggerPresent())
#endif
LoadLibraryA("exchndl.dll");
#ifndef __MINGW32__
prevExceptionFilter = SetUnhandledExceptionFilter(RecordExceptionInfo);
#endif
Result = HandledWinMain(hInstance);
#if 0
p_IsDebuggerPresent pfnIsDebuggerPresent = (p_IsDebuggerPresent)GetProcAddress(GetModuleHandleA("kernel32.dll"),"IsDebuggerPresent");
if((!pfnIsDebuggerPresent || !pfnIsDebuggerPresent())
#ifdef BUGTRAP
&& !InitBugTrap()
#endif
)
#endif
{
LoadLibraryA("exchndl.dll");
}
}
#ifndef __MINGW32__
prevExceptionFilter = SetUnhandledExceptionFilter(RecordExceptionInfo);
#endif
Result = HandledWinMain(hInstance);
#ifdef BUGTRAP
} // BT failure clause.
// This is safe even if BT didn't start.
ShutdownBugTrap();
#endif

View file

@ -54,6 +54,8 @@
#include "../screen.h"
#include "../m_menu.h"
// Wheel support for Win95/WinNT3.51
#include <zmouse.h>
@ -650,6 +652,7 @@ void I_Error(const char *error, ...)
G_StopMetalRecording(false);
D_QuitNetGame();
M_FreePlayerSetupColors();
// shutdown everything that was started
I_ShutdownSystem();
@ -746,6 +749,8 @@ void I_Quit(void)
// so do it before.
D_QuitNetGame();
M_FreePlayerSetupColors();
// shutdown everything that was started
I_ShutdownSystem();

View file

@ -73,7 +73,7 @@ typedef union
UINT32 score, total; // fake score, total
UINT32 tics; // time
INT32 actnum; // act number being displayed
UINT8 actnum; // act number being displayed
patch_t *ptotal; // TOTAL
UINT8 gotlife; // Number of extra lives obtained
} coop;
@ -99,7 +99,7 @@ typedef union
UINT8 continues;
patch_t *pcontinues;
INT32 *playerchar; // Continue HUD
UINT8 *playercolor;
UINT16 *playercolor;
UINT8 gotlife; // Number of extra lives obtained
} spec;
@ -107,7 +107,7 @@ typedef union
struct
{
UINT32 scores[MAXPLAYERS]; // Winner's score
UINT8 *color[MAXPLAYERS]; // Winner's color #
UINT16 *color[MAXPLAYERS]; // Winner's color #
boolean spectator[MAXPLAYERS]; // Spectator list
INT32 *character[MAXPLAYERS]; // Winner's character #
INT32 num[MAXPLAYERS]; // Winner's player #
@ -121,7 +121,7 @@ typedef union
struct
{
UINT8 *color[MAXPLAYERS]; // Winner's color #
UINT16 *color[MAXPLAYERS]; // Winner's color #
INT32 *character[MAXPLAYERS]; // Winner's character #
INT32 num[MAXPLAYERS]; // Winner's player #
char name[MAXPLAYERS][9]; // Winner's name