Merge remote-tracking branch 'origin/master' into newmenus

This commit is contained in:
Jaime Passos 2019-09-11 22:17:42 -03:00
commit f2915817a7
55 changed files with 3106 additions and 1238 deletions

View file

@ -152,7 +152,7 @@ ticcmd_t netcmds[BACKUPTICS][MAXPLAYERS];
static textcmdtic_t *textcmds[TEXTCMD_HASH_SIZE] = {NULL};
static consvar_t cv_showjoinaddress = {"showjoinaddress", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_showjoinaddress = {"showjoinaddress", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t playbackspeed_cons_t[] = {{1, "MIN"}, {10, "MAX"}, {0, NULL}};
consvar_t cv_playbackspeed = {"playbackspeed", "1", 0, playbackspeed_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
@ -579,6 +579,7 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i)
rsp->starpostnum = LONG(players[i].starpostnum);
rsp->starposttime = (tic_t)LONG(players[i].starposttime);
rsp->starpostangle = (angle_t)LONG(players[i].starpostangle);
rsp->starpostscale = (fixed_t)LONG(players[i].starpostscale);
rsp->maxlink = LONG(players[i].maxlink);
rsp->dashspeed = (fixed_t)LONG(players[i].dashspeed);
@ -714,6 +715,7 @@ static void resynch_read_player(resynch_pak *rsp)
players[i].starpostnum = LONG(rsp->starpostnum);
players[i].starposttime = (tic_t)LONG(rsp->starposttime);
players[i].starpostangle = (angle_t)LONG(rsp->starpostangle);
players[i].starpostscale = (fixed_t)LONG(rsp->starpostscale);
players[i].maxlink = LONG(rsp->maxlink);
players[i].dashspeed = (fixed_t)LONG(rsp->dashspeed);
@ -2946,13 +2948,13 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
CL_RemovePlayer(pnum, kickreason);
}
consvar_t cv_allownewplayer = {"allowjoin", "On", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL };
consvar_t cv_joinnextround = {"joinnextround", "Off", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; /// \todo not done
consvar_t cv_allownewplayer = {"allowjoin", "On", CV_SAVE|CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL };
consvar_t cv_joinnextround = {"joinnextround", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; /// \todo not done
static CV_PossibleValue_t maxplayers_cons_t[] = {{2, "MIN"}, {32, "MAX"}, {0, NULL}};
consvar_t cv_maxplayers = {"maxplayers", "8", CV_SAVE, maxplayers_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t resynchattempts_cons_t[] = {{0, "MIN"}, {20, "MAX"}, {0, NULL}};
consvar_t cv_resynchattempts = {"resynchattempts", "10", 0, resynchattempts_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL };
consvar_t cv_blamecfail = {"blamecfail", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL };
consvar_t cv_resynchattempts = {"resynchattempts", "10", CV_SAVE, resynchattempts_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL };
consvar_t cv_blamecfail = {"blamecfail", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL };
// max file size to send to a player (in kilobytes)
static CV_PossibleValue_t maxsend_cons_t[] = {{0, "MIN"}, {51200, "MAX"}, {0, NULL}};
@ -2993,11 +2995,6 @@ void D_ClientServerInit(void)
RegisterNetXCmd(XD_KICK, Got_KickCmd);
RegisterNetXCmd(XD_ADDPLAYER, Got_AddPlayer);
#ifndef NONET
CV_RegisterVar(&cv_allownewplayer);
CV_RegisterVar(&cv_joinnextround);
CV_RegisterVar(&cv_showjoinaddress);
CV_RegisterVar(&cv_resynchattempts);
CV_RegisterVar(&cv_blamecfail);
#ifdef DUMPCONSISTENCY
CV_RegisterVar(&cv_dumpconsistency);
#endif

View file

@ -228,6 +228,7 @@ typedef struct
INT32 starpostnum;
tic_t starposttime;
angle_t starpostangle;
fixed_t starpostscale;
INT32 maxlink;
fixed_t dashspeed;
@ -444,6 +445,7 @@ extern INT32 mapchangepending;
// Points inside doomcom
extern doomdata_t *netbuffer;
extern consvar_t cv_showjoinaddress;
extern consvar_t cv_playbackspeed;
#define BASEPACKETSIZE offsetof(doomdata_t, u)

View file

@ -287,7 +287,7 @@ static void D_Display(void)
F_TitleScreenDrawer();
break;
}
// Intentional fall-through
/* FALLTHRU */
case GS_LEVEL:
if (!gametic)
break;

View file

@ -556,9 +556,16 @@ void D_RegisterServerCommands(void)
// d_clisrv
CV_RegisterVar(&cv_maxplayers);
CV_RegisterVar(&cv_resynchattempts);
CV_RegisterVar(&cv_maxsend);
CV_RegisterVar(&cv_noticedownload);
CV_RegisterVar(&cv_downloadspeed);
#ifndef NONET
CV_RegisterVar(&cv_allownewplayer);
CV_RegisterVar(&cv_joinnextround);
CV_RegisterVar(&cv_showjoinaddress);
CV_RegisterVar(&cv_blamecfail);
#endif
COM_AddCommand("ping", Command_Ping_f);
CV_RegisterVar(&cv_nettimeout);

View file

@ -441,6 +441,7 @@ typedef struct player_s
INT32 starpostnum; // The number of the last starpost you hit
tic_t starposttime; // Your time when you hit the starpost
angle_t starpostangle; // Angle that the starpost is facing - you respawn facing this way
fixed_t starpostscale; // Scale of the player; if negative, player is gravflipped
/////////////////
// NiGHTS Stuff//

View file

@ -1190,6 +1190,20 @@ static void readlevelheader(MYFILE *f, INT32 num)
mapheaderinfo[num-1]->muspostbosspos = (UINT32)get_number(word2);
else if (fastcmp(word, "MUSICPOSTBOSSFADEIN"))
mapheaderinfo[num-1]->muspostbossfadein = (UINT32)get_number(word2);
else if (fastcmp(word, "FORCERESETMUSIC"))
{
// This is a weird one because "FALSE"/"NO" could either apply to "leave to default preference" (cv_resetmusic)
// or "force off". Let's assume it means "force off", and let an unspecified value mean "default preference"
if (fastcmp(word2, "OFF") || word2[0] == 'F' || word2[0] == 'N') i = 0;
else if (fastcmp(word2, "ON") || word2[0] == 'T' || word2[0] == 'Y') i = 1;
else i = -1; // (fastcmp(word2, "DEFAULT"))
if (i >= -1 && i <= 1) // -1 to force off, 1 to force on, 0 to honor default.
// This behavior can be disabled with cv_resetmusicbyheader
mapheaderinfo[num-1]->musforcereset = (SINT8)i;
else
deh_warning("Level header %d: invalid forceresetmusic option %d", num, i);
}
else if (fastcmp(word, "FORCECHARACTER"))
{
strlcpy(mapheaderinfo[num-1]->forcecharacter, word2, SKINNAMESIZE+1);
@ -2966,6 +2980,17 @@ static void readunlockable(MYFILE *f, INT32 num)
Z_Free(s);
}
static const char NIGHTSGRADE_LIST[] = {
'F', // GRADE_F
'E', // GRADE_E
'D', // GRADE_D
'C', // GRADE_C
'B', // GRADE_B
'A', // GRADE_A
'S', // GRADE_S
'\0'
};
#define PARAMCHECK(n) do { if (!params[n]) { deh_warning("Too few parameters, need %d", n); return; }} while (0)
static void readcondition(UINT8 set, UINT32 id, char *word2)
{
@ -3067,7 +3092,21 @@ static void readcondition(UINT8 set, UINT32 id, char *word2)
PARAMCHECK(2); // one optional one
ty = UC_NIGHTSSCORE + offset;
re = atoi(params[2 + !!(params[3])]);
i = (params[3] ? 3 : 2);
if (fastncmp("GRADE_",params[i],6))
{
char *p = params[i]+6;
for (re = 0; NIGHTSGRADE_LIST[re]; re++)
if (*p == NIGHTSGRADE_LIST[re])
break;
if (!NIGHTSGRADE_LIST[re])
{
deh_warning("Invalid NiGHTS grade %s\n", params[i]);
return;
}
}
else
re = atoi(params[i]);
// Convert to map number if it appears to be one
if (params[1][0] >= 'A' && params[1][0] <= 'Z')
@ -4598,10 +4637,10 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_SONIC3KBOSSEXPLOSION6",
"S_JETFUME1",
"S_JETFUME2",
// Boss 1
"S_EGGMOBILE_STND",
"S_EGGMOBILE_ROFL",
"S_EGGMOBILE_LATK1",
"S_EGGMOBILE_LATK2",
"S_EGGMOBILE_LATK3",
@ -4611,7 +4650,6 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_EGGMOBILE_LATK7",
"S_EGGMOBILE_LATK8",
"S_EGGMOBILE_LATK9",
"S_EGGMOBILE_LATK10",
"S_EGGMOBILE_RATK1",
"S_EGGMOBILE_RATK2",
"S_EGGMOBILE_RATK3",
@ -4621,7 +4659,6 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_EGGMOBILE_RATK7",
"S_EGGMOBILE_RATK8",
"S_EGGMOBILE_RATK9",
"S_EGGMOBILE_RATK10",
"S_EGGMOBILE_PANIC1",
"S_EGGMOBILE_PANIC2",
"S_EGGMOBILE_PANIC3",
@ -4629,6 +4666,14 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_EGGMOBILE_PANIC5",
"S_EGGMOBILE_PANIC6",
"S_EGGMOBILE_PANIC7",
"S_EGGMOBILE_PANIC8",
"S_EGGMOBILE_PANIC9",
"S_EGGMOBILE_PANIC10",
"S_EGGMOBILE_PANIC11",
"S_EGGMOBILE_PANIC12",
"S_EGGMOBILE_PANIC13",
"S_EGGMOBILE_PANIC14",
"S_EGGMOBILE_PANIC15",
"S_EGGMOBILE_PAIN",
"S_EGGMOBILE_PAIN2",
"S_EGGMOBILE_DIE1",
@ -4639,6 +4684,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_EGGMOBILE_FLEE2",
"S_EGGMOBILE_BALL",
"S_EGGMOBILE_TARGET",
"S_BOSSEGLZ1",
"S_BOSSEGLZ2",
// Boss 2
"S_EGGMOBILE2_STND",
@ -4670,11 +4717,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
// Boss 3
"S_EGGMOBILE3_STND",
"S_EGGMOBILE3_LAUGH1",
"S_EGGMOBILE3_LAUGH2",
"S_EGGMOBILE3_LAUGH3",
"S_EGGMOBILE3_LAUGH4",
"S_EGGMOBILE3_LAUGH5",
"S_EGGMOBILE3_SHOCK",
"S_EGGMOBILE3_ATK1",
"S_EGGMOBILE3_ATK2",
"S_EGGMOBILE3_ATK3A",
@ -4683,21 +4726,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_EGGMOBILE3_ATK3D",
"S_EGGMOBILE3_ATK4",
"S_EGGMOBILE3_ATK5",
"S_EGGMOBILE3_LAUGH6",
"S_EGGMOBILE3_LAUGH7",
"S_EGGMOBILE3_LAUGH8",
"S_EGGMOBILE3_LAUGH9",
"S_EGGMOBILE3_LAUGH10",
"S_EGGMOBILE3_LAUGH11",
"S_EGGMOBILE3_LAUGH12",
"S_EGGMOBILE3_LAUGH13",
"S_EGGMOBILE3_LAUGH14",
"S_EGGMOBILE3_LAUGH15",
"S_EGGMOBILE3_LAUGH16",
"S_EGGMOBILE3_LAUGH17",
"S_EGGMOBILE3_LAUGH18",
"S_EGGMOBILE3_LAUGH19",
"S_EGGMOBILE3_LAUGH20",
"S_EGGMOBILE3_ROFL",
"S_EGGMOBILE3_PAIN",
"S_EGGMOBILE3_PAIN2",
"S_EGGMOBILE3_DIE1",
@ -4707,15 +4736,6 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_EGGMOBILE3_FLEE1",
"S_EGGMOBILE3_FLEE2",
// Boss 3 Propeller
"S_PROPELLER1",
"S_PROPELLER2",
"S_PROPELLER3",
"S_PROPELLER4",
"S_PROPELLER5",
"S_PROPELLER6",
"S_PROPELLER7",
// Boss 3 pinch
"S_FAKEMOBILE_INIT",
"S_FAKEMOBILE",
@ -4728,6 +4748,9 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_FAKEMOBILE_DIE1",
"S_FAKEMOBILE_DIE2",
"S_BOSSSEBH1",
"S_BOSSSEBH2",
// Boss 4
"S_EGGMOBILE4_STND",
"S_EGGMOBILE4_LATK1",
@ -5131,16 +5154,6 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_MSSHIELD_F1",
"S_MSSHIELD_F2",
"S_MSSHIELD_F3",
"S_MSSHIELD_F4",
"S_MSSHIELD_F5",
"S_MSSHIELD_F6",
"S_MSSHIELD_F7",
"S_MSSHIELD_F8",
"S_MSSHIELD_F9",
"S_MSSHIELD_F10",
"S_MSSHIELD_F11",
"S_MSSHIELD_F12",
// Ring
"S_RING",
@ -7224,6 +7237,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_EGGTRAP",
"MT_BOSS3WAYPOINT",
"MT_BOSS9GATHERPOINT",
"MT_BOSSJUNK",
// Boss 1
"MT_EGGMOBILE",
@ -7235,15 +7249,11 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
// Boss 2
"MT_EGGMOBILE2",
"MT_EGGMOBILE2_POGO",
"MT_BOSSTANK1",
"MT_BOSSTANK2",
"MT_BOSSSPIGOT",
"MT_GOOP",
"MT_GOOPTRAIL",
// Boss 3
"MT_EGGMOBILE3",
"MT_PROPELLER",
"MT_FAKEMOBILE",
"MT_SHOCK",
@ -8483,15 +8493,6 @@ struct {
{"LF2_NOVISITNEEDED",LF2_NOVISITNEEDED},
{"LF2_WIDEICON",LF2_WIDEICON},
// NiGHTS grades
{"GRADE_F",GRADE_F},
{"GRADE_E",GRADE_E},
{"GRADE_D",GRADE_D},
{"GRADE_C",GRADE_C},
{"GRADE_B",GRADE_B},
{"GRADE_A",GRADE_A},
{"GRADE_S",GRADE_S},
// Emeralds
{"EMERALD1",EMERALD1},
{"EMERALD2",EMERALD2},
@ -9313,6 +9314,19 @@ static fixed_t find_const(const char **rword)
free(word);
return 0;
}
else if (fastncmp("GRADE_",word,6))
{
char *p = word+6;
for (i = 0; NIGHTSGRADE_LIST[i]; i++)
if (*p == NIGHTSGRADE_LIST[i])
{
free(word);
return i;
}
const_warning("NiGHTS grade",word);
free(word);
return 0;
}
for (i = 0; INT_CONST[i].n; i++)
if (fastcmp(word,INT_CONST[i].n)) {
free(word);
@ -9761,6 +9775,18 @@ static inline int lib_getenum(lua_State *L)
if (mathlib) return luaL_error(L, "skincolor '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("GRADE_",word,6))
{
p = word+6;
for (i = 0; NIGHTSGRADE_LIST[i]; i++)
if (*p == NIGHTSGRADE_LIST[i])
{
lua_pushinteger(L, i);
return 1;
}
if (mathlib) return luaL_error(L, "NiGHTS grade '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("MN_",word,3)) {
p = word+3;
for (i = 0; i < NUMMENUTYPES; i++)

View file

@ -616,4 +616,8 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
/// SRB2CB itself ported this from PrBoom+
#define NEWCLIP
#ifndef HAVE_PNG
#define NO_PNG_LUMPS
#endif
#endif // __DOOMDEF__

View file

@ -333,6 +333,8 @@ typedef struct
UINT32 muspostbosspos; ///< Post-bossdeath position
UINT32 muspostbossfadein; ///< Post-bossdeath fade-in milliseconds.
SINT8 musforcereset; ///< Force resetmusic (-1 for default; 0 for force off; 1 for force on)
// Lua stuff.
// (This is not ifdeffed so the map header structure can stay identical, just in case.)
UINT8 numCustomOptions; ///< Internal. For Lua custom value support.

View file

@ -1596,11 +1596,11 @@ void F_StartEnding(void)
sprframe = &sprdef->spriteframes[XTRA_ENDING+2];
endfwrk[2] = W_CachePatchNum(sprframe->lumppat[0], PU_LEVEL);
}
else // eh, yknow what? too lazy to put MISSINGs here. eggman wins if you don't give your character an ending firework display.
else // Show a star if your character doesn't have an ending firework display. (Basically the MISSINGs for this)
{
endfwrk[0] = W_CachePatchName("ENDFWRK0", PU_LEVEL);
endfwrk[1] = W_CachePatchName("ENDFWRK1", PU_LEVEL);
endfwrk[2] = W_CachePatchName("ENDFWRK2", PU_LEVEL);
endfwrk[0] = W_CachePatchName("ENDFWRK3", PU_LEVEL);
endfwrk[1] = W_CachePatchName("ENDFWRK4", PU_LEVEL);
endfwrk[2] = W_CachePatchName("ENDFWRK5", PU_LEVEL);
}
endbrdr[0] = W_CachePatchName("ENDBRDR2", PU_LEVEL);

View file

@ -2083,6 +2083,7 @@ static inline void G_PlayerFinishLevel(INT32 player)
p->mo->flags2 &= ~MF2_SHADOW; // cancel invisibility
P_FlashPal(p, 0, 0); // Resets
p->starpostscale = 0;
p->starpostangle = 0;
p->starposttime = 0;
p->starpostx = 0;
@ -2129,6 +2130,7 @@ void G_PlayerReborn(INT32 player)
INT16 starpostz;
INT32 starpostnum;
INT32 starpostangle;
fixed_t starpostscale;
fixed_t jumpfactor;
fixed_t height;
fixed_t spinheight;
@ -2184,6 +2186,7 @@ void G_PlayerReborn(INT32 player)
starpostz = players[player].starpostz;
starpostnum = players[player].starpostnum;
starpostangle = players[player].starpostangle;
starpostscale = players[player].starpostscale;
jumpfactor = players[player].jumpfactor;
height = players[player].height;
spinheight = players[player].spinheight;
@ -2239,6 +2242,7 @@ void G_PlayerReborn(INT32 player)
p->starpostz = starpostz;
p->starpostnum = starpostnum;
p->starpostangle = starpostangle;
p->starpostscale = starpostscale;
p->jumpfactor = jumpfactor;
p->height = height;
p->spinheight = spinheight;
@ -2276,7 +2280,7 @@ void G_PlayerReborn(INT32 player)
}
// This is in S_Start, but this was not here previously.
// if (cv_resetmusic.value)
// if (RESETMUSIC)
// S_StopMusic();
S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0);
}
@ -2657,6 +2661,7 @@ void G_DoReborn(INT32 playernum)
{
if (!playeringame[i])
continue;
players[i].starpostscale = 0;
players[i].starpostangle = 0;
players[i].starposttime = 0;
players[i].starpostx = 0;
@ -2779,6 +2784,7 @@ void G_AddPlayer(INT32 playernum)
if (!(cv_coopstarposts.value && (gametype == GT_COOP) && (p->starpostnum < players[i].starpostnum)))
continue;
p->starpostscale = players[i].starpostscale;
p->starposttime = players[i].starposttime;
p->starpostx = players[i].starpostx;
p->starposty = players[i].starposty;
@ -3866,7 +3872,7 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean
for (i = 0; i < MAXPLAYERS; i++)
{
players[i].playerstate = PST_REBORN;
players[i].starpostangle = players[i].starpostnum = players[i].starposttime = 0;
players[i].starpostscale = players[i].starpostangle = players[i].starpostnum = players[i].starposttime = 0;
players[i].starpostx = players[i].starposty = players[i].starpostz = 0;
if (netgame || multiplayer)
@ -4577,7 +4583,7 @@ void G_GhostTicker(void)
default:
case GHC_RETURNSKIN:
g->mo->skin = g->oldmo.skin;
// fallthru
/* FALLTHRU */
case GHC_NORMAL: // Go back to skin color
g->mo->color = g->oldmo.color;
break;

View file

@ -30,6 +30,7 @@
#include "../z_zone.h"
#include "../v_video.h"
#include "../r_draw.h"
#include "../p_setup.h"
//Hurdler: 25/04/2000: used for new colormap code in hardware mode
//static UINT8 *gr_colormap = NULL; // by default it must be NULL ! (because colormap tables are not initialized)
@ -60,7 +61,6 @@ static const INT32 format2bpp[16] =
2, //14 GR_TEXFMT_AP_88
};
// This code was originally placed directly in HWR_DrawPatchInCache.
// It is now split from it for my sanity! (and the sanity of others)
// -- Monster Iestyn (13/02/19)
@ -138,18 +138,37 @@ static void HWR_DrawColumnInCache(const column_t *patchcol, UINT8 *block, GLMipm
// Alam: SRB2 uses Mingw, HUGS
switch (bpp)
{
case 2 : texelu16 = (UINT16)((alpha<<8) | texel);
case 2 : // uhhhhhhhh..........
if ((originPatch != NULL) && (originPatch->style != AST_COPY))
texel = ASTBlendPixel_8bpp(*(dest+1), texel, originPatch->style, originPatch->alpha);
texelu16 = (UINT16)((alpha<<8) | texel);
memcpy(dest, &texelu16, sizeof(UINT16));
break;
case 3 : colortemp = V_GetColor(texel);
if ((originPatch != NULL) && (originPatch->style != AST_COPY))
{
RGBA_t rgbatexel;
rgbatexel.rgba = *(UINT32 *)dest;
colortemp = ASTBlendPixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha);
}
memcpy(dest, &colortemp, sizeof(RGBA_t)-sizeof(UINT8));
break;
case 4 : colortemp = V_GetColor(texel);
colortemp.s.alpha = alpha;
if ((originPatch != NULL) && (originPatch->style != AST_COPY))
{
RGBA_t rgbatexel;
rgbatexel.rgba = *(UINT32 *)dest;
colortemp = ASTBlendPixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha);
}
memcpy(dest, &colortemp, sizeof(RGBA_t));
break;
// default is 1
default: *dest = texel;
default:
if ((originPatch != NULL) && (originPatch->style != AST_COPY))
*dest = ASTBlendPixel_8bpp(*dest, texel, originPatch->style, originPatch->alpha);
else
*dest = texel;
break;
}
@ -233,18 +252,37 @@ static void HWR_DrawFlippedColumnInCache(const column_t *patchcol, UINT8 *block,
// Alam: SRB2 uses Mingw, HUGS
switch (bpp)
{
case 2 : texelu16 = (UINT16)((alpha<<8) | texel);
case 2 : // uhhhhhhhh..........
if ((originPatch != NULL) && (originPatch->style != AST_COPY))
texel = ASTBlendPixel_8bpp(*(dest+1), texel, originPatch->style, originPatch->alpha);
texelu16 = (UINT16)((alpha<<8) | texel);
memcpy(dest, &texelu16, sizeof(UINT16));
break;
case 3 : colortemp = V_GetColor(texel);
if ((originPatch != NULL) && (originPatch->style != AST_COPY))
{
RGBA_t rgbatexel;
rgbatexel.rgba = *(UINT32 *)dest;
colortemp = ASTBlendPixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha);
}
memcpy(dest, &colortemp, sizeof(RGBA_t)-sizeof(UINT8));
break;
case 4 : colortemp = V_GetColor(texel);
colortemp.s.alpha = alpha;
if ((originPatch != NULL) && (originPatch->style != AST_COPY))
{
RGBA_t rgbatexel;
rgbatexel.rgba = *(UINT32 *)dest;
colortemp = ASTBlendPixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha);
}
memcpy(dest, &colortemp, sizeof(RGBA_t));
break;
// default is 1
default: *dest = texel;
default:
if ((originPatch != NULL) && (originPatch->style != AST_COPY))
*dest = ASTBlendPixel_8bpp(*dest, texel, originPatch->style, originPatch->alpha);
else
*dest = texel;
break;
}
@ -331,16 +369,7 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap,
if (texture->width <= 0 || texture->height <= 0)
return;
/*if ((patch->style == AST_TRANSLUCENT) && (patch->alpha <= (10*255/11))) // Alpha style set to translucent? Is the alpha small enough for translucency?
{
if (patch->alpha < 255/11) // Is the patch way too translucent? Don't render then.
continue;
ColumnDrawerPointer = (patch->flip & 2) ? HWR_DrawTransFlippedColumnInCache : HWR_DrawTransColumnInCache;
}
else*/
{
ColumnDrawerPointer = (patch->flip & 2) ? HWR_DrawFlippedColumnInCache : HWR_DrawColumnInCache;
}
ColumnDrawerPointer = (patch->flip & 2) ? HWR_DrawFlippedColumnInCache : HWR_DrawColumnInCache;
x1 = patch->originx;
width = SHORT(realpatch->width);
@ -420,6 +449,7 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap,
static void HWR_ResizeBlock(INT32 originalwidth, INT32 originalheight,
GrTexInfo *grInfo)
{
#ifdef GLIDE_API_COMPATIBILITY
// Build the full textures from patches.
static const GrLOD_t gr_lods[9] =
{
@ -456,6 +486,9 @@ static void HWR_ResizeBlock(INT32 originalwidth, INT32 originalheight,
INT32 j,k;
INT32 max,min;
#else
(void)grInfo;
#endif
// find a power of 2 width/height
if (cv_grrounddown.value)
@ -511,6 +544,7 @@ static void HWR_ResizeBlock(INT32 originalwidth, INT32 originalheight,
}
else
{
#ifdef GLIDE_API_COMPATIBILITY
//size up to nearest power of 2
blockwidth = 1;
while (blockwidth < originalwidth)
@ -528,9 +562,14 @@ static void HWR_ResizeBlock(INT32 originalwidth, INT32 originalheight,
if (blockheight > 2048)
blockheight = 2048;
//I_Error("3D GenerateTexture : too big");
#else
blockwidth = originalwidth;
blockheight = originalheight;
#endif
}
// do the boring LOD stuff.. blech!
#ifdef GLIDE_API_COMPATIBILITY
if (blockwidth >= blockheight)
{
max = blockwidth;
@ -562,6 +601,7 @@ static void HWR_ResizeBlock(INT32 originalwidth, INT32 originalheight,
if (blockwidth < blockheight)
j += 4;
grInfo->aspectRatioLog2 = gr_aspects[j].aspect;
#endif
blocksize = blockwidth * blockheight;
@ -650,7 +690,12 @@ static void HWR_GenerateTexture(INT32 texnum, GLTexture_t *grtex)
// Composite the columns together.
for (i = 0, patch = texture->patches; i < texture->patchcount; i++, patch++)
{
size_t lumplength = W_LumpLengthPwad(patch->wad, patch->lump);
realpatch = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE);
#ifndef NO_PNG_LUMPS
if (R_IsLumpPNG((UINT8 *)realpatch, lumplength))
realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength);
#endif
HWR_DrawTexturePatchInCache(&grtex->mipmap,
blockwidth, blockheight,
texture, patch,
@ -756,11 +801,13 @@ void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipm
static size_t gr_numtextures;
static GLTexture_t *gr_textures; // for ALL Doom textures
static GLTexture_t *gr_textures2;
void HWR_InitTextureCache(void)
{
gr_numtextures = 0;
gr_textures = NULL;
gr_textures2 = NULL;
}
@ -799,7 +846,10 @@ void HWR_FreeTextureCache(void)
// texturecache info, we can free it
if (gr_textures)
free(gr_textures);
if (gr_textures2)
free(gr_textures2);
gr_textures = NULL;
gr_textures2 = NULL;
gr_numtextures = 0;
}
@ -817,6 +867,9 @@ void HWR_PrepLevelCache(size_t pnumtextures)
gr_textures = calloc(pnumtextures, sizeof (*gr_textures));
if (gr_textures == NULL)
I_Error("3D can't alloc gr_textures");
gr_textures2 = calloc(pnumtextures, sizeof (*gr_textures2));
if (gr_textures2 == NULL)
I_Error("3D can't alloc gr_textures2");
}
void HWR_SetPalette(RGBA_t *palette)
@ -847,7 +900,7 @@ GLTexture_t *HWR_GetTexture(INT32 tex)
GLTexture_t *grtex;
#ifdef PARANOIA
if ((unsigned)tex >= gr_numtextures)
I_Error(" HWR_GetTexture: tex >= numtextures\n");
I_Error("HWR_GetTexture: tex >= numtextures\n");
#endif
grtex = &gr_textures[tex];
@ -862,15 +915,39 @@ GLTexture_t *HWR_GetTexture(INT32 tex)
return grtex;
}
// HWR_RenderPlane and HWR_RenderPolyObjectPlane need this to get the flat dimensions from a patch.
lumpnum_t gr_patchflat;
static void HWR_LoadPatchFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum)
{
UINT8 *flat;
patch_t *patch = (patch_t *)W_CacheLumpNum(flatlumpnum, PU_STATIC);
size_t lumplength = W_LumpLength(flatlumpnum);
#ifndef NO_PNG_LUMPS
if (R_IsLumpPNG((UINT8 *)patch, lumplength))
patch = R_PNGToPatch((UINT8 *)patch, lumplength);
#endif
grMipmap->width = (UINT16)SHORT(patch->width);
grMipmap->height = (UINT16)SHORT(patch->height);
flat = Z_Malloc(grMipmap->width * grMipmap->height, PU_HWRCACHE, &grMipmap->grInfo.data);
memset(flat, TRANSPARENTPIXEL, grMipmap->width * grMipmap->height);
R_PatchToFlat(patch, flat);
}
static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum)
{
size_t size, pflatsize;
// setup the texture info
#ifdef GLIDE_API_COMPATIBILITY
grMipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_64;
grMipmap->grInfo.largeLodLog2 = GR_LOD_LOG2_64;
grMipmap->grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
#endif
grMipmap->grInfo.format = GR_TEXFMT_P_8;
grMipmap->flags = TF_WRAPXY|TF_CHROMAKEYED;
@ -900,15 +977,20 @@ static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum)
pflatsize = 64;
break;
}
grMipmap->width = (UINT16)pflatsize;
grMipmap->height = (UINT16)pflatsize;
// the flat raw data needn't be converted with palettized textures
W_ReadLump(flatlumpnum, Z_Malloc(W_LumpLength(flatlumpnum),
PU_HWRCACHE, &grMipmap->grInfo.data));
if (R_CheckIfPatch(flatlumpnum))
HWR_LoadPatchFlat(grMipmap, flatlumpnum);
else
{
grMipmap->width = (UINT16)pflatsize;
grMipmap->height = (UINT16)pflatsize;
// the flat raw data needn't be converted with palettized textures
W_ReadLump(flatlumpnum, Z_Malloc(W_LumpLength(flatlumpnum),
PU_HWRCACHE, &grMipmap->grInfo.data));
}
}
// Download a Doom 'flat' to the hardware cache and make it ready for use
void HWR_GetFlat(lumpnum_t flatlumpnum)
{
@ -923,6 +1005,52 @@ void HWR_GetFlat(lumpnum_t flatlumpnum)
// The system-memory data can be purged now.
Z_ChangeTag(grmip->grInfo.data, PU_HWRCACHE_UNLOCKED);
gr_patchflat = 0;
if (R_CheckIfPatch(flatlumpnum))
gr_patchflat = flatlumpnum;
}
static void HWR_LoadTextureFlat(GLMipmap_t *grMipmap, INT32 texturenum)
{
UINT8 *flat;
// setup the texture info
#ifdef GLIDE_API_COMPATIBILITY
grMipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_64;
grMipmap->grInfo.largeLodLog2 = GR_LOD_LOG2_64;
grMipmap->grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
#endif
grMipmap->grInfo.format = GR_TEXFMT_P_8;
grMipmap->flags = TF_WRAPXY|TF_CHROMAKEYED;
grMipmap->width = (UINT16)textures[texturenum]->width;
grMipmap->height = (UINT16)textures[texturenum]->height;
flat = Z_Malloc(grMipmap->width * grMipmap->height, PU_HWRCACHE, &grMipmap->grInfo.data);
memset(flat, TRANSPARENTPIXEL, grMipmap->width * grMipmap->height);
R_TextureToFlat(texturenum, flat);
}
void HWR_GetTextureFlat(INT32 texturenum)
{
GLTexture_t *grtex;
#ifdef PARANOIA
if ((unsigned)texturenum >= gr_numtextures)
I_Error("HWR_GetTextureFlat: texturenum >= numtextures\n");
#endif
if (texturenum == 0 || texturenum == -1)
return;
grtex = &gr_textures2[texturenum];
if (!grtex->mipmap.grInfo.data && !grtex->mipmap.downloaded)
HWR_LoadTextureFlat(&grtex->mipmap, texturenum);
HWD.pfnSetTexture(&grtex->mipmap);
// The system-memory data can be purged now.
Z_ChangeTag(grtex->mipmap.grInfo.data, PU_HWRCACHE_UNLOCKED);
}
//

View file

@ -47,6 +47,7 @@ EXPORT void HWRAPI(SetPalette) (RGBA_t *ppal, RGBA_t *pgamma);
EXPORT void HWRAPI(FinishUpdate) (INT32 waitvbl);
EXPORT void HWRAPI(Draw2DLine) (F2DCoord *v1, F2DCoord *v2, RGBA_t Color);
EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags);
EXPORT void HWRAPI(RenderSkyDome) (INT32 tex, INT32 texture_width, INT32 texture_height, FTransform transform);
EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags);
EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask, FBOOLEAN DepthMask, FRGBAFloat *ClearColor);
EXPORT void HWRAPI(SetTexture) (FTextureInfo *TexInfo);
@ -89,6 +90,7 @@ struct hwdriver_s
FinishUpdate pfnFinishUpdate;
Draw2DLine pfnDraw2DLine;
DrawPolygon pfnDrawPolygon;
RenderSkyDome pfnRenderSkyDome;
SetBlend pfnSetBlend;
ClearBuffer pfnClearBuffer;
SetTexture pfnSetTexture;

View file

@ -59,9 +59,11 @@ typedef FxI32 GrTextureFormat_t;
typedef struct
{
#ifdef GLIDE_API_COMPATIBILITY
GrLOD_t smallLodLog2;
GrLOD_t largeLodLog2;
GrAspectRatio_t aspectRatioLog2;
#endif
GrTextureFormat_t format;
void *data;
} GrTexInfo;

View file

@ -101,6 +101,7 @@ void HWR_FreeTextureCache(void);
void HWR_FreeExtraSubsectors(void);
void HWR_GetFlat(lumpnum_t flatlumpnum);
void HWR_GetTextureFlat(INT32 texturenum);
GLTexture_t *HWR_GetTexture(INT32 tex);
void HWR_GetPatch(GLPatch_t *gpatch);
void HWR_GetMappedPatch(GLPatch_t *gpatch, const UINT8 *colormap);
@ -114,6 +115,8 @@ void HWR_GetFadeMask(lumpnum_t fademasklumpnum);
// --------
// hw_draw.c
// --------
extern lumpnum_t gr_patchflat;
extern float gr_patch_scalex;
extern float gr_patch_scaley;

View file

@ -186,17 +186,16 @@ light_t *t_lspr[NUMSPRITES] =
// Boss 1, (Greenflower)
&lspr[NOLIGHT], // SPR_EGGM
&lspr[NOLIGHT], // SPR_EGLZ
// Boss 2, (Techno Hill)
&lspr[NOLIGHT], // SPR_EGGN
&lspr[NOLIGHT], // SPR_TNKA
&lspr[NOLIGHT], // SPR_TNKB
&lspr[NOLIGHT], // SPR_SPNK
&lspr[NOLIGHT], // SPR_TANK
&lspr[NOLIGHT], // SPR_GOOP
// Boss 3 (Deep Sea)
&lspr[NOLIGHT], // SPR_EGGO
&lspr[NOLIGHT], // SPR_PRPL
&lspr[NOLIGHT], // SPR_SEBH
&lspr[NOLIGHT], // SPR_FAKE
// Boss 4 (Castle Eggman)
@ -1226,9 +1225,11 @@ static void HWR_SetLight(void)
lightmappatch.height = 128;
lightmappatch.mipmap.width = 128;
lightmappatch.mipmap.height = 128;
#ifdef GLIDE_API_COMPATIBILITY
lightmappatch.mipmap.grInfo.smallLodLog2 = GR_LOD_LOG2_128;
lightmappatch.mipmap.grInfo.largeLodLog2 = GR_LOD_LOG2_128;
lightmappatch.mipmap.grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
#endif
lightmappatch.mipmap.flags = 0; //TF_WRAPXY; // DEBUG: view the overdraw !
}
HWD.pfnSetTexture(&lightmappatch.mipmap);

View file

@ -70,9 +70,9 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing);
#endif
#ifdef SORTING
void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight,
void HWR_AddTransparentFloor(lumpnum_t lumpnum, INT32 texturenum, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight,
INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap);
void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight,
void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, INT32 texturenum, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight,
INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, extracolormap_t *planecolormap);
#else
static void HWR_Add3DWater(lumpnum_t lumpnum, extrasubsector_t *xsub, fixed_t fixedheight,
@ -522,7 +522,7 @@ static UINT8 HWR_FogBlockAlpha(INT32 light, UINT32 color) // Let's see if this c
// HWR_RenderPlane : Render a floor or ceiling convex polygon
// -----------------+
static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight,
FBITFIELD PolyFlags, INT32 lightlevel, lumpnum_t lumpnum, sector_t *FOFsector, UINT8 alpha, boolean fogplane, extracolormap_t *planecolormap)
FBITFIELD PolyFlags, INT32 lightlevel, lumpnum_t lumpnum, INT32 texturenum, sector_t *FOFsector, UINT8 alpha, boolean fogplane, extracolormap_t *planecolormap)
{
polyvertex_t * pv;
float height; //constant y for all points on the convex flat polygon
@ -530,8 +530,9 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
INT32 nrPlaneVerts; //verts original define of convex flat polygon
INT32 i;
float flatxref,flatyref;
float fflatsize;
float fflatwidth, fflatheight;
INT32 flatflag;
boolean texflat = true;
size_t len;
float scrollx = 0.0f, scrolly = 0.0f;
angle_t angle = 0;
@ -540,6 +541,7 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
#ifdef ESLOPE
pslope_t *slope = NULL;
#endif
patch_t *patch;
static FOutVector *planeVerts = NULL;
static UINT16 numAllocedPlaneVerts = 0;
@ -580,9 +582,10 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
if (nrPlaneVerts < 3) //not even a triangle ?
return;
if (nrPlaneVerts > (INT32)UINT16_MAX) // FIXME: exceeds plVerts size
// This check is so inconsistent between functions, it hurts.
if (nrPlaneVerts > INT16_MAX) // FIXME: exceeds plVerts size
{
CONS_Debug(DBG_RENDER, "polygon size of %d exceeds max value of %d vertices\n", nrPlaneVerts, UINT16_MAX);
CONS_Debug(DBG_RENDER, "polygon size of %d exceeds max value of %d vertices\n", nrPlaneVerts, INT16_MAX);
return;
}
@ -599,38 +602,47 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
switch (len)
{
case 4194304: // 2048x2048 lump
fflatsize = 2048.0f;
flatflag = 2047;
fflatwidth = fflatheight = 2048.0f;
break;
case 1048576: // 1024x1024 lump
fflatsize = 1024.0f;
flatflag = 1023;
fflatwidth = fflatheight = 1024.0f;
break;
case 262144:// 512x512 lump
fflatsize = 512.0f;
flatflag = 511;
fflatwidth = fflatheight = 512.0f;
break;
case 65536: // 256x256 lump
fflatsize = 256.0f;
flatflag = 255;
fflatwidth = fflatheight = 256.0f;
break;
case 16384: // 128x128 lump
fflatsize = 128.0f;
flatflag = 127;
fflatwidth = fflatheight = 128.0f;
break;
case 1024: // 32x32 lump
fflatsize = 32.0f;
flatflag = 31;
fflatwidth = fflatheight = 32.0f;
break;
default: // 64x64 lump
fflatsize = 64.0f;
flatflag = 63;
fflatwidth = fflatheight = 64.0f;
break;
}
flatflag = ((INT32)fflatwidth)-1;
if (texturenum != 0 && texturenum != -1)
{
fflatwidth = textures[texturenum]->width;
fflatheight = textures[texturenum]->height;
}
else if (gr_patchflat && R_CheckIfPatch(gr_patchflat)) // Just in case?
{
patch = (patch_t *)W_CacheLumpNum(gr_patchflat, PU_STATIC);
fflatwidth = SHORT(patch->width);
fflatheight = SHORT(patch->height);
}
else
texflat = false;
// reference point for flat texture coord for each vertex around the polygon
flatxref = (float)(((fixed_t)pv->x & (~flatflag)) / fflatsize);
flatyref = (float)(((fixed_t)pv->y & (~flatflag)) / fflatsize);
flatxref = (float)(((fixed_t)pv->x & (~flatflag)) / fflatwidth);
flatyref = (float)(((fixed_t)pv->y & (~flatflag)) / fflatheight);
// transform
v3d = planeVerts;
@ -639,14 +651,14 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
{
if (!isceiling) // it's a floor
{
scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatsize;
scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatsize;
scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatwidth;
scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatheight;
angle = FOFsector->floorpic_angle;
}
else // it's a ceiling
{
scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatsize;
scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatsize;
scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatwidth;
scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatheight;
angle = FOFsector->ceilingpic_angle;
}
}
@ -654,14 +666,14 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
{
if (!isceiling) // it's a floor
{
scrollx = FIXED_TO_FLOAT(gr_frontsector->floor_xoffs)/fflatsize;
scrolly = FIXED_TO_FLOAT(gr_frontsector->floor_yoffs)/fflatsize;
scrollx = FIXED_TO_FLOAT(gr_frontsector->floor_xoffs)/fflatwidth;
scrolly = FIXED_TO_FLOAT(gr_frontsector->floor_yoffs)/fflatheight;
angle = gr_frontsector->floorpic_angle;
}
else // it's a ceiling
{
scrollx = FIXED_TO_FLOAT(gr_frontsector->ceiling_xoffs)/fflatsize;
scrolly = FIXED_TO_FLOAT(gr_frontsector->ceiling_yoffs)/fflatsize;
scrollx = FIXED_TO_FLOAT(gr_frontsector->ceiling_xoffs)/fflatwidth;
scrolly = FIXED_TO_FLOAT(gr_frontsector->ceiling_yoffs)/fflatheight;
angle = gr_frontsector->ceilingpic_angle;
}
}
@ -680,17 +692,24 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
for (i = 0; i < nrPlaneVerts; i++,v3d++,pv++)
{
// Hurdler: add scrolling texture on floor/ceiling
v3d->sow = (float)((pv->x / fflatsize) - flatxref + scrollx);
v3d->tow = (float)(-(pv->y / fflatsize) + flatyref + scrolly);
//v3d->sow = (float)(pv->x / fflatsize);
//v3d->tow = (float)(pv->y / fflatsize);
if (texflat)
{
v3d->sow = (float)(pv->x / fflatwidth) + scrollx;
v3d->tow = -(float)(pv->y / fflatheight) + scrolly;
}
else
{
v3d->sow = (float)((pv->x / fflatwidth) - flatxref + scrollx);
v3d->tow = (float)(flatyref - (pv->y / fflatheight) + scrolly);
}
// Need to rotate before translate
if (angle) // Only needs to be done if there's an altered angle
{
tempxsow = FLOAT_TO_FIXED(v3d->sow);
tempytow = FLOAT_TO_FIXED(v3d->tow);
if (texflat)
tempytow = -tempytow;
v3d->sow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle))));
v3d->tow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle))));
}
@ -3164,21 +3183,23 @@ static inline void HWR_AddPolyObjectSegs(void)
#ifdef POLYOBJECTS_PLANES
static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, fixed_t fixedheight,
FBITFIELD blendmode, UINT8 lightlevel, lumpnum_t lumpnum, sector_t *FOFsector,
FBITFIELD blendmode, UINT8 lightlevel, lumpnum_t lumpnum, INT32 texturenum, sector_t *FOFsector,
UINT8 alpha, extracolormap_t *planecolormap)
{
float height; //constant y for all points on the convex flat polygon
FOutVector *v3d;
INT32 i;
float flatxref,flatyref;
float fflatsize;
float fflatwidth, fflatheight;
INT32 flatflag;
boolean texflat = true;
size_t len;
float scrollx = 0.0f, scrolly = 0.0f;
angle_t angle = 0;
FSurfaceInfo Surf;
fixed_t tempxsow, tempytow;
size_t nrPlaneVerts;
patch_t *patch;
static FOutVector *planeVerts = NULL;
static UINT16 numAllocedPlaneVerts = 0;
@ -3209,38 +3230,47 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling,
switch (len)
{
case 4194304: // 2048x2048 lump
fflatsize = 2048.0f;
flatflag = 2047;
fflatwidth = fflatheight = 2048.0f;
break;
case 1048576: // 1024x1024 lump
fflatsize = 1024.0f;
flatflag = 1023;
fflatwidth = fflatheight = 1024.0f;
break;
case 262144:// 512x512 lump
fflatsize = 512.0f;
flatflag = 511;
fflatwidth = fflatheight = 512.0f;
break;
case 65536: // 256x256 lump
fflatsize = 256.0f;
flatflag = 255;
fflatwidth = fflatheight = 256.0f;
break;
case 16384: // 128x128 lump
fflatsize = 128.0f;
flatflag = 127;
fflatwidth = fflatheight = 128.0f;
break;
case 1024: // 32x32 lump
fflatsize = 32.0f;
flatflag = 31;
fflatwidth = fflatheight = 32.0f;
break;
default: // 64x64 lump
fflatsize = 64.0f;
flatflag = 63;
fflatwidth = fflatheight = 64.0f;
break;
}
flatflag = ((INT32)fflatwidth)-1;
if (texturenum != 0 && texturenum != -1)
{
fflatwidth = textures[texturenum]->width;
fflatheight = textures[texturenum]->height;
}
else if (gr_patchflat && R_CheckIfPatch(gr_patchflat)) // Just in case?
{
patch = (patch_t *)W_CacheLumpNum(gr_patchflat, PU_STATIC);
fflatwidth = SHORT(patch->width);
fflatheight = SHORT(patch->height);
}
else
texflat = false;
// reference point for flat texture coord for each vertex around the polygon
flatxref = (float)(((fixed_t)FIXED_TO_FLOAT(polysector->origVerts[0].x) & (~flatflag)) / fflatsize);
flatyref = (float)(((fixed_t)FIXED_TO_FLOAT(polysector->origVerts[0].y) & (~flatflag)) / fflatsize);
flatxref = (float)((polysector->origVerts[0].x & (~flatflag)) / fflatwidth);
flatyref = (float)((polysector->origVerts[0].y & (~flatflag)) / fflatheight);
// transform
v3d = planeVerts;
@ -3249,14 +3279,14 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling,
{
if (!isceiling) // it's a floor
{
scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatsize;
scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatsize;
scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatwidth;
scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatheight;
angle = FOFsector->floorpic_angle>>ANGLETOFINESHIFT;
}
else // it's a ceiling
{
scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatsize;
scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatsize;
scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatwidth;
scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatheight;
angle = FOFsector->ceilingpic_angle>>ANGLETOFINESHIFT;
}
}
@ -3264,14 +3294,14 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling,
{
if (!isceiling) // it's a floor
{
scrollx = FIXED_TO_FLOAT(gr_frontsector->floor_xoffs)/fflatsize;
scrolly = FIXED_TO_FLOAT(gr_frontsector->floor_yoffs)/fflatsize;
scrollx = FIXED_TO_FLOAT(gr_frontsector->floor_xoffs)/fflatwidth;
scrolly = FIXED_TO_FLOAT(gr_frontsector->floor_yoffs)/fflatheight;
angle = gr_frontsector->floorpic_angle>>ANGLETOFINESHIFT;
}
else // it's a ceiling
{
scrollx = FIXED_TO_FLOAT(gr_frontsector->ceiling_xoffs)/fflatsize;
scrolly = FIXED_TO_FLOAT(gr_frontsector->ceiling_yoffs)/fflatsize;
scrollx = FIXED_TO_FLOAT(gr_frontsector->ceiling_xoffs)/fflatwidth;
scrolly = FIXED_TO_FLOAT(gr_frontsector->ceiling_yoffs)/fflatheight;
angle = gr_frontsector->ceilingpic_angle>>ANGLETOFINESHIFT;
}
}
@ -3294,15 +3324,26 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling,
for (i = 0; i < (INT32)nrPlaneVerts; i++,v3d++)
{
// Hurdler: add scrolling texture on floor/ceiling
v3d->sow = (float)((FIXED_TO_FLOAT(polysector->origVerts[i].x) / fflatsize) - flatxref + scrollx); // Go from the polysector's original vertex locations
v3d->tow = (float)(flatyref - (FIXED_TO_FLOAT(polysector->origVerts[i].y) / fflatsize) + scrolly); // Means the flat is offset based on the original vertex locations
// Go from the polysector's original vertex locations
// Means the flat is offset based on the original vertex locations
if (texflat)
{
v3d->sow = (float)(FIXED_TO_FLOAT(polysector->origVerts[i].x) / fflatwidth) + scrollx;
v3d->tow = -(float)(FIXED_TO_FLOAT(polysector->origVerts[i].y) / fflatheight) + scrolly;
}
else
{
v3d->sow = (float)((FIXED_TO_FLOAT(polysector->origVerts[i].x) / fflatwidth) - flatxref + scrollx);
v3d->tow = (float)(flatyref - (FIXED_TO_FLOAT(polysector->origVerts[i].y) / fflatheight) + scrolly);
}
// Need to rotate before translate
if (angle) // Only needs to be done if there's an altered angle
{
tempxsow = FLOAT_TO_FIXED(v3d->sow);
tempytow = FLOAT_TO_FIXED(v3d->tow);
if (texflat)
tempytow = -tempytow;
v3d->sow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle))));
v3d->tow = (FIXED_TO_FLOAT(-FixedMul(tempxsow, FINESINE(angle)) - FixedMul(tempytow, FINECOSINE(angle))));
}
@ -3333,6 +3374,7 @@ static void HWR_AddPolyObjectPlanes(void)
{
size_t i;
sector_t *polyobjsector;
INT32 light = 0;
// Polyobject Planes need their own function for drawing because they don't have extrasubsectors by themselves
// It should be okay because polyobjects should always be convex anyway
@ -3351,19 +3393,23 @@ static void HWR_AddPolyObjectPlanes(void)
&& polyobjsector->floorheight >= gr_frontsector->floorheight
&& (viewz < polyobjsector->floorheight))
{
light = R_GetPlaneLight(gr_frontsector, polyobjsector->floorheight, true);
if (po_ptrs[i]->translucency > 0)
{
FSurfaceInfo Surf;
FBITFIELD blendmode = HWR_TranstableToAlpha(po_ptrs[i]->translucency, &Surf);
HWR_AddTransparentPolyobjectFloor(levelflats[polyobjsector->floorpic].lumpnum, po_ptrs[i], false, polyobjsector->floorheight,
polyobjsector->lightlevel, Surf.FlatColor.s.alpha, polyobjsector, blendmode, NULL);
FBITFIELD blendmode;
memset(&Surf, 0x00, sizeof(Surf));
blendmode = HWR_TranstableToAlpha(po_ptrs[i]->translucency, &Surf);
HWR_AddTransparentPolyobjectFloor(levelflats[polyobjsector->floorpic].lumpnum, levelflats[polyobjsector->floorpic].texturenum, po_ptrs[i], false, polyobjsector->floorheight,
(light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), Surf.FlatColor.s.alpha, polyobjsector, blendmode, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap));
}
else
{
HWR_GetFlat(levelflats[polyobjsector->floorpic].lumpnum);
HWR_GetTextureFlat(levelflats[polyobjsector->floorpic].texturenum);
HWR_RenderPolyObjectPlane(po_ptrs[i], false, polyobjsector->floorheight, PF_Occlude,
polyobjsector->lightlevel, levelflats[polyobjsector->floorpic].lumpnum,
polyobjsector, 255, NULL);
(light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), levelflats[polyobjsector->floorpic].lumpnum, levelflats[polyobjsector->floorpic].texturenum,
polyobjsector, 255, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap));
}
}
@ -3371,21 +3417,23 @@ static void HWR_AddPolyObjectPlanes(void)
&& polyobjsector->ceilingheight <= gr_frontsector->ceilingheight
&& (viewz > polyobjsector->ceilingheight))
{
light = R_GetPlaneLight(gr_frontsector, polyobjsector->ceilingheight, true);
if (po_ptrs[i]->translucency > 0)
{
FSurfaceInfo Surf;
FBITFIELD blendmode;
memset(&Surf, 0x00, sizeof(Surf));
blendmode = HWR_TranstableToAlpha(po_ptrs[i]->translucency, &Surf);
HWR_AddTransparentPolyobjectFloor(levelflats[polyobjsector->ceilingpic].lumpnum, po_ptrs[i], true, polyobjsector->ceilingheight,
polyobjsector->lightlevel, Surf.FlatColor.s.alpha, polyobjsector, blendmode, NULL);
HWR_AddTransparentPolyobjectFloor(levelflats[polyobjsector->ceilingpic].lumpnum, levelflats[polyobjsector->floorpic].texturenum, po_ptrs[i], true, polyobjsector->ceilingheight,
(light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), Surf.FlatColor.s.alpha, polyobjsector, blendmode, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap));
}
else
{
HWR_GetFlat(levelflats[polyobjsector->ceilingpic].lumpnum);
HWR_GetTextureFlat(levelflats[polyobjsector->ceilingpic].texturenum);
HWR_RenderPolyObjectPlane(po_ptrs[i], true, polyobjsector->ceilingheight, PF_Occlude,
polyobjsector->lightlevel, levelflats[polyobjsector->floorpic].lumpnum,
polyobjsector, 255, NULL);
(light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), levelflats[polyobjsector->floorpic].lumpnum, levelflats[polyobjsector->floorpic].texturenum,
polyobjsector, 255, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap));
}
}
}
@ -3536,11 +3584,12 @@ static void HWR_Subsector(size_t num)
if (sub->validcount != validcount)
{
HWR_GetFlat(levelflats[gr_frontsector->floorpic].lumpnum);
HWR_GetTextureFlat(levelflats[gr_frontsector->floorpic].texturenum);
HWR_RenderPlane(gr_frontsector, &extrasubsectors[num], false,
// Hack to make things continue to work around slopes.
locFloorHeight == cullFloorHeight ? locFloorHeight : gr_frontsector->floorheight,
// We now return you to your regularly scheduled rendering.
PF_Occlude, floorlightlevel, levelflats[gr_frontsector->floorpic].lumpnum, NULL, 255, false, floorcolormap);
PF_Occlude, floorlightlevel, levelflats[gr_frontsector->floorpic].lumpnum, levelflats[gr_frontsector->floorpic].texturenum, NULL, 255, false, floorcolormap);
}
}
else
@ -3558,11 +3607,12 @@ static void HWR_Subsector(size_t num)
if (sub->validcount != validcount)
{
HWR_GetFlat(levelflats[gr_frontsector->ceilingpic].lumpnum);
HWR_GetTextureFlat(levelflats[gr_frontsector->ceilingpic].texturenum);
HWR_RenderPlane(NULL, &extrasubsectors[num], true,
// Hack to make things continue to work around slopes.
locCeilingHeight == cullCeilingHeight ? locCeilingHeight : gr_frontsector->ceilingheight,
// We now return you to your regularly scheduled rendering.
PF_Occlude, ceilinglightlevel, levelflats[gr_frontsector->ceilingpic].lumpnum,NULL, 255, false, ceilingcolormap);
PF_Occlude, ceilinglightlevel, levelflats[gr_frontsector->ceilingpic].lumpnum, levelflats[gr_frontsector->ceilingpic].texturenum, NULL, 255, false, ceilingcolormap);
}
}
else
@ -3621,7 +3671,7 @@ static void HWR_Subsector(size_t num)
else
alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, NORMALFOG);
HWR_AddTransparentFloor(0,
HWR_AddTransparentFloor(0, 0,
&extrasubsectors[num],
false,
*rover->bottomheight,
@ -3640,6 +3690,7 @@ static void HWR_Subsector(size_t num)
rover->alpha-1, rover->master->frontsector);
#else
HWR_AddTransparentFloor(levelflats[*rover->bottompic].lumpnum,
levelflats[*rover->bottompic].texturenum,
&extrasubsectors[num],
false,
*rover->bottomheight,
@ -3651,8 +3702,9 @@ static void HWR_Subsector(size_t num)
else
{
HWR_GetFlat(levelflats[*rover->bottompic].lumpnum);
HWR_GetTextureFlat(levelflats[*rover->bottompic].texturenum);
light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
HWR_RenderPlane(NULL, &extrasubsectors[num], false, *rover->bottomheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->bottompic].lumpnum,
HWR_RenderPlane(NULL, &extrasubsectors[num], false, *rover->bottomheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->bottompic].lumpnum, levelflats[*rover->bottompic].texturenum,
rover->master->frontsector, 255, false, *gr_frontsector->lightlist[light].extra_colormap);
}
}
@ -3684,7 +3736,7 @@ static void HWR_Subsector(size_t num)
else
alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, NORMALFOG);
HWR_AddTransparentFloor(0,
HWR_AddTransparentFloor(0, 0,
&extrasubsectors[num],
true,
*rover->topheight,
@ -3703,6 +3755,7 @@ static void HWR_Subsector(size_t num)
rover->alpha-1, rover->master->frontsector);
#else
HWR_AddTransparentFloor(levelflats[*rover->toppic].lumpnum,
levelflats[*rover->bottompic].texturenum,
&extrasubsectors[num],
true,
*rover->topheight,
@ -3715,8 +3768,9 @@ static void HWR_Subsector(size_t num)
else
{
HWR_GetFlat(levelflats[*rover->toppic].lumpnum);
HWR_GetTextureFlat(levelflats[*rover->toppic].texturenum);
light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
HWR_RenderPlane(NULL, &extrasubsectors[num], true, *rover->topheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->toppic].lumpnum,
HWR_RenderPlane(NULL, &extrasubsectors[num], true, *rover->topheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->toppic].lumpnum, levelflats[*rover->toppic].texturenum,
rover->master->frontsector, 255, false, *gr_frontsector->lightlist[light].extra_colormap);
}
}
@ -5045,6 +5099,7 @@ typedef struct
fixed_t fixedheight;
INT32 lightlevel;
lumpnum_t lumpnum;
INT32 texturenum;
INT32 alpha;
sector_t *FOFSector;
FBITFIELD blend;
@ -5063,6 +5118,7 @@ typedef struct
fixed_t fixedheight;
INT32 lightlevel;
lumpnum_t lumpnum;
INT32 texturenum;
INT32 alpha;
sector_t *FOFSector;
FBITFIELD blend;
@ -5093,7 +5149,7 @@ static INT32 drawcount = 0;
#define MAX_TRANSPARENTFLOOR 512
// This will likely turn into a copy of HWR_Add3DWater and replace it.
void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub, boolean isceiling,
void HWR_AddTransparentFloor(lumpnum_t lumpnum, INT32 texturenum, extrasubsector_t *xsub, boolean isceiling,
fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap)
{
static size_t allocedplanes = 0;
@ -5112,6 +5168,7 @@ void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub, boolean
planeinfo[numplanes].fixedheight = fixedheight;
planeinfo[numplanes].lightlevel = lightlevel;
planeinfo[numplanes].lumpnum = lumpnum;
planeinfo[numplanes].texturenum = texturenum;
planeinfo[numplanes].xsub = xsub;
planeinfo[numplanes].alpha = alpha;
planeinfo[numplanes].FOFSector = FOFSector;
@ -5125,7 +5182,7 @@ void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub, boolean
// Adding this for now until I can create extrasubsector info for polyobjects
// When that happens it'll just be done through HWR_AddTransparentFloor and HWR_RenderPlane
void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, polyobj_t *polysector, boolean isceiling,
void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, INT32 texturenum, polyobj_t *polysector, boolean isceiling,
fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, extracolormap_t *planecolormap)
{
static size_t allocedpolyplanes = 0;
@ -5144,6 +5201,7 @@ void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, polyobj_t *polysector,
polyplaneinfo[numpolyplanes].fixedheight = fixedheight;
polyplaneinfo[numpolyplanes].lightlevel = lightlevel;
polyplaneinfo[numpolyplanes].lumpnum = lumpnum;
polyplaneinfo[numpolyplanes].texturenum = texturenum;
polyplaneinfo[numpolyplanes].polysector = polysector;
polyplaneinfo[numpolyplanes].alpha = alpha;
polyplaneinfo[numpolyplanes].FOFSector = FOFSector;
@ -5305,9 +5363,12 @@ static void HWR_CreateDrawNodes(void)
gr_frontsector = NULL;
if (!(sortnode[sortindex[i]].plane->blend & PF_NoTexture))
{
HWR_GetFlat(sortnode[sortindex[i]].plane->lumpnum);
HWR_GetTextureFlat(sortnode[sortindex[i]].plane->texturenum);
}
HWR_RenderPlane(NULL, sortnode[sortindex[i]].plane->xsub, sortnode[sortindex[i]].plane->isceiling, sortnode[sortindex[i]].plane->fixedheight, sortnode[sortindex[i]].plane->blend, sortnode[sortindex[i]].plane->lightlevel,
sortnode[sortindex[i]].plane->lumpnum, sortnode[sortindex[i]].plane->FOFSector, sortnode[sortindex[i]].plane->alpha, sortnode[sortindex[i]].plane->fogplane, sortnode[sortindex[i]].plane->planecolormap);
sortnode[sortindex[i]].plane->lumpnum, sortnode[sortindex[i]].plane->texturenum, sortnode[sortindex[i]].plane->FOFSector, sortnode[sortindex[i]].plane->alpha, sortnode[sortindex[i]].plane->fogplane, sortnode[sortindex[i]].plane->planecolormap);
}
else if (sortnode[sortindex[i]].polyplane)
{
@ -5315,9 +5376,12 @@ static void HWR_CreateDrawNodes(void)
gr_frontsector = NULL;
if (!(sortnode[sortindex[i]].polyplane->blend & PF_NoTexture))
{
HWR_GetFlat(sortnode[sortindex[i]].polyplane->lumpnum);
HWR_GetTextureFlat(sortnode[sortindex[i]].polyplane->texturenum);
}
HWR_RenderPolyObjectPlane(sortnode[sortindex[i]].polyplane->polysector, sortnode[sortindex[i]].polyplane->isceiling, sortnode[sortindex[i]].polyplane->fixedheight, sortnode[sortindex[i]].polyplane->blend, sortnode[sortindex[i]].polyplane->lightlevel,
sortnode[sortindex[i]].polyplane->lumpnum, sortnode[sortindex[i]].polyplane->FOFSector, sortnode[sortindex[i]].polyplane->alpha, sortnode[sortindex[i]].polyplane->planecolormap);
sortnode[sortindex[i]].polyplane->lumpnum, sortnode[sortindex[i]].polyplane->texturenum, sortnode[sortindex[i]].polyplane->FOFSector, sortnode[sortindex[i]].polyplane->alpha, sortnode[sortindex[i]].polyplane->planecolormap);
}
else if (sortnode[sortindex[i]].wall)
{
@ -5805,86 +5869,122 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing)
// ==========================================================================
//
// ==========================================================================
static void HWR_DrawSkyBackground(void)
static void HWR_DrawSkyBackground(player_t *player)
{
FOutVector v[4];
angle_t angle;
float dimensionmultiply;
float aspectratio;
float angleturn;
HWR_GetTexture(texturetranslation[skytexture]);
aspectratio = (float)vid.width/(float)vid.height;
//Hurdler: the sky is the only texture who need 4.0f instead of 1.0
// because it's called just after clearing the screen
// and thus, the near clipping plane is set to 3.99
// Sryder: Just use the near clipping plane value then
// 3--2
// | /|
// |/ |
// 0--1
v[0].x = v[3].x = -ZCLIP_PLANE-1;
v[1].x = v[2].x = ZCLIP_PLANE+1;
v[0].y = v[1].y = -ZCLIP_PLANE-1;
v[2].y = v[3].y = ZCLIP_PLANE+1;
v[0].z = v[1].z = v[2].z = v[3].z = ZCLIP_PLANE+1;
// X
// NOTE: This doesn't work right with texture widths greater than 1024
// software doesn't draw any further than 1024 for skies anyway, but this doesn't overlap properly
// The only time this will probably be an issue is when a sky wider than 1024 is used as a sky AND a regular wall texture
angle = (dup_viewangle + gr_xtoviewangle[0]);
dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->width/256.0f);
v[0].sow = v[3].sow = (-1.0f * angle) / ((ANGLE_90-1)*dimensionmultiply); // left
v[2].sow = v[1].sow = v[0].sow + (1.0f/dimensionmultiply); // right (or left + 1.0f)
// use +angle and -1.0f above instead if you wanted old backwards behavior
// Y
angle = aimingangle;
dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->height/(128.0f*aspectratio));
if (splitscreen)
if (cv_grskydome.value)
{
dimensionmultiply *= 2;
angle *= 2;
}
FTransform transform;
const float fpov = FIXED_TO_FLOAT(cv_grfov.value+player->fovadd);
postimg_t *type;
// Middle of the sky should always be at angle 0
// need to keep correct aspect ratio with X
if (atransform.flip)
{
// During vertical flip the sky should be flipped and it's y movement should also be flipped obviously
v[3].tow = v[2].tow = -(0.5f-(0.5f/dimensionmultiply)); // top
v[0].tow = v[1].tow = v[3].tow - (1.0f/dimensionmultiply); // bottom (or top - 1.0f)
if (splitscreen && player == &players[secondarydisplayplayer])
type = &postimgtype2;
else
type = &postimgtype;
memset(&transform, 0x00, sizeof(FTransform));
//04/01/2000: Hurdler: added for T&L
// It should replace all other gr_viewxxx when finished
transform.anglex = (float)(aimingangle>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES);
transform.angley = (float)((viewangle-ANGLE_270)>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES);
if (*type == postimg_flip)
transform.flip = true;
else
transform.flip = false;
transform.scalex = 1;
transform.scaley = (float)vid.width/vid.height;
transform.scalez = 1;
transform.fovxangle = fpov; // Tails
transform.fovyangle = fpov; // Tails
transform.splitscreen = splitscreen;
HWR_GetTexture(texturetranslation[skytexture]);
HWD.pfnRenderSkyDome(skytexture, textures[skytexture]->width, textures[skytexture]->height, transform);
}
else
{
v[0].tow = v[1].tow = -(0.5f-(0.5f/dimensionmultiply)); // bottom
v[3].tow = v[2].tow = v[0].tow - (1.0f/dimensionmultiply); // top (or bottom - 1.0f)
}
FOutVector v[4];
angle_t angle;
float dimensionmultiply;
float aspectratio;
float angleturn;
angleturn = (((float)ANGLE_45-1.0f)*aspectratio)*dimensionmultiply;
HWR_GetTexture(texturetranslation[skytexture]);
aspectratio = (float)vid.width/(float)vid.height;
if (angle > ANGLE_180) // Do this because we don't want the sky to suddenly teleport when crossing over 0 to 360 and vice versa
{
angle = InvAngle(angle);
v[3].tow = v[2].tow += ((float) angle / angleturn);
v[0].tow = v[1].tow += ((float) angle / angleturn);
}
else
{
v[3].tow = v[2].tow -= ((float) angle / angleturn);
v[0].tow = v[1].tow -= ((float) angle / angleturn);
}
//Hurdler: the sky is the only texture who need 4.0f instead of 1.0
// because it's called just after clearing the screen
// and thus, the near clipping plane is set to 3.99
// Sryder: Just use the near clipping plane value then
HWD.pfnDrawPolygon(NULL, v, 4, 0);
// 3--2
// | /|
// |/ |
// 0--1
v[0].x = v[3].x = -ZCLIP_PLANE-1;
v[1].x = v[2].x = ZCLIP_PLANE+1;
v[0].y = v[1].y = -ZCLIP_PLANE-1;
v[2].y = v[3].y = ZCLIP_PLANE+1;
v[0].z = v[1].z = v[2].z = v[3].z = ZCLIP_PLANE+1;
// X
// NOTE: This doesn't work right with texture widths greater than 1024
// software doesn't draw any further than 1024 for skies anyway, but this doesn't overlap properly
// The only time this will probably be an issue is when a sky wider than 1024 is used as a sky AND a regular wall texture
angle = (dup_viewangle + gr_xtoviewangle[0]);
dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->width/256.0f);
v[0].sow = v[3].sow = (-1.0f * angle) / ((ANGLE_90-1)*dimensionmultiply); // left
v[2].sow = v[1].sow = v[0].sow + (1.0f/dimensionmultiply); // right (or left + 1.0f)
// use +angle and -1.0f above instead if you wanted old backwards behavior
// Y
angle = aimingangle;
dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->height/(128.0f*aspectratio));
if (splitscreen)
{
dimensionmultiply *= 2;
angle *= 2;
}
// Middle of the sky should always be at angle 0
// need to keep correct aspect ratio with X
if (atransform.flip)
{
// During vertical flip the sky should be flipped and it's y movement should also be flipped obviously
v[3].tow = v[2].tow = -(0.5f-(0.5f/dimensionmultiply)); // top
v[0].tow = v[1].tow = v[3].tow - (1.0f/dimensionmultiply); // bottom (or top - 1.0f)
}
else
{
v[0].tow = v[1].tow = -(0.5f-(0.5f/dimensionmultiply)); // bottom
v[3].tow = v[2].tow = v[0].tow - (1.0f/dimensionmultiply); // top (or bottom - 1.0f)
}
angleturn = (((float)ANGLE_45-1.0f)*aspectratio)*dimensionmultiply;
if (angle > ANGLE_180) // Do this because we don't want the sky to suddenly teleport when crossing over 0 to 360 and vice versa
{
angle = InvAngle(angle);
v[3].tow = v[2].tow += ((float) angle / angleturn);
v[0].tow = v[1].tow += ((float) angle / angleturn);
}
else
{
v[3].tow = v[2].tow -= ((float) angle / angleturn);
v[0].tow = v[1].tow -= ((float) angle / angleturn);
}
HWD.pfnDrawPolygon(NULL, v, 4, 0);
}
}
@ -6036,7 +6136,7 @@ if (0)
}
if (drawsky)
HWR_DrawSkyBackground();
HWR_DrawSkyBackground(player);
//Hurdler: it doesn't work in splitscreen mode
drawsky = splitscreen;
@ -6253,7 +6353,7 @@ if (0)
}
if (!skybox && drawsky) // Don't draw the regular sky if there's a skybox
HWR_DrawSkyBackground();
HWR_DrawSkyBackground(player);
//Hurdler: it doesn't work in splitscreen mode
drawsky = splitscreen;

View file

@ -98,6 +98,7 @@ extern consvar_t cv_voodoocompatibility;
extern consvar_t cv_grfovchange;
extern consvar_t cv_grsolvetjoin;
extern consvar_t cv_grspritebillboarding;
extern consvar_t cv_grskydome;
extern float gr_viewwidth, gr_viewheight, gr_baseviewwindowy;

View file

@ -747,10 +747,12 @@ static void md2_loadTexture(md2_t *model)
grpatch->mipmap.width = (UINT16)w;
grpatch->mipmap.height = (UINT16)h;
#ifdef GLIDE_API_COMPATIBILITY
// not correct!
grpatch->mipmap.grInfo.smallLodLog2 = GR_LOD_LOG2_256;
grpatch->mipmap.grInfo.largeLodLog2 = GR_LOD_LOG2_256;
grpatch->mipmap.grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
#endif
}
HWD.pfnSetTexture(&grpatch->mipmap);
HWR_UnlockCachedPatch(grpatch);
@ -798,10 +800,12 @@ static void md2_loadBlendTexture(md2_t *model)
grpatch->mipmap.width = (UINT16)w;
grpatch->mipmap.height = (UINT16)h;
#ifdef GLIDE_API_COMPATIBILITY
// not correct!
grpatch->mipmap.grInfo.smallLodLog2 = GR_LOD_LOG2_256;
grpatch->mipmap.grInfo.largeLodLog2 = GR_LOD_LOG2_256;
grpatch->mipmap.grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
#endif
}
HWD.pfnSetTexture(&grpatch->mipmap); // We do need to do this so that it can be cleared and knows to recreate it when necessary
HWR_UnlockCachedPatch(grpatch);

View file

@ -1427,6 +1427,232 @@ EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf,
Clamp2D(GL_TEXTURE_WRAP_T);
}
// PRBoom sky dome
typedef struct vbo_vertex_s
{
float x, y, z;
float u, v;
unsigned char r, g, b, a;
} vbo_vertex_t;
typedef struct
{
int mode;
int vertexcount;
int vertexindex;
int use_texture;
} GLSkyLoopDef;
typedef struct
{
int id;
int rows, columns;
int loopcount;
GLSkyLoopDef *loops;
vbo_vertex_t *data;
} GLSkyVBO;
// The texture offset to be applied to the texture coordinates in SkyVertex().
static int rows, columns;
static boolean yflip;
static int texw, texh;
static float yMult, yAdd;
static boolean foglayer;
static float delta = 0.0f;
static int gl_sky_detail = 16;
static INT32 lasttex = -1;
static RGBA_t SkyColor;
#define MAP_COEFF 128.0f
#define MAP_SCALE (MAP_COEFF*(float)FRACUNIT)
static void SkyVertex(vbo_vertex_t *vbo, int r, int c)
{
static fixed_t scale = 10000 << FRACBITS;
static angle_t maxSideAngle = ANGLE_180 / 3;
angle_t topAngle = (angle_t)(c / (float)columns * ANGLE_MAX);
angle_t sideAngle = maxSideAngle * (rows - r) / rows;
fixed_t height = FINESINE(sideAngle>>ANGLETOFINESHIFT);
fixed_t realRadius = FixedMul(scale, FINECOSINE(sideAngle>>ANGLETOFINESHIFT));
fixed_t x = FixedMul(realRadius, FINECOSINE(topAngle>>ANGLETOFINESHIFT));
fixed_t y = (!yflip) ? FixedMul(scale, height) : FixedMul(scale, height) * -1;
fixed_t z = FixedMul(realRadius, FINESINE(topAngle>>ANGLETOFINESHIFT));
float timesRepeat;
timesRepeat = (short)(4 * (256.0f / texw));
if (timesRepeat == 0.0f)
timesRepeat = 1.0f;
if (!foglayer)
{
boolean flip = yflip;
vbo->r = 255;
vbo->g = 255;
vbo->b = 255;
vbo->a = (r == 0 ? 0 : 255);
// Flip Y coordinate anyway for the top part of the hemisphere
if (r <= 1)
flip = !flip;
// And the texture coordinates.
vbo->u = (-timesRepeat * c / (float)columns);
if (!flip) // Flipped Y is for the lower hemisphere.
vbo->v = (r / (float)rows) * 1.f * yMult + yAdd;
else
vbo->v = ((rows-r)/(float)rows) * 1.f * yMult + yAdd;
}
// And finally the vertex.
vbo->x = (float)x/(float)MAP_SCALE;
vbo->y = (float)y/(float)MAP_SCALE + delta;
vbo->z = (float)z/(float)MAP_SCALE;
}
GLSkyVBO sky_vbo;
static void gld_BuildSky(int row_count, int col_count)
{
int c, r;
vbo_vertex_t *vertex_p;
int vertex_count = 2 * row_count * (col_count * 2 + 2) + col_count * 2;
GLSkyVBO *vbo = &sky_vbo;
if ((vbo->columns != col_count) || (vbo->rows != row_count))
{
free(vbo->loops);
free(vbo->data);
memset(vbo, 0, sizeof(&vbo));
}
if (!vbo->data)
{
memset(vbo, 0, sizeof(&vbo));
vbo->loops = malloc((row_count * 2 + 2) * sizeof(vbo->loops[0]));
// create vertex array
vbo->data = malloc(vertex_count * sizeof(vbo->data[0]));
}
vbo->columns = col_count;
vbo->rows = row_count;
vertex_p = &vbo->data[0];
vbo->loopcount = 0;
memset(&SkyColor, 0xFF, sizeof(SkyColor));
// Why not?
for (yflip = false; yflip <= true; yflip++)
{
vbo->loops[vbo->loopcount].mode = GL_TRIANGLE_FAN;
vbo->loops[vbo->loopcount].vertexindex = vertex_p - &vbo->data[0];
vbo->loops[vbo->loopcount].vertexcount = col_count;
vbo->loops[vbo->loopcount].use_texture = false;
vbo->loopcount++;
yAdd = 0.5f;
yMult = 1.0f;
/*if (yflip == 0)
SkyColor = &sky->CeilingSkyColor[vbo_idx];
else
SkyColor = &sky->FloorSkyColor[vbo_idx];*/
delta = 0.0f;
foglayer = true;
for (c = 0; c < col_count; c++)
{
SkyVertex(vertex_p, 1, c);
vertex_p->r = SkyColor.s.red;
vertex_p->g = SkyColor.s.green;
vertex_p->b = SkyColor.s.blue;
vertex_p->a = 255;
vertex_p++;
}
foglayer = false;
delta = (yflip ? 5.0f : -5.0f) / MAP_COEFF;
for (r = 0; r < row_count; r++)
{
vbo->loops[vbo->loopcount].mode = GL_TRIANGLE_STRIP;
vbo->loops[vbo->loopcount].vertexindex = vertex_p - &vbo->data[0];
vbo->loops[vbo->loopcount].vertexcount = 2 * col_count + 2;
vbo->loops[vbo->loopcount].use_texture = true; //(r > 1) ? true : false;
vbo->loopcount++;
for (c = 0; c <= col_count; c++)
{
SkyVertex(vertex_p++, r + (yflip ? 1 : 0), (c ? c : 0));
SkyVertex(vertex_p++, r + (yflip ? 0 : 1), (c ? c : 0));
}
}
}
}
static void RenderDomeForReal(INT32 skytexture)
{
int i, j;
GLSkyVBO *vbo = &sky_vbo;
pglRotatef(270.f, 0.f, 1.f, 0.f);
rows = 4;
columns = 4 * gl_sky_detail;
if (lasttex != skytexture)
{
lasttex = skytexture;
gld_BuildSky(rows, columns);
}
pglScalef(1.0f, (float)texh / 230.0f, 1.0f);
for (j = 0; j < 2; j++)
{
for (i = 0; i < vbo->loopcount; i++)
{
GLSkyLoopDef *loop = &vbo->loops[i];
if (j == 0 ? loop->use_texture : !loop->use_texture)
continue;
else
{
int k;
pglBegin(loop->mode);
for (k = loop->vertexindex; k < (loop->vertexindex + loop->vertexcount); k++)
{
vbo_vertex_t *v = &vbo->data[k];
if (loop->use_texture)
pglTexCoord2f(v->u, v->v);
pglColor4f(v->r, v->g, v->b, v->a);
pglVertex3f(v->x, v->y, v->z);
}
pglEnd();
}
}
}
pglScalef(1.0f, 1.0f, 1.0f);
// current color is undefined after glDrawArrays
pglColor4f(1.0f, 1.0f, 1.0f, 1.0f);
}
EXPORT void HWRAPI(RenderSkyDome) (INT32 tex, INT32 texture_width, INT32 texture_height, FTransform transform)
{
SetBlend(PF_Translucent|PF_NoDepthTest|PF_Modulated);
SetTransform(&transform);
texw = texture_width;
texh = texture_height;
RenderDomeForReal(tex);
// HWR_DrawSkyBackground left no blend flags after rendering the sky
SetBlend(0);
}
// ==========================================================================
//

View file

@ -73,18 +73,17 @@ char sprnames[NUMSPRITES + 1][5] =
"JETF", // Boss jet fumes
// Boss 1 (Greenflower)
"EGGM",
"EGGM", // Boss 1
"EGLZ", // Boss 1 Junk
// Boss 2 (Techno Hill)
"EGGN", // Boss 2
"TNKA", // Boss 2 Tank 1
"TNKB", // Boss 2 Tank 2
"SPNK", // Boss 2 Spigot
"TANK", // Boss 2 Junk
"GOOP", // Boss 2 Goop
// Boss 3 (Deep Sea)
"EGGO", // Boss 3
"PRPL", // Boss 3 Propeller
"SEBH", // Boss 3 Junk
"FAKE", // Boss 3 Fakemobile
// Boss 4 (Castle Eggman)
@ -1179,49 +1178,58 @@ state_t states[NUMSTATES] =
{SPR_BOM3, FF_FULLBRIGHT|4, 3, {NULL}, 0, 0, S_SONIC3KBOSSEXPLOSION6}, // S_SONIC3KBOSSEXPLOSION5
{SPR_BOM3, FF_FULLBRIGHT|5, 4, {NULL}, 0, 0, S_NULL}, // S_SONIC3KBOSSEXPLOSION6
{SPR_JETF, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_JETFUME2}, // S_JETFUME1
{SPR_NULL, 0, 1, {NULL}, 0, 0, S_JETFUME1}, // S_JETFUME2
{SPR_JETF, FF_ANIMATE|FF_FULLBRIGHT, -1, {NULL}, 2, 1, S_NULL}, // S_JETFUME1
// Boss 1
{SPR_EGGM, 0, 1, {A_Boss1Chase}, 0, 0, S_EGGMOBILE_STND}, // S_EGGMOBILE_STND
{SPR_EGGM, FF_ANIMATE|17, 35, {A_FaceTarget}, 1, 2, S_EGGMOBILE_STND}, // S_EGGMOBILE_ROFL
{SPR_EGGM, 1, 3, {A_FaceTarget}, 0, 0, S_EGGMOBILE_LATK2}, // S_EGGMOBILE_LATK1
{SPR_EGGM, 2, 15, {NULL}, 0, 0, S_EGGMOBILE_LATK3}, // S_EGGMOBILE_LATK2
{SPR_EGGM, 3, 2, {A_FaceTarget}, 0, 0, S_EGGMOBILE_LATK4}, // S_EGGMOBILE_LATK3
{SPR_EGGM, 4, 1, {NULL}, 0, 0, S_EGGMOBILE_LATK5}, // S_EGGMOBILE_LATK4
{SPR_EGGM, 5, 1, {NULL}, 0, 0, S_EGGMOBILE_LATK6}, // S_EGGMOBILE_LATK5
{SPR_EGGM, 6, 1, {NULL}, 0, 0, S_EGGMOBILE_LATK7}, // S_EGGMOBILE_LATK6
{SPR_EGGM, 7, 1, {NULL}, 0, 0, S_EGGMOBILE_LATK8}, // S_EGGMOBILE_LATK7
{SPR_EGGM, 8, 45, {A_Boss1Laser}, MT_LASER, 0, S_EGGMOBILE_LATK9}, // S_EGGMOBILE_LATK8
{SPR_EGGM, 9, 10, {NULL}, 0, 0, S_EGGMOBILE_LATK10}, // S_EGGMOBILE_LATK9
{SPR_EGGM, 10, 2, {NULL}, 0, 0, S_EGGMOBILE_STND}, // S_EGGMOBILE_LATK10
{SPR_EGGM, 11, 3, {A_FaceTarget}, 0, 0, S_EGGMOBILE_RATK2}, // S_EGGMOBILE_RATK1
{SPR_EGGM, 12, 15, {NULL}, 0, 0, S_EGGMOBILE_RATK3}, // S_EGGMOBILE_RATK2
{SPR_EGGM, 13, 2, {A_FaceTarget}, 0, 0, S_EGGMOBILE_RATK4}, // S_EGGMOBILE_RATK3
{SPR_EGGM, 14, 1, {NULL}, 0, 0, S_EGGMOBILE_RATK5}, // S_EGGMOBILE_RATK4
{SPR_EGGM, 15, 1, {NULL}, 0, 0, S_EGGMOBILE_RATK6}, // S_EGGMOBILE_RATK5
{SPR_EGGM, 16, 1, {NULL}, 0, 0, S_EGGMOBILE_RATK7}, // S_EGGMOBILE_RATK6
{SPR_EGGM, 17, 1, {NULL}, 0, 0, S_EGGMOBILE_RATK8}, // S_EGGMOBILE_RATK7
{SPR_EGGM, 18, 45, {A_Boss1Laser}, MT_LASER, 1, S_EGGMOBILE_RATK9}, // S_EGGMOBILE_RATK8
{SPR_EGGM, 19, 10, {NULL}, 0, 0, S_EGGMOBILE_RATK10}, // S_EGGMOBILE_RATK9
{SPR_EGGM, 20, 2, {NULL}, 0, 0, S_EGGMOBILE_STND}, // S_EGGMOBILE_RATK10
{SPR_EGGM, 3, 12, {NULL}, 0, 0, S_EGGMOBILE_PANIC2}, // S_EGGMOBILE_PANIC1
{SPR_EGGM, 4, 45, {A_Boss1Laser}, MT_LASER, 2, S_EGGMOBILE_PANIC3}, // S_EGGMOBILE_PANIC2
{SPR_EGGM, 3, 8, {NULL}, 0, 0, S_EGGMOBILE_PANIC4}, // S_EGGMOBILE_PANIC3
{SPR_EGGM, 4, 45, {A_Boss1Laser}, MT_LASER, 2, S_EGGMOBILE_PANIC5 }, // S_EGGMOBILE_PANIC4
{SPR_EGGM, 3, 8, {NULL}, 0, 0, S_EGGMOBILE_PANIC6}, // S_EGGMOBILE_PANIC5
{SPR_EGGM, 4, 45, {A_Boss1Laser}, MT_LASER, 2, S_EGGMOBILE_PANIC7 }, // S_EGGMOBILE_PANIC6
{SPR_EGGM, 0, 35, {NULL}, 0, 0, S_EGGMOBILE_STND }, // S_EGGMOBILE_PANIC7
{SPR_EGGM, 21, 24, {A_Pain}, 0, 0, S_EGGMOBILE_PAIN2}, // S_EGGMOBILE_PAIN
{SPR_EGGM, 21, 16, {A_SkullAttack}, 1, 1, S_EGGMOBILE_STND}, // S_EGGMOBILE_PAIN2
{SPR_EGGM, 22, 2, {A_Fall}, 0, 0, S_EGGMOBILE_DIE2}, // S_EGGMOBILE_DIE1
{SPR_EGGM, 22, 2, {A_BossScream}, 0, 0, S_EGGMOBILE_DIE3}, // S_EGGMOBILE_DIE2
{SPR_EGGM, 22, 0, {A_Repeat}, 17, S_EGGMOBILE_DIE2, S_EGGMOBILE_DIE4}, // S_EGGMOBILE_DIE3
{SPR_EGGM, 22, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_EGGMOBILE_DIE4
{SPR_EGGM, 23, 2, {A_BossScream}, 0, 0, S_EGGMOBILE_FLEE2}, // S_EGGMOBILE_FLEE1
{SPR_EGGM, 24, 2, {A_BossScream}, 0, 0, S_EGGMOBILE_FLEE1}, // S_EGGMOBILE_FLEE2
{SPR_EGGM, 3, 2, {NULL}, 0, 0, S_EGGMOBILE_LATK4}, // S_EGGMOBILE_LATK3
{SPR_EGGM, 4, 2, {A_FaceTarget}, 0, 0, S_EGGMOBILE_LATK5}, // S_EGGMOBILE_LATK4
{SPR_EGGM, 6, 0, {A_PrepareRepeat}, 45, 0, S_EGGMOBILE_LATK6}, // S_EGGMOBILE_LATK5
{SPR_EGGM, 5, 1, {A_Boss1Laser}, MT_LASER, 0, S_EGGMOBILE_LATK7}, // S_EGGMOBILE_LATK6
{SPR_EGGM, 6, 1, {A_Boss1Laser}, MT_LASER, (1<<16), S_EGGMOBILE_LATK8}, // S_EGGMOBILE_LATK7
{SPR_EGGM, 5, 0, {A_Repeat}, 45, S_EGGMOBILE_LATK6, S_EGGMOBILE_LATK9}, // S_EGGMOBILE_LATK8
{SPR_EGGM, 8, 2, {NULL}, 0, 0, S_EGGMOBILE_ROFL}, // S_EGGMOBILE_LATK9
{SPR_EGGM, 9, 3, {A_FaceTarget}, 0, 0, S_EGGMOBILE_RATK2}, // S_EGGMOBILE_RATK1
{SPR_EGGM, 10, 15, {NULL}, 0, 0, S_EGGMOBILE_RATK3}, // S_EGGMOBILE_RATK2
{SPR_EGGM, 11, 2, {NULL}, 0, 0, S_EGGMOBILE_RATK4}, // S_EGGMOBILE_RATK3
{SPR_EGGM, 12, 2, {A_FaceTarget}, 0, 0, S_EGGMOBILE_RATK5}, // S_EGGMOBILE_RATK4
{SPR_EGGM, 14, 0, {A_PrepareRepeat}, 45, 0, S_EGGMOBILE_RATK6}, // S_EGGMOBILE_RATK5
{SPR_EGGM, 13, 1, {A_Boss1Laser}, MT_LASER, 1, S_EGGMOBILE_RATK7}, // S_EGGMOBILE_RATK6
{SPR_EGGM, 14, 1, {A_Boss1Laser}, MT_LASER, 1|(1<<16), S_EGGMOBILE_RATK8}, // S_EGGMOBILE_RATK7
{SPR_EGGM, 13, 0, {A_Repeat}, 45, S_EGGMOBILE_RATK6, S_EGGMOBILE_RATK9}, // S_EGGMOBILE_RATK8
{SPR_EGGM, 16, 2, {NULL}, 0, 0, S_EGGMOBILE_ROFL}, // S_EGGMOBILE_RATK9
{SPR_EGGM, 0, 0, {A_PrepareRepeat}, 45, 0, S_EGGMOBILE_PANIC2}, // S_EGGMOBILE_PANIC1
{SPR_EGGM, FF_ANIMATE|1, 16, {A_FaceTarget}, 3, 4, S_EGGMOBILE_PANIC3}, // S_EGGMOBILE_PANIC2
{SPR_EGGM, 7, 1, {A_Boss1Laser}, MT_LASER, 2, S_EGGMOBILE_PANIC4}, // S_EGGMOBILE_PANIC3
{SPR_EGGM, 6, 1, {A_Boss1Laser}, MT_LASER, 2|(1<<16), S_EGGMOBILE_PANIC5}, // S_EGGMOBILE_PANIC4
{SPR_EGGM, 6, 0, {A_Repeat}, 45, S_EGGMOBILE_PANIC3, S_EGGMOBILE_PANIC6}, // S_EGGMOBILE_PANIC5
{SPR_EGGM, 0, 0, {A_PrepareRepeat}, 45, 0, S_EGGMOBILE_PANIC7}, // S_EGGMOBILE_PANIC6
{SPR_EGGM, FF_ANIMATE|9, 16, {A_FaceTarget}, 3, 4, S_EGGMOBILE_PANIC8}, // S_EGGMOBILE_PANIC7
{SPR_EGGM, 15, 1, {A_Boss1Laser}, MT_LASER, 2, S_EGGMOBILE_PANIC9}, // S_EGGMOBILE_PANIC8
{SPR_EGGM, 14, 1, {A_Boss1Laser}, MT_LASER, 2|(1<<16), S_EGGMOBILE_PANIC10}, // S_EGGMOBILE_PANIC9
{SPR_EGGM, 14, 0, {A_Repeat}, 45, S_EGGMOBILE_PANIC8, S_EGGMOBILE_PANIC11}, // S_EGGMOBILE_PANIC10
{SPR_EGGM, 0, 0, {A_PrepareRepeat}, 45, 0, S_EGGMOBILE_PANIC12}, // S_EGGMOBILE_PANIC11
{SPR_EGGM, FF_ANIMATE|1, 16, {A_FaceTarget}, 3, 4, S_EGGMOBILE_PANIC13}, // S_EGGMOBILE_PANIC12
{SPR_EGGM, 7, 1, {A_Boss1Laser}, MT_LASER, 2, S_EGGMOBILE_PANIC14}, // S_EGGMOBILE_PANIC13
{SPR_EGGM, 6, 1, {A_Boss1Laser}, MT_LASER, 2|(1<<16), S_EGGMOBILE_PANIC15}, // S_EGGMOBILE_PANIC14
{SPR_EGGM, 6, 0, {A_Repeat}, 45, S_EGGMOBILE_PANIC13, S_EGGMOBILE_ROFL}, // S_EGGMOBILE_PANIC15
{SPR_EGGM, 19, 24, {A_Pain}, 0, 0, S_EGGMOBILE_PAIN2}, // S_EGGMOBILE_PAIN
{SPR_EGGM, 19, 16, {A_SkullAttack}, 3, 1, S_EGGMOBILE_STND}, // S_EGGMOBILE_PAIN2
{SPR_EGGM, 20, 2, {A_Fall}, 17, 0, S_EGGMOBILE_DIE2}, // S_EGGMOBILE_DIE1
{SPR_EGGM, 20, 2, {A_BossScream}, 0, 0, S_EGGMOBILE_DIE3}, // S_EGGMOBILE_DIE2
{SPR_EGGM, 20, 0, {A_Repeat}, 17, S_EGGMOBILE_DIE2, S_EGGMOBILE_DIE4}, // S_EGGMOBILE_DIE3
{SPR_EGGM, 20, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_EGGMOBILE_DIE4
{SPR_EGGM, 21, 2, {A_BossScream}, 0, 0, S_EGGMOBILE_FLEE2}, // S_EGGMOBILE_FLEE1
{SPR_EGGM, 22, 2, {A_BossScream}, 0, 0, S_EGGMOBILE_FLEE1}, // S_EGGMOBILE_FLEE2
{SPR_UNID, 1, 1, {A_UnidusBall}, 2, 0, S_EGGMOBILE_BALL}, // S_EGGMOBILE_BALL
{SPR_NULL, 0, 1, {A_FocusTarget}, 0, 0, S_EGGMOBILE_TARGET}, // S_EGGMOBILE_TARGET
{SPR_EGLZ, 0, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSEGLZ1
{SPR_EGLZ, 1, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSEGLZ2
// Boss 2
{SPR_EGGN, 0, -1, {NULL}, 0, 0, S_NULL}, // S_EGGMOBILE2_STND
{SPR_EGGN, 1, 4, {NULL}, 0, 0, S_EGGMOBILE2_POGO2}, // S_EGGMOBILE2_POGO1
@ -1240,9 +1248,9 @@ state_t states[NUMSTATES] =
{SPR_EGGN, 6, 2, {A_BossScream}, 0, 0, S_EGGMOBILE2_FLEE2}, // S_EGGMOBILE2_FLEE1
{SPR_EGGN, 7, 2, {A_BossScream}, 0, 0, S_EGGMOBILE2_FLEE1}, // S_EGGMOBILE2_FLEE2
{SPR_TNKA, 0, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSTANK1
{SPR_TNKB, 0, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSTANK2
{SPR_SPNK, 0, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSSPIGOT
{SPR_TANK, 0, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSTANK1
{SPR_TANK, 1, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSTANK2
{SPR_TANK, 2, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSSPIGOT
// Boss 2 Goop
{SPR_GOOP, 0, 2, {A_SpawnObjectRelative}, 0, MT_GOOPTRAIL, S_GOOP2}, // S_GOOP1
@ -1252,34 +1260,16 @@ state_t states[NUMSTATES] =
// Boss 3
{SPR_EGGO, 0, 1, {NULL}, 0, 0, S_EGGMOBILE3_STND}, // S_EGGMOBILE3_STND
{SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH2}, // S_EGGMOBILE3_LAUGH1
{SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH3}, // S_EGGMOBILE3_LAUGH2
{SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH4}, // S_EGGMOBILE3_LAUGH3
{SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH5}, // S_EGGMOBILE3_LAUGH4
{SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_ATK1}, // S_EGGMOBILE3_LAUGH5
{SPR_EGGO, 1, 2, {NULL}, 0, 0, S_EGGMOBILE3_ATK2}, // S_EGGMOBILE3_ATK1
{SPR_EGGO, FF_ANIMATE, 24, {NULL}, 1, 2, S_EGGMOBILE3_ATK2}, // S_EGGMOBILE3_SHOCK
{SPR_EGGO, 6|FF_ANIMATE, 24, {NULL}, 1, 2, S_EGGMOBILE3_ATK2}, // S_EGGMOBILE3_ATK1
{SPR_EGGO, 2, 2, {NULL}, 0, 0, S_EGGMOBILE3_ATK3A}, // S_EGGMOBILE3_ATK2
{SPR_EGGO, 3, 2, {A_BossFireShot}, MT_TORPEDO, 2, S_EGGMOBILE3_ATK3B}, // S_EGGMOBILE3_ATK3A
{SPR_EGGO, 3, 2, {A_BossFireShot}, MT_TORPEDO, 4, S_EGGMOBILE3_ATK3C}, // S_EGGMOBILE3_ATK3B
{SPR_EGGO, 3, 2, {A_BossFireShot}, MT_TORPEDO, 3, S_EGGMOBILE3_ATK3D}, // S_EGGMOBILE3_ATK3C
{SPR_EGGO, 3, 2, {A_BossFireShot}, MT_TORPEDO, 5, S_EGGMOBILE3_ATK4}, // S_EGGMOBILE3_ATK3D
{SPR_EGGO, 4, 2, {NULL}, 0, 0, S_EGGMOBILE3_ATK5}, // S_EGGMOBILE3_ATK4
{SPR_EGGO, 5, 2, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH6}, // S_EGGMOBILE3_ATK5
{SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH7}, // S_EGGMOBILE3_LAUGH6
{SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH8}, // S_EGGMOBILE3_LAUGH7
{SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH9}, // S_EGGMOBILE3_LAUGH8
{SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH10}, // S_EGGMOBILE3_LAUGH9
{SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH11}, // S_EGGMOBILE3_LAUGH10
{SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH12}, // S_EGGMOBILE3_LAUGH11
{SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH13}, // S_EGGMOBILE3_LAUGH12
{SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH14}, // S_EGGMOBILE3_LAUGH13
{SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH15}, // S_EGGMOBILE3_LAUGH14
{SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH16}, // S_EGGMOBILE3_LAUGH15
{SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH17}, // S_EGGMOBILE3_LAUGH16
{SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH18}, // S_EGGMOBILE3_LAUGH17
{SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH19}, // S_EGGMOBILE3_LAUGH18
{SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH20}, // S_EGGMOBILE3_LAUGH19
{SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_STND}, // S_EGGMOBILE3_LAUGH20
{SPR_EGGO, 5, 2, {NULL}, 0, 0, S_EGGMOBILE3_ROFL}, // S_EGGMOBILE3_ATK5
{SPR_EGGO, 6|FF_ANIMATE, 60, {NULL}, 1, 2, S_EGGMOBILE3_STND}, // S_EGGMOBILE3_ROFL
{SPR_EGGO, 8, 1, {A_Boss3TakeDamage}, 0, 0, S_EGGMOBILE3_PAIN2}, // S_EGGMOBILE3_PAIN
{SPR_EGGO, 8, 23, {A_Pain}, 0, 0, S_EGGMOBILE3_STND}, // S_EGGMOBILE3_PAIN2
{SPR_EGGO, 9, 2, {A_Fall}, 0, 0, S_EGGMOBILE3_DIE2}, // S_EGGMOBILE3_DIE1
@ -1289,17 +1279,8 @@ state_t states[NUMSTATES] =
{SPR_EGGO, 10, 2, {A_BossScream}, 0, 0, S_EGGMOBILE3_FLEE2}, // S_EGGMOBILE3_FLEE1
{SPR_EGGO, 11, 2, {A_BossScream}, 0, 0, S_EGGMOBILE3_FLEE1}, // S_EGGMOBILE3_FLEE2
// Boss 3 Propeller
{SPR_PRPL, 0, 1, {NULL}, 0, 0, S_PROPELLER2}, // S_PROPELLER1
{SPR_PRPL, 1, 1, {NULL}, 0, 0, S_PROPELLER3}, // S_PROPELLER2
{SPR_PRPL, 2, 1, {NULL}, 0, 0, S_PROPELLER4}, // S_PROPELLER3
{SPR_PRPL, 3, 1, {NULL}, 0, 0, S_PROPELLER5}, // S_PROPELLER4
{SPR_PRPL, 4, 1, {NULL}, 0, 0, S_PROPELLER6}, // S_PROPELLER5
{SPR_PRPL, 5, 1, {NULL}, 0, 0, S_PROPELLER7}, // S_PROPELLER6
{SPR_PRPL, 6, 1, {NULL}, 0, 0, S_PROPELLER1}, // S_PROPELLER7
// Boss 3 Pinch
{SPR_FAKE, 0, 1, {A_BossJetFume}, 1, 0, S_FAKEMOBILE}, // S_FAKEMOBILE_INIT
{SPR_FAKE, 0, 1, {NULL}, 0, 0, S_FAKEMOBILE}, // S_FAKEMOBILE_INIT
{SPR_FAKE, 0, 1, {A_Boss3Path}, 0, 0, S_FAKEMOBILE}, // S_FAKEMOBILE
{SPR_FAKE, 0, 22, {NULL}, 0, 0, S_FAKEMOBILE_ATK2}, // S_FAKEMOBILE_ATK1
{SPR_FAKE, 0, 2, {NULL}, 0, 0, S_FAKEMOBILE_ATK3A}, // S_FAKEMOBILE_ATK2
@ -1307,33 +1288,36 @@ state_t states[NUMSTATES] =
{SPR_FAKE, 0, 2, {A_BossFireShot}, MT_TORPEDO2, 4, S_FAKEMOBILE_ATK3C}, // S_FAKEMOBILE_ATK3B
{SPR_FAKE, 0, 2, {A_BossFireShot}, MT_TORPEDO2, 3, S_FAKEMOBILE_ATK3D}, // S_FAKEMOBILE_ATK3C
{SPR_FAKE, 0, 2, {A_BossFireShot}, MT_TORPEDO2, 5, S_FAKEMOBILE}, // S_FAKEMOBILE_ATK3D
{SPR_FAKE, 0, 1, {NULL}, 0, 0, S_FAKEMOBILE_DIE2}, // S_FAKEMOBILE_DIE1
{SPR_FAKE, 1, 1, {NULL}, 0, 0, S_FAKEMOBILE_DIE2}, // S_FAKEMOBILE_DIE1
{SPR_NULL, 0, 1, {NULL}, 0, 0, S_FAKEMOBILE_DIE1}, // S_FAKEMOBILE_DIE2
{SPR_SEBH, 0, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSSEBH1
{SPR_SEBH, 1, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSSEBH2
// Boss 4
{SPR_EGGP, 0, -1, {NULL}, 0, 0, S_NULL}, // S_EGGMOBILE4_STND
{SPR_EGGP, 1, 3, {NULL}, 0, 0, S_EGGMOBILE4_LATK2}, // S_EGGMOBILE4_LATK1
{SPR_EGGP, 2, 15, {NULL}, 0, 0, S_EGGMOBILE4_LATK3}, // S_EGGMOBILE4_LATK2
{SPR_EGGP, 3, 2, {NULL}, 0, 0, S_EGGMOBILE4_LATK4}, // S_EGGMOBILE4_LATK3
{SPR_EGGP, 4, 4, {NULL}, 0, 0, S_EGGMOBILE4_LATK5}, // S_EGGMOBILE4_LATK4
{SPR_EGGP, 4, 50, {A_Boss4Reverse}, sfx_mswing, 0, S_EGGMOBILE4_LATK6}, // S_EGGMOBILE4_LATK5
{SPR_EGGP, 5, 2, {NULL}, 0, 0, S_EGGMOBILE4_STND}, // S_EGGMOBILE4_LATK6
{SPR_EGGP, 6, 3, {NULL}, 0, 0, S_EGGMOBILE4_RATK2}, // S_EGGMOBILE4_RATK1
{SPR_EGGP, 7, 15, {NULL}, 0, 0, S_EGGMOBILE4_RATK3}, // S_EGGMOBILE4_RATK2
{SPR_EGGP, 8, 2, {NULL}, 0, 0, S_EGGMOBILE4_RATK4}, // S_EGGMOBILE4_RATK3
{SPR_EGGP, 9, 4, {NULL}, 0, 0, S_EGGMOBILE4_RATK5}, // S_EGGMOBILE4_RATK4
{SPR_EGGP, 9,150, {A_Boss4SpeedUp}, sfx_mswing, 0, S_EGGMOBILE4_RATK6}, // S_EGGMOBILE4_RATK5
{SPR_EGGP,10, 2, {NULL}, 0, 0, S_EGGMOBILE4_STND}, // S_EGGMOBILE4_RATK6
{SPR_EGGP, 0, 20, {A_Boss4Raise}, sfx_doord1, 0, S_EGGMOBILE4_RAISE2}, // S_EGGMOBILE4_RAISE1
{SPR_EGGP,13|FF_ANIMATE, -1, {NULL}, 1, 10, S_NULL}, // S_EGGMOBILE4_RAISE2
{SPR_EGGP,11, 0, {A_Boss4Reverse}, sfx_alarm, sfx_s3k60, S_EGGMOBILE4_PAIN2}, // S_EGGMOBILE4_PAIN1
{SPR_EGGP,11, 24, {A_Pain}, 0, 0, S_EGGMOBILE4_STND}, // S_EGGMOBILE4_PAIN2
{SPR_EGGP,12, 2, {A_Fall}, 0, 0, S_EGGMOBILE4_DIE2}, // S_EGGMOBILE4_DIE1
{SPR_EGGP,12, 2, {A_BossScream}, 0, 0, S_EGGMOBILE4_DIE3}, // S_EGGMOBILE4_DIE2
{SPR_EGGP,12, 0, {A_Repeat}, 17, S_EGGMOBILE4_DIE2, S_EGGMOBILE4_DIE4}, // S_EGGMOBILE4_DIE3
{SPR_EGGP,12, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_EGGMOBILE4_DIE4
{SPR_EGGP,13, 2, {A_BossScream}, 0, 0, S_EGGMOBILE4_FLEE2}, // S_EGGMOBILE4_FLEE1
{SPR_EGGP,14, 2, {A_BossScream}, 0, 0, S_EGGMOBILE4_FLEE1}, // S_EGGMOBILE4_FLEE2
{SPR_EGGP, 4, 2, {NULL}, 0, 0, S_EGGMOBILE4_LATK5}, // S_EGGMOBILE4_LATK4
{SPR_EGGP, 5, 50, {A_Boss4Reverse}, sfx_mswing, 0, S_EGGMOBILE4_LATK6}, // S_EGGMOBILE4_LATK5
{SPR_EGGP, 6, 2, {NULL}, 0, 0, S_EGGMOBILE4_STND}, // S_EGGMOBILE4_LATK6
{SPR_EGGP, 7, 3, {NULL}, 0, 0, S_EGGMOBILE4_RATK2}, // S_EGGMOBILE4_RATK1
{SPR_EGGP, 8, 15, {NULL}, 0, 0, S_EGGMOBILE4_RATK3}, // S_EGGMOBILE4_RATK2
{SPR_EGGP, 9, 2, {NULL}, 0, 0, S_EGGMOBILE4_RATK4}, // S_EGGMOBILE4_RATK3
{SPR_EGGP,10, 2, {NULL}, 0, 0, S_EGGMOBILE4_RATK5}, // S_EGGMOBILE4_RATK4
{SPR_EGGP,11,150, {A_Boss4SpeedUp}, sfx_mswing, 0, S_EGGMOBILE4_RATK6}, // S_EGGMOBILE4_RATK5
{SPR_EGGP,12, 2, {NULL}, 0, 0, S_EGGMOBILE4_STND}, // S_EGGMOBILE4_RATK6
{SPR_EGGP,13, 20, {A_Boss4Raise}, sfx_doord1, 0, S_EGGMOBILE4_RAISE2}, // S_EGGMOBILE4_RAISE1
{SPR_EGGP,15|FF_ANIMATE, -1, {NULL}, 1, 10, S_NULL}, // S_EGGMOBILE4_RAISE2
{SPR_EGGP,13, 0, {A_Boss4Reverse}, sfx_alarm, sfx_s3k60, S_EGGMOBILE4_PAIN2}, // S_EGGMOBILE4_PAIN1
{SPR_EGGP,13, 24, {A_Pain}, 0, 0, S_EGGMOBILE4_STND}, // S_EGGMOBILE4_PAIN2
{SPR_EGGP,14, 2, {A_Fall}, 0, 0, S_EGGMOBILE4_DIE2}, // S_EGGMOBILE4_DIE1
{SPR_EGGP,14, 2, {A_BossScream}, 0, 0, S_EGGMOBILE4_DIE3}, // S_EGGMOBILE4_DIE2
{SPR_EGGP,14, 0, {A_Repeat}, 17, S_EGGMOBILE4_DIE2, S_EGGMOBILE4_DIE4}, // S_EGGMOBILE4_DIE3
{SPR_EGGP,14, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_EGGMOBILE4_DIE4
{SPR_EGGP,15, 2, {A_BossScream}, 0, 0, S_EGGMOBILE4_FLEE2}, // S_EGGMOBILE4_FLEE1
{SPR_EGGP,16, 2, {A_BossScream}, 0, 0, S_EGGMOBILE4_FLEE1}, // S_EGGMOBILE4_FLEE2
{SPR_BMCE, 0, -1, {NULL}, 0, 0, S_NULL}, // S_EGGMOBILE4_MACE
{SPR_BMCE, 0, 2, {A_BossScream}, 1, 0, S_EGGMOBILE4_MACE_DIE2}, // S_EGGMOBILE4_MACE_DIE1
{SPR_NULL, 0, 2, {A_BossScream}, 1, 0, S_EGGMOBILE4_MACE_DIE3}, // S_EGGMOBILE4_MACE_DIE2
@ -1732,18 +1716,8 @@ state_t states[NUMSTATES] =
{SPR_METL, 11, 1, {A_BossScream}, 0, 0, S_METALSONIC_FLEE2}, // S_METALSONIC_FLEE1
{SPR_METL, 11, 7, {NULL}, 0, 0, S_METALSONIC_FLEE1}, // S_METALSONIC_FLEE2
{SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 0, 1, {NULL}, 0, 0, S_MSSHIELD_F2}, // S_MSSHIELD_F1
{SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 1, 1, {NULL}, 0, 0, S_MSSHIELD_F3}, // S_MSSHIELD_F2
{SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 2, 1, {NULL}, 0, 0, S_MSSHIELD_F4}, // S_MSSHIELD_F3
{SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 3, 1, {NULL}, 0, 0, S_MSSHIELD_F5}, // S_MSSHIELD_F4
{SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 4, 1, {NULL}, 0, 0, S_MSSHIELD_F6}, // S_MSSHIELD_F5
{SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 5, 1, {NULL}, 0, 0, S_MSSHIELD_F7}, // S_MSSHIELD_F6
{SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 6, 1, {NULL}, 0, 0, S_MSSHIELD_F8}, // S_MSSHIELD_F7
{SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 7, 1, {NULL}, 0, 0, S_MSSHIELD_F9}, // S_MSSHIELD_F8
{SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 8, 1, {NULL}, 0, 0, S_MSSHIELD_F10}, // S_MSSHIELD_F9
{SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 9, 1, {NULL}, 0, 0, S_MSSHIELD_F11}, // S_MSSHIELD_F10
{SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30|10, 1, {NULL}, 0, 0, S_MSSHIELD_F12}, // S_MSSHIELD_F11
{SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30|11, 1, {NULL}, 0, 0, S_MSSHIELD_F1}, // S_MSSHIELD_F12
{SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30|FF_ANIMATE, -1, {NULL}, 11, 1, S_NULL}, // S_MSSHIELD_F1
{SPR_MSCF, FF_FULLBRIGHT|FF_ANIMATE|12, -1, {NULL}, 8, 2, S_NULL}, // S_MSSHIELD_F2
// Ring
{SPR_RING, FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 23, 1, S_RING}, // S_RING
@ -5144,6 +5118,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
{ // MT_BOSSJUNK
-1, // doomednum
S_BOSSEGLZ1, // spawnstate
1, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
8*FRACUNIT, // radius
64*FRACUNIT, // height
2, // display offset
100, // mass
1, // damage
sfx_None, // activesound
MF_SCENERY|MF_NOBLOCKMAP|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate
},
{ // MT_EGGMOBILE
200, // doomednum
S_EGGMOBILE_STND, // spawnstate
@ -5333,87 +5334,6 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_EGGMOBILE2_POGO5 // raisestate
},
{ // MT_BOSSTANK1
-1, // doomednum
S_BOSSTANK1, // spawnstate
1, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
8*FRACUNIT, // radius
64*FRACUNIT, // height
0, // display offset
100, // mass
1, // damage
sfx_None, // activesound
MF_SCENERY|MF_NOBLOCKMAP|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate
},
{ // MT_BOSSTANK2
-1, // doomednum
S_BOSSTANK2, // spawnstate
1, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
8*FRACUNIT, // radius
64*FRACUNIT, // height
0, // display offset
100, // mass
1, // damage
sfx_None, // activesound
MF_SCENERY|MF_NOBLOCKMAP|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate
},
{ // MT_BOSSSPIGOT
-1, // doomednum
S_BOSSSPIGOT, // spawnstate
1, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
8*FRACUNIT, // radius
24*FRACUNIT, // height
0, // display offset
100, // mass
1, // damage
sfx_None, // activesound
MF_SCENERY|MF_NOBLOCKMAP|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate
},
{ // MT_GOOP
-1, // doomednum
S_GOOP1, // spawnstate
@ -5477,10 +5397,10 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // reactiontime
sfx_None, // attacksound
S_EGGMOBILE3_PAIN, // painstate
MT_PROPELLER, // painchance
MT_NULL, // painchance
sfx_dmpain, // painsound
S_NULL, // meleestate
S_EGGMOBILE3_LAUGH1,// missilestate
S_EGGMOBILE3_SHOCK, // missilestate
S_EGGMOBILE3_DIE1, // deathstate
S_EGGMOBILE3_FLEE1, // xdeathstate
sfx_s3kb4, // deathsound
@ -5492,34 +5412,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
3, // damage
sfx_telept, // activesound
MF_SPECIAL|MF_SHOOTABLE|MF_NOGRAVITY|MF_BOSS|MF_NOCLIPHEIGHT, // flags
S_EGGMOBILE3_LAUGH20 // raisestate
},
{ // MT_PROPELLER
-1, // doomednum
S_PROPELLER1, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
1, // speed
4*FRACUNIT, // radius
4*FRACUNIT, // height
0, // display offset
4, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate
S_EGGMOBILE3_ROFL // raisestate
},
{ // MT_FAKEMOBILE
@ -5531,7 +5424,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
MT_PROPELLER, // painchance
MT_NULL, // painchance
sfx_s3k7b, // painsound
S_NULL, // meleestate
S_FAKEMOBILE_ATK1, // missilestate
@ -9211,7 +9104,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // mass
20, // damage
sfx_None, // activesound
MF_PAIN|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
MF_PAIN|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_NOCLIP, // flags
S_NULL // raisestate
},

View file

@ -319,18 +319,17 @@ typedef enum sprite
SPR_JETF, // Boss jet fumes
// Boss 1 (Greenflower)
SPR_EGGM,
SPR_EGGM, // Boss 1
SPR_EGLZ, // Boss 1 Junk
// Boss 2 (Techno Hill)
SPR_EGGN, // Boss 2
SPR_TNKA, // Boss 2 Tank 1
SPR_TNKB, // Boss 2 Tank 2
SPR_SPNK, // Boss 2 Spigot
SPR_TANK, // Boss 2 Junk
SPR_GOOP, // Boss 2 Goop
// Boss 3 (Deep Sea)
SPR_EGGO, // Boss 3
SPR_PRPL, // Boss 3 Propeller
SPR_SEBH, // Boss 3 Junk
SPR_FAKE, // Boss 3 Fakemobile
// Boss 4 (Castle Eggman)
@ -1339,10 +1338,10 @@ typedef enum state
S_SONIC3KBOSSEXPLOSION6,
S_JETFUME1,
S_JETFUME2,
// Boss 1
S_EGGMOBILE_STND,
S_EGGMOBILE_ROFL,
S_EGGMOBILE_LATK1,
S_EGGMOBILE_LATK2,
S_EGGMOBILE_LATK3,
@ -1352,7 +1351,6 @@ typedef enum state
S_EGGMOBILE_LATK7,
S_EGGMOBILE_LATK8,
S_EGGMOBILE_LATK9,
S_EGGMOBILE_LATK10,
S_EGGMOBILE_RATK1,
S_EGGMOBILE_RATK2,
S_EGGMOBILE_RATK3,
@ -1362,7 +1360,6 @@ typedef enum state
S_EGGMOBILE_RATK7,
S_EGGMOBILE_RATK8,
S_EGGMOBILE_RATK9,
S_EGGMOBILE_RATK10,
S_EGGMOBILE_PANIC1,
S_EGGMOBILE_PANIC2,
S_EGGMOBILE_PANIC3,
@ -1370,6 +1367,14 @@ typedef enum state
S_EGGMOBILE_PANIC5,
S_EGGMOBILE_PANIC6,
S_EGGMOBILE_PANIC7,
S_EGGMOBILE_PANIC8,
S_EGGMOBILE_PANIC9,
S_EGGMOBILE_PANIC10,
S_EGGMOBILE_PANIC11,
S_EGGMOBILE_PANIC12,
S_EGGMOBILE_PANIC13,
S_EGGMOBILE_PANIC14,
S_EGGMOBILE_PANIC15,
S_EGGMOBILE_PAIN,
S_EGGMOBILE_PAIN2,
S_EGGMOBILE_DIE1,
@ -1381,6 +1386,9 @@ typedef enum state
S_EGGMOBILE_BALL,
S_EGGMOBILE_TARGET,
S_BOSSEGLZ1,
S_BOSSEGLZ2,
// Boss 2
S_EGGMOBILE2_STND,
S_EGGMOBILE2_POGO1,
@ -1411,11 +1419,7 @@ typedef enum state
// Boss 3
S_EGGMOBILE3_STND,
S_EGGMOBILE3_LAUGH1,
S_EGGMOBILE3_LAUGH2,
S_EGGMOBILE3_LAUGH3,
S_EGGMOBILE3_LAUGH4,
S_EGGMOBILE3_LAUGH5,
S_EGGMOBILE3_SHOCK,
S_EGGMOBILE3_ATK1,
S_EGGMOBILE3_ATK2,
S_EGGMOBILE3_ATK3A,
@ -1424,21 +1428,7 @@ typedef enum state
S_EGGMOBILE3_ATK3D,
S_EGGMOBILE3_ATK4,
S_EGGMOBILE3_ATK5,
S_EGGMOBILE3_LAUGH6,
S_EGGMOBILE3_LAUGH7,
S_EGGMOBILE3_LAUGH8,
S_EGGMOBILE3_LAUGH9,
S_EGGMOBILE3_LAUGH10,
S_EGGMOBILE3_LAUGH11,
S_EGGMOBILE3_LAUGH12,
S_EGGMOBILE3_LAUGH13,
S_EGGMOBILE3_LAUGH14,
S_EGGMOBILE3_LAUGH15,
S_EGGMOBILE3_LAUGH16,
S_EGGMOBILE3_LAUGH17,
S_EGGMOBILE3_LAUGH18,
S_EGGMOBILE3_LAUGH19,
S_EGGMOBILE3_LAUGH20,
S_EGGMOBILE3_ROFL,
S_EGGMOBILE3_PAIN,
S_EGGMOBILE3_PAIN2,
S_EGGMOBILE3_DIE1,
@ -1448,15 +1438,6 @@ typedef enum state
S_EGGMOBILE3_FLEE1,
S_EGGMOBILE3_FLEE2,
// Boss 3 Propeller
S_PROPELLER1,
S_PROPELLER2,
S_PROPELLER3,
S_PROPELLER4,
S_PROPELLER5,
S_PROPELLER6,
S_PROPELLER7,
// Boss 3 Pinch
S_FAKEMOBILE_INIT,
S_FAKEMOBILE,
@ -1469,6 +1450,9 @@ typedef enum state
S_FAKEMOBILE_DIE1,
S_FAKEMOBILE_DIE2,
S_BOSSSEBH1,
S_BOSSSEBH2,
// Boss 4
S_EGGMOBILE4_STND,
S_EGGMOBILE4_LATK1,
@ -1872,16 +1856,6 @@ typedef enum state
S_MSSHIELD_F1,
S_MSSHIELD_F2,
S_MSSHIELD_F3,
S_MSSHIELD_F4,
S_MSSHIELD_F5,
S_MSSHIELD_F6,
S_MSSHIELD_F7,
S_MSSHIELD_F8,
S_MSSHIELD_F9,
S_MSSHIELD_F10,
S_MSSHIELD_F11,
S_MSSHIELD_F12,
// Ring
S_RING,
@ -3987,6 +3961,7 @@ typedef enum mobj_type
MT_EGGTRAP,
MT_BOSS3WAYPOINT,
MT_BOSS9GATHERPOINT,
MT_BOSSJUNK,
// Boss 1
MT_EGGMOBILE,
@ -3998,15 +3973,11 @@ typedef enum mobj_type
// Boss 2
MT_EGGMOBILE2,
MT_EGGMOBILE2_POGO,
MT_BOSSTANK1,
MT_BOSSTANK2,
MT_BOSSSPIGOT,
MT_GOOP,
MT_GOOPTRAIL,
// Boss 3
MT_EGGMOBILE3,
MT_PROPELLER,
MT_FAKEMOBILE,
MT_SHOCK,

View file

@ -2017,6 +2017,8 @@ static int mapheaderinfo_get(lua_State *L)
lua_pushinteger(L, header->muspostbosspos);
else if (fastcmp(field,"muspostbossfadein"))
lua_pushinteger(L, header->muspostbossfadein);
else if (fastcmp(field,"musforcereset"))
lua_pushinteger(L, header->musforcereset);
else if (fastcmp(field,"forcecharacter"))
lua_pushstring(L, header->forcecharacter);
else if (fastcmp(field,"weather"))

View file

@ -262,6 +262,8 @@ static int player_get(lua_State *L)
lua_pushinteger(L, plr->starposttime);
else if (fastcmp(field,"starpostangle"))
lua_pushangle(L, plr->starpostangle);
else if (fastcmp(field,"starpostscale"))
lua_pushfixed(L, plr->starpostscale);
else if (fastcmp(field,"angle_pos"))
lua_pushangle(L, plr->angle_pos);
else if (fastcmp(field,"old_angle_pos"))
@ -570,6 +572,8 @@ static int player_set(lua_State *L)
plr->starposttime = (tic_t)luaL_checkinteger(L, 3);
else if (fastcmp(field,"starpostangle"))
plr->starpostangle = luaL_checkangle(L, 3);
else if (fastcmp(field,"starpostscale"))
plr->starpostscale = luaL_checkfixed(L, 3);
else if (fastcmp(field,"angle_pos"))
plr->angle_pos = luaL_checkangle(L, 3);
else if (fastcmp(field,"old_angle_pos"))

View file

@ -831,6 +831,12 @@ void Command_Savecheckpoint_f(void)
players[consoleplayer].starposty = players[consoleplayer].mo->y>>FRACBITS;
players[consoleplayer].starpostz = players[consoleplayer].mo->floorz>>FRACBITS;
players[consoleplayer].starpostangle = players[consoleplayer].mo->angle;
players[consoleplayer].starpostscale = players[consoleplayer].mo->destscale;
if (players[consoleplayer].mo->flags2 & MF2_OBJECTFLIP)
{
players[consoleplayer].starpostscale *= -1;
players[consoleplayer].starpostz += players[consoleplayer].mo->height;
}
CONS_Printf(M_GetText("Temporary checkpoint created at %d, %d, %d\n"), players[consoleplayer].starpostx, players[consoleplayer].starposty, players[consoleplayer].starpostz);
}

View file

@ -274,6 +274,7 @@ static void M_ServerOptions(INT32 choice);
#ifndef NONET
static void M_StartServerMenu(INT32 choice);
static void M_ConnectMenu(INT32 choice);
static void M_ConnectMenuModChecks(INT32 choice);
static void M_Refresh(INT32 choice);
static void M_Connect(INT32 choice);
static void M_ChooseRoom(INT32 choice);
@ -893,12 +894,12 @@ static menuitem_t MP_SplitServerMenu[] =
static menuitem_t MP_MainMenu[] =
{
{IT_HEADER, NULL, "Host a game", NULL, 0},
{IT_STRING|IT_CALL, NULL, "Internet/LAN...", M_StartServerMenu, 12},
{IT_STRING|IT_CALL, NULL, "Splitscreen...", M_StartSplitServerMenu, 22},
{IT_HEADER, NULL, "Join a game", NULL, 40},
{IT_STRING|IT_CALL, NULL, "Server browser...", M_ConnectMenu, 52},
{IT_STRING|IT_KEYHANDLER, NULL, "Specify IPv4 address:", M_HandleConnectIP, 62},
{IT_HEADER, NULL, "Join a game", NULL, 0},
{IT_STRING|IT_CALL, NULL, "Server browser...", M_ConnectMenuModChecks, 12},
{IT_STRING|IT_KEYHANDLER, NULL, "Specify IPv4 address:", M_HandleConnectIP, 22},
{IT_HEADER, NULL, "Host a game", NULL, 54},
{IT_STRING|IT_CALL, NULL, "Internet/LAN...", M_StartServerMenu, 66},
{IT_STRING|IT_CALL, NULL, "Splitscreen...", M_StartSplitServerMenu, 76},
{IT_HEADER, NULL, "Player setup", NULL, 94},
{IT_STRING|IT_CALL, NULL, "Player 1...", M_SetupMultiPlayer, 106},
{IT_STRING|IT_CALL, NULL, "Player 2... ", M_SetupMultiPlayer2, 116},
@ -957,7 +958,7 @@ enum
static menuitem_t MP_RoomMenu[] =
{
{IT_STRING | IT_CALL, NULL, "<Offline Mode>", M_ChooseRoom, 9},
{IT_STRING | IT_CALL, NULL, "<Unlisted Mode>", M_ChooseRoom, 9},
{IT_DISABLED, NULL, "", M_ChooseRoom, 18},
{IT_DISABLED, NULL, "", M_ChooseRoom, 27},
{IT_DISABLED, NULL, "", M_ChooseRoom, 36},
@ -1331,6 +1332,12 @@ static menuitem_t OP_SoundOptionsMenu[] =
#define OPENMPT_MENUOFFSET 0
#endif
#ifdef HAVE_MIXERX
#define MIXERX_MENUOFFSET 81
#else
#define MIXERX_MENUOFFSET 0
#endif
static menuitem_t OP_SoundAdvancedMenu[] =
{
#ifdef HAVE_OPENMPT
@ -1342,12 +1349,15 @@ static menuitem_t OP_SoundAdvancedMenu[] =
{IT_HEADER, NULL, "MIDI Settings", NULL, OPENMPT_MENUOFFSET+10},
{IT_STRING | IT_CVAR, NULL, "MIDI Player", &cv_midiplayer, OPENMPT_MENUOFFSET+22},
{IT_STRING | IT_CVAR | IT_CV_STRING, NULL, "FluidSynth Sound Font File", &cv_midisoundfontpath, OPENMPT_MENUOFFSET+34},
{IT_STRING | IT_CVAR | IT_CV_STRING, NULL, "TiMidity++ Config Folder", &cv_miditimiditypath, OPENMPT_MENUOFFSET+61}
{IT_STRING | IT_CVAR | IT_CV_STRING, NULL, "TiMidity++ Config Folder", &cv_miditimiditypath, OPENMPT_MENUOFFSET+61},
#endif
{IT_HEADER, NULL, "Miscellaneous", NULL, OPENMPT_MENUOFFSET+MIXERX_MENUOFFSET+10},
{IT_STRING | IT_CVAR, NULL, "Let Levels Force Reset Music", &cv_resetmusicbyheader, OPENMPT_MENUOFFSET+MIXERX_MENUOFFSET+22},
};
#undef OPENMPT_MENUOFFSET
#undef MIXERX_MENUOFFSET
#endif
static menuitem_t OP_DataOptionsMenu[] =
@ -5877,7 +5887,7 @@ static boolean M_AddonsRefresh(void)
{
S_StartSound(NULL, sfx_lose);
if (refreshdirmenu & REFRESHDIR_MAX)
message = va("%c%s\x80\nMaximum number of add-ons reached.\nA file could not be loaded.\nIf you want to play with this add-on, restart the game to clear existing ones.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname);
message = va("%c%s\x80\nMaximum number of add-ons reached.\nA file could not be loaded.\nIf you wish to play with this add-on, restart the game to clear existing ones.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname);
else
message = va("%c%s\x80\nA file was not loaded.\nCheck the console log for more information.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname);
}
@ -8878,8 +8888,8 @@ static void M_NightsAttack(INT32 choice)
M_PatchSkinNameTable();
G_SetGamestate(GS_TIMEATTACK); // do this before M_SetupNextMenu so that menu meta state knows that we're switching
M_SetupNextMenu(&SP_NightsAttackDef);
titlemapinaction = TITLEMAP_OFF; // Nope don't give us HOMs please
M_SetupNextMenu(&SP_NightsAttackDef);
if (!M_CanShowLevelInList(cv_nextmap.value-1, -1) && levelselect.rows[0].maplist[0])
CV_SetValue(&cv_nextmap, levelselect.rows[0].maplist[0]);
else
@ -9271,7 +9281,7 @@ static void M_DrawConnectMenu(void)
// Room name
if (ms_RoomId < 0)
V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + MP_ConnectMenu[mp_connect_room].alphaKey,
V_YELLOWMAP, (itemOn == mp_connect_room) ? "<Select to change>" : "<Offline Mode>");
V_YELLOWMAP, (itemOn == mp_connect_room) ? "<Select to change>" : "<Unlisted Mode>");
else
V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + MP_ConnectMenu[mp_connect_room].alphaKey,
V_YELLOWMAP, room_list[menuRoomIndex].name);
@ -9421,11 +9431,32 @@ static void M_ConnectMenu(INT32 choice)
// first page of servers
serverlistpage = 0;
M_SetupNextMenu(&MP_ConnectDef);
if (ms_RoomId < 0)
{
M_RoomMenu(0); // Select a room instead of staring at an empty list
// This prevents us from returning to the modified game alert.
currentMenu->prevMenu = &MP_MainDef;
}
else
M_SetupNextMenu(&MP_ConnectDef);
itemOn = 0;
M_Refresh(0);
}
static void M_ConnectMenuModChecks(INT32 choice)
{
(void)choice;
// okay never mind we want to COMMUNICATE to the player pre-emptively instead of letting them try and then get confused when it doesn't work
if (modifiedgame)
{
M_StartMessage(M_GetText("Add-ons are currently loaded.\n\nYou will only be able to join a server if\nit has the same ones loaded in the same order, which may be unlikely.\n\nIf you wish to play on other servers,\nrestart the game to clear existing add-ons.\n\n(Press a key)\n"),M_ConnectMenu,MM_EVENTHANDLER);
return;
}
M_ConnectMenu(-1);
}
static UINT32 roomIds[NUM_LIST_ROOMS];
static void M_RoomMenu(INT32 choice)
@ -9480,7 +9511,16 @@ static void M_ChooseRoom(INT32 choice)
}
serverlistpage = 0;
M_SetupNextMenu(currentMenu->prevMenu);
/*
We were on the Multiplayer menu? That means that we must have been trying to
view the server browser, but we hadn't selected a room yet. So we need to go
to the browser next, not back there.
*/
if (currentMenu->prevMenu == &MP_MainDef)
M_SetupNextMenu(&MP_ConnectDef);
else
M_SetupNextMenu(currentMenu->prevMenu);
if (currentMenu == &MP_ConnectDef)
M_Refresh(0);
}
@ -9539,7 +9579,7 @@ static void M_DrawServerMenu(void)
M_DrawLevelPlatterHeader(currentMenu->y - lsheadingheight/2, "Server settings", true, false);
if (ms_RoomId < 0)
V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + MP_ServerMenu[mp_server_room].alphaKey,
V_YELLOWMAP, (itemOn == mp_server_room) ? "<Select to change>" : "<Offline Mode>");
V_YELLOWMAP, (itemOn == mp_server_room) ? "<Select to change>" : "<Unlisted Mode>");
else
V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + MP_ServerMenu[mp_server_room].alphaKey,
V_YELLOWMAP, room_list[menuRoomIndex].name);
@ -9646,7 +9686,7 @@ static void M_StartServerMenu(INT32 choice)
// CONNECT VIA IP
// ==============
static char setupm_ip[16];
static char setupm_ip[28];
// Draw the funky Connect IP menu. Tails 11-19-2002
// So much work for such a little thing!
@ -9658,30 +9698,26 @@ static void M_DrawMPMainMenu(void)
// use generic drawer for cursor, items and title
M_DrawGenericMenu();
#if MAXPLAYERS == 32
V_DrawRightAlignedString(BASEVIDWIDTH-x, y+12,
((itemOn == 1) ? V_YELLOWMAP : 0), "(2-32 players)");
#else
Update the maxplayers label...
#endif
V_DrawRightAlignedString(BASEVIDWIDTH-x, y+66,
((itemOn == 4) ? V_YELLOWMAP : 0), va("(2-%d players)", MAXPLAYERS));
V_DrawRightAlignedString(BASEVIDWIDTH-x, y+22,
((itemOn == 2) ? V_YELLOWMAP : 0), "(2 players)");
V_DrawRightAlignedString(BASEVIDWIDTH-x, y+76,
((itemOn == 5) ? V_YELLOWMAP : 0), "(2 players)");
V_DrawRightAlignedString(BASEVIDWIDTH-x, y+116,
((itemOn == 8) ? V_YELLOWMAP : 0), "(splitscreen)");
y += 62;
y += 22;
V_DrawFill(x+5, y+4+5, /*16*8 + 6,*/ BASEVIDWIDTH - 2*(x+5), 8+6, 159);
// draw name string
V_DrawString(x+8,y+12, V_MONOSPACE, setupm_ip);
V_DrawString(x+8,y+12, V_ALLOWLOWERCASE, setupm_ip);
// draw text cursor for name
if (itemOn == 5 //0
if (itemOn == 2 //0
&& skullAnimCounter < 4) //blink cursor
V_DrawCharacter(x+8+V_StringWidth(setupm_ip, V_MONOSPACE),y+12,'_',false);
V_DrawCharacter(x+8+V_StringWidth(setupm_ip, V_ALLOWLOWERCASE),y+12,'_',false);
}
// Tails 11-19-2002
@ -9752,10 +9788,11 @@ static void M_HandleConnectIP(INT32 choice)
default:
l = strlen(setupm_ip);
if (l >= 16-1)
if (l >= 28-1)
break;
if (choice == 46 || (choice >= 48 && choice <= 57)) // Rudimentary number and period enforcing
// Rudimentary number and period enforcing - also allows letters so hostnames can be used instead
if ((choice >= '-' && choice <= ':') || (choice >= 'A' && choice <= 'Z') || (choice >= 'a' && choice <= 'z'))
{
S_StartSound(NULL,sfx_menu1); // Tails
setupm_ip[l] = (char)choice;

View file

@ -3006,16 +3006,19 @@ void A_Boss7FireMissiles(mobj_t *actor)
// 0 - Boss 1 Left side
// 1 - Boss 1 Right side
// 2 - Triple laser
// >3 - Boss 1 Middle
// 3 - Boss 1 Middle
// >=3 - Generic middle
//
void A_Boss1Laser(mobj_t *actor)
{
fixed_t x, y, z, floorz, speed;
INT32 locvar1 = var1;
INT32 locvar2 = var2;
INT32 locvar2 = (var2 & 65535);
INT32 upperend = (var2>>16);
INT32 i;
angle_t angle;
mobj_t *point;
tic_t dur;
#ifdef HAVE_BLUA
if (LUA_CallAction("A_Boss1Laser", actor))
@ -3024,19 +3027,24 @@ void A_Boss1Laser(mobj_t *actor)
if (!actor->target)
return;
if ((upperend & 1) && (actor->extravalue2 > 1))
actor->extravalue2--;
dur = actor->extravalue2;
switch (locvar2)
{
case 0:
x = actor->x + P_ReturnThrustX(actor, actor->angle+ANGLE_90, FixedMul(43*FRACUNIT, actor->scale));
y = actor->y + P_ReturnThrustY(actor, actor->angle+ANGLE_90, FixedMul(43*FRACUNIT, actor->scale));
x = actor->x + P_ReturnThrustX(actor, actor->angle+ANGLE_90, FixedMul(44*FRACUNIT, actor->scale));
y = actor->y + P_ReturnThrustY(actor, actor->angle+ANGLE_90, FixedMul(44*FRACUNIT, actor->scale));
if (actor->eflags & MFE_VERTICALFLIP)
z = actor->z + actor->height - FixedMul(56*FRACUNIT, actor->scale) - mobjinfo[locvar1].height;
else
z = actor->z + FixedMul(56*FRACUNIT, actor->scale);
break;
case 1:
x = actor->x + P_ReturnThrustX(actor, actor->angle-ANGLE_90, FixedMul(43*FRACUNIT, actor->scale));
y = actor->y + P_ReturnThrustY(actor, actor->angle-ANGLE_90, FixedMul(43*FRACUNIT, actor->scale));
x = actor->x + P_ReturnThrustX(actor, actor->angle-ANGLE_90, FixedMul(44*FRACUNIT, actor->scale));
y = actor->y + P_ReturnThrustY(actor, actor->angle-ANGLE_90, FixedMul(44*FRACUNIT, actor->scale));
if (actor->eflags & MFE_VERTICALFLIP)
z = actor->z + actor->height - FixedMul(56*FRACUNIT, actor->scale) - mobjinfo[locvar1].height;
else
@ -3051,6 +3059,11 @@ void A_Boss1Laser(mobj_t *actor)
A_Boss1Laser(actor);
return;
break;
case 3:
x = actor->x + P_ReturnThrustX(actor, actor->angle, FixedMul(42*FRACUNIT, actor->scale));
y = actor->y + P_ReturnThrustY(actor, actor->angle, FixedMul(42*FRACUNIT, actor->scale));
z = actor->z + actor->height/2;
break;
default:
x = actor->x;
y = actor->y;
@ -3058,7 +3071,7 @@ void A_Boss1Laser(mobj_t *actor)
break;
}
if (!(actor->flags2 & MF2_FIRING) && actor->tics > 1)
if (!(actor->flags2 & MF2_FIRING) && dur > 1)
{
actor->angle = R_PointToAngle2(x, y, actor->target->x, actor->target->y);
if (mobjinfo[locvar1].seesound)
@ -3067,7 +3080,7 @@ void A_Boss1Laser(mobj_t *actor)
{
point = P_SpawnMobj(x + P_ReturnThrustX(actor, actor->angle, actor->radius), y + P_ReturnThrustY(actor, actor->angle, actor->radius), actor->z - actor->height / 2, MT_EGGMOBILE_TARGET);
point->angle = actor->angle;
point->fuse = actor->tics+1;
point->fuse = dur+1;
P_SetTarget(&point->target, actor->target);
P_SetTarget(&actor->target, point);
}
@ -3076,9 +3089,9 @@ void A_Boss1Laser(mobj_t *actor)
else if (actor->target && !(actor->spawnpoint && actor->spawnpoint->options & MTF_AMBUSH))
actor->angle = R_PointToAngle2(x, y, actor->target->x, actor->target->y);*/
if (actor->spawnpoint && actor->spawnpoint->options & MTF_AMBUSH)
angle = FixedAngle(FixedDiv(actor->tics*160*FRACUNIT, actor->state->tics*FRACUNIT) + 10*FRACUNIT);
else
/*if (actor->spawnpoint && actor->spawnpoint->options & MTF_AMBUSH)
angle = FixedAngle(FixedDiv(dur*160*FRACUNIT, actor->state->tics*FRACUNIT) + 10*FRACUNIT);
else*/
angle = R_PointToAngle2(z + (mobjinfo[locvar1].height>>1), 0, actor->target->z, R_PointToDist2(x, y, actor->target->x, actor->target->y));
point = P_SpawnMobj(x, y, z, locvar1);
@ -3112,7 +3125,7 @@ void A_Boss1Laser(mobj_t *actor)
point->fuse = TICRATE;
}
if (actor->tics > 1)
if (dur > 1)
actor->flags2 |= MF2_FIRING;
else
actor->flags2 &= ~MF2_FIRING;
@ -3256,6 +3269,7 @@ void A_Boss4Raise(mobj_t *actor)
// 0 - Fly at the player
// 1 - Fly away from the player
// 2 - Strafe in relation to the player
// 3 - Dynamic mode - don't get too close to walls
// var2:
// 0 - Fly horizontally and vertically
// 1 - Fly horizontal-only (momz = 0)
@ -3286,16 +3300,83 @@ void A_SkullAttack(mobj_t *actor)
S_StartSound(actor, actor->info->activesound);
A_FaceTarget(actor);
dist = P_AproxDistance(dest->x - actor->x, dest->y - actor->y);
if (locvar1 == 1)
actor->angle += ANGLE_180;
else if (locvar1 == 2)
actor->angle += (P_RandomChance(FRACUNIT/2)) ? ANGLE_90 : -ANGLE_90;
else if (locvar1 == 3)
{
statenum_t oldspawnstate = mobjinfo[MT_NULL].spawnstate;
UINT32 oldflags = mobjinfo[MT_NULL].flags;
fixed_t oldradius = mobjinfo[MT_NULL].radius;
fixed_t oldheight = mobjinfo[MT_NULL].height;
mobj_t *check;
INT32 i, j, k;
boolean allow;
angle_t testang;
mobjinfo[MT_NULL].spawnstate = S_INVISIBLE;
mobjinfo[MT_NULL].flags = MF_NOGRAVITY|MF_NOTHINK|MF_NOCLIPTHING|MF_NOBLOCKMAP;
mobjinfo[MT_NULL].radius = mobjinfo[actor->type].radius;
mobjinfo[MT_NULL].height = mobjinfo[actor->type].height;
if (P_RandomChance(FRACUNIT/2)) // port priority 1?
{
i = 9;
j = 27;
}
else
{
i = 27;
j = 9;
}
#define dostuff(q) check = P_SpawnMobjFromMobj(actor, 0, 0, 0, MT_NULL);\
testang = actor->angle + ((i+(q))*ANG10);\
allow = (P_TryMove(check,\
P_ReturnThrustX(check, testang, dist + 2*actor->radius),\
P_ReturnThrustY(check, testang, dist + 2*actor->radius),\
true));\
P_RemoveMobj(check);\
if (allow)\
break;
if (P_RandomChance(FRACUNIT/2)) // port priority 2?
{
for (k = 0; k < 9; k++)
{
dostuff(i+k)
dostuff(i-k)
dostuff(j+k)
dostuff(j-k)
}
}
else
{
for (k = 0; k < 9; k++)
{
dostuff(i-k)
dostuff(i+k)
dostuff(j-k)
dostuff(j+k)
}
}
actor->angle = testang;
#undef dostuff
mobjinfo[MT_NULL].spawnstate = oldspawnstate;
mobjinfo[MT_NULL].flags = oldflags;
mobjinfo[MT_NULL].radius = oldradius;
mobjinfo[MT_NULL].height = oldheight;
}
an = actor->angle >> ANGLETOFINESHIFT;
actor->momx = FixedMul(speed, FINECOSINE(an));
actor->momy = FixedMul(speed, FINESINE(an));
dist = P_AproxDistance(dest->x - actor->x, dest->y - actor->y);
dist = dist / speed;
if (dist < 1)
@ -3445,11 +3526,13 @@ void A_Pain(mobj_t *actor)
//
// Description: Changes a dying object's flags to reflect its having fallen to the ground.
//
// var1 = unused
// var1 = value to set repeat to if nonzero
// var2 = unused
//
void A_Fall(mobj_t *actor)
{
INT32 locvar1 = var1;
#ifdef HAVE_BLUA
if (LUA_CallAction("A_Fall", actor))
return;
@ -3462,6 +3545,9 @@ void A_Fall(mobj_t *actor)
// So change this if corpse objects
// are meant to be obstacles.
if (locvar1)
actor->extravalue2 = locvar1;
}
#define LIVESBOXDISPLAYPLAYER // Use displayplayer instead of closest player
@ -3857,6 +3943,72 @@ bossjustdie:
else if (P_MobjWasRemoved(mo))
return;
#endif
// Spawn your junk
switch (mo->type)
{
default:
break;
case MT_EGGMOBILE: // twin laser pods
{
mo2 = P_SpawnMobjFromMobj(mo,
P_ReturnThrustX(mo, mo->angle - ANGLE_90, 32<<FRACBITS),
P_ReturnThrustY(mo, mo->angle - ANGLE_90, 32<<FRACBITS),
32<<FRACBITS, MT_BOSSJUNK);
mo2->angle = mo->angle;
P_InstaThrust(mo2, mo2->angle - ANGLE_90, 4*mo2->scale);
P_SetObjectMomZ(mo2, 4*FRACUNIT, false);
P_SetMobjState(mo2, S_BOSSEGLZ1);
mo2 = P_SpawnMobjFromMobj(mo,
P_ReturnThrustX(mo, mo->angle + ANGLE_90, 32<<FRACBITS),
P_ReturnThrustY(mo, mo->angle + ANGLE_90, 32<<FRACBITS),
32<<FRACBITS, MT_BOSSJUNK);
mo2->angle = mo->angle;
P_InstaThrust(mo2, mo2->angle + ANGLE_90, 4*mo2->scale);
P_SetObjectMomZ(mo2, 4*FRACUNIT, false);
P_SetMobjState(mo2, S_BOSSEGLZ2);
}
break;
case MT_EGGMOBILE2: // twin tanks + spigot
{
mo2 = P_SpawnMobjFromMobj(mo,
P_ReturnThrustX(mo, mo->angle - ANGLE_90, 32<<FRACBITS),
P_ReturnThrustY(mo, mo->angle - ANGLE_90, 32<<FRACBITS),
32<<FRACBITS, MT_BOSSJUNK);
mo2->angle = mo->angle;
P_InstaThrust(mo2, mo2->angle - ANGLE_90, 4*mo2->scale);
P_SetObjectMomZ(mo2, 4*FRACUNIT, false);
P_SetMobjState(mo2, S_BOSSTANK1);
mo2 = P_SpawnMobjFromMobj(mo,
P_ReturnThrustX(mo, mo->angle + ANGLE_90, 32<<FRACBITS),
P_ReturnThrustY(mo, mo->angle + ANGLE_90, 32<<FRACBITS),
32<<FRACBITS, MT_BOSSJUNK);
mo2->angle = mo->angle;
P_InstaThrust(mo2, mo2->angle + ANGLE_90, 4*mo2->scale);
P_SetObjectMomZ(mo2, 4*FRACUNIT, false);
P_SetMobjState(mo2, S_BOSSTANK2);
mo2 = P_SpawnMobjFromMobj(mo, 0, 0,
mobjinfo[MT_EGGMOBILE2].height + (32<<FRACBITS),
MT_BOSSJUNK);
mo2->angle = mo->angle;
P_SetObjectMomZ(mo2, 4*FRACUNIT, false);
mo2->momz += mo->momz;
P_SetMobjState(mo2, S_BOSSSPIGOT);
}
break;
case MT_EGGMOBILE3:
{
mo2 = P_SpawnMobjFromMobj(mo, 0, 0, 0, MT_BOSSJUNK);
mo2->angle = mo->angle;
P_SetMobjState(mo2, S_BOSSSEBH1);
}
break;
}
// now do another switch case for escaping
switch (mo->type)
{
case MT_BLACKEGGMAN:
@ -3954,7 +4106,7 @@ bossjustdie:
mo->movedir = 0;
mo->extravalue1 = 35;
mo->flags2 |= MF2_BOSSFLEE;
mo->momz = 2*mo->scale;
mo->momz = P_MobjFlip(mo)*2*mo->scale;
if (mo->target)
{
@ -3972,50 +4124,6 @@ bossjustdie:
break;
}
}
if (mo->type == MT_EGGMOBILE2)
{
mo2 = P_SpawnMobj(mo->x + P_ReturnThrustX(mo, mo->angle - ANGLE_90, FixedMul(32*FRACUNIT, mo->scale)),
mo->y + P_ReturnThrustY(mo, mo->angle - ANGLE_90, FixedMul(32*FRACUNIT, mo->scale)),
mo->z + mo->height/2 + ((mo->eflags & MFE_VERTICALFLIP)? FixedMul(8*FRACUNIT, mo->scale)-mobjinfo[MT_BOSSTANK1].height : -FixedMul(8*FRACUNIT, mo->scale)), MT_BOSSTANK1); // Right tank
mo2->angle = mo->angle;
mo2->destscale = mo->scale;
P_SetScale(mo2, mo2->destscale);
if (mo->eflags & MFE_VERTICALFLIP)
{
mo2->eflags |= MFE_VERTICALFLIP;
mo2->flags2 |= MF2_OBJECTFLIP;
}
P_InstaThrust(mo2, mo2->angle - ANGLE_90, FixedMul(4*FRACUNIT, mo2->scale));
P_SetObjectMomZ(mo2, 4*FRACUNIT, false);
mo2 = P_SpawnMobj(mo->x + P_ReturnThrustX(mo, mo->angle + ANGLE_90, FixedMul(32*FRACUNIT, mo->scale)),
mo->y + P_ReturnThrustY(mo, mo->angle + ANGLE_90, FixedMul(32*FRACUNIT, mo->scale)),
mo->z + mo->height/2 + ((mo->eflags & MFE_VERTICALFLIP)? FixedMul(8*FRACUNIT, mo->scale)-mobjinfo[MT_BOSSTANK2].height : -FixedMul(8*FRACUNIT, mo->scale)), MT_BOSSTANK2); // Left tank
mo2->angle = mo->angle;
mo2->destscale = mo->scale;
P_SetScale(mo2, mo2->destscale);
if (mo->eflags & MFE_VERTICALFLIP)
{
mo2->eflags |= MFE_VERTICALFLIP;
mo2->flags2 |= MF2_OBJECTFLIP;
}
P_InstaThrust(mo2, mo2->angle + ANGLE_90, FixedMul(4*FRACUNIT, mo2->scale));
P_SetObjectMomZ(mo2, 4*FRACUNIT, false);
mo2 = P_SpawnMobj(mo->x, mo->y,
mo->z + ((mo->eflags & MFE_VERTICALFLIP)? mobjinfo[MT_BOSSSPIGOT].height-FixedMul(32*FRACUNIT,mo->scale): mo->height + FixedMul(32*FRACUNIT, mo->scale)), MT_BOSSSPIGOT);
mo2->angle = mo->angle;
mo2->destscale = mo->scale;
P_SetScale(mo2, mo2->destscale);
if (mo->eflags & MFE_VERTICALFLIP)
{
mo2->eflags |= MFE_VERTICALFLIP;
mo2->flags2 |= MF2_OBJECTFLIP;
}
P_SetObjectMomZ(mo2, 4*FRACUNIT, false);
return;
}
}
// Function: A_CustomPower
@ -6358,6 +6466,7 @@ void A_MixUp(mobj_t *actor)
INT32 starpostnum;
tic_t starposttime;
angle_t starpostangle;
fixed_t starpostscale;
INT32 mflags2;
@ -6405,6 +6514,7 @@ void A_MixUp(mobj_t *actor)
starposty = players[one].starposty;
starpostz = players[one].starpostz;
starpostangle = players[one].starpostangle;
starpostscale = players[one].starpostscale;
starpostnum = players[one].starpostnum;
starposttime = players[one].starposttime;
@ -6413,15 +6523,11 @@ void A_MixUp(mobj_t *actor)
P_MixUp(players[one].mo, players[two].mo->x, players[two].mo->y, players[two].mo->z, players[two].mo->angle,
players[two].starpostx, players[two].starposty, players[two].starpostz,
players[two].starpostnum, players[two].starposttime, players[two].starpostangle,
players[two].mo->flags2);
players[one].drawangle = players[two].drawangle;
players[two].starpostscale, players[two].drawangle, players[two].mo->flags2);
P_MixUp(players[two].mo, x, y, z, angle, starpostx, starposty, starpostz,
starpostnum, starposttime, starpostangle,
mflags2);
players[two].drawangle = drawangle;
starpostscale, drawangle, mflags2);
//carry set after mixup. Stupid P_ResetPlayer() takes away some of the stuff we look for...
//but not all of it! So we need to make sure they aren't set wrong or anything.
@ -6448,6 +6554,7 @@ void A_MixUp(mobj_t *actor)
INT32 starpostnum[MAXPLAYERS];
tic_t starposttime[MAXPLAYERS];
angle_t starpostangle[MAXPLAYERS];
fixed_t starpostscale[MAXPLAYERS];
INT32 flags2[MAXPLAYERS];
@ -6485,6 +6592,7 @@ void A_MixUp(mobj_t *actor)
starpostnum[counter] = players[i].starpostnum;
starposttime[counter] = players[i].starposttime;
starpostangle[counter] = players[i].starpostangle;
starpostscale[counter] = players[i].starpostscale;
flags2[counter] = players[i].mo->flags2;
@ -6525,9 +6633,7 @@ void A_MixUp(mobj_t *actor)
P_MixUp(players[i].mo, position[teleportfrom][0], position[teleportfrom][1], position[teleportfrom][2], anglepos[teleportfrom][0],
spposition[teleportfrom][0], spposition[teleportfrom][1], spposition[teleportfrom][2],
starpostnum[teleportfrom], starposttime[teleportfrom], starpostangle[teleportfrom],
flags2[teleportfrom]);
players[i].drawangle = anglepos[teleportfrom][1];
starpostscale[teleportfrom], anglepos[teleportfrom][1], flags2[teleportfrom]);
//...carry after. same reasoning.
players[i].powers[pw_carry] = transcarry[teleportfrom];
@ -8702,7 +8808,7 @@ void A_SetObjectFlags2(mobj_t *actor)
//
// var1:
// 0 - Triple jet fume pattern
// 1 - Boss 3's propeller
// 1 - Unused (formerly Boss 3's propeller)
// 2 - Metal Sonic jet fume
// 3 - Boss 4 jet flame
// var2 = unused
@ -8762,7 +8868,7 @@ void A_BossJetFume(mobj_t *actor)
P_SetTarget(&actor->tracer, filler);
}
else if (locvar1 == 1) // Boss 3 propeller
/*else if (locvar1 == 1) // Boss 3 propeller
{
fixed_t jetx, jety, jetz;
@ -8782,14 +8888,14 @@ void A_BossJetFume(mobj_t *actor)
filler->angle = actor->angle - ANGLE_180;
P_SetTarget(&actor->tracer, filler);
}
}*/
else if (locvar1 == 2) // Metal Sonic jet fumes
{
filler = P_SpawnMobj(actor->x, actor->y, actor->z, MT_JETFUME1);
P_SetTarget(&filler->target, actor);
filler->fuse = 59;
P_SetTarget(&actor->tracer, filler);
filler->destscale = actor->scale/2;
filler->destscale = actor->scale/3;
P_SetScale(filler, filler->destscale);
if (actor->eflags & MFE_VERTICALFLIP)
filler->flags2 |= MF2_OBJECTFLIP;

View file

@ -1427,6 +1427,12 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
players[i].starposty = player->mo->y>>FRACBITS;
players[i].starpostz = special->z>>FRACBITS;
players[i].starpostangle = special->angle;
players[i].starpostscale = player->mo->destscale;
if (special->flags2 & MF2_OBJECTFLIP)
{
players[i].starpostscale *= -1;
players[i].starpostz += special->height>>FRACBITS;
}
players[i].starpostnum = special->health;
if (cv_coopstarposts.value == 2 && (players[i].playerstate == PST_DEAD || players[i].spectator) && P_GetLives(&players[i]))
@ -1443,6 +1449,12 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
player->starposty = toucher->y>>FRACBITS;
player->starpostz = special->z>>FRACBITS;
player->starpostangle = special->angle;
player->starpostscale = player->mo->destscale;
if (special->flags2 & MF2_OBJECTFLIP)
{
player->starpostscale *= -1;
player->starpostz += special->height>>FRACBITS;
}
player->starpostnum = special->health;
S_StartSound(toucher, special->info->painsound);
}
@ -2594,6 +2606,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
case MT_EGGMOBILE3:
{
mobj_t *mo2;
thinker_t *th;
UINT32 i = 0; // to check how many clones we've removed
@ -2614,6 +2627,11 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
mo->scalespeed = (mo->scale - mo->destscale)/(2*TICRATE);
mo->momz = mo->info->speed;
mo->angle = FixedAngle((P_RandomKey(36)*10)<<FRACBITS);
mo2 = P_SpawnMobjFromMobj(mo, 0, 0, 0, MT_BOSSJUNK);
mo2->angle = mo->angle;
P_SetMobjState(mo2, S_BOSSSEBH2);
if (++i == 2) // we've already removed 2 of these, let's stop now
break;
else

View file

@ -509,7 +509,7 @@ extern INT32 ceilmovesound;
void P_MixUp(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle,
INT16 starpostx, INT16 starposty, INT16 starpostz,
INT32 starpostnum, tic_t starposttime, angle_t starpostangle,
INT32 flags2);
fixed_t starpostscale, angle_t drawangle, INT32 flags2);
boolean P_Teleport(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle, boolean flash, boolean dontstopmove);
boolean P_SetMobjStateNF(mobj_t *mobj, statenum_t state);
boolean P_CheckMissileSpawn(mobj_t *th);

View file

@ -4359,12 +4359,6 @@ static void P_Boss3Thinker(mobj_t *mobj)
if (mobj->flags2 & MF2_FRET)
mobj->movedir = 1;
if (!mobj->tracer)
{
var1 = 1;
A_BossJetFume(mobj);
}
if (mobj->health <= 0)
return;
/*
@ -4493,7 +4487,7 @@ static void P_Boss3Thinker(mobj_t *mobj)
if (mobj->health <= mobj->info->damage) // pinch phase
mobj->movecount--; // limited number of shots before diving again
if (mobj->movecount)
P_SetMobjState(mobj, mobj->info->missilestate);
P_SetMobjState(mobj, mobj->info->missilestate+1);
}
}
else if (mobj->threshold >= 0) // Traveling mode
@ -4592,6 +4586,15 @@ static void P_Boss3Thinker(mobj_t *mobj)
ang += (ANGLE_MAX/64);
}
S_StartSound(mobj, sfx_fizzle);
// look for a new target
P_BossTargetPlayer(mobj, false);
if (mobj->target && mobj->target->player)
{
A_FaceTarget(mobj);
P_SetMobjState(mobj, mobj->info->missilestate);
}
}
else if (mobj->flags2 & (MF2_STRONGBOX|MF2_CLASSICPUSH)) // just hit the bottom of your tube
{
@ -5527,8 +5530,7 @@ static void P_Boss9Thinker(mobj_t *mobj)
mobj->tracer->destscale = FRACUNIT + (4*TICRATE - mobj->fuse)*(FRACUNIT/2)/TICRATE + FixedMul(FINECOSINE(angle>>ANGLETOFINESHIFT),FRACUNIT/2);
P_SetScale(mobj->tracer, mobj->tracer->destscale);
}
else
mobj->tracer->frame &= ~FF_TRANSMASK; // this causes a flicker but honestly i like it this way
P_TeleportMove(mobj->tracer, mobj->x, mobj->y, mobj->z + mobj->height/2 - mobj->tracer->height/2);
mobj->tracer->momx = mobj->momx;
mobj->tracer->momy = mobj->momy;
@ -5645,12 +5647,12 @@ static void P_Boss9Thinker(mobj_t *mobj)
if (mobj->health > mobj->info->damage)
{
P_SetScale(missile, FRACUNIT/2);
P_SetScale(missile, FRACUNIT/3);
missile->color = SKINCOLOR_GOLD; // sonic cd electric power
}
else
{
P_SetScale(missile, FRACUNIT/4);
P_SetScale(missile, FRACUNIT/5);
missile->color = SKINCOLOR_MAGENTA; // sonic OVA/4 purple power
}
missile->destscale = missile->scale*2;
@ -5940,9 +5942,7 @@ static void P_Boss9Thinker(mobj_t *mobj)
P_SetTarget(&mobj->tracer, shield);
P_SetTarget(&shield->target, mobj);
shield->height -= 20*FRACUNIT; // different offset...
shield->color = SKINCOLOR_MAGENTA;
shield->colorized = true;
P_SetMobjState(shield, S_FIRS1);
P_SetMobjState(shield, S_MSSHIELD_F2);
//P_LinedefExecute(LE_PINCHPHASE, mobj, NULL); -- why does this happen twice? see case 2...
}
mobj->fuse = 4*TICRATE;
@ -7093,9 +7093,7 @@ void P_MobjThinker(mobj_t *mobj)
switch (mobj->type)
{
case MT_BOSSTANK1:
case MT_BOSSTANK2:
case MT_BOSSSPIGOT:
case MT_BOSSJUNK:
mobj->flags2 ^= MF2_DONTDRAW;
break;
case MT_MACEPOINT:
@ -7681,12 +7679,22 @@ void P_MobjThinker(mobj_t *mobj)
switch (mobj->type)
{
case MT_EGGMOBILE:
if (mobj->health < mobj->info->damage+1 && leveltime & 1 && mobj->health > 0)
P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_SMOKE);
if (mobj->health < mobj->info->damage+1 && leveltime & 2)
{
fixed_t rad = mobj->radius>>FRACBITS;
fixed_t hei = mobj->height>>FRACBITS;
mobj_t *particle = P_SpawnMobjFromMobj(mobj,
P_RandomRange(rad, -rad)<<FRACBITS,
P_RandomRange(rad, -rad)<<FRACBITS,
P_RandomRange(hei/2, hei)<<FRACBITS,
MT_SMOKE);
P_SetObjectMomZ(particle, 2<<FRACBITS, false);
particle->momz += mobj->momz;
}
if (mobj->flags2 & MF2_SKULLFLY)
#if 1
P_SpawnGhostMobj(mobj);
#else
#else // all the way back from final demo... MT_THOK isn't even the same size anymore!
{
mobj_t *spawnmobj;
spawnmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobj->info->painchance);
@ -7697,12 +7705,48 @@ void P_MobjThinker(mobj_t *mobj)
P_Boss1Thinker(mobj);
break;
case MT_EGGMOBILE2:
if (mobj->health < mobj->info->damage+1 && leveltime & 2)
{
fixed_t rad = mobj->radius>>FRACBITS;
fixed_t hei = mobj->height>>FRACBITS;
mobj_t *particle = P_SpawnMobjFromMobj(mobj,
P_RandomRange(rad, -rad)<<FRACBITS,
P_RandomRange(rad, -rad)<<FRACBITS,
P_RandomRange(hei/2, hei)<<FRACBITS,
MT_SMOKE);
P_SetObjectMomZ(particle, 2<<FRACBITS, false);
particle->momz += mobj->momz;
}
P_Boss2Thinker(mobj);
break;
case MT_EGGMOBILE3:
if (mobj->health < mobj->info->damage+1 && leveltime & 2)
{
fixed_t rad = mobj->radius>>FRACBITS;
fixed_t hei = mobj->height>>FRACBITS;
mobj_t *particle = P_SpawnMobjFromMobj(mobj,
P_RandomRange(rad, -rad)<<FRACBITS,
P_RandomRange(rad, -rad)<<FRACBITS,
P_RandomRange(hei/2, hei)<<FRACBITS,
MT_SMOKE);
P_SetObjectMomZ(particle, 2<<FRACBITS, false);
particle->momz += mobj->momz;
}
P_Boss3Thinker(mobj);
break;
case MT_EGGMOBILE4:
if (mobj->health < mobj->info->damage+1 && leveltime & 2)
{
fixed_t rad = mobj->radius>>FRACBITS;
fixed_t hei = mobj->height>>FRACBITS;
mobj_t *particle = P_SpawnMobjFromMobj(mobj,
P_RandomRange(rad, -rad)<<FRACBITS,
P_RandomRange(rad, -rad)<<FRACBITS,
P_RandomRange(hei/2, hei)<<FRACBITS,
MT_SMOKE);
P_SetObjectMomZ(particle, 2<<FRACBITS, false);
particle->momz += mobj->momz;
}
P_Boss4Thinker(mobj);
break;
case MT_FANG:
@ -8318,30 +8362,6 @@ void P_MobjThinker(mobj_t *mobj)
mobj->fuse++;
}
break;
case MT_PROPELLER:
{
fixed_t jetx, jety;
if (!mobj->target // if you have no target
|| (!(mobj->target->flags & MF_BOSS) && mobj->target->health <= 0)) // or your target isn't a boss and it's popped now
{ // then remove yourself as well!
P_RemoveMobj(mobj);
return;
}
jetx = mobj->target->x + P_ReturnThrustX(mobj->target, mobj->target->angle, FixedMul(-60*FRACUNIT, mobj->target->scale));
jety = mobj->target->y + P_ReturnThrustY(mobj->target, mobj->target->angle, FixedMul(-60*FRACUNIT, mobj->target->scale));
P_UnsetThingPosition(mobj);
mobj->x = jetx;
mobj->y = jety;
mobj->z = mobj->target->z + FixedMul(17*FRACUNIT, mobj->target->scale);
mobj->angle = mobj->target->angle - ANGLE_180;
mobj->floorz = mobj->z;
mobj->ceilingz = mobj->z+mobj->height;
P_SetThingPosition(mobj);
}
break;
case MT_JETFLAME:
{
if (!mobj->target // if you have no target
@ -8405,6 +8425,17 @@ void P_MobjThinker(mobj_t *mobj)
}
else
{
fixed_t basex = mobj->cusval, basey = mobj->cvmem;
if (mobj->spawnpoint && mobj->spawnpoint->options & (MTF_AMBUSH|MTF_OBJECTSPECIAL))
{
angle_t sideang = mobj->movedir + ((mobj->spawnpoint->options & MTF_AMBUSH) ? ANGLE_90 : -ANGLE_90);
fixed_t oscillate = FixedMul(FINESINE(((leveltime*ANG1)>>(ANGLETOFINESHIFT+2)) & FINEMASK), 250*mobj->scale);
basex += P_ReturnThrustX(mobj, sideang, oscillate);
basey += P_ReturnThrustY(mobj, sideang, oscillate);
}
mobj->z = mobj->threshold + FixedMul(FINESINE(((leveltime + mobj->movecount)*ANG2>>(ANGLETOFINESHIFT-2)) & FINEMASK), 8*mobj->scale);
if (mobj->state != &states[mobj->info->meleestate])
{
@ -8433,8 +8464,8 @@ void P_MobjThinker(mobj_t *mobj)
if (players[i].mo->z + players[i].mo->height < mobj->z - 8*mobj->scale)
continue;
compdist = P_AproxDistance(
players[i].mo->x + players[i].mo->momx - mobj->cusval,
players[i].mo->y + players[i].mo->momy - mobj->cvmem);
players[i].mo->x + players[i].mo->momx - basex,
players[i].mo->y + players[i].mo->momy - basey);
if (compdist >= dist)
continue;
dist = compdist;
@ -8448,14 +8479,14 @@ void P_MobjThinker(mobj_t *mobj)
mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y);
if (P_AproxDistance(
mobj->x - mobj->cusval,
mobj->y - mobj->cvmem)
mobj->x - basex,
mobj->y - basey)
< mobj->scale)
S_StartSound(mobj, mobj->info->seesound);
P_TeleportMove(mobj,
(15*(mobj->x>>4)) + (mobj->cusval>>4) + P_ReturnThrustX(mobj, mobj->angle, SPECTATORRADIUS>>4),
(15*(mobj->y>>4)) + (mobj->cvmem>>4) + P_ReturnThrustY(mobj, mobj->angle, SPECTATORRADIUS>>4),
(15*(mobj->x>>4)) + (basex>>4) + P_ReturnThrustX(mobj, mobj->angle, SPECTATORRADIUS>>4),
(15*(mobj->y>>4)) + (basey>>4) + P_ReturnThrustY(mobj, mobj->angle, SPECTATORRADIUS>>4),
mobj->z);
}
else
@ -8478,18 +8509,12 @@ void P_MobjThinker(mobj_t *mobj)
if (!didmove)
{
if (P_AproxDistance(
mobj->x - mobj->cusval,
mobj->y - mobj->cvmem)
< mobj->scale)
P_TeleportMove(mobj,
mobj->cusval,
mobj->cvmem,
mobj->z);
if (P_AproxDistance(mobj->x - basex, mobj->y - basey) < mobj->scale)
P_TeleportMove(mobj, basex, basey, mobj->z);
else
P_TeleportMove(mobj,
(15*(mobj->x>>4)) + (mobj->cusval>>4),
(15*(mobj->y>>4)) + (mobj->cvmem>>4),
(15*(mobj->x>>4)) + (basex>>4),
(15*(mobj->y>>4)) + (basey>>4),
mobj->z);
}
}
@ -9038,9 +9063,9 @@ void P_MobjThinker(mobj_t *mobj)
{
if (mobj->state->action.acp1 == (actionf_p1)A_Boss1Laser)
{
var1 = mobj->state->var1;
var2 = mobj->state->var2;
mobj->state->action.acp1(mobj);
/*var1 = mobj->state->var1;
var2 = mobj->state->var2 & 65535;
mobj->state->action.acp1(mobj);*/
}
else if (leveltime & 1) // Fire mode
{
@ -10521,10 +10546,6 @@ void P_AfterPlayerSpawn(INT32 playernum)
else
p->viewz = p->mo->z + p->viewheight;
if (p->powers[pw_carry] != CR_NIGHTSMODE)
P_SetPlayerMobjState(p->mo, S_PLAY_STND);
p->pflags &= ~PF_SPINNING;
if (playernum == consoleplayer)
{
// wake up the status bar
@ -10609,6 +10630,8 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing)
mobj->eflags |= MFE_VERTICALFLIP;
mobj->flags2 |= MF2_OBJECTFLIP;
}
if (mthing->options & MTF_AMBUSH)
P_SetPlayerMobjState(mobj, S_PLAY_FALL);
}
else
z = floor;
@ -10627,7 +10650,12 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing)
P_SetThingPosition(mobj);
mobj->z = z;
if (mobj->z == mobj->floorz)
if (mobj->flags2 & MF2_OBJECTFLIP)
{
if (mobj->z + mobj->height == mobj->ceilingz)
mobj->eflags |= MFE_ONGROUND;
}
else if (mobj->z == mobj->floorz)
mobj->eflags |= MFE_ONGROUND;
mobj->angle = angle;
@ -10663,17 +10691,29 @@ void P_MovePlayerToStarpost(INT32 playernum)
sector->ceilingheight;
z = p->starpostz << FRACBITS;
if (z < floor)
P_SetScale(mobj, (mobj->destscale = abs(p->starpostscale)));
if (p->starpostscale < 0)
{
mobj->flags2 |= MF2_OBJECTFLIP;
if (z >= ceiling)
{
mobj->eflags |= MFE_ONGROUND;
z = ceiling;
}
z -= mobj->height;
}
else if (z <= floor)
{
mobj->eflags |= MFE_ONGROUND;
z = floor;
else if (z > ceiling - mobjinfo[MT_PLAYER].height)
z = ceiling - mobjinfo[MT_PLAYER].height;
}
mobj->floorz = floor;
mobj->ceilingz = ceiling;
mobj->z = z;
if (mobj->z == mobj->floorz)
mobj->eflags |= MFE_ONGROUND;
mobj->angle = p->starpostangle;

View file

@ -189,6 +189,7 @@ static void P_NetArchivePlayers(void)
WRITEINT16(save_p, players[i].starpostz);
WRITEINT32(save_p, players[i].starpostnum);
WRITEANGLE(save_p, players[i].starpostangle);
WRITEFIXED(save_p, players[i].starpostscale);
WRITEANGLE(save_p, players[i].angle_pos);
WRITEANGLE(save_p, players[i].old_angle_pos);
@ -397,6 +398,7 @@ static void P_NetUnArchivePlayers(void)
players[i].starpostz = READINT16(save_p);
players[i].starpostnum = READINT32(save_p);
players[i].starpostangle = READANGLE(save_p);
players[i].starpostscale = READFIXED(save_p);
players[i].angle_pos = READANGLE(save_p);
players[i].old_angle_pos = READANGLE(save_p);

View file

@ -225,6 +225,7 @@ static void P_ClearSingleMapHeaderInfo(INT16 i)
mapheaderinfo[num]->muspostbosstrack = 0;
mapheaderinfo[num]->muspostbosspos = 0;
mapheaderinfo[num]->muspostbossfadein = 0;
mapheaderinfo[num]->musforcereset = -1;
mapheaderinfo[num]->forcecharacter[0] = '\0';
mapheaderinfo[num]->weather = 0;
mapheaderinfo[num]->skynum = 1;
@ -577,6 +578,11 @@ INT32 P_AddLevelFlat(const char *flatname, levelflat_t *levelflat)
// store the flat lump number
levelflat->lumpnum = R_GetFlatNumForName(flatname);
levelflat->texturenum = R_CheckTextureNumForName(flatname);
levelflat->lasttexturenum = levelflat->texturenum;
levelflat->baselumpnum = LUMPERROR;
levelflat->basetexturenum = -1;
#ifndef ZDEBUG
CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name);
@ -621,6 +627,11 @@ INT32 P_AddLevelFlatRuntime(const char *flatname)
// store the flat lump number
levelflat->lumpnum = R_GetFlatNumForName(flatname);
levelflat->texturenum = R_CheckTextureNumForName(flatname);
levelflat->lasttexturenum = levelflat->texturenum;
levelflat->baselumpnum = LUMPERROR;
levelflat->basetexturenum = -1;
#ifndef ZDEBUG
CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name);
@ -1484,6 +1495,7 @@ static void P_LoadRawSideDefs2(void *data)
case 425: // Calls P_SetMobjState on calling mobj
case 434: // Custom Power
case 442: // Calls P_SetMobjState on mobjs of a given type in the tagged sectors
case 461: // Spawns an object on the map based on texture offsets
{
char process[8*3+1];
memset(process,0,8*3+1);
@ -2697,7 +2709,7 @@ boolean P_SetupLevel(boolean skipprecip)
S_StartSound(NULL, sfx_s3kaf);
// Fade music! Time it to S3KAF: 0.25 seconds is snappy.
if (cv_resetmusic.value ||
if (RESETMUSIC ||
strnicmp(S_MusicName(),
(mapmusflags & MUSIC_RELOADRESET) ? mapheaderinfo[gamemap-1]->musname : mapmusname, 7))
S_FadeOutStopMusic(MUSICRATE/4); //FixedMul(FixedDiv(F_GetWipeLength(wipedefs[wipe_speclevel_towhite])*NEWTICRATERATIO, NEWTICRATE), MUSICRATE)
@ -2730,7 +2742,7 @@ boolean P_SetupLevel(boolean skipprecip)
// Fade out music here. Deduct 2 tics so the fade volume actually reaches 0.
// But don't halt the music! S_Start will take care of that. This dodges a MIDI crash bug.
if (!titlemapinaction && (cv_resetmusic.value ||
if (!titlemapinaction && (RESETMUSIC ||
strnicmp(S_MusicName(),
(mapmusflags & MUSIC_RELOADRESET) ? mapheaderinfo[gamemap-1]->musname : mapmusname, 7)))
S_FadeMusic(0, FixedMul(

View file

@ -37,12 +37,19 @@ typedef struct
{
char name[9]; // resource name from wad
lumpnum_t lumpnum; // lump number of the flat
INT32 texturenum, lasttexturenum; // texture number of the flat
UINT16 width, height;
fixed_t topoffset, leftoffset;
// for flat animation
lumpnum_t baselumpnum;
INT32 basetexturenum;
INT32 animseq; // start pos. in the anim sequence
INT32 numpics;
INT32 speed;
// for patchflats
UINT8 *flatpatch;
} levelflat_t;
extern size_t numlevelflats;

View file

@ -205,8 +205,8 @@ void P_InitPicAnims(void)
if ((W_CheckNumForName(animdefs[i].startname)) == LUMPERROR)
continue;
lastanim->picnum = R_FlatNumForName(animdefs[i].endname);
lastanim->basepic = R_FlatNumForName(animdefs[i].startname);
lastanim->picnum = R_GetFlatNumForName(animdefs[i].endname);
lastanim->basepic = R_GetFlatNumForName(animdefs[i].startname);
}
lastanim->istexture = animdefs[i].istexture;
@ -464,7 +464,19 @@ static inline void P_FindAnimatedFlat(INT32 animnum)
for (i = 0; i < numlevelflats; i++, foundflats++)
{
// is that levelflat from the flat anim sequence ?
if (foundflats->lumpnum >= startflatnum && foundflats->lumpnum <= endflatnum)
if ((anims[animnum].istexture) && (foundflats->texturenum != 0 && foundflats->texturenum != -1)
&& ((UINT16)foundflats->texturenum >= startflatnum && (UINT16)foundflats->texturenum <= endflatnum))
{
foundflats->basetexturenum = startflatnum;
foundflats->animseq = foundflats->texturenum - startflatnum;
foundflats->numpics = endflatnum - startflatnum + 1;
foundflats->speed = anims[animnum].speed;
CONS_Debug(DBG_SETUP, "animflat: #%03d name:%.8s animseq:%d numpics:%d speed:%d\n",
atoi(sizeu1(i)), foundflats->name, foundflats->animseq,
foundflats->numpics,foundflats->speed);
}
else if (foundflats->lumpnum >= startflatnum && foundflats->lumpnum <= endflatnum)
{
foundflats->baselumpnum = startflatnum;
foundflats->animseq = foundflats->lumpnum - startflatnum;
@ -488,10 +500,7 @@ void P_SetupLevelFlatAnims(void)
// the original game flat anim sequences
for (i = 0; anims[i].istexture != -1; i++)
{
if (!anims[i].istexture)
P_FindAnimatedFlat(i);
}
P_FindAnimatedFlat(i);
}
//
@ -3953,6 +3962,39 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
}
break;
case 461: // Spawns an object on the map based on texture offsets
{
const mobjtype_t type = (mobjtype_t)(sides[line->sidenum[0]].toptexture);
mobj_t *mobj;
fixed_t x, y, z;
x = sides[line->sidenum[0]].textureoffset;
y = sides[line->sidenum[0]].rowoffset;
z = line->frontsector->floorheight;
if (line->flags & ML_NOCLIMB) // If noclimb is set, spawn randomly within a range
{
if (line->sidenum[1] != 0xffff) // Make sure the linedef has a back side
{
x = P_RandomRange(sides[line->sidenum[0]].textureoffset>>FRACBITS, sides[line->sidenum[1]].textureoffset>>FRACBITS)<<FRACBITS;
y = P_RandomRange(sides[line->sidenum[0]].rowoffset>>FRACBITS, sides[line->sidenum[1]].rowoffset>>FRACBITS)<<FRACBITS;
z = P_RandomRange(line->frontsector->floorheight>>FRACBITS, line->frontsector->ceilingheight>>FRACBITS)<<FRACBITS;
}
else
{
CONS_Alert(CONS_WARNING,"Linedef Type %d - Spawn Object: Linedef is set for random range but has no back side.\n", line->special);
break;
}
}
mobj = P_SpawnMobj(x, y, z, type);
if (mobj)
CONS_Debug(DBG_GAMELOGIC, "Linedef Type %d - Spawn Object: %d spawned at (%d, %d, %d)\n", line->special, mobj->type, mobj->x>>FRACBITS, mobj->y>>FRACBITS, mobj->z>>FRACBITS); //TODO: Convert mobj->type to a string somehow.
else
CONS_Alert(CONS_ERROR,"Linedef Type %d - Spawn Object: Object did not spawn!\n", line->special);
}
break;
#ifdef POLYOBJECTS
case 480: // Polyobj_DoorSlide
case 481: // Polyobj_DoorSwing
@ -4942,7 +4984,7 @@ DoneSection2:
CONS_Printf(M_GetText("%s started lap %u\n"), player_names[player-players], (UINT32)player->laps+1);
// Reset starposts (checkpoints) info
player->starpostangle = player->starposttime = player->starpostnum = 0;
player->starpostscale = player->starpostangle = player->starposttime = player->starpostnum = 0;
player->starpostx = player->starposty = player->starpostz = 0;
P_ResetStarposts();
@ -5636,9 +5678,12 @@ void P_UpdateSpecials(void)
{
if (foundflats->speed) // it is an animated flat
{
// update the levelflat texture number
if (foundflats->basetexturenum != -1)
foundflats->texturenum = foundflats->basetexturenum + ((leveltime/foundflats->speed + foundflats->animseq) % foundflats->numpics);
// update the levelflat lump number
foundflats->lumpnum = foundflats->baselumpnum +
((leveltime/foundflats->speed + foundflats->animseq) % foundflats->numpics);
else if (foundflats->baselumpnum != LUMPERROR)
foundflats->lumpnum = foundflats->baselumpnum + ((leveltime/foundflats->speed + foundflats->animseq) % foundflats->numpics);
}
}
}

View file

@ -33,7 +33,7 @@
void P_MixUp(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle,
INT16 starpostx, INT16 starposty, INT16 starpostz,
INT32 starpostnum, tic_t starposttime, angle_t starpostangle,
INT32 flags2)
fixed_t starpostscale, angle_t drawangle, INT32 flags2)
{
const INT32 takeflags2 = MF2_TWOD|MF2_OBJECTFLIP;
@ -89,8 +89,11 @@ void P_MixUp(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle,
thing->player->starpostz = starpostz;
thing->player->starposttime = starposttime;
thing->player->starpostangle = starpostangle;
thing->player->starpostscale = starpostscale;
thing->player->starpostnum = starpostnum;
thing->player->drawangle = drawangle;
// Reset map starposts for the player's new info.
P_ResetStarposts();
P_ClearStarPost(starpostnum);

View file

@ -1088,9 +1088,9 @@ static void R_Subsector(size_t num)
{
light = R_GetPlaneLight(frontsector, polysec->floorheight, viewz < polysec->floorheight);
ffloor[numffloors].plane = R_FindPlane(polysec->floorheight, polysec->floorpic,
polysec->lightlevel, polysec->floor_xoffs, polysec->floor_yoffs,
(light == -1 ? frontsector->lightlevel : *frontsector->lightlist[light].lightlevel), polysec->floor_xoffs, polysec->floor_yoffs,
polysec->floorpic_angle-po->angle,
NULL, NULL, po
(light == -1 ? frontsector->extra_colormap : *frontsector->lightlist[light].extra_colormap), NULL, po
#ifdef ESLOPE
, NULL // will ffloors be slopable eventually?
#endif
@ -1115,10 +1115,10 @@ static void R_Subsector(size_t num)
&& polysec->ceilingheight <= ceilingcenterz
&& (viewz > polysec->ceilingheight))
{
light = R_GetPlaneLight(frontsector, polysec->ceilingheight, viewz < polysec->ceilingheight);
light = R_GetPlaneLight(frontsector, polysec->floorheight, viewz < polysec->floorheight);
ffloor[numffloors].plane = R_FindPlane(polysec->ceilingheight, polysec->ceilingpic,
polysec->lightlevel, polysec->ceiling_xoffs, polysec->ceiling_yoffs, polysec->ceilingpic_angle-po->angle,
NULL, NULL, po
(light == -1 ? frontsector->lightlevel : *frontsector->lightlist[light].lightlevel), polysec->ceiling_xoffs, polysec->ceiling_yoffs, polysec->ceilingpic_angle-po->angle,
(light == -1 ? frontsector->extra_colormap : *frontsector->lightlist[light].extra_colormap), NULL, po
#ifdef ESLOPE
, NULL // will ffloors be slopable eventually?
#endif

View file

@ -40,6 +40,28 @@
#include <errno.h>
#endif
#ifdef HAVE_PNG
#ifndef _MSC_VER
#ifndef _LARGEFILE64_SOURCE
#define _LARGEFILE64_SOURCE
#endif
#endif
#ifndef _LFS64_LARGEFILE
#define _LFS64_LARGEFILE
#endif
#ifndef _FILE_OFFSET_BITS
#define _FILE_OFFSET_BITS 0
#endif
#include "png.h"
#ifndef PNG_READ_SUPPORTED
#undef HAVE_PNG
#endif
#endif
//
// Texture definition.
// Each texture is composed of one or more patches,
@ -98,12 +120,11 @@ INT32 numtextures = 0; // total number of textures found,
// size of following tables
texture_t **textures = NULL;
textureflat_t *texflats = NULL;
static UINT32 **texturecolumnofs; // column offset lookup table for each texture
static UINT8 **texturecache; // graphics data for each generated full-size texture
// texture width is a power of 2, so it can easily repeat along sidedefs using a simple mask
INT32 *texturewidthmask;
INT32 *texturewidth;
fixed_t *textureheight; // needed for texture pegging
INT32 *texturetranslation;
@ -220,15 +241,110 @@ static inline void R_DrawFlippedColumnInCache(column_t *patch, UINT8 *cache, tex
}
}
RGBA_t ASTBlendPixel(RGBA_t background, RGBA_t foreground, int style, UINT8 alpha)
{
RGBA_t output;
if (style == AST_TRANSLUCENT)
{
if (alpha == 0)
output.rgba = background.rgba;
else if (alpha == 0xFF)
output.rgba = foreground.rgba;
else if (alpha < 0xFF)
{
UINT8 beta = (0xFF - alpha);
output.s.red = ((background.s.red * beta) + (foreground.s.red * alpha)) / 0xFF;
output.s.green = ((background.s.green * beta) + (foreground.s.green * alpha)) / 0xFF;
output.s.blue = ((background.s.blue * beta) + (foreground.s.blue * alpha)) / 0xFF;
}
// write foreground pixel alpha
// if there's no pixel in here
if (!background.rgba)
output.s.alpha = foreground.s.alpha;
}
#define clamp(c) max(min(c, 0xFF), 0x00);
else
{
float falpha = ((float)alpha / 256.0f);
float fr = ((float)foreground.s.red * falpha);
float fg = ((float)foreground.s.green * falpha);
float fb = ((float)foreground.s.blue * falpha);
if (style == AST_ADD)
{
output.s.red = clamp((int)(background.s.red + fr));
output.s.green = clamp((int)(background.s.green + fg));
output.s.blue = clamp((int)(background.s.blue + fb));
}
else if (style == AST_SUBTRACT)
{
output.s.red = clamp((int)(background.s.red - fr));
output.s.green = clamp((int)(background.s.green - fg));
output.s.blue = clamp((int)(background.s.blue - fb));
}
else if (style == AST_REVERSESUBTRACT)
{
output.s.red = clamp((int)((-background.s.red) + fr));
output.s.green = clamp((int)((-background.s.green) + fg));
output.s.blue = clamp((int)((-background.s.blue) + fb));
}
else if (style == AST_MODULATE)
{
fr = ((float)foreground.s.red / 256.0f);
fg = ((float)foreground.s.green / 256.0f);
fb = ((float)foreground.s.blue / 256.0f);
output.s.red = clamp((int)(background.s.red * fr));
output.s.green = clamp((int)(background.s.green * fg));
output.s.blue = clamp((int)(background.s.blue * fb));
}
// just copy the pixel
else if (style == AST_COPY)
return background;
}
#undef clamp
// unimplemented blend modes return the background pixel
output = background;
output.s.alpha = 0xFF;
return output;
}
UINT8 ASTBlendPixel_8bpp(UINT8 background, UINT8 foreground, int style, UINT8 alpha)
{
if ((style == AST_TRANSLUCENT) && (alpha <= (10*255/11))) // Alpha style set to translucent? Is the alpha small enough for translucency?
{
UINT8 *mytransmap;
if (alpha < 255/11) // Is the patch way too translucent? Don't render then.
return background;
// The equation's not exact but it works as intended. I'll call it a day for now.
mytransmap = transtables + ((8*(alpha) + 255/8)/(255 - 255/11) << FF_TRANSSHIFT);
if (background != 0xFF)
return *(mytransmap + (background<<8) + foreground);
}
// just copy the pixel
else if (style == AST_COPY)
return background;
// use ASTBlendPixel for all other blend modes
// and find the nearest colour in the palette
else if (style != AST_TRANSLUCENT)
{
RGBA_t texel;
RGBA_t bg = V_GetColor(background);
RGBA_t fg = V_GetColor(foreground);
texel = ASTBlendPixel(bg, fg, style, alpha);
return NearestColor(texel.s.red, texel.s.green, texel.s.blue);
}
// fallback if all above fails, somehow
// return the background pixel
return background;
}
//
// R_DrawTransColumnInCache
// R_DrawBlendColumnInCache
// Draws a translucent column into the cache, applying a half-cooked equation to get a proper translucency value (Needs code in R_GenerateTexture()).
//
static inline void R_DrawTransColumnInCache(column_t *patch, UINT8 *cache, texpatch_t *originPatch, INT32 cacheheight, INT32 patchheight)
static inline void R_DrawBlendColumnInCache(column_t *patch, UINT8 *cache, texpatch_t *originPatch, INT32 cacheheight, INT32 patchheight)
{
INT32 count, position;
UINT8 *source, *dest;
UINT8 *mytransmap = transtables + ((8*(originPatch->alpha) + 255/8)/(255 - 255/11) << FF_TRANSSHIFT); // The equation's not exact but it works as intended. I'll call it a day for now.
INT32 topdelta, prevdelta = -1;
INT32 originy = originPatch->originy;
@ -258,7 +374,8 @@ static inline void R_DrawTransColumnInCache(column_t *patch, UINT8 *cache, texpa
if (count > 0)
{
for (; dest < cache + position + count; source++, dest++)
if (*dest != 0xFF) *dest = *(mytransmap + ((*dest)<<8) + (*source));
if (*dest != 0xFF)
*dest = ASTBlendPixel_8bpp(*dest, *source, originPatch->style, originPatch->alpha);
}
patch = (column_t *)((UINT8 *)patch + patch->length + 4);
@ -269,11 +386,10 @@ static inline void R_DrawTransColumnInCache(column_t *patch, UINT8 *cache, texpa
// R_DrawTransColumnInCache
// Similar to the one above except that the column is inverted.
//
static inline void R_DrawTransFlippedColumnInCache(column_t *patch, UINT8 *cache, texpatch_t *originPatch, INT32 cacheheight, INT32 patchheight)
static inline void R_DrawBlendFlippedColumnInCache(column_t *patch, UINT8 *cache, texpatch_t *originPatch, INT32 cacheheight, INT32 patchheight)
{
INT32 count, position;
UINT8 *source, *dest;
UINT8 *mytransmap = transtables + ((8*(originPatch->alpha) + 255/8)/(255 - 255/11) << FF_TRANSSHIFT); // The equation's not exact but it works as intended. I'll call it a day for now.
INT32 topdelta, prevdelta = -1;
INT32 originy = originPatch->originy;
@ -302,7 +418,8 @@ static inline void R_DrawTransFlippedColumnInCache(column_t *patch, UINT8 *cache
if (count > 0)
{
for (; dest < cache + position + count; --source, dest++)
if (*dest != 0xFF) *dest = *(mytransmap + ((*dest)<<8) + (*source));
if (*dest != 0xFF)
*dest = ASTBlendPixel_8bpp(*dest, *source, originPatch->style, originPatch->alpha);
}
patch = (column_t *)((UINT8 *)patch + patch->length + 4);
@ -315,7 +432,7 @@ static inline void R_DrawTransFlippedColumnInCache(column_t *patch, UINT8 *cache
// Allocate space for full size texture, either single patch or 'composite'
// Build the full textures from patches.
// The texture caching system is a little more hungry of memory, but has
// been simplified for the sake of highcolor, dynamic ligthing, & speed.
// been simplified for the sake of highcolor (lol), dynamic ligthing, & speed.
//
// This is not optimised, but it's supposed to be executed only once
// per level, when enough memory is available.
@ -332,6 +449,10 @@ static UINT8 *R_GenerateTexture(size_t texnum)
column_t *patchcol;
UINT32 *colofs;
UINT16 wadnum;
lumpnum_t lumpnum;
size_t lumplength;
I_Assert(texnum <= (size_t)numtextures);
texture = textures[texnum];
I_Assert(texture != NULL);
@ -346,7 +467,19 @@ static UINT8 *R_GenerateTexture(size_t texnum)
{
boolean holey = false;
patch = texture->patches;
realpatch = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE);
wadnum = patch->wad;
lumpnum = patch->lump;
lumplength = W_LumpLengthPwad(wadnum, lumpnum);
realpatch = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE);
#ifndef NO_PNG_LUMPS
if (R_IsLumpPNG((UINT8 *)realpatch, lumplength))
{
realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength);
goto multipatch;
}
#endif
// Check the patch for holes.
if (texture->width > SHORT(realpatch->width) || texture->height > SHORT(realpatch->height))
@ -376,7 +509,7 @@ static UINT8 *R_GenerateTexture(size_t texnum)
{
texture->holes = true;
texture->flip = patch->flip;
blocksize = W_LumpLengthPwad(patch->wad, patch->lump);
blocksize = lumplength;
block = Z_Calloc(blocksize, PU_STATIC, // will change tag at end of this function
&texturecache[texnum]);
M_Memcpy(block, realpatch, blocksize);
@ -403,6 +536,9 @@ static UINT8 *R_GenerateTexture(size_t texnum)
}
// multi-patch textures (or 'composite')
#ifndef NO_PNG_LUMPS
multipatch:
#endif
texture->holes = false;
texture->flip = 0;
blocksize = (texture->width * 4) + (texture->width * texture->height);
@ -422,18 +558,20 @@ static UINT8 *R_GenerateTexture(size_t texnum)
for (i = 0, patch = texture->patches; i < texture->patchcount; i++, patch++)
{
static void (*ColumnDrawerPointer)(column_t *, UINT8 *, texpatch_t *, INT32, INT32); // Column drawing function pointer.
if ((patch->style == AST_TRANSLUCENT) && (patch->alpha <= (10*255/11))) // Alpha style set to translucent? Is the alpha small enough for translucency?
{
if (patch->alpha < 255/11) // Is the patch way too translucent? Don't render then.
continue;
ColumnDrawerPointer = (patch->flip & 2) ? R_DrawTransFlippedColumnInCache : R_DrawTransColumnInCache;
}
if (patch->style != AST_COPY)
ColumnDrawerPointer = (patch->flip & 2) ? R_DrawBlendFlippedColumnInCache : R_DrawBlendColumnInCache;
else
{
ColumnDrawerPointer = (patch->flip & 2) ? R_DrawFlippedColumnInCache : R_DrawColumnInCache;
}
realpatch = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE);
wadnum = patch->wad;
lumpnum = patch->lump;
lumplength = W_LumpLengthPwad(wadnum, lumpnum);
realpatch = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE);
#ifndef NO_PNG_LUMPS
if (R_IsLumpPNG((UINT8 *)realpatch, lumplength))
realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength);
#endif
x1 = patch->originx;
width = SHORT(realpatch->width);
height = SHORT(realpatch->height);
@ -509,10 +647,14 @@ void R_CheckTextureCache(INT32 tex)
UINT8 *R_GetColumn(fixed_t tex, INT32 col)
{
UINT8 *data;
INT32 width = texturewidth[tex];
if (width & (width - 1))
col = (UINT32)col % width;
else
col &= (width - 1);
col &= texturewidthmask[tex];
data = texturecache[tex];
if (!data)
data = R_GenerateTexture(tex);
@ -550,7 +692,7 @@ void R_ParseTEXTURESLump(UINT16 wadNum, UINT16 lumpNum, INT32 *index);
#define TX_END "TX_END"
void R_LoadTextures(void)
{
INT32 i, k, w;
INT32 i, w;
UINT16 j;
UINT16 texstart, texend, texturesLumpPos;
patch_t *patchlump;
@ -567,6 +709,7 @@ void R_LoadTextures(void)
}
Z_Free(texturetranslation);
Z_Free(textures);
Z_Free(texflats);
}
// Load patches and textures.
@ -627,15 +770,16 @@ void R_LoadTextures(void)
// Allocate memory and initialize to 0 for all the textures we are initialising.
// There are actually 5 buffers allocated in one for convenience.
textures = Z_Calloc((numtextures * sizeof(void *)) * 5, PU_STATIC, NULL);
texflats = Z_Calloc((numtextures * sizeof(*texflats)), PU_STATIC, NULL);
// Allocate texture column offset table.
texturecolumnofs = (void *)((UINT8 *)textures + (numtextures * sizeof(void *)));
// Allocate texture referencing cache.
texturecache = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 2));
// Allocate texture width mask table.
texturewidthmask = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 3));
// Allocate texture height mask table.
textureheight = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 4));
texturecache = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 2));
// Allocate texture width table.
texturewidth = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 3));
// Allocate texture height table.
textureheight = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 4));
// Create translation table for global animation.
texturetranslation = Z_Malloc((numtextures + 1) * sizeof(*texturetranslation), PU_STATIC, NULL);
@ -673,20 +817,39 @@ void R_LoadTextures(void)
// Work through each lump between the markers in the WAD.
for (j = 0; j < (texend - texstart); j++)
{
UINT16 wadnum = (UINT16)w;
lumpnum_t lumpnum = texstart + j;
size_t lumplength;
if (wadfiles[w]->type == RET_PK3)
{
if (W_IsLumpFolder((UINT16)w, texstart + j)) // Check if lump is a folder
if (W_IsLumpFolder(wadnum, lumpnum)) // Check if lump is a folder
continue; // If it is then SKIP IT
}
patchlump = W_CacheLumpNumPwad((UINT16)w, texstart + j, PU_CACHE);
lumplength = W_LumpLengthPwad(wadnum, lumpnum);
patchlump = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE);
//CONS_Printf("\n\"%s\" is a single patch, dimensions %d x %d",W_CheckNameForNumPwad((UINT16)w,texstart+j),patchlump->width, patchlump->height);
texture = textures[i] = Z_Calloc(sizeof(texture_t) + sizeof(texpatch_t), PU_STATIC, NULL);
// Set texture properties.
M_Memcpy(texture->name, W_CheckNameForNumPwad((UINT16)w, texstart + j), sizeof(texture->name));
texture->width = SHORT(patchlump->width);
texture->height = SHORT(patchlump->height);
M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name));
#ifndef NO_PNG_LUMPS
if (R_IsLumpPNG((UINT8 *)patchlump, lumplength))
{
INT16 width, height;
R_PNGDimensions((UINT8 *)patchlump, &width, &height, lumplength);
texture->width = width;
texture->height = height;
}
else
#endif
{
texture->width = SHORT(patchlump->width);
texture->height = SHORT(patchlump->height);
}
texture->patchcount = 1;
texture->holes = false;
texture->flip = 0;
@ -701,11 +864,7 @@ void R_LoadTextures(void)
Z_Unlock(patchlump);
k = 1;
while (k << 1 <= texture->width)
k <<= 1;
texturewidthmask[i] = k - 1;
texturewidth[i] = texture->width;
textureheight[i] = texture->height << FRACBITS;
i++;
}
@ -848,8 +1007,16 @@ static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch)
{
Z_Free(texturesToken);
texturesToken = M_GetToken(NULL);
if(stricmp(texturesToken, "TRANSLUCENT")==0)
if (stricmp(texturesToken, "TRANSLUCENT")==0)
style = AST_TRANSLUCENT;
else if (stricmp(texturesToken, "ADD")==0)
style = AST_ADD;
else if (stricmp(texturesToken, "SUBTRACT")==0)
style = AST_SUBTRACT;
else if (stricmp(texturesToken, "REVERSESUBTRACT")==0)
style = AST_REVERSESUBTRACT;
else if (stricmp(texturesToken, "MODULATE")==0)
style = AST_MODULATE;
}
else if (stricmp(texturesToken, "FLIPX")==0)
flip |= 1;
@ -1097,7 +1264,7 @@ int R_CountTexturesInTEXTURESLump(UINT16 wadNum, UINT16 lumpNum)
texturesToken = M_GetToken(texturesText);
while (texturesToken != NULL)
{
if (stricmp(texturesToken, "WALLTEXTURE")==0)
if (stricmp(texturesToken, "WALLTEXTURE") == 0 || stricmp(texturesToken, "TEXTURE") == 0)
{
numTexturesInLump++;
Z_Free(texturesToken);
@ -1105,7 +1272,7 @@ int R_CountTexturesInTEXTURESLump(UINT16 wadNum, UINT16 lumpNum)
}
else
{
I_Error("Error parsing TEXTURES lump: Expected \"WALLTEXTURE\", got \"%s\"",texturesToken);
I_Error("Error parsing TEXTURES lump: Expected \"WALLTEXTURE\" or \"TEXTURE\", got \"%s\"",texturesToken);
}
texturesToken = M_GetToken(NULL);
}
@ -1146,21 +1313,21 @@ void R_ParseTEXTURESLump(UINT16 wadNum, UINT16 lumpNum, INT32 *texindex)
texturesToken = M_GetToken(texturesText);
while (texturesToken != NULL)
{
if (stricmp(texturesToken, "WALLTEXTURE")==0)
if (stricmp(texturesToken, "WALLTEXTURE") == 0 || stricmp(texturesToken, "TEXTURE") == 0)
{
Z_Free(texturesToken);
// Get the new texture
newTexture = R_ParseTexture(true);
// Store the new texture
textures[*texindex] = newTexture;
texturewidthmask[*texindex] = newTexture->width - 1;
texturewidth[*texindex] = newTexture->width;
textureheight[*texindex] = newTexture->height << FRACBITS;
// Increment i back in R_LoadTextures()
(*texindex)++;
}
else
{
I_Error("Error parsing TEXTURES lump: Expected \"WALLTEXTURE\", got \"%s\"",texturesToken);
I_Error("Error parsing TEXTURES lump: Expected \"WALLTEXTURE\" or \"TEXTURE\", got \"%s\"",texturesToken);
}
texturesToken = M_GetToken(NULL);
}
@ -1267,6 +1434,41 @@ lumpnum_t R_GetFlatNumForName(const char *name)
lump = LUMPERROR;
}
// Detect textures
if (lump == LUMPERROR)
{
// Scan wad files backwards so patched textures take preference.
for (i = numwadfiles - 1; i >= 0; i--)
{
switch (wadfiles[i]->type)
{
case RET_WAD:
if ((start = W_CheckNumForNamePwad("TX_START", (UINT16)i, 0)) == INT16_MAX)
continue;
if ((end = W_CheckNumForNamePwad("TX_END", (UINT16)i, start)) == INT16_MAX)
continue;
break;
case RET_PK3:
if ((start = W_CheckNumForFolderStartPK3("Textures/", i, 0)) == INT16_MAX)
continue;
if ((end = W_CheckNumForFolderEndPK3("Textures/", i, start)) == INT16_MAX)
continue;
break;
default:
continue;
}
// Now find lump with specified name in that range.
lump = W_CheckNumForNamePwad(name, (UINT16)i, start);
if (lump < end)
{
lump += (i<<16); // found it, in our constraints
break;
}
lump = LUMPERROR;
}
}
if (lump == LUMPERROR)
{
if (strcmp(name, SKYFLATNAME))
@ -1615,7 +1817,6 @@ extracolormap_t *R_ColormapForName(char *name)
//
static double deltas[256][3], map[256][3];
static UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b);
static int RoundUp(double number);
lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap)
@ -2027,7 +2228,7 @@ extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *ex
// Thanks to quake2 source!
// utils3/qdata/images.c
static UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b)
UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b)
{
int dr, dg, db;
int distortion, bestdistortion = 256 * 256 * 4, bestcolor = 0, i;
@ -2306,3 +2507,479 @@ void R_PrecacheLevel(void)
"texturememory: %s k\n"
"spritememory: %s k\n", sizeu1(flatmemory>>10), sizeu2(texturememory>>10), sizeu3(spritememory>>10));
}
// https://github.com/coelckers/prboom-plus/blob/master/prboom2/src/r_patch.c#L350
boolean R_CheckIfPatch(lumpnum_t lump)
{
size_t size;
INT16 width, height;
patch_t *patch;
boolean result;
size = W_LumpLength(lump);
// minimum length of a valid Doom patch
if (size < 13)
return false;
patch = (patch_t *)W_CacheLumpNum(lump, PU_STATIC);
width = SHORT(patch->width);
height = SHORT(patch->height);
result = (height > 0 && height <= 16384 && width > 0 && width <= 16384 && width < (INT16)(size / 4));
if (result)
{
// The dimensions seem like they might be valid for a patch, so
// check the column directory for extra security. All columns
// must begin after the column directory, and none of them must
// point past the end of the patch.
INT16 x;
for (x = 0; x < width; x++)
{
UINT32 ofs = LONG(patch->columnofs[x]);
// Need one byte for an empty column (but there's patches that don't know that!)
if (ofs < (UINT32)width * 4 + 8 || ofs >= (UINT32)size)
{
result = false;
break;
}
}
}
return result;
}
void R_PatchToFlat(patch_t *patch, UINT8 *flat)
{
fixed_t col, ofs;
column_t *column;
UINT8 *desttop, *dest, *deststop;
UINT8 *source;
desttop = flat;
deststop = desttop + (SHORT(patch->width) * SHORT(patch->height));
for (col = 0; col < SHORT(patch->width); col++, desttop++)
{
INT32 topdelta, prevdelta = -1;
column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[col]));
while (column->topdelta != 0xff)
{
topdelta = column->topdelta;
if (topdelta <= prevdelta)
topdelta += prevdelta;
prevdelta = topdelta;
dest = desttop + (topdelta * SHORT(patch->width));
source = (UINT8 *)(column) + 3;
for (ofs = 0; dest < deststop && ofs < column->length; ofs++)
{
*dest = source[ofs];
dest += SHORT(patch->width);
}
column = (column_t *)((UINT8 *)column + column->length + 4);
}
}
}
#ifndef NO_PNG_LUMPS
boolean R_IsLumpPNG(UINT8 *d, size_t s)
{
if (s < 67) // http://garethrees.org/2007/11/14/pngcrush/
return false;
// Check for PNG file signature using memcmp
// As it may be faster on CPUs with slow unaligned memory access
// Ref: http://www.libpng.org/pub/png/spec/1.2/PNG-Rationale.html#R.PNG-file-signature
return (memcmp(&d[0], "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a", 8) == 0);
}
#ifdef HAVE_PNG
typedef struct {
png_bytep buffer;
png_uint_32 bufsize;
png_uint_32 current_pos;
} png_ioread;
static void PNG_IOReader(png_structp png_ptr, png_bytep data, png_size_t length)
{
png_ioread *f = png_get_io_ptr(png_ptr);
if (length > (f->bufsize - f->current_pos))
png_error(png_ptr, "PNG_IOReader: buffer overrun");
memcpy(data, f->buffer + f->current_pos, length);
f->current_pos += length;
}
static void PNG_error(png_structp PNG, png_const_charp pngtext)
{
CONS_Debug(DBG_RENDER, "libpng error at %p: %s", PNG, pngtext);
//I_Error("libpng error at %p: %s", PNG, pngtext);
}
static void PNG_warn(png_structp PNG, png_const_charp pngtext)
{
CONS_Debug(DBG_RENDER, "libpng warning at %p: %s", PNG, pngtext);
}
static png_bytep *PNG_Read(UINT8 *png, UINT16 *w, UINT16 *h, size_t size)
{
png_structp png_ptr;
png_infop png_info_ptr;
png_uint_32 width, height;
int bit_depth, color_type;
png_uint_32 y;
#ifdef PNG_SETJMP_SUPPORTED
#ifdef USE_FAR_KEYWORD
jmp_buf jmpbuf;
#endif
#endif
png_ioread png_io;
png_bytep *row_pointers;
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
PNG_error, PNG_warn);
if (!png_ptr)
{
CONS_Debug(DBG_RENDER, "PNG_Load: Error on initialize libpng\n");
return NULL;
}
png_info_ptr = png_create_info_struct(png_ptr);
if (!png_info_ptr)
{
CONS_Debug(DBG_RENDER, "PNG_Load: Error on allocate for libpng\n");
png_destroy_read_struct(&png_ptr, NULL, NULL);
return NULL;
}
#ifdef USE_FAR_KEYWORD
if (setjmp(jmpbuf))
#else
if (setjmp(png_jmpbuf(png_ptr)))
#endif
{
//CONS_Debug(DBG_RENDER, "libpng load error on %s\n", filename);
png_destroy_read_struct(&png_ptr, &png_info_ptr, NULL);
return NULL;
}
#ifdef USE_FAR_KEYWORD
png_memcpy(png_jmpbuf(png_ptr), jmpbuf, sizeof jmp_buf);
#endif
// set our own read_function
png_io.buffer = (png_bytep)png;
png_io.bufsize = size;
png_io.current_pos = 0;
png_set_read_fn(png_ptr, &png_io, PNG_IOReader);
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
png_set_user_limits(png_ptr, 2048, 2048);
#endif
png_read_info(png_ptr, png_info_ptr);
png_get_IHDR(png_ptr, png_info_ptr, &width, &height, &bit_depth, &color_type,
NULL, NULL, NULL);
if (bit_depth == 16)
png_set_strip_16(png_ptr);
if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
png_set_gray_to_rgb(png_ptr);
else if (color_type == PNG_COLOR_TYPE_PALETTE)
png_set_palette_to_rgb(png_ptr);
if (png_get_valid(png_ptr, png_info_ptr, PNG_INFO_tRNS))
png_set_tRNS_to_alpha(png_ptr);
else if (color_type != PNG_COLOR_TYPE_RGB_ALPHA && color_type != PNG_COLOR_TYPE_GRAY_ALPHA)
{
#if PNG_LIBPNG_VER < 10207
png_set_filler(png_ptr, 0xFF, PNG_FILLER_AFTER);
#else
png_set_add_alpha(png_ptr, 0xFF, PNG_FILLER_AFTER);
#endif
}
png_read_update_info(png_ptr, png_info_ptr);
// Read the image
row_pointers = (png_bytep*)malloc(sizeof(png_bytep) * height);
for (y = 0; y < height; y++)
row_pointers[y] = (png_byte*)malloc(png_get_rowbytes(png_ptr, png_info_ptr));
png_read_image(png_ptr, row_pointers);
png_destroy_read_struct(&png_ptr, &png_info_ptr, NULL);
*w = (INT32)width;
*h = (INT32)height;
return row_pointers;
}
// Convert a PNG to a raw image.
static UINT8 *PNG_RawConvert(UINT8 *png, UINT16 *w, UINT16 *h, size_t size)
{
UINT8 *flat;
png_uint_32 x, y;
png_bytep *row_pointers = PNG_Read(png, w, h, size);
png_uint_32 width = *w, height = *h;
if (!row_pointers)
I_Error("PNG_RawConvert: conversion failed");
// Convert the image to 8bpp
flat = Z_Malloc(width * height, PU_LEVEL, NULL);
memset(flat, TRANSPARENTPIXEL, width * height);
for (y = 0; y < height; y++)
{
png_bytep row = row_pointers[y];
for (x = 0; x < width; x++)
{
png_bytep px = &(row[x * 4]);
if ((UINT8)px[3])
flat[((y * width) + x)] = NearestColor((UINT8)px[0], (UINT8)px[1], (UINT8)px[2]);
}
}
free(row_pointers);
return flat;
}
// Convert a PNG to a flat.
UINT8 *R_PNGToFlat(levelflat_t *levelflat, UINT8 *png, size_t size)
{
return PNG_RawConvert(png, &levelflat->width, &levelflat->height, size);
}
// Convert a PNG to a patch.
static unsigned char imgbuf[1<<26];
patch_t *R_PNGToPatch(UINT8 *png, size_t size)
{
UINT16 width, height;
UINT8 *raw = PNG_RawConvert(png, &width, &height, size);
UINT32 x, y;
UINT8 *img;
UINT8 *imgptr = imgbuf;
UINT8 *colpointers, *startofspan;
#define WRITE8(buf, a) ({*buf = (a); buf++;})
#define WRITE16(buf, a) ({*buf = (a)&255; buf++; *buf = (a)>>8; buf++;})
#define WRITE32(buf, a) ({WRITE16(buf, (a)&65535); WRITE16(buf, (a)>>16);})
if (!raw)
I_Error("R_PNGToPatch: conversion failed");
// Write image size and offset
WRITE16(imgptr, width);
WRITE16(imgptr, height);
// no offsets
WRITE16(imgptr, 0);
WRITE16(imgptr, 0);
// Leave placeholder to column pointers
colpointers = imgptr;
imgptr += width*4;
// Write columns
for (x = 0; x < width; x++)
{
int lastStartY = 0;
int spanSize = 0;
startofspan = NULL;
//printf("%d ", x);
// Write column pointer (@TODO may be wrong)
WRITE32(colpointers, imgptr - imgbuf);
// Write pixels
for (y = 0; y < height; y++)
{
UINT8 paletteIndex = raw[((y * width) + x)];
// Start new column if we need to
if (!startofspan || spanSize == 255)
{
int writeY = y;
// If we reached the span size limit, finish the previous span
if (startofspan)
WRITE8(imgptr, 0);
if (y > 254)
{
// Make sure we're aligned to 254
if (lastStartY < 254)
{
WRITE8(imgptr, 254);
WRITE8(imgptr, 0);
imgptr += 2;
lastStartY = 254;
}
// Write stopgap empty spans if needed
writeY = y - lastStartY;
while (writeY > 254)
{
WRITE8(imgptr, 254);
WRITE8(imgptr, 0);
imgptr += 2;
writeY -= 254;
}
}
startofspan = imgptr;
WRITE8(imgptr, writeY);///@TODO calculate starting y pos
imgptr += 2;
spanSize = 0;
lastStartY = y;
}
// Write the pixel
WRITE8(imgptr, paletteIndex);
spanSize++;
startofspan[1] = spanSize;
}
if (startofspan)
WRITE8(imgptr, 0);
WRITE8(imgptr, 0xFF);
}
#undef WRITE8
#undef WRITE16
#undef WRITE32
size = imgptr-imgbuf;
img = malloc(size);
memcpy(img, imgbuf, size);
Z_Free(raw);
return (patch_t *)img;
}
boolean R_PNGDimensions(UINT8 *png, INT16 *width, INT16 *height, size_t size)
{
png_structp png_ptr;
png_infop png_info_ptr;
png_uint_32 w, h;
int bit_depth, color_type;
#ifdef PNG_SETJMP_SUPPORTED
#ifdef USE_FAR_KEYWORD
jmp_buf jmpbuf;
#endif
#endif
png_ioread png_io;
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
PNG_error, PNG_warn);
if (!png_ptr)
{
CONS_Debug(DBG_RENDER, "PNG_Load: Error on initialize libpng\n");
return false;
}
png_info_ptr = png_create_info_struct(png_ptr);
if (!png_info_ptr)
{
CONS_Debug(DBG_RENDER, "PNG_Load: Error on allocate for libpng\n");
png_destroy_read_struct(&png_ptr, NULL, NULL);
return false;
}
#ifdef USE_FAR_KEYWORD
if (setjmp(jmpbuf))
#else
if (setjmp(png_jmpbuf(png_ptr)))
#endif
{
//CONS_Debug(DBG_RENDER, "libpng load error on %s\n", filename);
png_destroy_read_struct(&png_ptr, &png_info_ptr, NULL);
return false;
}
#ifdef USE_FAR_KEYWORD
png_memcpy(png_jmpbuf(png_ptr), jmpbuf, sizeof jmp_buf);
#endif
// set our own read_function
png_io.buffer = (png_bytep)png;
png_io.bufsize = size;
png_io.current_pos = 0;
png_set_read_fn(png_ptr, &png_io, PNG_IOReader);
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
png_set_user_limits(png_ptr, 2048, 2048);
#endif
png_read_info(png_ptr, png_info_ptr);
png_get_IHDR(png_ptr, png_info_ptr, &w, &h, &bit_depth, &color_type,
NULL, NULL, NULL);
// okay done. stop.
png_destroy_read_struct(&png_ptr, &png_info_ptr, NULL);
*width = (INT32)w;
*height = (INT32)h;
return true;
}
#endif
#endif
void R_TextureToFlat(size_t tex, UINT8 *flat)
{
texture_t *texture = textures[tex];
fixed_t col, ofs;
column_t *column;
UINT8 *desttop, *dest, *deststop;
UINT8 *source;
desttop = flat;
deststop = desttop + (texture->width * texture->height);
for (col = 0; col < texture->width; col++, desttop++)
{
column = (column_t *)R_GetColumn(tex, col);
if (!texture->holes)
{
dest = desttop;
source = (UINT8 *)(column);
for (ofs = 0; dest < deststop && ofs < texture->height; ofs++)
{
if (source[ofs] != TRANSPARENTPIXEL)
*dest = source[ofs];
dest += texture->width;
}
}
else
{
INT32 topdelta, prevdelta = -1;
while (column->topdelta != 0xff)
{
topdelta = column->topdelta;
if (topdelta <= prevdelta)
topdelta += prevdelta;
prevdelta = topdelta;
dest = desttop + (topdelta * texture->width);
source = (UINT8 *)(column) + 3;
for (ofs = 0; dest < deststop && ofs < column->length; ofs++)
{
if (source[ofs] != TRANSPARENTPIXEL)
*dest = source[ofs];
dest += texture->width;
}
column = (column_t *)((UINT8 *)column + column->length + 4);
}
}
}
}

View file

@ -16,13 +16,19 @@
#include "r_defs.h"
#include "r_state.h"
#include "p_setup.h" // levelflats
#ifdef __GNUG__
#pragma interface
#endif
// Possible alpha types for a patch.
enum patchalphastyle {AST_COPY, AST_TRANSLUCENT}; // , AST_ADD, AST_SUBTRACT, AST_REVERSESUBTRACT, AST_MODULATE, AST_OVERLAY};
enum patchalphastyle {AST_COPY, AST_TRANSLUCENT, AST_ADD, AST_SUBTRACT, AST_REVERSESUBTRACT, AST_MODULATE, AST_OVERLAY};
RGBA_t ASTBlendPixel(RGBA_t background, RGBA_t foreground, int style, UINT8 alpha);
UINT8 ASTBlendPixel_8bpp(UINT8 background, UINT8 foreground, int style, UINT8 alpha);
UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b);
// moved here for r_sky.c (texpatch_t is used)
@ -55,12 +61,17 @@ typedef struct
texpatch_t patches[0];
} texture_t;
typedef struct
{
UINT8 *flat;
INT16 width, height;
} textureflat_t;
// all loaded and prepared textures from the start of the game
extern texture_t **textures;
extern textureflat_t *texflats;
// texture width is a power of 2, so it can easily repeat along sidedefs using a simple mask
extern INT32 *texturewidthmask;
extern INT32 *texturewidth;
extern fixed_t *textureheight; // needed for texture pegging
extern INT16 color8to16[256]; // remap color index to highcolor
@ -88,7 +99,6 @@ void R_PrecacheLevel(void);
// Floor/ceiling opaque texture tiles,
// lookup by name. For animation?
lumpnum_t R_GetFlatNumForName(const char *name);
#define R_FlatNumForName(x) R_GetFlatNumForName(x)
// Called by P_Ticker for switches and animations,
// returns the texture number for the texture name.
@ -148,6 +158,20 @@ const char *R_NameForColormap(extracolormap_t *extra_colormap);
#define R_PutRgbaRGB(r, g, b) (R_PutRgbaR(r) + R_PutRgbaG(g) + R_PutRgbaB(b))
#define R_PutRgbaRGBA(r, g, b, a) (R_PutRgbaRGB(r, g, b) + R_PutRgbaA(a))
boolean R_CheckIfPatch(lumpnum_t lump);
UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b);
void R_PatchToFlat(patch_t *patch, UINT8 *flat);
void R_TextureToFlat(size_t tex, UINT8 *flat);
#ifndef NO_PNG_LUMPS
boolean R_IsLumpPNG(UINT8 *d, size_t s);
UINT8 *R_PNGToFlat(levelflat_t *levelflat, UINT8 *png, size_t size);
patch_t *R_PNGToPatch(UINT8 *png, size_t size);
boolean R_PNGDimensions(UINT8 *png, INT16 *width, INT16 *height, size_t size);
#endif
extern INT32 numtextures;
#endif

View file

@ -99,6 +99,8 @@ INT32 dc_numlights = 0, dc_maxlights, dc_texheight;
INT32 ds_y, ds_x1, ds_x2;
lighttable_t *ds_colormap;
fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep;
UINT16 ds_flatwidth, ds_flatheight;
boolean ds_powersoftwo;
UINT8 *ds_source; // start of a 64*64 tile image
UINT8 *ds_transmap; // one of the translucency tables
@ -557,9 +559,16 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U
// White!
if (skinnum == TC_BOSS)
dest_colormap[31] = 0;
{
for (i = 0; i < 16; i++)
dest_colormap[31-i] = i;
}
else if (skinnum == TC_METALSONIC)
dest_colormap[159] = 0;
{
for (i = 0; i < 6; i++)
dest_colormap[Color_Index[SKINCOLOR_BLUE-1][12-i]] = Color_Index[SKINCOLOR_BLUE-1][i];
dest_colormap[159] = dest_colormap[253] = dest_colormap[254] = 0;
}
return;
}
else if (color == SKINCOLOR_NONE)

View file

@ -57,7 +57,9 @@ extern INT32 dc_texheight;
extern INT32 ds_y, ds_x1, ds_x2;
extern lighttable_t *ds_colormap;
extern fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep;
extern UINT8 *ds_source; // start of a 64*64 tile image
extern UINT16 ds_flatwidth, ds_flatheight;
extern boolean ds_powersoftwo;
extern UINT8 *ds_source;
extern UINT8 *ds_transmap;
#ifdef ESLOPE
@ -128,6 +130,8 @@ void R_FillBackScreen(void);
void R_DrawViewBorder(void);
#endif
#define TRANSPARENTPIXEL 255
// -----------------
// 8bpp DRAWING CODE
// -----------------
@ -169,6 +173,13 @@ void R_DrawFogSpan_8(void);
void R_DrawFogColumn_8(void);
void R_DrawColumnShadowed_8(void);
#ifndef NOWATER
void R_DrawTranslucentWaterSpan_8(void);
extern INT32 ds_bgofs;
extern INT32 ds_waterofs;
#endif
// ------------------
// 16bpp DRAWING CODE
// ------------------

File diff suppressed because it is too large Load diff

View file

@ -1215,6 +1215,7 @@ void R_RegisterEngineStuff(void)
#endif
CV_RegisterVar(&cv_grmd2);
CV_RegisterVar(&cv_grspritebillboarding);
CV_RegisterVar(&cv_grskydome);
#endif
#ifdef HWRENDER

View file

@ -127,91 +127,13 @@ void R_InitPlanes(void)
// viewheight
#ifndef NOWATER
static INT32 bgofs;
INT32 ds_bgofs;
INT32 ds_waterofs;
static INT32 wtofs=0;
static INT32 waterofs;
static boolean itswater;
#endif
#ifndef NOWATER
static void R_DrawTranslucentWaterSpan_8(void)
{
UINT32 xposition;
UINT32 yposition;
UINT32 xstep, ystep;
UINT8 *source;
UINT8 *colormap;
UINT8 *dest;
UINT8 *dsrc;
size_t count;
// SoM: we only need 6 bits for the integer part (0 thru 63) so the rest
// can be used for the fraction part. This allows calculation of the memory address in the
// texture with two shifts, an OR and one AND. (see below)
// for texture sizes > 64 the amount of precision we can allow will decrease, but only by one
// bit per power of two (obviously)
// Ok, because I was able to eliminate the variable spot below, this function is now FASTER
// than the original span renderer. Whodathunkit?
xposition = ds_xfrac << nflatshiftup; yposition = (ds_yfrac + waterofs) << nflatshiftup;
xstep = ds_xstep << nflatshiftup; ystep = ds_ystep << nflatshiftup;
source = ds_source;
colormap = ds_colormap;
dest = ylookup[ds_y] + columnofs[ds_x1];
dsrc = screens[1] + (ds_y+bgofs)*vid.width + ds_x1;
count = ds_x2 - ds_x1 + 1;
while (count >= 8)
{
// SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't
// have the uber complicated math to calculate it now, so that was a memory write we didn't
// need!
dest[0] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)];
xposition += xstep;
yposition += ystep;
dest[1] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)];
xposition += xstep;
yposition += ystep;
dest[2] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)];
xposition += xstep;
yposition += ystep;
dest[3] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)];
xposition += xstep;
yposition += ystep;
dest[4] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)];
xposition += xstep;
yposition += ystep;
dest[5] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)];
xposition += xstep;
yposition += ystep;
dest[6] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)];
xposition += xstep;
yposition += ystep;
dest[7] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)];
xposition += xstep;
yposition += ystep;
dest += 8;
count -= 8;
}
while (count--)
{
*dest++ = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)];
xposition += xstep;
yposition += ystep;
}
}
#endif
void R_MapPlane(INT32 y, INT32 x1, INT32 x2)
{
angle_t angle, planecos, planesin;
@ -258,17 +180,17 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2)
{
const INT32 yay = (wtofs + (distance>>9) ) & 8191;
// ripples da water texture
bgofs = FixedDiv(FINESINE(yay), (1<<12) + (distance>>11))>>FRACBITS;
ds_bgofs = FixedDiv(FINESINE(yay), (1<<12) + (distance>>11))>>FRACBITS;
angle = (currentplane->viewangle + currentplane->plangle + xtoviewangle[x1])>>ANGLETOFINESHIFT;
angle = (angle + 2048) & 8191; // 90 degrees
ds_xfrac += FixedMul(FINECOSINE(angle), (bgofs<<FRACBITS));
ds_yfrac += FixedMul(FINESINE(angle), (bgofs<<FRACBITS));
ds_xfrac += FixedMul(FINECOSINE(angle), (ds_bgofs<<FRACBITS));
ds_yfrac += FixedMul(FINESINE(angle), (ds_bgofs<<FRACBITS));
if (y+bgofs>=viewheight)
bgofs = viewheight-y-1;
if (y+bgofs<0)
bgofs = -y;
if (y+ds_bgofs>=viewheight)
ds_bgofs = viewheight-y-1;
if (y+ds_bgofs<0)
ds_bgofs = -y;
}
#endif
@ -680,7 +602,7 @@ void R_DrawPlanes(void)
}
}
#ifndef NOWATER
waterofs = (leveltime & 1)*16384;
ds_waterofs = (leveltime & 1)*16384;
wtofs = leveltime * 140;
#endif
}
@ -728,13 +650,162 @@ static void R_DrawSkyPlane(visplane_t *pl)
}
}
boolean R_CheckPowersOfTwo(void)
{
if (ds_flatwidth & (ds_flatwidth - 1))
ds_powersoftwo = false;
else if (ds_flatheight & (ds_flatheight - 1))
ds_powersoftwo = false;
else if (ds_flatwidth == ds_flatheight)
ds_powersoftwo = true;
return ds_powersoftwo;
}
void R_CheckFlatLength(size_t size)
{
switch (size)
{
case 4194304: // 2048x2048 lump
nflatmask = 0x3FF800;
nflatxshift = 21;
nflatyshift = 10;
nflatshiftup = 5;
ds_flatwidth = ds_flatheight = 2048;
break;
case 1048576: // 1024x1024 lump
nflatmask = 0xFFC00;
nflatxshift = 22;
nflatyshift = 12;
nflatshiftup = 6;
ds_flatwidth = ds_flatheight = 1024;
break;
case 262144:// 512x512 lump
nflatmask = 0x3FE00;
nflatxshift = 23;
nflatyshift = 14;
nflatshiftup = 7;
ds_flatwidth = ds_flatheight = 512;
break;
case 65536: // 256x256 lump
nflatmask = 0xFF00;
nflatxshift = 24;
nflatyshift = 16;
nflatshiftup = 8;
ds_flatwidth = ds_flatheight = 256;
break;
case 16384: // 128x128 lump
nflatmask = 0x3F80;
nflatxshift = 25;
nflatyshift = 18;
nflatshiftup = 9;
ds_flatwidth = ds_flatheight = 128;
break;
case 1024: // 32x32 lump
nflatmask = 0x3E0;
nflatxshift = 27;
nflatyshift = 22;
nflatshiftup = 11;
ds_flatwidth = ds_flatheight = 32;
break;
default: // 64x64 lump
nflatmask = 0xFC0;
nflatxshift = 26;
nflatyshift = 20;
nflatshiftup = 10;
ds_flatwidth = ds_flatheight = 64;
break;
}
}
static UINT8 *R_GetPatchFlat(levelflat_t *levelflat, boolean leveltexture, boolean ispng)
{
UINT8 *flat;
textureflat_t *texflat = &texflats[levelflat->texturenum];
patch_t *patch = NULL;
boolean texturechanged = (leveltexture ? (levelflat->texturenum != levelflat->lasttexturenum) : false);
// Check if the texture changed.
if (leveltexture && (!texturechanged))
{
if (texflat != NULL && texflat->flat)
{
flat = texflat->flat;
ds_flatwidth = texflat->width;
ds_flatheight = texflat->height;
texturechanged = false;
}
else
texturechanged = true;
}
// If the texture changed, or the patch doesn't exist, convert either of them to a flat.
if (levelflat->flatpatch == NULL || texturechanged)
{
if (leveltexture)
{
texture_t *texture = textures[levelflat->texturenum];
texflat->width = ds_flatwidth = texture->width;
texflat->height = ds_flatheight = texture->height;
texflat->flat = Z_Malloc(ds_flatwidth * ds_flatheight, PU_LEVEL, NULL);
memset(texflat->flat, TRANSPARENTPIXEL, ds_flatwidth * ds_flatheight);
R_TextureToFlat(levelflat->texturenum, texflat->flat);
flat = texflat->flat;
levelflat->flatpatch = flat;
levelflat->width = ds_flatwidth;
levelflat->height = ds_flatheight;
}
else
{
patch = (patch_t *)ds_source;
#ifndef NO_PNG_LUMPS
if (ispng)
{
levelflat->flatpatch = R_PNGToFlat(levelflat, ds_source, W_LumpLength(levelflat->lumpnum));
levelflat->topoffset = levelflat->leftoffset = 0;
ds_flatwidth = levelflat->width;
ds_flatheight = levelflat->height;
}
else
#endif
{
levelflat->width = ds_flatwidth = SHORT(patch->width);
levelflat->height = ds_flatheight = SHORT(patch->height);
levelflat->topoffset = patch->topoffset * FRACUNIT;
levelflat->leftoffset = patch->leftoffset * FRACUNIT;
levelflat->flatpatch = Z_Malloc(ds_flatwidth * ds_flatheight, PU_LEVEL, NULL);
memset(levelflat->flatpatch, TRANSPARENTPIXEL, ds_flatwidth * ds_flatheight);
R_PatchToFlat(patch, levelflat->flatpatch);
}
flat = levelflat->flatpatch;
}
}
else
{
flat = levelflat->flatpatch;
ds_flatwidth = levelflat->width;
ds_flatheight = levelflat->height;
xoffs += levelflat->leftoffset;
yoffs += levelflat->topoffset;
}
levelflat->lasttexturenum = levelflat->texturenum;
return flat;
}
void R_DrawSinglePlane(visplane_t *pl)
{
UINT8 *flat;
INT32 light = 0;
INT32 x;
INT32 stop, angle;
size_t size;
ffloor_t *rover;
levelflat_t *levelflat;
if (!(pl->minx <= pl->maxx))
return;
@ -874,64 +945,47 @@ void R_DrawSinglePlane(visplane_t *pl)
viewangle = pl->viewangle+pl->plangle;
}
currentplane = pl;
ds_source = (UINT8 *)
W_CacheLumpNum(levelflats[pl->picnum].lumpnum,
PU_STATIC); // Stay here until Z_ChangeTag
size = W_LumpLength(levelflats[pl->picnum].lumpnum);
switch (size)
{
case 4194304: // 2048x2048 lump
nflatmask = 0x3FF800;
nflatxshift = 21;
nflatyshift = 10;
nflatshiftup = 5;
break;
case 1048576: // 1024x1024 lump
nflatmask = 0xFFC00;
nflatxshift = 22;
nflatyshift = 12;
nflatshiftup = 6;
break;
case 262144:// 512x512 lump'
nflatmask = 0x3FE00;
nflatxshift = 23;
nflatyshift = 14;
nflatshiftup = 7;
break;
case 65536: // 256x256 lump
nflatmask = 0xFF00;
nflatxshift = 24;
nflatyshift = 16;
nflatshiftup = 8;
break;
case 16384: // 128x128 lump
nflatmask = 0x3F80;
nflatxshift = 25;
nflatyshift = 18;
nflatshiftup = 9;
break;
case 1024: // 32x32 lump
nflatmask = 0x3E0;
nflatxshift = 27;
nflatyshift = 22;
nflatshiftup = 11;
break;
default: // 64x64 lump
nflatmask = 0xFC0;
nflatxshift = 26;
nflatyshift = 20;
nflatshiftup = 10;
break;
}
xoffs = pl->xoffs;
yoffs = pl->yoffs;
planeheight = abs(pl->height - pl->viewz);
currentplane = pl;
levelflat = &levelflats[pl->picnum];
size = W_LumpLength(levelflat->lumpnum);
ds_source = (UINT8 *)W_CacheLumpNum(levelflat->lumpnum, PU_STATIC); // Stay here until Z_ChangeTag
// Check if the flat is actually a wall texture.
if (levelflat->texturenum != 0 && levelflat->texturenum != -1)
flat = R_GetPatchFlat(levelflat, true, false);
#ifndef NO_PNG_LUMPS
// Maybe it's a PNG?!
else if (R_IsLumpPNG(ds_source, size))
flat = R_GetPatchFlat(levelflat, false, true);
#endif
// Maybe it's just a patch, then?
else if (R_CheckIfPatch(levelflat->lumpnum))
flat = R_GetPatchFlat(levelflat, false, false);
// It's a raw flat.
else
{
R_CheckFlatLength(size);
flat = ds_source;
}
Z_ChangeTag(ds_source, PU_CACHE);
ds_source = flat;
if (ds_source == NULL)
return;
// Check if the flat has dimensions that are powers-of-two numbers.
if (R_CheckPowersOfTwo())
{
R_CheckFlatLength(ds_flatwidth * ds_flatheight);
if (spanfunc == basespanfunc)
spanfunc = mmxspanfunc;
}
if (light >= LIGHTLEVELS)
light = LIGHTLEVELS-1;
@ -945,60 +999,63 @@ void R_DrawSinglePlane(visplane_t *pl)
floatv3_t p, m, n;
float ang;
float vx, vy, vz;
float fudge = 0;
// 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
fixed_t temp;
// Okay, look, don't ask me why this works, but without this setup there's a disgusting-looking misalignment with the textures. -Red
const float fudge = ((1<<nflatshiftup)+1.0f)/(1<<nflatshiftup);
angle_t hack = (pl->plangle & (ANGLE_90-1));
yoffs *= 1;
if (hack)
if (ds_powersoftwo)
{
/*
Essentially: We can't & the components along the regular axes when the plane is rotated.
This is because the distance on each regular axis in order to loop is different.
We rotate them, & the components, add them together, & them again, and then rotate them back.
These three seperate & operations are done per axis in order to prevent overflows.
toast 10/04/17
*/
const fixed_t cosinecomponent = FINECOSINE(hack>>ANGLETOFINESHIFT);
const fixed_t sinecomponent = FINESINE(hack>>ANGLETOFINESHIFT);
// Okay, look, don't ask me why this works, but without this setup there's a disgusting-looking misalignment with the textures. -Red
fudge = ((1<<nflatshiftup)+1.0f)/(1<<nflatshiftup);
if (hack)
{
/*
Essentially: We can't & the components along the regular axes when the plane is rotated.
This is because the distance on each regular axis in order to loop is different.
We rotate them, & the components, add them together, & them again, and then rotate them back.
These three seperate & operations are done per axis in order to prevent overflows.
toast 10/04/17
*/
const fixed_t cosinecomponent = FINECOSINE(hack>>ANGLETOFINESHIFT);
const fixed_t sinecomponent = FINESINE(hack>>ANGLETOFINESHIFT);
const fixed_t modmask = ((1 << (32-nflatshiftup)) - 1);
const fixed_t modmask = ((1 << (32-nflatshiftup)) - 1);
fixed_t ox = (FixedMul(pl->slope->o.x,cosinecomponent) & modmask) - (FixedMul(pl->slope->o.y,sinecomponent) & modmask);
fixed_t oy = (-FixedMul(pl->slope->o.x,sinecomponent) & modmask) - (FixedMul(pl->slope->o.y,cosinecomponent) & modmask);
fixed_t ox = (FixedMul(pl->slope->o.x,cosinecomponent) & modmask) - (FixedMul(pl->slope->o.y,sinecomponent) & modmask);
fixed_t oy = (-FixedMul(pl->slope->o.x,sinecomponent) & modmask) - (FixedMul(pl->slope->o.y,cosinecomponent) & modmask);
temp = ox & modmask;
oy &= modmask;
ox = FixedMul(temp,cosinecomponent)+FixedMul(oy,-sinecomponent); // negative sine for opposite direction
oy = -FixedMul(temp,-sinecomponent)+FixedMul(oy,cosinecomponent);
temp = ox & modmask;
oy &= modmask;
ox = FixedMul(temp,cosinecomponent)+FixedMul(oy,-sinecomponent); // negative sine for opposite direction
oy = -FixedMul(temp,-sinecomponent)+FixedMul(oy,cosinecomponent);
temp = xoffs;
xoffs = (FixedMul(temp,cosinecomponent) & modmask) + (FixedMul(yoffs,sinecomponent) & modmask);
yoffs = (-FixedMul(temp,sinecomponent) & modmask) + (FixedMul(yoffs,cosinecomponent) & modmask);
temp = xoffs;
xoffs = (FixedMul(temp,cosinecomponent) & modmask) + (FixedMul(yoffs,sinecomponent) & modmask);
yoffs = (-FixedMul(temp,sinecomponent) & modmask) + (FixedMul(yoffs,cosinecomponent) & modmask);
temp = xoffs & modmask;
yoffs &= modmask;
xoffs = FixedMul(temp,cosinecomponent)+FixedMul(yoffs,-sinecomponent); // ditto
yoffs = -FixedMul(temp,-sinecomponent)+FixedMul(yoffs,cosinecomponent);
temp = xoffs & modmask;
yoffs &= modmask;
xoffs = FixedMul(temp,cosinecomponent)+FixedMul(yoffs,-sinecomponent); // ditto
yoffs = -FixedMul(temp,-sinecomponent)+FixedMul(yoffs,cosinecomponent);
xoffs -= (pl->slope->o.x - ox);
yoffs += (pl->slope->o.y + oy);
xoffs -= (pl->slope->o.x - ox);
yoffs += (pl->slope->o.y + oy);
}
else
{
xoffs &= ((1 << (32-nflatshiftup))-1);
yoffs &= ((1 << (32-nflatshiftup))-1);
xoffs -= (pl->slope->o.x + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1);
yoffs += (pl->slope->o.y + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1);
}
xoffs = (fixed_t)(xoffs*fudge);
yoffs = (fixed_t)(yoffs/fudge);
}
else
{
xoffs &= ((1 << (32-nflatshiftup))-1);
yoffs &= ((1 << (32-nflatshiftup))-1);
xoffs -= (pl->slope->o.x + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1);
yoffs += (pl->slope->o.y + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1);
}
xoffs = (fixed_t)(xoffs*fudge);
yoffs = (fixed_t)(yoffs/fudge);
vx = FIXED_TO_FLOAT(pl->viewx+xoffs);
vy = FIXED_TO_FLOAT(pl->viewy-yoffs);
@ -1033,13 +1090,16 @@ void R_DrawSinglePlane(visplane_t *pl)
temp = P_GetZAt(pl->slope, pl->viewx + FLOAT_TO_FIXED(cos(ang)), pl->viewy - FLOAT_TO_FIXED(sin(ang)));
n.y = FIXED_TO_FLOAT(temp) - zeroheight;
m.x /= fudge;
m.y /= fudge;
m.z /= fudge;
if (ds_powersoftwo)
{
m.x /= fudge;
m.y /= fudge;
m.z /= fudge;
n.x *= fudge;
n.y *= fudge;
n.z *= fudge;
n.x *= fudge;
n.y *= fudge;
n.z *= fudge;
}
// Eh. I tried making this stuff fixed-point and it exploded on me. Here's a macro for the only floating-point vector function I recall using.
#define CROSS(d, v1, v2) \
@ -1056,14 +1116,26 @@ void R_DrawSinglePlane(visplane_t *pl)
ds_sz.z *= focallengthf;
// Premultiply the texture vectors with the scale factors
if (ds_powersoftwo)
{
#define SFMULT 65536.f*(1<<nflatshiftup)
ds_su.x *= SFMULT;
ds_su.y *= SFMULT;
ds_su.z *= SFMULT;
ds_sv.x *= SFMULT;
ds_sv.y *= SFMULT;
ds_sv.z *= SFMULT;
ds_su.x *= SFMULT;
ds_su.y *= SFMULT;
ds_su.z *= SFMULT;
ds_sv.x *= SFMULT;
ds_sv.y *= SFMULT;
ds_sv.z *= SFMULT;
#undef SFMULT
}
else
{
ds_su.x *= 65536.f;
ds_su.y *= 65536.f;
ds_su.z *= 65536.f;
ds_sv.x *= 65536.f;
ds_sv.y *= 65536.f;
ds_sv.z *= 65536.f;
}
if (spanfunc == R_DrawTranslucentSpan_8)
spanfunc = R_DrawTiltedTranslucentSpan_8;
@ -1170,8 +1242,6 @@ using the palette colors.
}
}
#endif
Z_ChangeTag(ds_source, PU_CACHE);
}
void R_PlaneBounds(visplane_t *plane)

View file

@ -96,6 +96,8 @@ void R_PlaneBounds(visplane_t *plane);
// Draws a single visplane.
void R_DrawSinglePlane(visplane_t *pl);
void R_CheckFlatLength(size_t size);
boolean R_CheckPowersOfTwo(void);
typedef struct planemgr_s
{

View file

@ -108,7 +108,9 @@ consvar_t cv_closedcaptioning = {"closedcaptioning", "Off", CV_SAVE|CV_CALL, CV_
consvar_t cv_numChannels = {"snd_channels", "32", CV_SAVE|CV_CALL, CV_Unsigned, SetChannelsNum, 0, NULL, NULL, 0, 0, NULL};
static consvar_t surround = {"surround", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_resetmusic = {"resetmusic", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_resetmusic = {"resetmusic", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_resetmusicbyheader = {"resetmusicbyheader", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
// Sound system toggles, saved into the config
consvar_t cv_gamedigimusic = {"digimusic", "On", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, GameDigiMusic_OnChange, 0, NULL, NULL, 0, 0, NULL};
@ -275,6 +277,7 @@ void S_RegisterSoundStuff(void)
CV_RegisterVar(&surround);
CV_RegisterVar(&cv_samplerate);
CV_RegisterVar(&cv_resetmusic);
CV_RegisterVar(&cv_resetmusicbyheader);
CV_RegisterVar(&cv_gamesounds);
CV_RegisterVar(&cv_gamedigimusic);
CV_RegisterVar(&cv_gamemidimusic);
@ -2096,7 +2099,7 @@ void S_StartEx(boolean reset)
mapmusposition = mapheaderinfo[gamemap-1]->muspos;
}
if (cv_resetmusic.value || reset)
if (RESETMUSIC || reset)
S_StopMusic();
S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0);

View file

@ -31,7 +31,16 @@ openmpt_module *openmpt_mhandle;
extern consvar_t stereoreverse;
extern consvar_t cv_soundvolume, cv_closedcaptioning, cv_digmusicvolume, cv_midimusicvolume;
extern consvar_t cv_numChannels;
extern consvar_t cv_resetmusic;
extern consvar_t cv_resetmusicbyheader;
#define RESETMUSIC (!modeattacking && \
(cv_resetmusicbyheader.value ? \
(mapheaderinfo[gamemap-1]->musforcereset != -1 ? mapheaderinfo[gamemap-1]->musforcereset : cv_resetmusic.value) \
: cv_resetmusic.value) \
)
extern consvar_t cv_gamedigimusic;
extern consvar_t cv_gamemidimusic;
extern consvar_t cv_gamesounds;

View file

@ -49,6 +49,7 @@ void (*fuzzcolfunc)(void); // standard fuzzy effect column drawer
void (*transcolfunc)(void); // translation column drawer
void (*shadecolfunc)(void); // smokie test..
void (*spanfunc)(void); // span drawer, use a 64x64 tile
void (*mmxspanfunc)(void); // span drawer in MMX assembly
void (*splatfunc)(void); // span drawer w/ transparency
void (*basespanfunc)(void); // default span func for color mode
void (*transtransfunc)(void); // translucent translated column drawer
@ -112,7 +113,7 @@ void SCR_SetMode(void)
//
if (true)//vid.bpp == 1) //Always run in 8bpp. todo: remove all 16bpp code?
{
spanfunc = basespanfunc = R_DrawSpan_8;
spanfunc = basespanfunc = mmxspanfunc = R_DrawSpan_8;
splatfunc = R_DrawSplat_8;
transcolfunc = R_DrawTranslatedColumn_8;
transtransfunc = R_DrawTranslatedTranslucentColumn_8;
@ -133,7 +134,7 @@ void SCR_SetMode(void)
//fuzzcolfunc = R_DrawTranslucentColumn_8_ASM;
walldrawerfunc = R_DrawWallColumn_8_MMX;
twosmultipatchfunc = R_Draw2sMultiPatchColumn_8_MMX;
spanfunc = basespanfunc = R_DrawSpan_8_MMX;
mmxspanfunc = R_DrawSpan_8_MMX;
}
else
{

View file

@ -123,6 +123,7 @@ extern void (*transcolfunc)(void);
extern void (*shadecolfunc)(void);
extern void (*spanfunc)(void);
extern void (*basespanfunc)(void);
extern void (*mmxspanfunc)(void);
extern void (*splatfunc)(void);
extern void (*transtransfunc)(void);
extern void (*twosmultipatchfunc)(void);

View file

@ -79,6 +79,7 @@ void *hwSym(const char *funcName,void *handle)
GETFUNC(Init);
GETFUNC(Draw2DLine);
GETFUNC(DrawPolygon);
GETFUNC(RenderSkyDome);
GETFUNC(SetBlend);
GETFUNC(ClearBuffer);
GETFUNC(SetTexture);

View file

@ -530,7 +530,7 @@ static void Impl_HandleKeyboardConsoleEvent(KEY_EVENT_RECORD evt, HANDLE co)
break;
case VK_RETURN:
entering_con_command = false;
// Fall through.
/* FALLTHRU */
default:
event.data1 = MapVirtualKey(evt.wVirtualKeyCode,2); // convert in to char
}

View file

@ -1499,6 +1499,7 @@ void I_StartupGraphics(void)
HWD.pfnFinishUpdate = NULL;
HWD.pfnDraw2DLine = hwSym("Draw2DLine",NULL);
HWD.pfnDrawPolygon = hwSym("DrawPolygon",NULL);
HWD.pfnRenderSkyDome = hwSym("RenderSkyDome",NULL);
HWD.pfnSetBlend = hwSym("SetBlend",NULL);
HWD.pfnClearBuffer = hwSym("ClearBuffer",NULL);
HWD.pfnSetTexture = hwSym("SetTexture",NULL);

View file

@ -112,6 +112,7 @@ static CV_PossibleValue_t CV_MD2[] = {{0, "Off"}, {1, "On"}, {2, "Old"}, {0, NUL
// console variables in development
consvar_t cv_grmd2 = {"gr_md2", "Off", CV_SAVE, CV_MD2, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_grspritebillboarding = {"gr_spritebillboarding", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_grskydome = {"gr_skydome", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
#endif
// local copy of the palette for V_GetColor()

View file

@ -1182,8 +1182,6 @@ void zerr(int ret)
}
#endif
#define NO_PNG_LUMPS
#ifdef NO_PNG_LUMPS
static void ErrorIfPNG(UINT8 *d, size_t s, char *f, char *l)
{

View file

@ -102,6 +102,7 @@ static loadfunc_t hwdFuncTable[] = {
{"FinishUpdate@4", &hwdriver.pfnFinishUpdate},
{"Draw2DLine@12", &hwdriver.pfnDraw2DLine},
{"DrawPolygon@16", &hwdriver.pfnDrawPolygon},
{"RenderSkyDome@16", &hwdriver.pfnRenderDome},
{"SetBlend@4", &hwdriver.pfnSetBlend},
{"ClearBuffer@12", &hwdriver.pfnClearBuffer},
{"SetTexture@4", &hwdriver.pfnSetTexture},
@ -133,6 +134,7 @@ static loadfunc_t hwdFuncTable[] = {
{"FinishUpdate", &hwdriver.pfnFinishUpdate},
{"Draw2DLine", &hwdriver.pfnDraw2DLine},
{"DrawPolygon", &hwdriver.pfnDrawPolygon},
{"RenderSkyDome", &hwdriver.pfnRenderDome},
{"SetBlend", &hwdriver.pfnSetBlend},
{"ClearBuffer", &hwdriver.pfnClearBuffer},
{"SetTexture", &hwdriver.pfnSetTexture},

View file

@ -327,7 +327,7 @@ static inline VOID I_GetConsoleEvents(VOID)
break;
case VK_RETURN:
entering_con_command = false;
// Fall through.
/* FALLTHRU */
default:
ev.data1 = MapVirtualKey(input.Event.KeyEvent.wVirtualKeyCode,2); // convert in to char
}

View file

@ -322,9 +322,9 @@ static inline boolean I_SkipFrame(void)
case GS_LEVEL:
if (!paused)
return false;
/* FALLTHRU */
//case GS_TIMEATTACK: -- sorry optimisation but now we have a cool level platter and that being laggardly looks terrible
#ifndef CLIENT_LOADINGSCREEN
/* FALLTHRU */
case GS_WAITINGPLAYERS:
#endif
return skip; // Skip odd frames