Merge remote-tracking branch 'origin/next' into more-cleanup

This commit is contained in:
James R 2020-01-11 15:07:23 -08:00
commit 5ec326972c
30 changed files with 893 additions and 522 deletions

View file

@ -3430,6 +3430,8 @@ static void readextraemblemdata(MYFILE *f, INT32 num)
sizeof (extraemblems[num-1].description), va("Extra emblem %d: objective", num));
else if (fastcmp(word, "CONDITIONSET"))
extraemblems[num-1].conditionset = (UINT8)value;
else if (fastcmp(word, "SHOWCONDITIONSET"))
extraemblems[num-1].showconditionset = (UINT8)value;
else
{
strupr(word2);
@ -3516,6 +3518,8 @@ static void readunlockable(MYFILE *f, INT32 num)
unlockables[num].height = (UINT16)i;
else if (fastcmp(word, "CONDITIONSET"))
unlockables[num].conditionset = (UINT8)i;
else if (fastcmp(word, "SHOWCONDITIONSET"))
unlockables[num].showconditionset = (UINT8)i;
else if (fastcmp(word, "NOCECHO"))
unlockables[num].nocecho = (UINT8)(i || word2[0] == 'T' || word2[0] == 'Y');
else if (fastcmp(word, "NOCHECKLIST"))
@ -8669,6 +8673,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_NIGHTSCHIP", // NiGHTS Chip
"MT_FLINGNIGHTSCHIP", // Lost NiGHTS Chip
"MT_NIGHTSSTAR", // NiGHTS Star
"MT_FLINGNIGHTSSTAR", // Lost NiGHTS Star
"MT_NIGHTSSUPERLOOP",
"MT_NIGHTSDRILLREFILL",
"MT_NIGHTSHELPER",

View file

@ -72,6 +72,7 @@
#include "../v_video.h"
#include "hw_clip.h"
#include "hw_glob.h"
#include "../r_main.h"
#include "../r_state.h"
#include "../tables.h"
#include "r_opengl/r_opengl.h"
@ -328,7 +329,7 @@ angle_t gld_FrustumAngle(void)
// NEWCLIP TODO: SRB2CBTODO: make a global render_fov for this function
float render_fov = FIXED_TO_FLOAT(cv_grfov.value);
float render_fov = FIXED_TO_FLOAT(cv_fov.value);
float render_fovratio = (float)BASEVIDWIDTH / (float)BASEVIDHEIGHT; // SRB2CBTODO: NEWCLIPTODO: Is this right?
float render_multiplier = 64.0f / render_fovratio / RMUL;

View file

@ -1026,6 +1026,34 @@ static float HWR_ClipViewSegment(INT32 x, polyvertex_t *v1, polyvertex_t *v2)
}
#endif
static FUINT HWR_CalcWallLight(FUINT lightnum, fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t v2y)
{
INT16 finallight = lightnum;
if (cv_grfakecontrast.value != 0)
{
const UINT8 contrast = 8;
fixed_t extralight = 0;
if (v1y == v2y)
extralight = -contrast;
else if (v1x == v2x)
extralight = contrast;
if (extralight != 0)
{
finallight += extralight;
if (finallight < 0)
finallight = 0;
if (finallight > 255)
finallight = 255;
}
}
return (FUINT)finallight;
}
//
// HWR_SplitWall
//
@ -1044,19 +1072,20 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum,
float endpegt, endpegb, endpegmul;
float endheight = 0.0f, endbheight = 0.0f;
fixed_t v1x = FLOAT_TO_FIXED(wallVerts[0].x);
fixed_t v1y = FLOAT_TO_FIXED(wallVerts[0].z); // not a typo
fixed_t v2x = FLOAT_TO_FIXED(wallVerts[1].x);
fixed_t v2y = FLOAT_TO_FIXED(wallVerts[1].z); // not a typo
// 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;
#endif
INT32 solid, i;
fixed_t v1x = FLOAT_TO_FIXED(wallVerts[0].x);
fixed_t v1y = FLOAT_TO_FIXED(wallVerts[0].z); // not a typo
fixed_t v2x = FLOAT_TO_FIXED(wallVerts[1].x);
fixed_t v2y = FLOAT_TO_FIXED(wallVerts[1].z); // not a typo
INT32 solid, i;
lightlist_t * list = sector->lightlist;
const UINT8 alpha = Surf->FlatColor.s.alpha;
FUINT lightnum = sector->lightlevel;
FUINT lightnum = HWR_CalcWallLight(sector->lightlevel, v1x, v1y, v2x, v2y);
extracolormap_t *colormap = NULL;
realtop = top = wallVerts[3].y;
@ -1086,12 +1115,12 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum,
{
if (pfloor && (pfloor->flags & FF_FOG))
{
lightnum = pfloor->master->frontsector->lightlevel;
lightnum = HWR_CalcWallLight(pfloor->master->frontsector->lightlevel, v1x, v1y, v2x, v2y);
colormap = pfloor->master->frontsector->extra_colormap;
}
else
{
lightnum = *list[i].lightlevel;
lightnum = HWR_CalcWallLight(*list[i].lightlevel, v1x, v1y, v2x, v2y);
colormap = *list[i].extra_colormap;
}
}
@ -1395,7 +1424,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
cliphigh = (float)(texturehpeg + (gr_curline->flength*FRACUNIT));
}
lightnum = gr_frontsector->lightlevel;
lightnum = HWR_CalcWallLight(gr_frontsector->lightlevel, vs.x, vs.y, ve.x, ve.y);
colormap = gr_frontsector->extra_colormap;
if (gr_frontsector)
@ -2150,7 +2179,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
blendmode = PF_Fog|PF_NoTexture;
lightnum = rover->master->frontsector->lightlevel;
lightnum = HWR_CalcWallLight(rover->master->frontsector->lightlevel, vs.x, vs.y, ve.x, ve.y);
colormap = rover->master->frontsector->extra_colormap;
if (rover->master->frontsector->extra_colormap)
@ -2270,7 +2299,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
blendmode = PF_Fog|PF_NoTexture;
lightnum = rover->master->frontsector->lightlevel;
lightnum = HWR_CalcWallLight(rover->master->frontsector->lightlevel, vs.x, vs.y, ve.x, ve.y);
colormap = rover->master->frontsector->extra_colormap;
if (rover->master->frontsector->extra_colormap)
@ -5118,7 +5147,12 @@ void HWR_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boo
planeinfo[numplanes].isceiling = isceiling;
planeinfo[numplanes].fixedheight = fixedheight;
planeinfo[numplanes].lightlevel = lightlevel;
if (planecolormap && (planecolormap->fog & 1))
planeinfo[numplanes].lightlevel = lightlevel;
else
planeinfo[numplanes].lightlevel = 255;
planeinfo[numplanes].levelflat = levelflat;
planeinfo[numplanes].xsub = xsub;
planeinfo[numplanes].alpha = alpha;
@ -5150,7 +5184,12 @@ void HWR_AddTransparentPolyobjectFloor(levelflat_t *levelflat, polyobj_t *polyse
polyplaneinfo[numpolyplanes].isceiling = isceiling;
polyplaneinfo[numpolyplanes].fixedheight = fixedheight;
polyplaneinfo[numpolyplanes].lightlevel = lightlevel;
if (planecolormap && (planecolormap->fog & 1))
polyplaneinfo[numpolyplanes].lightlevel = lightlevel;
else
polyplaneinfo[numpolyplanes].lightlevel = 255;
polyplaneinfo[numpolyplanes].levelflat = levelflat;
polyplaneinfo[numpolyplanes].polysector = polysector;
polyplaneinfo[numpolyplanes].alpha = alpha;
@ -5491,9 +5530,10 @@ static void HWR_ProjectSprite(mobj_t *thing)
spritedef_t *sprdef;
spriteframe_t *sprframe;
spriteinfo_t *sprinfo;
md2_t *md2;
size_t lumpoff;
unsigned rot;
UINT8 flip;
UINT16 flip;
boolean vflip = (!(thing->eflags & MFE_VERTICALFLIP) != !(thing->frame & FF_VERTICALFLIP));
angle_t ang;
@ -5522,8 +5562,21 @@ static void HWR_ProjectSprite(mobj_t *thing)
tz = (tr_x * gr_viewcos) + (tr_y * gr_viewsin);
// thing is behind view plane?
if (tz < ZCLIP_PLANE && !papersprite && (!cv_grmodels.value || md2_models[thing->sprite].notfound == true)) //Yellow: Only MD2's dont disappear
return;
if (tz < ZCLIP_PLANE && !papersprite)
{
if (cv_grmodels.value) //Yellow: Only MD2's dont disappear
{
if (thing->skin && thing->sprite == SPR_PLAY)
md2 = &md2_playermodels[( (skin_t *)thing->skin - skins )];
else
md2 = &md2_models[thing->sprite];
if (md2->notfound || md2->scale < 0.0f)
return;
}
else
return;
}
// The above can stay as it works for cutting sprites that are too close
tr_x = FIXED_TO_FLOAT(thing->x);
@ -5579,12 +5632,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
flip = sprframe->flip; // Will only be 0x00 or 0xFF
if (papersprite && ang < ANGLE_180)
{
if (flip)
flip = 0;
else
flip = 255;
}
flip ^= 0xFFFF;
}
else
{
@ -5593,6 +5641,11 @@ static void HWR_ProjectSprite(mobj_t *thing)
rot = 6; // F7 slot
else if ((sprframe->rotate & SRF_LEFT) && (ang >= ANGLE_180)) // See from left
rot = 2; // F3 slot
else if (sprframe->rotate & SRF_3DGE) // 16-angle mode
{
rot = (ang+ANGLE_180+ANGLE_11hh)>>28;
rot = ((rot & 1)<<3)|(rot>>1);
}
else // Normal behaviour
rot = (ang+ANGLE_202h)>>29;
@ -5601,12 +5654,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
flip = sprframe->flip & (1<<rot);
if (papersprite && ang < ANGLE_180)
{
if (flip)
flip = 0;
else
flip = 1<<rot;
}
flip ^= (1<<rot);
}
if (thing->skin && ((skin_t *)thing->skin)->flags & SF_HIRES)
@ -5621,7 +5669,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
if (thing->rollangle)
{
rollangle = R_GetRollAngle(thing->rollangle);
if (!sprframe->rotsprite.cached[rot])
if (!(sprframe->rotsprite.cached & (1<<rot)))
R_CacheRotSprite(thing->sprite, (thing->frame & FF_FRAMEMASK), sprinfo, sprframe, rot, flip);
rotsprite = sprframe->rotsprite.patch[rot][rollangle];
if (rotsprite != NULL)
@ -5896,7 +5944,7 @@ static void HWR_DrawSkyBackground(player_t *player)
if (cv_grskydome.value)
{
FTransform dometransform;
const float fpov = FIXED_TO_FLOAT(cv_grfov.value+player->fovadd);
const float fpov = FIXED_TO_FLOAT(cv_fov.value+player->fovadd);
postimg_t *type;
if (splitscreen && player == &players[secondarydisplayplayer])
@ -6074,7 +6122,7 @@ void HWR_SetViewSize(void)
// ==========================================================================
void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player)
{
const float fpov = FIXED_TO_FLOAT(cv_grfov.value+player->fovadd);
const float fpov = FIXED_TO_FLOAT(cv_fov.value+player->fovadd);
postimg_t *type;
if (splitscreen && player == &players[secondarydisplayplayer])
@ -6200,7 +6248,7 @@ if (0)
viewangle = localaiming2;
// Handle stuff when you are looking farther up or down.
if ((aimingangle || cv_grfov.value+player->fovadd > 90*FRACUNIT))
if ((aimingangle || cv_fov.value+player->fovadd > 90*FRACUNIT))
{
dup_viewangle += ANGLE_90;
HWR_ClearClipSegs();
@ -6278,7 +6326,7 @@ if (0)
// ==========================================================================
void HWR_RenderPlayerView(INT32 viewnumber, player_t *player)
{
const float fpov = FIXED_TO_FLOAT(cv_grfov.value+player->fovadd);
const float fpov = FIXED_TO_FLOAT(cv_fov.value+player->fovadd);
postimg_t *type;
const boolean skybox = (skyboxmo[0] && cv_skybox.value); // True if there's a skybox object and skyboxes are on
@ -6420,7 +6468,7 @@ if (0)
viewangle = localaiming2;
// Handle stuff when you are looking farther up or down.
if ((aimingangle || cv_grfov.value+player->fovadd > 90*FRACUNIT))
if ((aimingangle || cv_fov.value+player->fovadd > 90*FRACUNIT))
{
dup_viewangle += ANGLE_90;
HWR_ClearClipSegs();
@ -6549,9 +6597,7 @@ static void CV_grmodellighting_OnChange(void);
static void CV_grfiltermode_OnChange(void);
static void CV_granisotropic_OnChange(void);
static void CV_grfogdensity_OnChange(void);
static void CV_grfov_OnChange(void);
static CV_PossibleValue_t grfov_cons_t[] = {{0, "MIN"}, {179*FRACUNIT, "MAX"}, {0, NULL}};
static CV_PossibleValue_t grfiltermode_cons_t[]= {{HWD_SET_TEXTUREFILTER_POINTSAMPLED, "Nearest"},
{HWD_SET_TEXTUREFILTER_BILINEAR, "Bilinear"}, {HWD_SET_TEXTUREFILTER_TRILINEAR, "Trilinear"},
{HWD_SET_TEXTUREFILTER_MIXED1, "Linear_Nearest"},
@ -6560,7 +6606,7 @@ static CV_PossibleValue_t grfiltermode_cons_t[]= {{HWD_SET_TEXTUREFILTER_POINTSA
{0, NULL}};
CV_PossibleValue_t granisotropicmode_cons_t[] = {{1, "MIN"}, {16, "MAX"}, {0, NULL}};
consvar_t cv_grfovchange = {"gr_fovchange", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_fovchange = {"gr_fovchange", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_grfog = {"gr_fog", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_grfogcolor = {"gr_fogcolor", "AAAAAA", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_grsoftwarefog = {"gr_softwarefog", "Off", CV_SAVE, grsoftwarefog_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
@ -6578,9 +6624,9 @@ consvar_t cv_grmodellighting = {"gr_modellighting", "Off", CV_SAVE|CV_CALL, CV_O
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};
consvar_t cv_grfakecontrast = {"gr_fakecontrast", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_grrounddown = {"gr_rounddown", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_grfov = {"gr_fov", "90", CV_FLOAT|CV_CALL, grfov_cons_t, CV_grfov_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_grfogdensity = {"gr_fogdensity", "150", CV_CALL|CV_NOINIT, CV_Unsigned,
CV_grfogdensity_OnChange, 0, NULL, NULL, 0, 0, NULL};
@ -6616,17 +6662,10 @@ static void CV_granisotropic_OnChange(void)
HWD.pfnSetSpecialState(HWD_SET_TEXTUREANISOTROPICMODE, cv_granisotropicmode.value);
}
static void CV_grfov_OnChange(void)
{
if ((netgame || multiplayer) && !cv_debug && cv_grfov.value != 90*FRACUNIT)
CV_Set(&cv_grfov, cv_grfov.defaultvalue);
}
//added by Hurdler: console varibale that are saved
void HWR_AddCommands(void)
{
CV_RegisterVar(&cv_grfovchange);
CV_RegisterVar(&cv_grfov);
CV_RegisterVar(&cv_fovchange);
CV_RegisterVar(&cv_grfogdensity);
CV_RegisterVar(&cv_grfogcolor);
@ -6646,6 +6685,7 @@ void HWR_AddCommands(void)
CV_RegisterVar(&cv_grskydome);
CV_RegisterVar(&cv_grspritebillboarding);
CV_RegisterVar(&cv_grfakecontrast);
CV_RegisterVar(&cv_grfiltermode);
CV_RegisterVar(&cv_grrounddown);

View file

@ -84,7 +84,6 @@ extern consvar_t cv_grstaticlighting;
extern consvar_t cv_grcoronas;
extern consvar_t cv_grcoronasize;
#endif
extern consvar_t cv_grfov;
extern consvar_t cv_grmodels;
extern consvar_t cv_grmodelinterpolation;
extern consvar_t cv_grmodellighting;
@ -95,10 +94,11 @@ extern consvar_t cv_grsoftwarefog;
extern consvar_t cv_grfiltermode;
extern consvar_t cv_granisotropicmode;
extern consvar_t cv_grcorrecttricks;
extern consvar_t cv_grfovchange;
extern consvar_t cv_fovchange;
extern consvar_t cv_grsolvetjoin;
extern consvar_t cv_grspritebillboarding;
extern consvar_t cv_grskydome;
extern consvar_t cv_grfakecontrast;
extern float gr_viewwidth, gr_viewheight, gr_baseviewwindowy;

View file

@ -654,10 +654,14 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch,
UINT16 w = gpatch->width, h = gpatch->height;
UINT32 size = w*h;
RGBA_t *image, *blendimage, *cur, blendcolor;
UINT8 translation[16]; // First the color index
UINT8 cutoff[16]; // Brightness cutoff before using the next color
UINT8 translen = 0;
UINT8 i;
// vanilla port
UINT8 translation[16];
blendcolor = V_GetColor(0); // initialize
memset(translation, 0, sizeof(translation));
memset(cutoff, 0, sizeof(cutoff));
if (grmip->width == 0)
{
@ -681,17 +685,46 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch,
image = gpatch->mipmap->grInfo.data;
blendimage = blendgpatch->mipmap->grInfo.data;
blendcolor = V_GetColor(0); // initialize
// TC_METALSONIC includes an actual skincolor translation, on top of its flashing.
if (skinnum == TC_METALSONIC)
color = SKINCOLOR_COBALT;
if (color != SKINCOLOR_NONE)
memcpy(&translation, &Color_Index[color - 1], 16);
{
UINT8 numdupes = 1;
translation[translen] = Color_Index[color-1][0];
cutoff[translen] = 255;
for (i = 1; i < 16; i++)
{
if (translation[translen] == Color_Index[color-1][i])
{
numdupes++;
continue;
}
if (translen > 0)
{
cutoff[translen] = cutoff[translen-1] - (256 / (16 / numdupes));
}
numdupes = 1;
translen++;
translation[translen] = (UINT8)Color_Index[color-1][i];
}
translen++;
}
while (size--)
{
if (skinnum == TC_BOSS)
{
// Turn everything below a certain threshold white
if ((image->s.red == image->s.green) && (image->s.green == image->s.blue) && image->s.blue <= 82)
if ((image->s.red == image->s.green) && (image->s.green == image->s.blue) && image->s.blue < 127)
{
// Lactozilla: Invert the colors
cur->s.red = cur->s.green = cur->s.blue = (255 - image->s.blue);
@ -705,53 +738,6 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch,
cur->s.alpha = image->s.alpha;
}
else if (skinnum == TC_METALSONIC)
{
// Turn everything below a certain blue threshold white
if (image->s.red == 0 && image->s.green == 0 && image->s.blue <= 82)
{
cur->s.red = cur->s.green = cur->s.blue = 255;
}
else
{
cur->s.red = image->s.red;
cur->s.green = image->s.green;
cur->s.blue = image->s.blue;
}
cur->s.alpha = image->s.alpha;
}
else if (skinnum == TC_DASHMODE)
{
if (image->s.alpha == 0 && blendimage->s.alpha == 0)
{
// Don't bother with blending the pixel if the alpha of the blend pixel is 0
cur->rgba = image->rgba;
}
else
{
UINT8 ialpha = 255 - blendimage->s.alpha, balpha = blendimage->s.alpha;
RGBA_t icolor = *image, bcolor;
memset(&bcolor, 0x00, sizeof(RGBA_t));
if (blendimage->s.alpha)
{
bcolor.s.blue = 0;
bcolor.s.red = 255;
bcolor.s.green = (blendimage->s.red + blendimage->s.green + blendimage->s.blue) / 3;
}
if (image->s.alpha && image->s.red > image->s.green << 1) // this is pretty arbitrary, but it works well for Metal Sonic
{
icolor.s.red = image->s.blue;
icolor.s.blue = image->s.red;
}
cur->s.red = (ialpha * icolor.s.red + balpha * bcolor.s.red)/255;
cur->s.green = (ialpha * icolor.s.green + balpha * bcolor.s.green)/255;
cur->s.blue = (ialpha * icolor.s.blue + balpha * bcolor.s.blue)/255;
cur->s.alpha = image->s.alpha;
}
}
else if (skinnum == TC_ALLWHITE)
{
// Turn everything white
@ -760,185 +746,268 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch,
}
else
{
UINT16 brightness;
// Everything below requires a blend image
if (blendimage == NULL)
{
cur->rgba = image->rgba;
goto skippixel;
}
// Don't bother with blending the pixel if the alpha of the blend pixel is 0
if (skinnum == TC_RAINBOW)
// Metal Sonic dash mode
if (skinnum == TC_DASHMODE)
{
if (image->s.alpha == 0 && blendimage->s.alpha == 0)
{
// Don't bother with blending the pixel if the alpha of the blend pixel is 0
cur->rgba = image->rgba;
cur++; image++; blendimage++;
continue;
}
else
{
UINT16 imagebright, blendbright;
SETBRIGHTNESS(imagebright,image->s.red,image->s.green,image->s.blue);
SETBRIGHTNESS(blendbright,blendimage->s.red,blendimage->s.green,blendimage->s.blue);
// slightly dumb average between the blend image color and base image colour, usually one or the other will be fully opaque anyway
brightness = (imagebright*(255-blendimage->s.alpha))/255 + (blendbright*blendimage->s.alpha)/255;
UINT8 ialpha = 255 - blendimage->s.alpha, balpha = blendimage->s.alpha;
RGBA_t icolor = *image, bcolor;
memset(&bcolor, 0x00, sizeof(RGBA_t));
if (blendimage->s.alpha)
{
bcolor.s.blue = 0;
bcolor.s.red = 255;
bcolor.s.green = (blendimage->s.red + blendimage->s.green + blendimage->s.blue) / 3;
}
if (image->s.alpha && image->s.red > image->s.green << 1) // this is pretty arbitrary, but it works well for Metal Sonic
{
icolor.s.red = image->s.blue;
icolor.s.blue = image->s.red;
}
cur->s.red = (ialpha * icolor.s.red + balpha * bcolor.s.red)/255;
cur->s.green = (ialpha * icolor.s.green + balpha * bcolor.s.green)/255;
cur->s.blue = (ialpha * icolor.s.blue + balpha * bcolor.s.blue)/255;
cur->s.alpha = image->s.alpha;
}
}
else
{
if (blendimage->s.alpha == 0)
// All settings that use skincolors!
UINT16 brightness;
if (translen <= 0)
{
cur->rgba = image->rgba;
cur++; image++; blendimage++;
continue;
goto skippixel;
}
else
{
SETBRIGHTNESS(brightness,blendimage->s.red,blendimage->s.green,blendimage->s.blue);
}
}
// Calculate a sort of "gradient" for the skincolor
// (Me splitting this into a function didn't work, so I had to ruin this entire function's groove...)
{
RGBA_t nextcolor;
UINT8 firsti, secondi, mul;
UINT32 r, g, b;
// Rainbow needs to find the closest match to the textures themselves, instead of matching brightnesses to other colors.
// Ensue horrible mess.
// Don't bother with blending the pixel if the alpha of the blend pixel is 0
if (skinnum == TC_RAINBOW)
{
UINT16 brightdif = 256;
UINT8 colorbrightnesses[16];
INT32 compare, m, d;
UINT8 i;
// Ignore pure white & pitch black
if (brightness > 253 || brightness < 2)
if (image->s.alpha == 0 && blendimage->s.alpha == 0)
{
cur->rgba = image->rgba;
cur++; image++; blendimage++;
continue;
}
firsti = 0;
mul = 0;
for (i = 0; i < 16; i++)
{
RGBA_t tempc = V_GetColor(translation[i]);
SETBRIGHTNESS(colorbrightnesses[i], tempc.s.red, tempc.s.green, tempc.s.blue); // store brightnesses for comparison
}
for (i = 0; i < 16; i++)
{
if (brightness > colorbrightnesses[i]) // don't allow greater matches (because calculating a makeshift gradient for this is already a huge mess as is)
continue;
compare = abs((INT16)(colorbrightnesses[i]) - (INT16)(brightness));
if (compare < brightdif)
{
brightdif = (UINT16)compare;
firsti = i; // best matching color that's equal brightness or darker
}
}
secondi = firsti+1; // next color in line
if (secondi == 16)
{
m = (INT16)brightness; // - 0;
d = (INT16)colorbrightnesses[firsti]; // - 0;
goto skippixel;
}
else
{
m = (INT16)brightness - (INT16)colorbrightnesses[secondi];
d = (INT16)colorbrightnesses[firsti] - (INT16)colorbrightnesses[secondi];
UINT16 imagebright, blendbright;
SETBRIGHTNESS(imagebright,image->s.red,image->s.green,image->s.blue);
SETBRIGHTNESS(blendbright,blendimage->s.red,blendimage->s.green,blendimage->s.blue);
// slightly dumb average between the blend image color and base image colour, usually one or the other will be fully opaque anyway
brightness = (imagebright*(255-blendimage->s.alpha))/255 + (blendbright*blendimage->s.alpha)/255;
}
if (m >= d)
m = d-1;
// calculate the "gradient" multiplier based on how close this color is to the one next in line
if (m <= 0 || d <= 0)
mul = 0;
else
mul = 15 - ((m * 16) / d);
}
else
{
// Thankfully, it's normally way more simple.
// Just convert brightness to a skincolor value, use remainder to find the gradient multipler
firsti = ((UINT8)(255-brightness) / 16);
secondi = firsti+1;
mul = ((UINT8)(255-brightness) % 16);
}
blendcolor = V_GetColor(translation[firsti]);
if (mul > 0 // If it's 0, then we only need the first color.
&& translation[firsti] != translation[secondi]) // Some colors have duplicate colors in a row, so let's just save the process
{
if (secondi == 16) // blend to black
nextcolor = V_GetColor(31);
if (blendimage->s.alpha == 0)
{
cur->rgba = image->rgba;
goto skippixel; // for metal sonic blend
}
else
nextcolor = V_GetColor(translation[secondi]);
// Find difference between points
r = (UINT32)(nextcolor.s.red - blendcolor.s.red);
g = (UINT32)(nextcolor.s.green - blendcolor.s.green);
b = (UINT32)(nextcolor.s.blue - blendcolor.s.blue);
// Find the gradient of the two points
r = ((mul * r) / 16);
g = ((mul * g) / 16);
b = ((mul * b) / 16);
// Add gradient value to color
blendcolor.s.red += r;
blendcolor.s.green += g;
blendcolor.s.blue += b;
{
SETBRIGHTNESS(brightness,blendimage->s.red,blendimage->s.green,blendimage->s.blue);
}
}
}
if (skinnum == TC_RAINBOW)
{
UINT32 tempcolor;
UINT16 colorbright;
// Calculate a sort of "gradient" for the skincolor
// (Me splitting this into a function didn't work, so I had to ruin this entire function's groove...)
{
RGBA_t nextcolor;
UINT8 firsti, secondi, mul, mulmax;
INT32 r, g, b;
SETBRIGHTNESS(colorbright,blendcolor.s.red,blendcolor.s.green,blendcolor.s.blue);
if (colorbright == 0)
colorbright = 1; // no dividing by 0 please
// Rainbow needs to find the closest match to the textures themselves, instead of matching brightnesses to other colors.
// Ensue horrible mess.
if (skinnum == TC_RAINBOW)
{
UINT16 brightdif = 256;
UINT8 colorbrightnesses[16];
INT32 compare, m, d;
tempcolor = (brightness * blendcolor.s.red) / colorbright;
tempcolor = min(255, tempcolor);
cur->s.red = (UINT8)tempcolor;
// Ignore pure white & pitch black
if (brightness > 253 || brightness < 2)
{
cur->rgba = image->rgba;
cur++; image++; blendimage++;
continue;
}
tempcolor = (brightness * blendcolor.s.green) / colorbright;
tempcolor = min(255, tempcolor);
cur->s.green = (UINT8)tempcolor;
firsti = 0;
mul = 0;
mulmax = 1;
tempcolor = (brightness * blendcolor.s.blue) / colorbright;
tempcolor = min(255, tempcolor);
cur->s.blue = (UINT8)tempcolor;
cur->s.alpha = image->s.alpha;
}
else
{
// Color strength depends on image alpha
INT32 tempcolor;
for (i = 0; i < translen; i++)
{
RGBA_t tempc = V_GetColor(translation[i]);
SETBRIGHTNESS(colorbrightnesses[i], tempc.s.red, tempc.s.green, tempc.s.blue); // store brightnesses for comparison
}
tempcolor = ((image->s.red * (255-blendimage->s.alpha)) / 255) + ((blendcolor.s.red * blendimage->s.alpha) / 255);
tempcolor = min(255, tempcolor);
cur->s.red = (UINT8)tempcolor;
for (i = 0; i < translen; i++)
{
if (brightness > colorbrightnesses[i]) // don't allow greater matches (because calculating a makeshift gradient for this is already a huge mess as is)
continue;
tempcolor = ((image->s.green * (255-blendimage->s.alpha)) / 255) + ((blendcolor.s.green * blendimage->s.alpha) / 255);
tempcolor = min(255, tempcolor);
cur->s.green = (UINT8)tempcolor;
compare = abs((INT16)(colorbrightnesses[i]) - (INT16)(brightness));
tempcolor = ((image->s.blue * (255-blendimage->s.alpha)) / 255) + ((blendcolor.s.blue * blendimage->s.alpha) / 255);
tempcolor = min(255, tempcolor);
cur->s.blue = (UINT8)tempcolor;
cur->s.alpha = image->s.alpha;
if (compare < brightdif)
{
brightdif = (UINT16)compare;
firsti = i; // best matching color that's equal brightness or darker
}
}
secondi = firsti+1; // next color in line
if (secondi >= translen)
{
m = (INT16)brightness; // - 0;
d = (INT16)colorbrightnesses[firsti]; // - 0;
}
else
{
m = (INT16)brightness - (INT16)colorbrightnesses[secondi];
d = (INT16)colorbrightnesses[firsti] - (INT16)colorbrightnesses[secondi];
}
if (m >= d)
m = d-1;
mulmax = 16;
// calculate the "gradient" multiplier based on how close this color is to the one next in line
if (m <= 0 || d <= 0)
mul = 0;
else
mul = (mulmax-1) - ((m * mulmax) / d);
}
else
{
// Just convert brightness to a skincolor value, use distance to next position to find the gradient multipler
firsti = 0;
for (i = 1; i < translen; i++)
{
if (brightness >= cutoff[i])
break;
firsti = i;
}
secondi = firsti+1;
mulmax = cutoff[firsti];
if (secondi < translen)
mulmax -= cutoff[secondi];
mul = cutoff[firsti] - brightness;
}
blendcolor = V_GetColor(translation[firsti]);
if (mul > 0) // If it's 0, then we only need the first color.
{
if (secondi >= translen) // blend to black
nextcolor = V_GetColor(31);
else
nextcolor = V_GetColor(translation[secondi]);
// Find difference between points
r = (INT32)(nextcolor.s.red - blendcolor.s.red);
g = (INT32)(nextcolor.s.green - blendcolor.s.green);
b = (INT32)(nextcolor.s.blue - blendcolor.s.blue);
// Find the gradient of the two points
r = ((mul * r) / mulmax);
g = ((mul * g) / mulmax);
b = ((mul * b) / mulmax);
// Add gradient value to color
blendcolor.s.red += r;
blendcolor.s.green += g;
blendcolor.s.blue += b;
}
}
if (skinnum == TC_RAINBOW)
{
UINT32 tempcolor;
UINT16 colorbright;
SETBRIGHTNESS(colorbright,blendcolor.s.red,blendcolor.s.green,blendcolor.s.blue);
if (colorbright == 0)
colorbright = 1; // no dividing by 0 please
tempcolor = (brightness * blendcolor.s.red) / colorbright;
tempcolor = min(255, tempcolor);
cur->s.red = (UINT8)tempcolor;
tempcolor = (brightness * blendcolor.s.green) / colorbright;
tempcolor = min(255, tempcolor);
cur->s.green = (UINT8)tempcolor;
tempcolor = (brightness * blendcolor.s.blue) / colorbright;
tempcolor = min(255, tempcolor);
cur->s.blue = (UINT8)tempcolor;
cur->s.alpha = image->s.alpha;
}
else
{
// Color strength depends on image alpha
INT32 tempcolor;
tempcolor = ((image->s.red * (255-blendimage->s.alpha)) / 255) + ((blendcolor.s.red * blendimage->s.alpha) / 255);
tempcolor = min(255, tempcolor);
cur->s.red = (UINT8)tempcolor;
tempcolor = ((image->s.green * (255-blendimage->s.alpha)) / 255) + ((blendcolor.s.green * blendimage->s.alpha) / 255);
tempcolor = min(255, tempcolor);
cur->s.green = (UINT8)tempcolor;
tempcolor = ((image->s.blue * (255-blendimage->s.alpha)) / 255) + ((blendcolor.s.blue * blendimage->s.alpha) / 255);
tempcolor = min(255, tempcolor);
cur->s.blue = (UINT8)tempcolor;
cur->s.alpha = image->s.alpha;
}
skippixel:
// *Now* we can do Metal Sonic's flashing
if (skinnum == TC_METALSONIC)
{
// Blend dark blue into white
if (cur->s.alpha > 0 && cur->s.red == 0 && cur->s.green == 0 && cur->s.blue < 255 && cur->s.blue > 31)
{
// Sal: Invert non-blue
cur->s.red = cur->s.green = (255 - cur->s.blue);
cur->s.blue = 255;
}
cur->s.alpha = image->s.alpha;
}
}
}
cur++; image++; blendimage++;
cur++; image++;
if (blendimage != NULL)
blendimage++;
}
return;
@ -977,6 +1046,14 @@ static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, INT
// If here, the blended texture has not been created
// So we create it
if ((blendgpatch && blendgpatch->mipmap->grInfo.format)
&& (gpatch->width != blendgpatch->width || gpatch->height != blendgpatch->height))
{
// Blend image exists, but it's bad.
HWD.pfnSetTexture(gpatch->mipmap);
return;
}
//BP: WARNING: don't free it manually without clearing the cache of harware renderer
// (it have a liste of mipmap)
// this malloc is cleared in HWR_FreeTextureCache
@ -1221,50 +1298,44 @@ boolean HWR_DrawModel(gr_vissprite_t *spr)
if (gpatch && gpatch->mipmap->grInfo.format) // else if meant that if a texture couldn't be loaded, it would just end up using something else's texture
{
if (md2->blendgrpatch && ((GLPatch_t *)md2->blendgrpatch)->mipmap->grInfo.format
&& gpatch->width == ((GLPatch_t *)md2->blendgrpatch)->width && gpatch->height == ((GLPatch_t *)md2->blendgrpatch)->height)
{
INT32 skinnum = INT32_MAX;
if ((spr->mobj->flags & (MF_ENEMY|MF_BOSS)) && (spr->mobj->flags2 & MF2_FRET) && !(spr->mobj->flags & MF_GRENADEBOUNCE) && (leveltime & 1)) // Bosses "flash"
{
if (spr->mobj->type == MT_CYBRAKDEMON || spr->mobj->colorized)
skinnum = TC_ALLWHITE;
else if (spr->mobj->type == MT_METALSONIC_BATTLE)
skinnum = TC_METALSONIC;
else
skinnum = TC_BOSS;
}
else if ((skincolors_t)spr->mobj->color != SKINCOLOR_NONE)
{
if (spr->mobj->colorized)
skinnum = TC_RAINBOW;
else if (spr->mobj->player && spr->mobj->player->dashmode >= DASHMODE_THRESHOLD
&& (spr->mobj->player->charflags & SF_DASHMODE)
&& ((leveltime/2) & 1))
{
if (spr->mobj->player->charflags & SF_MACHINE)
skinnum = TC_DASHMODE;
else
skinnum = TC_RAINBOW;
}
else if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY)
skinnum = (INT32)((skin_t*)spr->mobj->skin-skins);
else
skinnum = TC_DEFAULT;
}
INT32 skinnum = INT32_MAX;
// Translation or skin number found
if (skinnum != INT32_MAX)
HWR_GetBlendedTexture(gpatch, (GLPatch_t *)md2->blendgrpatch, skinnum, spr->colormap, (skincolors_t)spr->mobj->color);
if ((spr->mobj->flags & (MF_ENEMY|MF_BOSS)) && (spr->mobj->flags2 & MF2_FRET) && !(spr->mobj->flags & MF_GRENADEBOUNCE) && (leveltime & 1)) // Bosses "flash"
{
if (spr->mobj->type == MT_CYBRAKDEMON || spr->mobj->colorized)
skinnum = TC_ALLWHITE;
else if (spr->mobj->type == MT_METALSONIC_BATTLE)
skinnum = TC_METALSONIC;
else
skinnum = TC_BOSS;
}
else if ((skincolors_t)spr->mobj->color != SKINCOLOR_NONE)
{
if (spr->mobj->colorized)
skinnum = TC_RAINBOW;
else if (spr->mobj->player && spr->mobj->player->dashmode >= DASHMODE_THRESHOLD
&& (spr->mobj->player->charflags & SF_DASHMODE)
&& ((leveltime/2) & 1))
{
// Sorry nothing
HWD.pfnSetTexture(gpatch->mipmap);
if (spr->mobj->player->charflags & SF_MACHINE)
skinnum = TC_DASHMODE;
else
skinnum = TC_RAINBOW;
}
else if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY)
skinnum = (INT32)((skin_t*)spr->mobj->skin-skins);
else
skinnum = TC_DEFAULT;
}
// Translation or skin number found
if (skinnum != INT32_MAX)
{
HWR_GetBlendedTexture(gpatch, (GLPatch_t *)md2->blendgrpatch, skinnum, spr->colormap, (skincolors_t)spr->mobj->color);
}
else
{
// This is safe, since we know the texture has been downloaded
// Sorry nothing
HWD.pfnSetTexture(gpatch->mipmap);
}
}

View file

@ -2222,11 +2222,11 @@ EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration,
EXPORT void HWRAPI(SetTransform) (FTransform *stransform)
{
static boolean special_splitscreen;
float used_fov;
pglLoadIdentity();
if (stransform)
{
boolean fovx90;
used_fov = stransform->fovxangle;
#ifdef USE_FTRANSFORM_MIRROR
// mirroring from Kart
if (stransform->mirror)
@ -2242,32 +2242,28 @@ EXPORT void HWRAPI(SetTransform) (FTransform *stransform)
pglRotatef(stransform->angley+270.0f, 0.0f, 1.0f, 0.0f);
pglTranslatef(-stransform->x, -stransform->z, -stransform->y);
pglMatrixMode(GL_PROJECTION);
pglLoadIdentity();
fovx90 = stransform->fovxangle > 0.0f && fabsf(stransform->fovxangle - 90.0f) < 0.5f;
special_splitscreen = (stransform->splitscreen && fovx90);
if (special_splitscreen)
GLPerspective(53.13f, 2*ASPECT_RATIO); // 53.13 = 2*atan(0.5)
else
GLPerspective(stransform->fovxangle, ASPECT_RATIO);
pglGetFloatv(GL_PROJECTION_MATRIX, projMatrix); // added for new coronas' code (without depth buffer)
pglMatrixMode(GL_MODELVIEW);
special_splitscreen = stransform->splitscreen;
}
else
{
used_fov = fov;
pglScalef(1.0f, 1.0f, -1.0f);
pglMatrixMode(GL_PROJECTION);
pglLoadIdentity();
if (special_splitscreen)
GLPerspective(53.13f, 2*ASPECT_RATIO); // 53.13 = 2*atan(0.5)
else
//Hurdler: is "fov" correct?
GLPerspective(fov, ASPECT_RATIO);
pglGetFloatv(GL_PROJECTION_MATRIX, projMatrix); // added for new coronas' code (without depth buffer)
pglMatrixMode(GL_MODELVIEW);
}
pglMatrixMode(GL_PROJECTION);
pglLoadIdentity();
if (special_splitscreen)
{
used_fov = atan(tan(used_fov*M_PI/360)*0.8)*360/M_PI;
GLPerspective(used_fov, 2*ASPECT_RATIO);
}
else
GLPerspective(used_fov, ASPECT_RATIO);
pglGetFloatv(GL_PROJECTION_MATRIX, projMatrix); // added for new coronas' code (without depth buffer)
pglMatrixMode(GL_MODELVIEW);
pglGetFloatv(GL_MODELVIEW_MATRIX, modelMatrix); // added for new coronas' code (without depth buffer)
}

View file

@ -19760,14 +19760,14 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
{ // MT_FLINGNIGHTSCHIP
-1, // doomednum
S_NIGHTSCHIP, // spawnstate
S_NIGHTSCHIP, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
MT_FLINGNIGHTSCHIP, // reactiontime
MT_FLINGNIGHTSCHIP, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
MT_NIGHTSCHIP, // painchance
MT_NIGHTSCHIP, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
@ -19791,7 +19791,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
1000, // spawnhealth
S_NIGHTSSTARXMAS, // seestate
sfx_None, // seesound
8, // reactiontime
MT_FLINGNIGHTSSTAR, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
@ -19811,6 +19811,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
MF_SLIDEME|MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate
},
{ // MT_FLINGNIGHTSSTAR
-1, // doomednum
S_NIGHTSSTAR, // spawnstate
1000, // spawnhealth
S_NIGHTSSTARXMAS, // seestate
sfx_None, // seesound
MT_FLINGNIGHTSSTAR, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
MT_NIGHTSSTAR, // painchance
sfx_s3k33, // painsound
S_RING, // meleestate
S_NULL, // missilestate
S_SPRK1, // deathstate
S_NULL, // xdeathstate
sfx_ncitem, // deathsound
38*FRACUNIT, // speed
16*FRACUNIT, // radius
24*FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_SLIDEME|MF_SPECIAL, // flags
S_NULL // raisestate
},
{ // MT_NIGHTSSUPERLOOP
1707, // doomednum

View file

@ -4702,6 +4702,7 @@ typedef enum mobj_type
MT_NIGHTSCHIP, // NiGHTS Chip
MT_FLINGNIGHTSCHIP, // Lost NiGHTS Chip
MT_NIGHTSSTAR, // NiGHTS Star
MT_FLINGNIGHTSSTAR, // Lost NiGHTS Star
MT_NIGHTSSUPERLOOP,
MT_NIGHTSDRILLREFILL,
MT_NIGHTSHELPER,

View file

@ -57,6 +57,7 @@ enum hook {
hook_TeamSwitch,
hook_ViewpointSwitch,
hook_SeenPlayer,
hook_PlayerThink,
hook_MAX // last hook
};
@ -108,5 +109,6 @@ UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean
#ifdef SEENAMES
boolean LUAh_SeenPlayer(player_t *player, player_t *seenfriend); // Hook for MT_NAMECHECK
#endif
#define LUAh_PlayerThink(player) LUAh_PlayerHook(player, hook_PlayerThink) // Hook for P_PlayerThink
#endif

View file

@ -68,6 +68,7 @@ const char *const hookNames[hook_MAX+1] = {
"TeamSwitch",
"ViewpointSwitch",
"SeenPlayer",
"PlayerThink",
NULL
};
@ -216,6 +217,7 @@ static int lib_addHook(lua_State *L)
case hook_SeenPlayer:
case hook_ShieldSpawn:
case hook_ShieldSpecial:
case hook_PlayerThink:
lastp = &playerhooks;
break;
case hook_LinedefExecute:

View file

@ -468,11 +468,11 @@ static int libd_getSpritePatch(lua_State *L)
// convert WAD editor angle numbers (1-8) to internal angle numbers (0-7)
// keep 0 the same since we'll make it default to angle 1 (which is internally 0)
// in case somebody didn't know that angle 0 really just maps all 8 angles to the same patch
// in case somebody didn't know that angle 0 really just maps all 8/16 angles to the same patch
if (angle != 0)
angle--;
if (angle >= 8) // out of range?
if (angle >= ((sprframe->rotate & SRF_3DGE) ? 16 : 8)) // out of range?
return 0;
// push both the patch and it's "flip" value
@ -563,11 +563,11 @@ static int libd_getSprite2Patch(lua_State *L)
// convert WAD editor angle numbers (1-8) to internal angle numbers (0-7)
// keep 0 the same since we'll make it default to angle 1 (which is internally 0)
// in case somebody didn't know that angle 0 really just maps all 8 angles to the same patch
// in case somebody didn't know that angle 0 really just maps all 8/16 angles to the same patch
if (angle != 0)
angle--;
if (angle >= 8) // out of range?
if (angle >= ((sprframe->rotate & SRF_3DGE) ? 16 : 8)) // out of range?
return 0;
// push both the patch and it's "flip" value

View file

@ -157,13 +157,21 @@ static const char *const side_opt[] = {
enum vertex_e {
vertex_valid = 0,
vertex_x,
vertex_y
vertex_y,
vertex_floorz,
vertex_floorzset,
vertex_ceilingz,
vertex_ceilingzset
};
static const char *const vertex_opt[] = {
"valid",
"x",
"y",
"floorz",
"floorzset",
"ceilingz",
"ceilingzset",
NULL};
enum ffloor_e {
@ -968,6 +976,18 @@ static int vertex_get(lua_State *L)
case vertex_y:
lua_pushfixed(L, vertex->y);
return 1;
case vertex_floorzset:
lua_pushboolean(L, vertex->floorzset);
return 1;
case vertex_ceilingzset:
lua_pushboolean(L, vertex->ceilingzset);
return 1;
case vertex_floorz:
lua_pushfixed(L, vertex->floorz);
return 1;
case vertex_ceilingz:
lua_pushfixed(L, vertex->ceilingz);
return 1;
}
return 0;
}

View file

@ -97,12 +97,13 @@ typedef struct
} emblem_t;
typedef struct
{
char name[20]; ///< Name of the goal (used in the "emblem awarded" cecho)
char description[40];///< Description of goal (used in statistics)
UINT8 conditionset; ///< Condition set that awards this emblem.
UINT8 sprite; ///< emblem sprite to use, 0 - 25
UINT8 color; ///< skincolor to use
UINT8 collected; ///< Do you have this emblem?
char name[20]; ///< Name of the goal (used in the "emblem awarded" cecho)
char description[40]; ///< Description of goal (used in statistics)
UINT8 conditionset; ///< Condition set that awards this emblem.
UINT8 showconditionset; ///< Condition set that shows this emblem.
UINT8 sprite; ///< emblem sprite to use, 0 - 25
UINT8 color; ///< skincolor to use
UINT8 collected; ///< Do you have this emblem?
} extraemblem_t;
// Unlockable information
@ -112,6 +113,7 @@ typedef struct
char objective[64];
UINT16 height; // menu height
UINT8 conditionset;
UINT8 showconditionset;
INT16 type;
INT16 variable;
UINT8 nocecho;

View file

@ -1397,7 +1397,7 @@ static menuitem_t OP_OpenGLOptionsMenu[] =
{IT_STRING|IT_CVAR, NULL, "Model lighting", &cv_grmodellighting, 32},
{IT_HEADER, NULL, "General", NULL, 51},
{IT_STRING|IT_CVAR, NULL, "Field of view", &cv_grfov, 63},
{IT_STRING|IT_CVAR, NULL, "Field of view", &cv_fov, 63},
{IT_STRING|IT_CVAR, NULL, "Quality", &cv_scr_depth, 73},
{IT_STRING|IT_CVAR, NULL, "Texture Filter", &cv_grfiltermode, 83},
{IT_STRING|IT_CVAR, NULL, "Anisotropic", &cv_granisotropicmode,93},
@ -6897,6 +6897,8 @@ static void M_HandleChecklist(INT32 choice)
continue;
if (unlockables[j].conditionset > MAXCONDITIONSETS)
continue;
if (!unlockables[j].unlocked && unlockables[j].showconditionset && !M_Achieved(unlockables[j].showconditionset))
continue;
if (unlockables[j].conditionset == unlockables[check_on].conditionset)
continue;
break;
@ -6920,6 +6922,8 @@ static void M_HandleChecklist(INT32 choice)
continue;
if (unlockables[j].conditionset > MAXCONDITIONSETS)
continue;
if (!unlockables[j].unlocked && unlockables[j].showconditionset && !M_Achieved(unlockables[j].showconditionset))
continue;
if (j && unlockables[j].conditionset == unlockables[j-1].conditionset)
continue;
break;
@ -6957,7 +6961,8 @@ static void M_DrawChecklist(void)
while (i < MAXUNLOCKABLES)
{
if (unlockables[i].name[0] == 0 //|| unlockables[i].nochecklist
|| !unlockables[i].conditionset || unlockables[i].conditionset > MAXCONDITIONSETS)
|| !unlockables[i].conditionset || unlockables[i].conditionset > MAXCONDITIONSETS
|| (!unlockables[i].unlocked && unlockables[i].showconditionset && !M_Achieved(unlockables[i].showconditionset)))
{
i += 1;
continue;
@ -6983,10 +6988,11 @@ static void M_DrawChecklist(void)
if (unlockables[i].objective[0] != '/')
{
addy(8);
V_DrawString(currentMenu->x, y,
addy(16);
V_DrawString(currentMenu->x, y-8,
V_ALLOWLOWERCASE,
va("\x1E %s", unlockables[i].objective));
y -= 8;
}
else
{
@ -7227,12 +7233,26 @@ static void M_EmblemHints(INT32 choice)
static void M_DrawEmblemHints(void)
{
INT32 i, j = 0;
UINT32 collected = 0;
INT32 i, j = 0, x, y;
UINT32 collected = 0, local = 0;
emblem_t *emblem;
const char *hint;
for (i = 0; i < numemblems; i++)
{
emblem = &emblemlocations[i];
if (emblem->level != gamemap || emblem->type > ET_SKIN)
continue;
if (++local >= NUMHINTS*2)
break;
}
x = (local > NUMHINTS ? 4 : 12);
y = 8;
if (!local)
V_DrawCenteredString(160, 48, V_YELLOWMAP, "No hidden emblems on this map.");
else for (i = 0; i < numemblems; i++)
{
emblem = &emblemlocations[i];
if (emblem->level != gamemap || emblem->type > ET_SKIN)
@ -7241,27 +7261,35 @@ static void M_DrawEmblemHints(void)
if (emblem->collected)
{
collected = V_GREENMAP;
V_DrawMappedPatch(12, 12+(28*j), 0, W_CachePatchName(M_GetEmblemPatch(emblem, false), PU_PATCH),
V_DrawMappedPatch(x, y+4, 0, W_CachePatchName(M_GetEmblemPatch(emblem, false), PU_PATCH),
R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_CACHE));
}
else
{
collected = 0;
V_DrawScaledPatch(12, 12+(28*j), 0, W_CachePatchName("NEEDIT", PU_PATCH));
V_DrawScaledPatch(x, y+4, 0, W_CachePatchName("NEEDIT", PU_PATCH));
}
if (emblem->hint[0])
hint = emblem->hint;
else
hint = M_GetText("No hints available.");
hint = M_GetText("No hint available for this emblem.");
hint = V_WordWrap(40, BASEVIDWIDTH-12, 0, hint);
V_DrawString(40, 8+(28*j), V_RETURN8|V_ALLOWLOWERCASE|collected, hint);
if (local > NUMHINTS)
V_DrawThinString(x+28, y, V_RETURN8|V_ALLOWLOWERCASE|collected, hint);
else
V_DrawString(x+28, y, V_RETURN8|V_ALLOWLOWERCASE|collected, hint);
if (++j >= NUMHINTS)
y += 28;
if (++j == NUMHINTS)
{
x = 4+(BASEVIDWIDTH/2);
y = 8;
}
else if (j >= NUMHINTS*2)
break;
}
if (!j)
V_DrawCenteredString(160, 48, V_YELLOWMAP, "No hidden emblems on this map.");
M_DrawGenericMenu();
}
@ -9196,7 +9224,10 @@ static void M_DrawStatsMaps(int location)
else
V_DrawSmallScaledPatch(292, y, 0, W_CachePatchName("NEEDIT", PU_PATCH));
V_DrawString(20, y, V_YELLOWMAP|V_ALLOWLOWERCASE, va("%s", exemblem->description));
V_DrawString(20, y, V_YELLOWMAP|V_ALLOWLOWERCASE,
(!exemblem->collected && exemblem->showconditionset && !M_Achieved(exemblem->showconditionset))
? M_CreateSecretMenuOption(exemblem->description)
: exemblem->description);
}
y += 8;

View file

@ -14603,12 +14603,9 @@ void A_RolloutRock(mobj_t *actor)
if (!actor->tracer || P_MobjWasRemoved(actor->tracer) || !actor->tracer->health)
actor->flags |= MF_PUSHABLE;
if (!(actor->flags & MF_PUSHABLE)) // if being ridden, don't disappear
actor->fuse = 0;
else if (!actor->fuse && actor->movecount == 1) // otherwise if rock has moved, set its fuse
if (!(actor->flags & MF_PUSHABLE) || (actor->movecount != 1)) // if being ridden or haven't moved, don't disappear
actor->fuse = actor->info->painchance;
if (actor->fuse && actor->fuse < 2*TICRATE)
else if (actor->fuse < 2*TICRATE)
actor->flags2 ^= MF2_DONTDRAW;
}

View file

@ -2005,7 +2005,7 @@ static boolean PIT_CheckLine(line_t *ld)
if (lowfloor < tmdropoffz)
tmdropoffz = lowfloor;
return true;
}

View file

@ -1892,7 +1892,7 @@ void P_XYMovement(mobj_t *mo)
#endif
// Pushables can break some blocks
if (CheckForBustableBlocks && mo->flags & MF_PUSHABLE)
if (CheckForBustableBlocks && ((mo->flags & MF_PUSHABLE) || ((mo->info->flags & MF_PUSHABLE) && mo->fuse)))
P_PushableCheckBustables(mo);
if (!P_TryMove(mo, mo->x + xmove, mo->y + ymove, true)
@ -3127,7 +3127,7 @@ nightsdone:
{
// DO THE MARIO!
if (rover->flags & FF_SHATTERBOTTOM) // Brick block!
EV_CrumbleChain(NULL, rover); // node->m_sector
EV_CrumbleChain(node->m_sector, rover);
else // Question block!
EV_MarioBlock(rover, node->m_sector, mo);
}
@ -7977,7 +7977,7 @@ static void P_MobjSceneryThink(mobj_t *mobj)
mobj->x = mobj->extravalue1 + P_ReturnThrustX(mobj, mobj->movedir, mobj->cvmem*mobj->scale);
mobj->y = mobj->extravalue2 + P_ReturnThrustY(mobj, mobj->movedir, mobj->cvmem*mobj->scale);
P_SetThingPosition(mobj);
if (!mobj->fuse)
{
#ifdef HAVE_BLUA

View file

@ -845,6 +845,8 @@ static void P_LoadVertices(UINT8 *data)
{
v->x = SHORT(mv->x)<<FRACBITS;
v->y = SHORT(mv->y)<<FRACBITS;
v->floorzset = v->ceilingzset = false;
v->floorz = v->ceilingz = 0;
}
}
@ -1104,8 +1106,8 @@ static void P_LoadSidedefs(UINT8 *data)
if (((sd->line->flags & (ML_TWOSIDED|ML_EFFECT5)) == (ML_TWOSIDED|ML_EFFECT5))
&& !(sd->special >= 300 && sd->special < 500)) // exempt linedef exec specials
{
sd->repeatcnt = (INT16)(((unsigned)textureoffset) >> 12);
sd->textureoffset = (((unsigned)textureoffset) & 2047) << FRACBITS;
sd->repeatcnt = (INT16)(((UINT16)textureoffset) >> 12);
sd->textureoffset = (((UINT16)textureoffset) & 2047) << FRACBITS;
}
else
{
@ -1119,7 +1121,6 @@ static void P_LoadSidedefs(UINT8 *data)
// Special info stored in texture fields!
switch (sd->special)
{
case 63: // Fake floor/ceiling planes
case 606: //SoM: 4/4/2000: Just colormap transfer
case 447: // Change colormap of tagged sectors! -- Monster Iestyn 14/06/18
case 455: // Fade colormaps! mazmazz 9/12/2018 (:flag_us:)
@ -1366,6 +1367,16 @@ static void ParseTextmapVertexParameter(UINT32 i, char *param, char *val)
vertexes[i].x = FLOAT_TO_FIXED(atof(val));
else if (fastcmp(param, "y"))
vertexes[i].y = FLOAT_TO_FIXED(atof(val));
else if (fastcmp(param, "zfloor"))
{
vertexes[i].floorz = FLOAT_TO_FIXED(atof(val));
vertexes[i].floorzset = true;
}
else if (fastcmp(param, "zceiling"))
{
vertexes[i].ceilingz = FLOAT_TO_FIXED(atof(val));
vertexes[i].ceilingzset = true;
}
}
static void ParseTextmapSectorParameter(UINT32 i, char *param, char *val)
@ -1573,6 +1584,8 @@ static void P_LoadTextmap(void)
{
// Defaults.
vt->x = vt->y = INT32_MAX;
vt->floorzset = vt->ceilingzset = false;
vt->floorz = vt->ceilingz = 0;
TextmapParse(vertexesPos[i], i, ParseTextmapVertexParameter);
@ -3567,11 +3580,11 @@ boolean P_LoadLevel(boolean fromnetsave)
return false;
// init gravity, tag lists,
// anything that P_ResetDynamicSlopes/P_LoadThings needs to know
// anything that P_SpawnSlopes/P_LoadThings needs to know
P_InitSpecials();
#ifdef ESLOPE
P_ResetDynamicSlopes(fromnetsave);
P_SpawnSlopes(fromnetsave);
#endif
P_SpawnMapThings(!fromnetsave);

View file

@ -458,8 +458,8 @@ static pslope_t *MakeViaMapthings(INT16 tag1, INT16 tag2, INT16 tag3, UINT8 flag
return ret;
}
/// Create vertex based slopes.
static void line_SpawnViaVertexes(const int linenum, const boolean spawnthinker)
/// Create vertex based slopes using tagged mapthings.
static void line_SpawnViaMapthingVertexes(const int linenum, const boolean spawnthinker)
{
line_t *line = lines + linenum;
side_t *side;
@ -507,6 +507,55 @@ static void line_SpawnViaVertexes(const int linenum, const boolean spawnthinker)
side->sector->hasslope = true;
}
/// Spawn textmap vertex slopes.
static void SpawnVertexSlopes(void)
{
line_t *l1, *l2;
sector_t* sc;
vertex_t *v1, *v2, *v3;
size_t i;
for (i = 0, sc = sectors; i < numsectors; i++, sc++)
{
// The vertex slopes only work for 3-vertex sectors (and thus 3-sided sectors).
if (sc->linecount != 3)
continue;
l1 = sc->lines[0];
l2 = sc->lines[1];
// Determine the vertexes.
v1 = l1->v1;
v2 = l1->v2;
if ((l2->v1 != v1) && (l2->v1 != v2))
v3 = l2->v1;
else
v3 = l2->v2;
if (v1->floorzset || v2->floorzset || v3->floorzset)
{
vector3_t vtx[3] = {
{v1->x, v1->y, v1->floorzset ? v1->floorz : sc->floorheight},
{v2->x, v2->y, v2->floorzset ? v2->floorz : sc->floorheight},
{v3->x, v3->y, v3->floorzset ? v3->floorz : sc->floorheight}};
pslope_t *slop = Slope_Add(0);
sc->f_slope = slop;
sc->hasslope = true;
ReconfigureViaVertexes(slop, vtx[0], vtx[1], vtx[2]);
}
if (v1->ceilingzset || v2->ceilingzset || v3->ceilingzset)
{
vector3_t vtx[3] = {
{v1->x, v1->y, v1->ceilingzset ? v1->ceilingz : sc->ceilingheight},
{v2->x, v2->y, v2->ceilingzset ? v2->ceilingz : sc->ceilingheight},
{v3->x, v3->y, v3->ceilingzset ? v3->ceilingz : sc->ceilingheight}};
pslope_t *slop = Slope_Add(0);
sc->c_slope = slop;
sc->hasslope = true;
ReconfigureViaVertexes(slop, vtx[0], vtx[1], vtx[2]);
}
}
}
//
// P_CopySectorSlope
@ -551,12 +600,16 @@ pslope_t *P_SlopeById(UINT16 id)
return ret;
}
/// Reset slopes and read them from special lines.
void P_ResetDynamicSlopes(const boolean fromsave) {
/// Initializes and reads the slopes from the map data.
void P_SpawnSlopes(const boolean fromsave) {
size_t i;
slopelist = NULL;
slopecount = 0;
/// Generates vertex slopes.
SpawnVertexSlopes();
/// Generates line special-defined slopes.
for (i = 0; i < numlines; i++)
{
@ -577,7 +630,7 @@ void P_ResetDynamicSlopes(const boolean fromsave) {
case 705:
case 714:
case 715:
line_SpawnViaVertexes(i, !fromsave);
line_SpawnViaMapthingVertexes(i, !fromsave);
break;
default:

View file

@ -23,7 +23,7 @@ extern UINT16 slopecount;
void P_LinkSlopeThinkers (void);
void P_CalculateSlopeNormal(pslope_t *slope);
void P_ResetDynamicSlopes(const boolean fromsave);
void P_SpawnSlopes(const boolean fromsave);
//
// P_CopySectorSlope

View file

@ -1887,7 +1887,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller
while (node)
{
mo = node->m_thing;
if (mo->flags & MF_PUSHABLE)
if ((mo->flags & MF_PUSHABLE) || ((mo->info->flags & MF_PUSHABLE) && mo->fuse))
numpush++;
node = node->m_thinglist_next;
}
@ -6353,7 +6353,7 @@ static void P_RunLevelLoadExecutors(void)
}
/** Before things are loaded, initialises certain stuff in case they're needed
* by P_ResetDynamicSlopes or P_LoadThings. This was split off from
* by P_SpawnSlopes or P_LoadThings. This was split off from
* P_SpawnSpecials, in case you couldn't tell.
*
* \sa P_SpawnSpecials, P_InitTagLists
@ -8974,7 +8974,8 @@ void T_Pusher(pusher_t *p)
|| thing->type == MT_EXTRALARGEBUBBLE))
continue;
if (!(thing->flags & MF_PUSHABLE) && !(thing->type == MT_PLAYER
if (!((thing->flags & MF_PUSHABLE) || ((thing->info->flags & MF_PUSHABLE) && thing->fuse))
&& !(thing->type == MT_PLAYER
|| thing->type == MT_SMALLBUBBLE
|| thing->type == MT_MEDIUMBUBBLE
|| thing->type == MT_EXTRALARGEBUBBLE

View file

@ -349,11 +349,11 @@ void P_GiveEmerald(boolean spawnObj)
continue;
P_SetTarget(&emmo->target, players[i].mo);
P_SetMobjState(emmo, mobjinfo[MT_GOTEMERALD].meleestate + em);
// Make sure we're not being carried before our tracer is changed
if (players[i].powers[pw_carry] != CR_NIGHTSMODE)
players[i].powers[pw_carry] = CR_NONE;
P_SetTarget(&players[i].mo->tracer, emmo);
if (pnum == 255)
@ -8672,7 +8672,7 @@ static void P_MovePlayer(player_t *player)
}
#ifdef HWRENDER
if (rendermode != render_soft && rendermode != render_none && cv_grfovchange.value)
if (rendermode != render_soft && rendermode != render_none && cv_fovchange.value)
{
fixed_t speed;
const fixed_t runnyspeed = 20*FRACUNIT;
@ -10105,13 +10105,6 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
{
dist = camdist;
// x1.5 dist for splitscreen
if (splitscreen)
{
dist = FixedMul(dist, 3*FRACUNIT/2);
camheight = FixedMul(camheight, 3*FRACUNIT/2);
}
if (sign) // signpost camera has specific placement
{
camheight = mo->scale << 7;
@ -10511,13 +10504,17 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
if (!(multiplayer || netgame) && !splitscreen)
{
fixed_t vx = thiscam->x, vy = thiscam->y;
fixed_t vz = thiscam->z + thiscam->height / 2;
if (player->awayviewtics && player->awayviewmobj != NULL && !P_MobjWasRemoved(player->awayviewmobj)) // Camera must obviously exist
{
vx = player->awayviewmobj->x;
vy = player->awayviewmobj->y;
vz = player->awayviewmobj->z + player->awayviewmobj->height / 2;
}
if (P_AproxDistance(vx - mo->x, vy - mo->y) < FixedMul(48*FRACUNIT, mo->scale))
/* check z distance too for orbital camera */
if (P_AproxDistance(P_AproxDistance(vx - mo->x, vy - mo->y),
vz - ( mo->z + mo->height / 2 )) < FixedMul(48*FRACUNIT, mo->scale))
mo->flags2 |= MF2_SHADOW;
else
mo->flags2 &= ~MF2_SHADOW;
@ -11572,7 +11569,12 @@ void P_PlayerThink(player_t *player)
player->playerstate = PST_REBORN;
}
if (player->playerstate == PST_REBORN)
{
#ifdef HAVE_BLUA
LUAh_PlayerThink(player);
#endif
return;
}
}
#ifdef SEENAMES
@ -11673,7 +11675,12 @@ void P_PlayerThink(player_t *player)
player->lives = 0;
if (player->playerstate == PST_DEAD)
{
#ifdef HAVE_BLUA
LUAh_PlayerThink(player);
#endif
return;
}
}
}
@ -11792,7 +11799,9 @@ void P_PlayerThink(player_t *player)
{
player->mo->flags2 &= ~MF2_SHADOW;
P_DeathThink(player);
#ifdef HAVE_BLUA
LUAh_PlayerThink(player);
#endif
return;
}
@ -11833,7 +11842,12 @@ void P_PlayerThink(player_t *player)
if (player->spectator && cmd->buttons & BT_ATTACK && !player->powers[pw_flashing] && G_GametypeHasSpectators())
{
if (P_SpectatorJoinGame(player))
{
#ifdef HAVE_BLUA
LUAh_PlayerThink(player);
#endif
return; // player->mo was removed.
}
}
// Even if not NiGHTS, pull in nearby objects when walking around as John Q. Elliot.
@ -11935,7 +11949,12 @@ void P_PlayerThink(player_t *player)
}
if (!player->mo)
{
#ifdef HAVE_BLUA
LUAh_PlayerThink(player);
#endif
return; // P_MovePlayer removed player->mo.
}
// deez New User eXperiences.
{
@ -12367,6 +12386,11 @@ void P_PlayerThink(player_t *player)
dashmode = 0;
}
#undef dashmode
#ifdef HAVE_BLUA
LUAh_PlayerThink(player);
#endif
/*
// Colormap verification
{

View file

@ -2710,14 +2710,29 @@ void R_PrecacheLevel(void)
for (j = 0; j < sprites[i].numframes; j++)
{
sf = &sprites[i].spriteframes[j];
for (k = 0; k < 8; k++)
#define cacheang(a) {\
lump = sf->lumppat[a];\
if (devparm)\
spritememory += W_LumpLength(lump);\
W_CachePatchNum(lump, PU_PATCH);\
}
// see R_InitSprites for more about lumppat,lumpid
switch (sf->rotate)
{
// see R_InitSprites for more about lumppat,lumpid
lump = sf->lumppat[k];
if (devparm)
spritememory += W_LumpLength(lump);
W_CachePatchNum(lump, PU_PATCH);
case SRF_SINGLE:
cacheang(0);
break;
case SRF_2D:
cacheang(2);
cacheang(6);
break;
default:
k = (sf->rotate & SRF_3DGE ? 16 : 8);
while (k--)
cacheang(k);
break;
}
#undef cacheang
}
}
free(spritepresent);

View file

@ -84,6 +84,8 @@ typedef struct extracolormap_s
typedef struct
{
fixed_t x, y;
boolean floorzset, ceilingzset;
fixed_t floorz, ceilingz;
} vertex_t;
// Forward of linedefs, for sectors.
@ -727,8 +729,8 @@ typedef struct
#ifdef ROTSPRITE
typedef struct
{
patch_t *patch[8][ROTANGLES];
boolean cached[8];
patch_t *patch[16][ROTANGLES];
UINT16 cached;
} rotsprite_t;
#endif/*ROTSPRITE*/
@ -736,9 +738,11 @@ typedef enum
{
SRF_SINGLE = 0, // 0-angle for all rotations
SRF_3D = 1, // Angles 1-8
SRF_LEFT = 2, // Left side uses single patch
SRF_RIGHT = 4, // Right side uses single patch
SRF_2D = SRF_LEFT|SRF_RIGHT, // 6
SRF_3DGE = 2, // 3DGE, ZDoom and Doom Legacy all have 16-angle support. Why not us?
SRF_3DMASK = SRF_3D|SRF_3DGE, // 3
SRF_LEFT = 4, // Left side uses single patch
SRF_RIGHT = 8, // Right side uses single patch
SRF_2D = SRF_LEFT|SRF_RIGHT, // 12
SRF_NONE = 0xff // Initial value
} spriterotateflags_t; // SRF's up!
@ -764,7 +768,7 @@ typedef struct patchinfo_s patchinfo_t;
// Sprites are patches with a special naming convention so they can be
// recognized by R_InitSprites.
// The base name is NNNNFx or NNNNFxFx, with x indicating the rotation,
// x = 0, 1-8, L/R
// x = 0, 1-8, 9+A-G, L/R
// The sprite and frame specified by a thing_t is range checked at run time.
// A sprite is a patch_t that is assumed to represent a three dimensional
// object and may have multiple rotations predrawn.
@ -781,12 +785,12 @@ typedef struct
// name eight times.
UINT8 rotate; // see spriterotateflags_t above
// Lump to use for view angles 0-7.
lumpnum_t lumppat[8]; // lump number 16 : 16 wad : lump
size_t lumpid[8]; // id in the spriteoffset, spritewidth, etc. tables
// Lump to use for view angles 0-7/15.
lumpnum_t lumppat[16]; // lump number 16 : 16 wad : lump
size_t lumpid[16]; // id in the spriteoffset, spritewidth, etc. tables
// Flip bits (1 = flip) to use for view angles 0-7.
UINT8 flip;
// Flip bits (1 = flip) to use for view angles 0-7/15.
UINT16 flip;
#ifdef ROTSPRITE
rotsprite_t rotsprite;

View file

@ -59,6 +59,7 @@ INT32 centerx, centery;
fixed_t centerxfrac, centeryfrac;
fixed_t projection;
fixed_t projectiony; // aspect ratio
fixed_t fovtan; // field of view
// just for profiling purposes
size_t framecount;
@ -108,10 +109,12 @@ static CV_PossibleValue_t drawdist_precip_cons_t[] = {
{1024, "1024"}, {1536, "1536"}, {2048, "2048"},
{0, "None"}, {0, NULL}};
static CV_PossibleValue_t fov_cons_t[] = {{60*FRACUNIT, "MIN"}, {179*FRACUNIT, "MAX"}, {0, NULL}};
static CV_PossibleValue_t translucenthud_cons_t[] = {{0, "MIN"}, {10, "MAX"}, {0, NULL}};
static CV_PossibleValue_t maxportals_cons_t[] = {{0, "MIN"}, {12, "MAX"}, {0, NULL}}; // lmao rendering 32 portals, you're a card
static CV_PossibleValue_t homremoval_cons_t[] = {{0, "No"}, {1, "Yes"}, {2, "Flash"}, {0, NULL}};
static void Fov_OnChange(void);
static void ChaseCam_OnChange(void);
static void ChaseCam2_OnChange(void);
static void FlipCam_OnChange(void);
@ -141,6 +144,7 @@ consvar_t cv_drawdist = {"drawdist", "Infinite", CV_SAVE, drawdist_cons_t, NULL,
consvar_t cv_drawdist_nights = {"drawdist_nights", "2048", CV_SAVE, drawdist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_drawdist_precip = {"drawdist_precip", "1024", CV_SAVE, drawdist_precip_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
//consvar_t cv_precipdensity = {"precipdensity", "Moderate", CV_SAVE, precipdensity_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_fov = {"fov", "90", CV_FLOAT|CV_CALL, fov_cons_t, Fov_OnChange, 0, NULL, NULL, 0, 0, NULL};
// Okay, whoever said homremoval causes a performance hit should be shot.
consvar_t cv_homremoval = {"homremoval", "No", CV_SAVE, homremoval_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
@ -184,6 +188,14 @@ void SplitScreen_OnChange(void)
}
}
}
static void Fov_OnChange(void)
{
// Shouldn't be needed with render parity?
//if ((netgame || multiplayer) && !cv_debug && cv_fov.value != 90*FRACUNIT)
// CV_Set(&cv_fov, cv_fov.defaultvalue);
R_SetViewSize();
}
static void ChaseCam_OnChange(void)
{
@ -448,8 +460,8 @@ static void R_InitTextureMapping(void)
//
// Calc focallength
// so FIELDOFVIEW angles covers SCREENWIDTH.
focallength = FixedDiv(centerxfrac,
FINETANGENT(FINEANGLES/4+/*cv_fov.value*/ FIELDOFVIEW/2));
focallength = FixedDiv(projection,
FINETANGENT(FINEANGLES/4+FIELDOFVIEW/2));
#ifdef ESLOPE
focallengthf = FIXED_TO_FLOAT(focallength);
@ -457,9 +469,9 @@ static void R_InitTextureMapping(void)
for (i = 0; i < FINEANGLES/2; i++)
{
if (FINETANGENT(i) > FRACUNIT*2)
if (FINETANGENT(i) > fovtan*2)
t = -1;
else if (FINETANGENT(i) < -FRACUNIT*2)
else if (FINETANGENT(i) < -fovtan*2)
t = viewwidth+1;
else
{
@ -563,6 +575,7 @@ void R_ExecuteSetViewSize(void)
INT32 j;
INT32 level;
INT32 startmapl;
angle_t fov;
setsizeneeded = false;
@ -585,9 +598,12 @@ void R_ExecuteSetViewSize(void)
centerxfrac = centerx<<FRACBITS;
centeryfrac = centery<<FRACBITS;
projection = centerxfrac;
//projectiony = (((vid.height*centerx*BASEVIDWIDTH)/BASEVIDHEIGHT)/vid.width)<<FRACBITS;
projectiony = centerxfrac;
fov = FixedAngle(cv_fov.value/2) + ANGLE_90;
fovtan = FINETANGENT(fov >> ANGLETOFINESHIFT);
if (splitscreen == 1) // Splitscreen FOV should be adjusted to maintain expected vertical view
fovtan = 17*fovtan/10;
projection = projectiony = FixedDiv(centerxfrac, fovtan);
R_InitViewBuffer(scaledviewwidth, viewheight);
@ -613,7 +629,7 @@ void R_ExecuteSetViewSize(void)
for (i = 0; i < j; i++)
{
dy = ((i - viewheight*8)<<FRACBITS) + FRACUNIT/2;
dy = abs(dy);
dy = FixedMul(abs(dy), fovtan);
yslopetab[i] = FixedDiv(centerx*FRACUNIT, dy);
}
}
@ -734,7 +750,7 @@ subsector_t *R_IsPointInSubsector(fixed_t x, fixed_t y)
static mobj_t *viewmobj;
// WARNING: a should be unsigned but to add with 2048, it isn't!
#define AIMINGTODY(a) ((FINETANGENT((2048+(((INT32)a)>>ANGLETOFINESHIFT)) & FINEMASK)*160)>>FRACBITS)
#define AIMINGTODY(a) FixedDiv((FINETANGENT((2048+(((INT32)a)>>ANGLETOFINESHIFT)) & FINEMASK)*160)>>FRACBITS, fovtan)
// recalc necessary stuff for mouseaiming
// slopes are already calculated for the full possible view (which is 4*viewheight).
@ -1203,6 +1219,7 @@ void R_RegisterEngineStuff(void)
CV_RegisterVar(&cv_drawdist);
CV_RegisterVar(&cv_drawdist_nights);
CV_RegisterVar(&cv_drawdist_precip);
CV_RegisterVar(&cv_fov);
CV_RegisterVar(&cv_chasecam);
CV_RegisterVar(&cv_chasecam2);

View file

@ -84,6 +84,7 @@ extern conscar_t cv_shadowoffs;
#endif //#ifdef GLBADSHADOWS
extern consvar_t cv_translucency;
extern consvar_t cv_drawdist, cv_drawdist_nights, cv_drawdist_precip;
extern consvar_t cv_fov;
extern consvar_t cv_skybox;
extern consvar_t cv_tailspickup;

View file

@ -1205,7 +1205,7 @@ void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, sp
#define ROTSPRITE_XCENTER (newwidth / 2)
#define ROTSPRITE_YCENTER (newheight / 2)
if (!sprframe->rotsprite.cached[rot])
if (!(sprframe->rotsprite.cached & (1<<rot)))
{
INT32 dx, dy;
INT32 px, py;
@ -1375,7 +1375,7 @@ void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, sp
}
// This rotation is cached now
sprframe->rotsprite.cached[rot] = true;
sprframe->rotsprite.cached |= (1<<rot);
// free image data
Z_Free(patch);
@ -1399,9 +1399,9 @@ void R_FreeSingleRotSprite(spritedef_t *spritedef)
for (frame = 0; frame < spritedef->numframes; frame++)
{
spriteframe_t *sprframe = &spritedef->spriteframes[frame];
for (rot = 0; rot < 8; rot++)
for (rot = 0; rot < 16; rot++)
{
if (sprframe->rotsprite.cached[rot])
if (sprframe->rotsprite.cached & (1<<rot))
{
for (ang = 0; ang < ROTANGLES; ang++)
{
@ -1432,7 +1432,7 @@ void R_FreeSingleRotSprite(spritedef_t *spritedef)
Z_Free(rotsprite);
}
}
sprframe->rotsprite.cached[rot] = false;
sprframe->rotsprite.cached &= ~(1<<rot);
}
}
}

View file

@ -105,24 +105,21 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch
UINT8 rotation,
UINT8 flipped)
{
char cn = R_Frame2Char(frame); // for debugging
char cn = R_Frame2Char(frame), cr = R_Rotation2Char(rotation); // for debugging
INT32 r, ang;
lumpnum_t lumppat = wad;
lumppat <<= 16;
lumppat += lump;
if (frame >= 64 || !(R_ValidSpriteAngle(rotation)))
I_Error("R_InstallSpriteLump: Bad frame characters in lump %s", W_CheckNameForNum(lumppat));
if (maxframe ==(size_t)-1 || frame > maxframe)
maxframe = frame;
// rotsprite
#ifdef ROTSPRITE
for (r = 0; r < 8; r++)
sprtemp[frame].rotsprite.cached = 0;
for (r = 0; r < 16; r++)
{
sprtemp[frame].rotsprite.cached[r] = false;
for (ang = 0; ang < ROTANGLES; ang++)
sprtemp[frame].rotsprite.patch[r][ang] = NULL;
}
@ -133,16 +130,16 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch
// the lump should be used for all rotations
if (sprtemp[frame].rotate == SRF_SINGLE)
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has multiple rot = 0 lump\n", spritename, cn);
else if (sprtemp[frame].rotate != SRF_NONE) // Let's bundle 1-8 and L/R rotations into one debug message.
else if (sprtemp[frame].rotate != SRF_NONE) // Let's bundle 1-8/16 and L/R rotations into one debug message.
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has rotations and a rot = 0 lump\n", spritename, cn);
sprtemp[frame].rotate = SRF_SINGLE;
for (r = 0; r < 8; r++)
for (r = 0; r < 16; r++)
{
sprtemp[frame].lumppat[r] = lumppat;
sprtemp[frame].lumpid[r] = lumpid;
}
sprtemp[frame].flip = flipped ? 0xFF : 0; // 11111111 in binary
sprtemp[frame].flip = flipped ? 0xFFFF : 0; // 1111111111111111 in binary
return;
}
@ -151,54 +148,67 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch
UINT8 rightfactor = ((rotation == ROT_R) ? 4 : 0);
// the lump should be used for half of all rotations
if (sprtemp[frame].rotate == SRF_SINGLE)
if (sprtemp[frame].rotate == SRF_NONE)
sprtemp[frame].rotate = SRF_SINGLE;
else if (sprtemp[frame].rotate == SRF_SINGLE)
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has L/R rotations and a rot = 0 lump\n", spritename, cn);
else if (sprtemp[frame].rotate == SRF_3D)
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has both L/R and 1-8 rotations\n", spritename, cn);
else if (sprtemp[frame].rotate == SRF_3DGE)
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has both L/R and 1-G rotations\n", spritename, cn);
else if ((sprtemp[frame].rotate & SRF_LEFT) && (rotation == ROT_L))
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has multiple L rotations\n", spritename, cn);
else if ((sprtemp[frame].rotate & SRF_RIGHT) && (rotation == ROT_R))
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has multiple R rotations\n", spritename, cn);
if (sprtemp[frame].rotate == SRF_NONE)
sprtemp[frame].rotate = SRF_SINGLE;
sprtemp[frame].rotate |= ((rotation == ROT_R) ? SRF_RIGHT : SRF_LEFT);
if (sprtemp[frame].rotate == (SRF_3D|SRF_2D))
sprtemp[frame].rotate = SRF_2D; // SRF_3D|SRF_2D being enabled at the same time doesn't HURT in the current sprite angle implementation, but it DOES mean more to check in some of the helper functions. Let's not allow this scenario to happen.
if ((sprtemp[frame].rotate & SRF_2D) == SRF_2D)
sprtemp[frame].rotate &= ~SRF_3DMASK; // SRF_3D|SRF_2D being enabled at the same time doesn't HURT in the current sprite angle implementation, but it DOES mean more to check in some of the helper functions. Let's not allow this scenario to happen.
for (r = 0; r < 4; r++) // Thanks to R_PrecacheLevel, we can't leave sprtemp[*].lumppat[*] == LUMPERROR... so we load into the front/back angle too.
// load into every relevant angle, including the front one
for (r = 0; r < 4; r++)
{
sprtemp[frame].lumppat[r + rightfactor] = lumppat;
sprtemp[frame].lumpid[r + rightfactor] = lumpid;
sprtemp[frame].lumppat[r + rightfactor + 8] = lumppat;
sprtemp[frame].lumpid[r + rightfactor + 8] = lumpid;
}
if (flipped)
sprtemp[frame].flip |= (0x0F<<rightfactor); // 00001111 or 11110000 in binary, depending on rotation being ROT_L or ROT_R
sprtemp[frame].flip |= (0x0F0F<<rightfactor); // 0000111100001111 or 1111000011110000 in binary, depending on rotation being ROT_L or ROT_R
else
sprtemp[frame].flip &= ~(0x0F<<rightfactor); // ditto
sprtemp[frame].flip &= ~(0x0F0F<<rightfactor); // ditto
return;
}
// the lump is only used for one rotation
if (sprtemp[frame].rotate == SRF_SINGLE)
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has 1-8 rotations and a rot = 0 lump\n", spritename, cn);
else if ((sprtemp[frame].rotate != SRF_3D) && (sprtemp[frame].rotate != SRF_NONE))
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has both L/R and 1-8 rotations\n", spritename, cn);
if (sprtemp[frame].rotate == SRF_NONE)
sprtemp[frame].rotate = SRF_SINGLE;
else if (sprtemp[frame].rotate == SRF_SINGLE)
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has 1-8/G rotations and a rot = 0 lump\n", spritename, cn);
else if (sprtemp[frame].rotate & SRF_2D)
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has both L/R and 1-8/G rotations\n", spritename, cn);
// make 0 based
rotation--;
if (rotation == 0 || rotation == 4) // Front or back...
sprtemp[frame].rotate = SRF_3D; // Prevent L and R changeover
else if (rotation > 3) // Right side
sprtemp[frame].rotate = (SRF_3D | (sprtemp[frame].rotate & SRF_LEFT)); // Continue allowing L frame changeover
else // if (rotation <= 3) // Left side
sprtemp[frame].rotate = (SRF_3D | (sprtemp[frame].rotate & SRF_RIGHT)); // Continue allowing R frame changeover
{
// SRF_3D|SRF_3DGE being enabled at the same time doesn't HURT in the current sprite angle implementation, but it DOES mean more to check in some of the helper functions. Let's not allow this scenario to happen.
UINT8 threedrot = (rotation > 7) ? SRF_3DGE : (sprtemp[frame].rotate & SRF_3DMASK);
if (!threedrot)
threedrot = SRF_3D;
if (rotation == 0 || rotation == 4) // Front or back...
sprtemp[frame].rotate = threedrot; // Prevent L and R changeover
else if ((rotation & 7) > 3) // Right side
sprtemp[frame].rotate = (threedrot | (sprtemp[frame].rotate & SRF_LEFT)); // Continue allowing L frame changeover
else // if ((rotation & 7) <= 3) // Left side
sprtemp[frame].rotate = (threedrot | (sprtemp[frame].rotate & SRF_RIGHT)); // Continue allowing R frame changeover
}
if (sprtemp[frame].lumppat[rotation] != LUMPERROR)
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s: %c%c has two lumps mapped to it\n", spritename, cn, '1'+rotation);
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s: %c%c has two lumps mapped to it\n", spritename, cn, cr);
// lumppat & lumpid are the same for original Doom, but different
// when using sprites in pwad : the lumppat points the new graphics
@ -259,9 +269,9 @@ static boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef,
if (memcmp(lumpinfo[l].name,sprname,4)==0)
{
frame = R_Char2Frame(lumpinfo[l].name[4]);
rotation = (UINT8)(lumpinfo[l].name[5] - '0');
rotation = R_Char2Rotation(lumpinfo[l].name[5]);
if (frame >= 64 || !(R_ValidSpriteAngle(rotation))) // Give an actual NAME error -_-...
if (frame >= 64 || rotation == 255) // Give an actual NAME error -_-...
{
CONS_Alert(CONS_WARNING, M_GetText("Bad sprite name: %s\n"), W_CheckNameForNumPwad(wadnum,l));
continue;
@ -308,7 +318,13 @@ static boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef,
if (lumpinfo[l].name[6])
{
frame = R_Char2Frame(lumpinfo[l].name[6]);
rotation = (UINT8)(lumpinfo[l].name[7] - '0');
rotation = R_Char2Rotation(lumpinfo[l].name[7]);
if (frame >= 64 || rotation == 255) // Give an actual NAME error -_-...
{
CONS_Alert(CONS_WARNING, M_GetText("Bad sprite name: %s\n"), W_CheckNameForNumPwad(wadnum,l));
continue;
}
R_InstallSpriteLump(wadnum, l, numspritelumps, frame, rotation, 1);
}
@ -369,18 +385,19 @@ static boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef,
case SRF_2D: // both Left and Right rotations
// we test to see whether the left and right slots are present
if ((sprtemp[frame].lumppat[2] == LUMPERROR) || (sprtemp[frame].lumppat[6] == LUMPERROR))
I_Error("R_AddSingleSpriteDef: Sprite %.4s frame %c is missing rotations",
I_Error("R_AddSingleSpriteDef: Sprite %.4s frame %c is missing rotations (L-R mode)",
sprname, R_Frame2Char(frame));
break;
default:
// must have all 8 frames
for (rotation = 0; rotation < 8; rotation++)
// must have all 8/16 frames
rotation = ((sprtemp[frame].rotate & SRF_3DGE) ? 16 : 8);
while (rotation--)
// we test the patch lump, or the id lump whatever
// if it was not loaded the two are LUMPERROR
if (sprtemp[frame].lumppat[rotation] == LUMPERROR)
I_Error("R_AddSingleSpriteDef: Sprite %.4s frame %c is missing rotations",
sprname, R_Frame2Char(frame));
I_Error("R_AddSingleSpriteDef: Sprite %.4s frame %c is missing rotations (1-%c mode)",
sprname, R_Frame2Char(frame), ((sprtemp[frame].rotate & SRF_3DGE) ? 'G' : '8'));
break;
}
}
@ -739,9 +756,7 @@ void R_DrawFlippedMaskedColumn(column_t *column, INT32 texheight)
static void R_DrawVisSprite(vissprite_t *vis)
{
column_t *column;
#ifdef RANGECHECK
INT32 texturecolumn;
#endif
fixed_t frac;
patch_t *patch = vis->patch;
fixed_t this_scale = vis->mobj->scale;
@ -889,28 +904,51 @@ static void R_DrawVisSprite(vissprite_t *vis)
if (vis->x2 >= vid.width)
vis->x2 = vid.width-1;
for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale)
// Split drawing loops for paper and non-paper to reduce conditional checks per sprite
if (vis->scalestep)
{
#ifdef RANGECHECK
// Papersprite drawing loop
texturecolumn = frac>>FRACBITS;
if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width))
I_Error("R_DrawSpriteRange: bad texturecolumn at %d from end", vis->x2 - dc_x);
column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[texturecolumn]));
#else
column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[frac>>FRACBITS]));
#endif
if (vis->scalestep)
for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, spryscale += vis->scalestep)
{
angle_t angle = ((vis->centerangle + xtoviewangle[dc_x]) >> ANGLETOFINESHIFT) & 0xFFF;
texturecolumn = (vis->paperoffset - FixedMul(FINETANGENT(angle), vis->paperdistance)) / this_scale;
if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width))
continue;
if (vis->xiscale < 0) // Flipped sprite
texturecolumn = SHORT(patch->width) - 1 - texturecolumn;
sprtopscreen = (centeryfrac - FixedMul(dc_texturemid, spryscale));
dc_iscale = (0xffffffffu / (unsigned)spryscale);
column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[texturecolumn]));
if (vis->cut & SC_VFLIP)
R_DrawFlippedMaskedColumn(column, patch->height);
else
R_DrawMaskedColumn(column);
}
}
else
{
// Non-paper drawing loop
for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale)
{
#ifdef RANGECHECK
texturecolumn = frac>>FRACBITS;
if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width))
I_Error("R_DrawSpriteRange: bad texturecolumn at %d from end", vis->x2 - dc_x);
column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[texturecolumn]));
#else
column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[frac>>FRACBITS]));
#endif
if (vis->cut & SC_VFLIP)
R_DrawFlippedMaskedColumn(column, patch->height);
else
R_DrawMaskedColumn(column);
}
if (vis->cut & SC_VFLIP)
R_DrawFlippedMaskedColumn(column, patch->height);
else
R_DrawMaskedColumn(column);
spryscale += vis->scalestep;
}
colfunc = colfuncs[BASEDRAWFUNC];
@ -1069,8 +1107,6 @@ static void R_SplitSprite(vissprite_t *sprite)
}
}
//#define PROPERPAPER // This was reverted less than 7 hours before 2.2's release because of very strange, frequent crashes.
//
// R_ProjectSprite
// Generates a vissprite for a thing
@ -1094,7 +1130,7 @@ static void R_ProjectSprite(mobj_t *thing)
size_t lump;
size_t rot;
UINT8 flip;
UINT16 flip;
boolean vflip = (!(thing->eflags & MFE_VERTICALFLIP) != !(thing->frame & FF_VERTICALFLIP));
INT32 lindex;
@ -1107,7 +1143,9 @@ static void R_ProjectSprite(mobj_t *thing)
fixed_t iscale;
fixed_t scalestep;
fixed_t offset, offset2;
boolean papersprite = !!(thing->frame & FF_PAPERSPRITE);
fixed_t paperoffset = 0, paperdistance = 0; angle_t centerangle = 0;
INT32 dispoffset = thing->info->dispoffset;
@ -1125,10 +1163,6 @@ static void R_ProjectSprite(mobj_t *thing)
INT32 rollangle = 0;
#endif
#ifndef PROPERPAPER
fixed_t ang_scale = FRACUNIT;
#endif
// transform the origin point
tr_x = thing->x - viewx;
tr_y = thing->y - viewy;
@ -1139,7 +1173,7 @@ static void R_ProjectSprite(mobj_t *thing)
tz = gxt-gyt;
// thing is behind view plane?
if (!(papersprite) && (tz < FixedMul(MINZ, this_scale))) // papersprite clipping is handled later
if (!papersprite && (tz < FixedMul(MINZ, this_scale))) // papersprite clipping is handled later
return;
gxt = -FixedMul(tr_x, viewsin);
@ -1147,7 +1181,7 @@ static void R_ProjectSprite(mobj_t *thing)
tx = -(gyt + gxt);
// too far off the side?
if (abs(tx) > tz<<2)
if (!papersprite && abs(tx) > tz<<2) // papersprite clipping is handled later
return;
// aspect ratio stuff
@ -1211,20 +1245,14 @@ static void R_ProjectSprite(mobj_t *thing)
#endif
if (sprframe->rotate != SRF_SINGLE || papersprite)
{
ang = R_PointToAngle (thing->x, thing->y) - (thing->player ? thing->player->drawangle : thing->angle);
#ifndef PROPERPAPER
if (papersprite)
ang_scale = abs(FINESINE(ang>>ANGLETOFINESHIFT));
#endif
}
if (sprframe->rotate == SRF_SINGLE)
{
// use single rotation for all views
rot = 0; //Fab: for vis->patch below
lump = sprframe->lumpid[0]; //Fab: see note above
flip = sprframe->flip; // Will only be 0x00 or 0xFF
flip = sprframe->flip; // Will only be 0 or 0xFFFF
}
else
{
@ -1235,6 +1263,11 @@ static void R_ProjectSprite(mobj_t *thing)
rot = 6; // F7 slot
else if ((sprframe->rotate & SRF_LEFT) && (ang >= ANGLE_180)) // See from left
rot = 2; // F3 slot
else if (sprframe->rotate & SRF_3DGE) // 16-angle mode
{
rot = (ang+ANGLE_180+ANGLE_11hh)>>28;
rot = ((rot & 1)<<3)|(rot>>1);
}
else // Normal behaviour
rot = (ang+ANGLE_202h)>>29;
@ -1257,7 +1290,7 @@ static void R_ProjectSprite(mobj_t *thing)
if (thing->rollangle)
{
rollangle = R_GetRollAngle(thing->rollangle);
if (!sprframe->rotsprite.cached[rot])
if (!(sprframe->rotsprite.cached & (1<<rot)))
R_CacheRotSprite(thing->sprite, (thing->frame & FF_FRAMEMASK), sprinfo, sprframe, rot, flip);
rotsprite = sprframe->rotsprite.patch[rot][rollangle];
if (rotsprite != NULL)
@ -1278,31 +1311,11 @@ static void R_ProjectSprite(mobj_t *thing)
else
offset = -spr_offset;
offset = FixedMul(offset, this_scale);
#ifndef PROPERPAPER
tx += FixedMul(offset, ang_scale);
x1 = (centerxfrac + FixedMul (tx,xscale)) >>FRACBITS;
// off the right side?
if (x1 > viewwidth)
return;
#endif
offset2 = FixedMul(spr_width, this_scale);
#ifndef PROPERPAPER
tx += FixedMul(offset2, ang_scale);
x2 = ((centerxfrac + FixedMul (tx,xscale)) >> FRACBITS) - (papersprite ? 2 : 1);
// off the left side
if (x2 < 0)
return;
#endif
if (papersprite)
{
fixed_t
#ifdef PROPERPAPER
xscale2,
#endif
yscale2, cosmul, sinmul, tz2;
fixed_t xscale2, yscale2, cosmul, sinmul, tx2, tz2;
INT32 range;
if (ang >= ANGLE_180)
@ -1320,19 +1333,23 @@ static void R_ProjectSprite(mobj_t *thing)
gyt = -FixedMul(tr_y, viewsin);
tz = gxt-gyt;
yscale = FixedDiv(projectiony, tz);
if (yscale < 64) return; // Fix some funky visuals
//if (yscale < 64) return; // Fix some funky visuals
#ifdef PROPERPAPER
gxt = -FixedMul(tr_x, viewsin);
gyt = FixedMul(tr_y, viewcos);
tx = -(gyt + gxt);
xscale = FixedDiv(projection, tz);
x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS;
// off the right side?
if (x1 > viewwidth)
return;
#endif
// Get paperoffset (offset) and paperoffset (distance)
paperoffset = -FixedMul(tr_x, cosmul) - FixedMul(tr_y, sinmul);
paperdistance = -FixedMul(tr_x, sinmul) + FixedMul(tr_y, cosmul);
if (paperdistance < 0)
{
paperoffset = -paperoffset;
paperdistance = -paperdistance;
}
centerangle = viewangle - thing->angle;
tr_x += FixedMul(offset2, cosmul);
tr_y += FixedMul(offset2, sinmul);
@ -1340,38 +1357,52 @@ static void R_ProjectSprite(mobj_t *thing)
gyt = -FixedMul(tr_y, viewsin);
tz2 = gxt-gyt;
yscale2 = FixedDiv(projectiony, tz2);
if (yscale2 < 64) return; // ditto
//if (yscale2 < 64) return; // ditto
#ifdef PROPERPAPER
gxt = -FixedMul(tr_x, viewsin);
gyt = FixedMul(tr_y, viewcos);
tx = -(gyt + gxt);
tx2 = -(gyt + gxt);
xscale2 = FixedDiv(projection, tz2);
x2 = (centerxfrac + FixedMul(tx,xscale2))>>FRACBITS; x2--;
x2 = ((centerxfrac + FixedMul(tx2,xscale2))>>FRACBITS);
if (max(tz, tz2) < FixedMul(MINZ, this_scale)) // non-papersprite clipping is handled earlier
return;
// Needs partially clipped
if (tz < FixedMul(MINZ, this_scale))
{
fixed_t div = FixedDiv(tz2-tz, FixedMul(MINZ, this_scale)-tz);
tx += FixedDiv(tx2-tx, div);
tz = FixedMul(MINZ, this_scale);
yscale = FixedDiv(projectiony, tz);
xscale = FixedDiv(projection, tz);
x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS;
}
else if (tz2 < FixedMul(MINZ, this_scale))
{
fixed_t div = FixedDiv(tz-tz2, FixedMul(MINZ, this_scale)-tz2);
tx2 += FixedDiv(tx-tx2, div);
tz2 = FixedMul(MINZ, this_scale);
yscale2 = FixedDiv(projectiony, tz2);
xscale2 = FixedDiv(projection, tz2);
x2 = (centerxfrac + FixedMul(tx2,xscale2))>>FRACBITS;
}
// off the right side?
if (x1 > viewwidth)
return;
// off the left side
if (x2 < 0)
return;
#endif
if (max(tz, tz2) < FixedMul(MINZ, this_scale)) // non-papersprite clipping is handled earlier
return;
if ((range = x2 - x1) <= 0)
return;
#ifdef PROPERPAPER
range++; // fencepost problem
#endif
scalestep = (yscale2 - yscale)/range;
xscale =
#ifdef PROPERPAPER
FixedDiv(range<<FRACBITS, abs(offset2))+1
#else
FixedMul(xscale, ang_scale)
#endif
;
scalestep = ((yscale2 - yscale)/range) ?: 1;
xscale = FixedDiv(range<<FRACBITS, abs(offset2));
// The following two are alternate sorting methods which might be more applicable in some circumstances. TODO - maybe enable via MF2?
// sortscale = max(yscale, yscale2);
@ -1381,7 +1412,6 @@ static void R_ProjectSprite(mobj_t *thing)
{
scalestep = 0;
yscale = sortscale;
#ifdef PROPERPAPER
tx += offset;
x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS;
@ -1395,7 +1425,6 @@ static void R_ProjectSprite(mobj_t *thing)
// off the left side
if (x2 < 0)
return;
#endif
}
if ((thing->flags2 & MF2_LINKDRAW) && thing->tracer) // toast 16/09/16 (SYMMETRY)
@ -1516,6 +1545,9 @@ static void R_ProjectSprite(mobj_t *thing)
vis->pzt = vis->pz + vis->thingheight;
vis->texturemid = vis->gzt - viewz;
vis->scalestep = scalestep;
vis->paperoffset = paperoffset;
vis->paperdistance = paperdistance;
vis->centerangle = centerangle;
vis->mobj = thing; // Easy access! Tails 06-07-2002

View file

@ -20,10 +20,6 @@
#include "r_portal.h"
#include "r_defs.h"
// "Left" and "Right" character symbols for additional rotation functionality
#define ROT_L ('L' - '0')
#define ROT_R ('R' - '0')
// number of sprite lumps for spritewidth,offset,topoffset lookup tables
// Fab: this is a hack : should allocate the lookup tables per sprite
#define MAXVISSPRITES 2048 // added 2-2-98 was 128
@ -181,8 +177,11 @@ typedef struct vissprite_s
fixed_t startfrac; // horizontal position of x1
fixed_t scale, sortscale; // sortscale only differs from scale for paper sprites and MF2_LINKDRAW
fixed_t scalestep; // only for paper sprites, 0 otherwise
fixed_t paperoffset, paperdistance; // for paper sprites, offset/dist relative to the angle
fixed_t xiscale; // negative if flipped
angle_t centerangle; // for paper sprites
fixed_t texturemid;
patch_t *patch;
@ -270,7 +269,7 @@ FUNCMATH FUNCINLINE static ATTRINLINE UINT8 R_Char2Frame(char cn)
if (cn == '+') return '\\' - 'A'; // PK3 can't use backslash, so use + instead
return cn - 'A';
#else
if (cn >= 'A' && cn <= 'Z') return cn - 'A';
if (cn >= 'A' && cn <= 'Z') return (cn - 'A');
if (cn >= '0' && cn <= '9') return (cn - '0') + 26;
if (cn >= 'a' && cn <= 'z') return (cn - 'a') + 36;
if (cn == '!') return 62;
@ -279,9 +278,26 @@ FUNCMATH FUNCINLINE static ATTRINLINE UINT8 R_Char2Frame(char cn)
#endif
}
FUNCMATH FUNCINLINE static ATTRINLINE boolean R_ValidSpriteAngle(UINT8 rotation)
// "Left" and "Right" character symbols for additional rotation functionality
#define ROT_L 17
#define ROT_R 18
FUNCMATH FUNCINLINE static ATTRINLINE char R_Rotation2Char(UINT8 rot)
{
return ((rotation <= 8) || (rotation == ROT_L) || (rotation == ROT_R));
if (rot <= 9) return '0' + rot;
if (rot <= 16) return 'A' + (rot - 10);
if (rot == ROT_L) return 'L';
if (rot == ROT_R) return 'R';
return '\xFF';
}
FUNCMATH FUNCINLINE static ATTRINLINE UINT8 R_Char2Rotation(char cn)
{
if (cn >= '0' && cn <= '9') return (cn - '0');
if (cn >= 'A' && cn <= 'G') return (cn - 'A') + 10;
if (cn == 'L') return ROT_L;
if (cn == 'R') return ROT_R;
return 255;
}
#endif //__R_THINGS__

View file

@ -2208,7 +2208,7 @@ static void ST_drawTextHUD(void)
#define textHUDdraw(str) \
{\
V_DrawThinString(16, y, V_PERPLAYER|V_HUDTRANS|V_SNAPTOLEFT|V_SNAPTOBOTTOM, str);\
V_DrawThinString(16, y, V_PERPLAYER|V_HUDTRANS|V_SNAPTOLEFT|V_SNAPTOTOP, str);\
y += 8;\
}