Merge branch SRB2:next into addonloadedhook

This commit is contained in:
Skydusk 2024-07-05 10:24:19 +00:00
commit 675667cb83
66 changed files with 1858 additions and 912 deletions

View file

@ -1,5 +1,5 @@
===============================================================================
Universal Doom Map Format Sonic Robo Blast 2 extensions v1.0 19.02.2024
Universal Doom Map Format Sonic Robo Blast 2 extensions v1.0 19.06.2024
Copyright (c) 2024 Sonic Team Junior
uses Universal Doom Map Format Specification v1.1 as a template,
@ -143,6 +143,9 @@ Sonic Robo Blast 2 defines the following standardized fields:
offsetx_bottom = <float>; // X offset for lower texture. Default = 0.0.
offsety_bottom = <float>; // Y offset for lower texture. Default = 0.0.
light = <integer>; // Light level, relative to 'sector' light level. Default = 0.
lightabsolute = <bool>; // true = 'light' is an absolute value, ignoring 'sector' light level.
comment = <string>; // A comment. Implementors should attach no special
// semantic meaning to this field.
}

View file

@ -115,7 +115,7 @@ mapformat_udmf
// Enables setting distinct brightness for floor, ceiling, and walls
distinctfloorandceilingbrightness = true;
distinctwallbrightness = false;
distinctwallbrightness = true;
// Enables setting distinct brightness for upper, middle, and lower sidedef parts
distinctsidedefpartbrightness = false;

View file

@ -280,18 +280,18 @@ universalfields
default = "";
}
//light
//{
// type = 0;
// default = 0;
//}
//
//lightabsolute
//{
// type = 3;
// default = false;
//}
//
light
{
type = 0;
default = 0;
}
lightabsolute
{
type = 3;
default = false;
}
//light_top
//{
// type = 0;

View file

@ -71,7 +71,7 @@ apng_create_info_struct (png_structp pngp)
{
apng_infop ainfop;
(void)pngp;
if (( ainfop = calloc(sizeof (apng_info),1) ))
if (( ainfop = calloc(1,sizeof (apng_info)) ))
{
apng_set_write_fn(pngp, ainfop, 0, 0, 0, 0, 0);
apng_set_set_acTL_fn(pngp, ainfop, 0);

View file

@ -11,9 +11,6 @@
/// \brief Macros to read/write from/to a UINT8 *,
/// used for packet creation and such
#if defined (__alpha__) || defined (__arm__) || defined (__mips__) || defined (__ia64__) || defined (__clang__)
#define DEALIGNED
#endif
#include "endian.h"
@ -21,7 +18,6 @@
//
// Little-endian machines
//
#ifdef DEALIGNED
#define WRITEUINT8(p,b) do { UINT8 *p_tmp = (void *)p; const UINT8 tv = ( UINT8)(b); memcpy(p, &tv, sizeof( UINT8)); p_tmp++; p = (void *)p_tmp; } while (0)
#define WRITESINT8(p,b) do { SINT8 *p_tmp = (void *)p; const SINT8 tv = ( UINT8)(b); memcpy(p, &tv, sizeof( UINT8)); p_tmp++; p = (void *)p_tmp; } while (0)
#define WRITEINT16(p,b) do { INT16 *p_tmp = (void *)p; const INT16 tv = ( INT16)(b); memcpy(p, &tv, sizeof( INT16)); p_tmp++; p = (void *)p_tmp; } while (0)
@ -31,20 +27,8 @@
#define WRITECHAR(p,b) do { char *p_tmp = (void *)p; const char tv = ( char)(b); memcpy(p, &tv, sizeof( char)); p_tmp++; p = (void *)p_tmp; } while (0)
#define WRITEFIXED(p,b) do { fixed_t *p_tmp = (void *)p; const fixed_t tv = (fixed_t)(b); memcpy(p, &tv, sizeof(fixed_t)); p_tmp++; p = (void *)p_tmp; } while (0)
#define WRITEANGLE(p,b) do { angle_t *p_tmp = (void *)p; const angle_t tv = (angle_t)(b); memcpy(p, &tv, sizeof(angle_t)); p_tmp++; p = (void *)p_tmp; } while (0)
#else
#define WRITEUINT8(p,b) do { UINT8 *p_tmp = ( UINT8 *)p; *p_tmp = ( UINT8)(b); p_tmp++; p = (void *)p_tmp; } while (0)
#define WRITESINT8(p,b) do { SINT8 *p_tmp = ( SINT8 *)p; *p_tmp = ( SINT8)(b); p_tmp++; p = (void *)p_tmp; } while (0)
#define WRITEINT16(p,b) do { INT16 *p_tmp = ( INT16 *)p; *p_tmp = ( INT16)(b); p_tmp++; p = (void *)p_tmp; } while (0)
#define WRITEUINT16(p,b) do { UINT16 *p_tmp = ( UINT16 *)p; *p_tmp = ( UINT16)(b); p_tmp++; p = (void *)p_tmp; } while (0)
#define WRITEINT32(p,b) do { INT32 *p_tmp = ( INT32 *)p; *p_tmp = ( INT32)(b); p_tmp++; p = (void *)p_tmp; } while (0)
#define WRITEUINT32(p,b) do { UINT32 *p_tmp = ( UINT32 *)p; *p_tmp = ( UINT32)(b); p_tmp++; p = (void *)p_tmp; } while (0)
#define WRITECHAR(p,b) do { char *p_tmp = ( char *)p; *p_tmp = ( char)(b); p_tmp++; p = (void *)p_tmp; } while (0)
#define WRITEFIXED(p,b) do { fixed_t *p_tmp = (fixed_t *)p; *p_tmp = (fixed_t)(b); p_tmp++; p = (void *)p_tmp; } while (0)
#define WRITEANGLE(p,b) do { angle_t *p_tmp = (angle_t *)p; *p_tmp = (angle_t)(b); p_tmp++; p = (void *)p_tmp; } while (0)
#endif
#ifdef __GNUC__
#ifdef DEALIGNED
#define READUINT8(p) ({ UINT8 *p_tmp = (void *)p; UINT8 b; memcpy(&b, p, sizeof( UINT8)); p_tmp++; p = (void *)p_tmp; b; })
#define READSINT8(p) ({ SINT8 *p_tmp = (void *)p; SINT8 b; memcpy(&b, p, sizeof( SINT8)); p_tmp++; p = (void *)p_tmp; b; })
#define READINT16(p) ({ INT16 *p_tmp = (void *)p; INT16 b; memcpy(&b, p, sizeof( INT16)); p_tmp++; p = (void *)p_tmp; b; })
@ -55,17 +39,6 @@
#define READFIXED(p) ({ fixed_t *p_tmp = (void *)p; fixed_t b; memcpy(&b, p, sizeof(fixed_t)); p_tmp++; p = (void *)p_tmp; b; })
#define READANGLE(p) ({ angle_t *p_tmp = (void *)p; angle_t b; memcpy(&b, p, sizeof(angle_t)); p_tmp++; p = (void *)p_tmp; b; })
#else
#define READUINT8(p) ({ UINT8 *p_tmp = ( UINT8 *)p; UINT8 b = *p_tmp; p_tmp++; p = (void *)p_tmp; b; })
#define READSINT8(p) ({ SINT8 *p_tmp = ( SINT8 *)p; SINT8 b = *p_tmp; p_tmp++; p = (void *)p_tmp; b; })
#define READINT16(p) ({ INT16 *p_tmp = ( INT16 *)p; INT16 b = *p_tmp; p_tmp++; p = (void *)p_tmp; b; })
#define READUINT16(p) ({ UINT16 *p_tmp = ( UINT16 *)p; UINT16 b = *p_tmp; p_tmp++; p = (void *)p_tmp; b; })
#define READINT32(p) ({ INT32 *p_tmp = ( INT32 *)p; INT32 b = *p_tmp; p_tmp++; p = (void *)p_tmp; b; })
#define READUINT32(p) ({ UINT32 *p_tmp = ( UINT32 *)p; UINT32 b = *p_tmp; p_tmp++; p = (void *)p_tmp; b; })
#define READCHAR(p) ({ char *p_tmp = ( char *)p; char b = *p_tmp; p_tmp++; p = (void *)p_tmp; b; })
#define READFIXED(p) ({ fixed_t *p_tmp = (fixed_t *)p; fixed_t b = *p_tmp; p_tmp++; p = (void *)p_tmp; b; })
#define READANGLE(p) ({ angle_t *p_tmp = (angle_t *)p; angle_t b = *p_tmp; p_tmp++; p = (void *)p_tmp; b; })
#endif
#else
#define READUINT8(p) *(( UINT8 *)p)++
#define READSINT8(p) *(( SINT8 *)p)++
#define READINT16(p) *(( INT16 *)p)++
@ -148,8 +121,6 @@ FUNCINLINE static ATTRINLINE UINT32 readulong(void *ptr)
#define READANGLE(p) ({ angle_t *p_tmp = (angle_t *)p; angle_t b = readulong(p); p_tmp++; p = (void *)p_tmp; b; })
#endif //SRB2_BIG_ENDIAN
#undef DEALIGNED
#define WRITESTRINGN(p, s, n) { \
size_t tmp_i; \
\

View file

@ -1992,7 +1992,7 @@ static void CV_SetCVar(consvar_t *var, const char *value, boolean stealth)
if (var->flags & CV_NETVAR)
{
// send the value of the variable
UINT8 buf[128];
UINT8 buf[512];
UINT8 *p = buf;
// Loading from a config in a netgame? Set revert value.
@ -2065,11 +2065,10 @@ static void CV_SetValueMaybeStealth(consvar_t *var, INT32 value, boolean stealth
if (var == &cv_forceskin) // Special handling.
{
const char *tmpskin = NULL;
if ((value < 0) || (value >= numskins))
;
else
if (value >= 0 && value < numskins)
tmpskin = skins[value]->name;
memcpy(val, tmpskin, SKINNAMESIZE);
if (tmpskin)
memcpy(val, tmpskin, SKINNAMESIZE);
}
else
sprintf(val, "%d", value);

View file

@ -679,13 +679,13 @@ static void D_Display(void)
s[sizeof s - 1] = '\0';
snprintf(s, sizeof s - 1, "get %d b/s", getbps);
V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-ST_HEIGHT-40, V_YELLOWMAP, s);
V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-40, V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "send %d b/s", sendbps);
V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-ST_HEIGHT-30, V_YELLOWMAP, s);
V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-30, V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "GameMiss %.2f%%", gamelostpercent);
V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-ST_HEIGHT-20, V_YELLOWMAP, s);
V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-20, V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "SysMiss %.2f%%", lostpercent);
V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-ST_HEIGHT-10, V_YELLOWMAP, s);
V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-10, V_YELLOWMAP, s);
}
if (cv_perfstats.value)
@ -1024,7 +1024,7 @@ void D_StartTitle(void)
#define REALLOC_FILE_LIST \
if (list->files == NULL) \
{ \
list->files = calloc(sizeof(list->files), 2); \
list->files = calloc(2, sizeof(list->files)); \
list->numfiles = 1; \
} \
else \
@ -1535,7 +1535,7 @@ void D_SRB2Main(void)
I_Error("Cannot find a map remotely named '%s'\n", word);
else
{
if (!M_CheckParm("-server"))
if (!(M_CheckParm("-server") || dedicated))
G_SetUsedCheats(true);
autostart = true;
}

View file

@ -1390,8 +1390,8 @@ static const char *searchWad(const char *searchDir)
#define CHECKWADPATH(ret) \
do { \
I_OutputMsg(",%s", returnWadPath); \
if (isWadPathOk(returnWadPath)) \
I_OutputMsg(",%s", ret); \
if (isWadPathOk(ret)) \
return ret; \
} while (0)
@ -1416,7 +1416,9 @@ static const char *locateWad(void)
#ifndef NOCWD
// examine current dir
strcpy(returnWadPath, ".");
CHECKWADPATH(NULL);
I_OutputMsg(",%s", returnWadPath);
if (isWadPathOk(returnWadPath))
return NULL;
#endif
#ifdef __APPLE__
@ -1433,9 +1435,15 @@ static const char *locateWad(void)
#ifndef NOHOME
// find in $HOME
I_OutputMsg(",HOME");
if ((envstr = I_GetEnv("HOME")) != NULL)
SEARCHWAD(envstr);
{
char *tmp = malloc(strlen(envstr) + 1 + sizeof(DEFAULTDIR));
strcpy(tmp, envstr);
strcat(tmp, "/");
strcat(tmp, DEFAULTDIR);
CHECKWADPATH(tmp);
free(tmp);
}
#endif
// search paths

View file

@ -2791,7 +2791,7 @@ void readframe(MYFILE *f, INT32 num)
size_t z;
boolean found = false;
size_t actionlen = strlen(word2) + 1;
char *actiontocompare = calloc(actionlen, 1);
char *actiontocompare = calloc(1, actionlen);
strcpy(actiontocompare, word2);
strupr(actiontocompare);

View file

@ -4483,6 +4483,8 @@ const char *const PLAYERFLAG_LIST[] = {
"CANCARRY", // Can carry?
"FINISHED",
"SHIELDDOWN", // Shield has been pressed.
NULL // stop loop here.
};

View file

@ -444,12 +444,11 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
strcpy(&searchpath[searchpathindex[depthleft]],dent->d_name);
#if defined(__linux__) || defined(__FreeBSD__)
if (dent->d_type == DT_UNKNOWN)
if (lstat(searchpath,&fsstat) == 0 && S_ISDIR(fsstat.st_mode))
if (dent->d_type == DT_UNKNOWN || dent->d_type == DT_LNK)
if (stat(searchpath,&fsstat) == 0 && S_ISDIR(fsstat.st_mode))
dent->d_type = DT_DIR;
// Linux and FreeBSD has a special field for file type on dirent, so use that to speed up lookups.
// FIXME: should we also follow symlinks?
if (dent->d_type == DT_DIR && depthleft)
#else
if (stat(searchpath,&fsstat) < 0) // do we want to follow symlinks? if not: change it to lstat
@ -1191,7 +1190,7 @@ boolean preparefilemenu(boolean samedepth)
size_t i;
if (filenamebuf == NULL)
filenamebuf = calloc(sizeof(char) * MAX_WADPATH, numwadfiles);
filenamebuf = calloc(numwadfiles, sizeof(char) * MAX_WADPATH);
for (i = 0; i < numwadfiles; i++)
{

View file

@ -3352,7 +3352,7 @@ void G_AddPlayer(INT32 playernum)
p->playerstate = PST_REBORN;
p->height = mobjinfo[MT_PLAYER].height;
p->height = skins[p->skin]->height;
if (G_GametypeUsesLives() || ((netgame || multiplayer) && (gametyperules & GTR_FRIENDLY)))
p->lives = cv_startinglives.value;

View file

@ -450,15 +450,10 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex, GLMipmap_t
texture = textures[texnum];
mipmap->flags = TF_WRAPXY;
mipmap->width = (UINT16)texture->width;
mipmap->height = (UINT16)texture->height;
mipmap->format = textureformat;
blockwidth = texture->width;
blockheight = texture->height;
blocksize = (blockwidth * blockheight);
block = MakeBlock(&grtex->mipmap);
blocksize = blockwidth * blockheight;
block = MakeBlock(mipmap);
// Composite the columns together.
for (i = 0, patch = texture->patches; i < texture->patchcount; i++, patch++)
@ -488,7 +483,7 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex, GLMipmap_t
realpatch = W_CachePatchNumPwad(wadnum, lumpnum, PU_PATCH);
}
HWR_DrawTexturePatchInCache(&grtex->mipmap, blockwidth, blockheight, texture, patch, realpatch);
HWR_DrawTexturePatchInCache(mipmap, blockwidth, blockheight, texture, patch, realpatch);
if (free_patch)
Patch_Free(realpatch);
@ -680,25 +675,24 @@ void HWR_InitMapTextures(void)
gl_maptexturesloaded = false;
}
static void DeleteTextureMipmap(GLMipmap_t *grMipmap)
static void DeleteTextureMipmap(GLMipmap_t *grMipmap, boolean delete_mipmap)
{
HWD.pfnDeleteTexture(grMipmap);
// Chroma-keyed textures do not own their texture data, so do not free it
if (!(grMipmap->flags & TF_CHROMAKEYED))
if (delete_mipmap)
Z_Free(grMipmap->data);
}
static void FreeMapTexture(GLMapTexture_t *tex)
static void FreeMapTexture(GLMapTexture_t *tex, boolean delete_chromakeys)
{
if (tex->mipmap.nextcolormap)
{
DeleteTextureMipmap(tex->mipmap.nextcolormap);
DeleteTextureMipmap(tex->mipmap.nextcolormap, delete_chromakeys);
free(tex->mipmap.nextcolormap);
tex->mipmap.nextcolormap = NULL;
}
DeleteTextureMipmap(&tex->mipmap);
DeleteTextureMipmap(&tex->mipmap, true);
}
void HWR_FreeMapTextures(void)
@ -707,8 +701,8 @@ void HWR_FreeMapTextures(void)
for (i = 0; i < gl_numtextures; i++)
{
FreeMapTexture(&gl_textures[i]);
FreeMapTexture(&gl_flats[i]);
FreeMapTexture(&gl_textures[i], true);
FreeMapTexture(&gl_flats[i], false);
}
// now the heap don't have any 'user' pointing to our
@ -741,22 +735,7 @@ void HWR_LoadMapTextures(size_t pnumtextures)
// --------------------------------------------------------------------------
// Make sure texture is downloaded and set it as the source
// --------------------------------------------------------------------------
static void GetMapTexture(INT32 tex, GLMapTexture_t *grtex, GLMipmap_t *mipmap)
{
// Generate texture if missing from the cache
if (!mipmap->data && !mipmap->downloaded)
HWR_GenerateTexture(tex, grtex, mipmap);
// If hardware does not have the texture, then call pfnSetTexture to upload it
if (!mipmap->downloaded)
HWD.pfnSetTexture(mipmap);
HWR_SetCurrentTexture(mipmap);
// The system-memory data can be purged now.
Z_ChangeTag(mipmap->data, PU_HWRCACHE_UNLOCKED);
}
GLMapTexture_t *HWR_GetTexture(INT32 tex)
GLMapTexture_t *HWR_GetTexture(INT32 tex, boolean chromakeyed)
{
if (tex < 0 || tex >= (signed)gl_numtextures)
{
@ -769,7 +748,46 @@ GLMapTexture_t *HWR_GetTexture(INT32 tex)
GLMapTexture_t *grtex = &gl_textures[tex];
GetMapTexture(tex, grtex, &grtex->mipmap);
GLMipmap_t *grMipmap = &grtex->mipmap;
GLMipmap_t *originalMipmap = grMipmap;
if (!originalMipmap->downloaded)
{
originalMipmap->flags = TF_WRAPXY;
originalMipmap->width = (UINT16)textures[tex]->width;
originalMipmap->height = (UINT16)textures[tex]->height;
originalMipmap->format = textureformat;
}
// If chroma-keyed, create or use a different mipmap for the variant
if (chromakeyed && !textures[tex]->transparency)
{
// Allocate it if it wasn't already
if (!originalMipmap->nextcolormap)
{
GLMipmap_t *newMipmap = calloc(1, sizeof (*grMipmap));
if (newMipmap == NULL)
I_Error("%s: Out of memory", "HWR_GetTexture");
newMipmap->flags = originalMipmap->flags | TF_CHROMAKEYED;
newMipmap->width = originalMipmap->width;
newMipmap->height = originalMipmap->height;
newMipmap->format = originalMipmap->format;
originalMipmap->nextcolormap = newMipmap;
}
// Generate, upload and bind the variant texture instead of the original one
grMipmap = originalMipmap->nextcolormap;
}
if (!grMipmap->data)
HWR_GenerateTexture(tex, grtex, grMipmap);
if (!grMipmap->downloaded)
HWD.pfnSetTexture(grMipmap);
HWR_SetCurrentTexture(grMipmap);
Z_ChangeTag(grMipmap->data, PU_HWRCACHE_UNLOCKED);
return grtex;
}

View file

@ -120,7 +120,7 @@ void HWR_GetPatch(patch_t *patch);
void HWR_GetMappedPatch(patch_t *patch, const UINT8 *colormap);
void HWR_GetFadeMask(lumpnum_t fademasklumpnum);
GLMapTexture_t *HWR_GetTexture(INT32 tex);
GLMapTexture_t *HWR_GetTexture(INT32 tex, boolean chromakeyed);
void HWR_GetLevelFlat(levelflat_t *levelflat, boolean chromakeyed);
void HWR_GetRawFlat(lumpnum_t flatlumpnum);

View file

@ -309,6 +309,43 @@ static FUINT HWR_CalcSlopeLight(FUINT lightnum, angle_t dir, fixed_t delta)
return (FUINT)finallight;
}
static UINT8 HWR_SideLightLevel(side_t *side, INT16 base_lightlevel)
{
return max(0, min(255, side->light +
((side->lightabsolute) ? 0 : base_lightlevel)));
}
/* TODO: implement per-texture lighting
static UINT8 HWR_TopLightLevel(side_t *side, INT16 base_lightlevel)
{
return max(0, min(255, side->light_top +
((side->lightabsolute_top) ? 0 : HWR_SideLightLevel(side, base_lightlevel))));
}
static UINT8 HWR_MidLightLevel(side_t *side, INT16 base_lightlevel)
{
return max(0, min(255, side->light_mid +
((side->lightabsolute_mid) ? 0 : HWR_SideLightLevel(side, base_lightlevel))));
}
static UINT8 HWR_BottomLightLevel(side_t *side, INT16 base_lightlevel)
{
return max(0, min(255, side->light_bottom +
((side->lightabsolute_bottom) ? 0 : HWR_SideLightLevel(side, base_lightlevel))));
}
*/
static UINT8 HWR_FloorLightLevel(sector_t *sector, INT16 base_lightlevel)
{
return max(0, min(255, sector->floorlightlevel +
((sector->floorlightabsolute) ? 0 : base_lightlevel)));
}
static UINT8 HWR_CeilingLightLevel(sector_t *sector, INT16 base_lightlevel)
{
return max(0, min(255, sector->ceilinglightlevel +
((sector->ceilinglightabsolute) ? 0 : base_lightlevel)));
}
// ==========================================================================
// FLOOR/CEILING GENERATION FROM SUBSECTORS
// ==========================================================================
@ -705,8 +742,9 @@ static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum,
fixed_t v2x = FloatToFixed(wallVerts[1].x);
fixed_t v2y = FloatToFixed(wallVerts[1].z);
FUINT lightnum = HWR_SideLightLevel(gl_sidedef, sector->lightlevel);
const UINT8 alpha = Surf->PolyColor.s.alpha;
FUINT lightnum = HWR_CalcWallLight(sector->lightlevel, v1x, v1y, v2x, v2y);
lightnum = HWR_CalcWallLight(lightnum, v1x, v1y, v2x, v2y);
extracolormap_t *colormap = NULL;
if (!r_renderwalls)
@ -750,13 +788,13 @@ static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum,
{
if (pfloor && (pfloor->fofflags & FOF_FOG))
{
lightnum = pfloor->master->frontsector->lightlevel;
lightnum = HWR_SideLightLevel(gl_sidedef, pfloor->master->frontsector->lightlevel);
colormap = pfloor->master->frontsector->extra_colormap;
lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, v1x, v1y, v2x, v2y);
}
else
{
lightnum = *list[i].lightlevel;
lightnum = HWR_SideLightLevel(gl_sidedef, *list[i].lightlevel);
colormap = *list[i].extra_colormap;
lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, v1x, v1y, v2x, v2y);
}
@ -951,7 +989,7 @@ static void HWR_RenderMidtexture(INT32 gl_midtexture, float cliplow, float cliph
else
repeats = 1;
GLMapTexture_t *grTex = HWR_GetTexture(gl_midtexture);
GLMapTexture_t *grTex = HWR_GetTexture(gl_midtexture, true);
float xscale = FixedToFloat(gl_sidedef->scalex_mid);
float yscale = FixedToFloat(gl_sidedef->scaley_mid);
@ -1167,7 +1205,7 @@ static void HWR_ProcessSeg(void)
float cliplow = (float)gl_curline->offset;
float cliphigh = cliplow + (gl_curline->flength * FRACUNIT);
FUINT lightnum = gl_frontsector->lightlevel;
FUINT lightnum = HWR_SideLightLevel(gl_sidedef, gl_frontsector->lightlevel);
extracolormap_t *colormap = gl_frontsector->extra_colormap;
lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, vs.x, vs.y, ve.x, ve.y);
@ -1210,7 +1248,7 @@ static void HWR_ProcessSeg(void)
// check TOP TEXTURE
if ((worldhighslope < worldtopslope || worldhigh < worldtop) && gl_toptexture)
{
grTex = HWR_GetTexture(gl_toptexture);
grTex = HWR_GetTexture(gl_toptexture, false);
xscale = FixedToFloat(abs(gl_sidedef->scalex_top));
yscale = FixedToFloat(abs(gl_sidedef->scaley_top));
@ -1300,7 +1338,7 @@ static void HWR_ProcessSeg(void)
// check BOTTOM TEXTURE
if ((worldlowslope > worldbottomslope || worldlow > worldbottom) && gl_bottomtexture)
{
grTex = HWR_GetTexture(gl_bottomtexture);
grTex = HWR_GetTexture(gl_bottomtexture, false);
xscale = FixedToFloat(abs(gl_sidedef->scalex_bottom));
yscale = FixedToFloat(abs(gl_sidedef->scaley_bottom));
@ -1414,7 +1452,7 @@ static void HWR_ProcessSeg(void)
// Single sided line... Deal only with the middletexture (if one exists)
if (gl_midtexture && gl_linedef->special != SPECIAL_HORIZON_LINE) // (Ignore horizon line for OGL)
{
grTex = HWR_GetTexture(gl_midtexture);
grTex = HWR_GetTexture(gl_midtexture, false);
xscale = FixedToFloat(gl_sidedef->scalex_mid);
yscale = FixedToFloat(gl_sidedef->scaley_mid);
@ -1588,7 +1626,7 @@ static void HWR_ProcessSeg(void)
// -- Monster Iestyn 26/06/18
fixed_t texturevpeg = side->rowoffset + side->offsety_mid;
grTex = HWR_GetTexture(texnum);
grTex = HWR_GetTexture(texnum, true);
xscale = FixedToFloat(side->scalex_mid);
yscale = FixedToFloat(side->scaley_mid);
@ -1628,11 +1666,11 @@ static void HWR_ProcessSeg(void)
{
blendmode = PF_Fog|PF_NoTexture;
lightnum = rover->master->frontsector->lightlevel;
lightnum = HWR_SideLightLevel(gl_sidedef, rover->master->frontsector->lightlevel);
colormap = rover->master->frontsector->extra_colormap;
lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, vs.x, vs.y, ve.x, ve.y);
Surf.PolyColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel, rover->master->frontsector->extra_colormap);
Surf.PolyColor.s.alpha = HWR_FogBlockAlpha(HWR_SideLightLevel(gl_sidedef, rover->master->frontsector->lightlevel), rover->master->frontsector->extra_colormap);
if (gl_frontsector->numlights)
HWR_SplitWall(gl_frontsector, wallVerts, 0, &Surf, rover->fofflags, rover, blendmode);
@ -1745,7 +1783,7 @@ static void HWR_ProcessSeg(void)
// -- Monster Iestyn 26/06/18
fixed_t texturevpeg = side->rowoffset + side->offsety_mid;
grTex = HWR_GetTexture(texnum);
grTex = HWR_GetTexture(texnum, true);
xscale = FixedToFloat(side->scalex_mid);
yscale = FixedToFloat(side->scaley_mid);
@ -1785,7 +1823,7 @@ static void HWR_ProcessSeg(void)
{
blendmode = PF_Fog|PF_NoTexture;
lightnum = rover->master->frontsector->lightlevel;
lightnum = HWR_SideLightLevel(gl_sidedef, rover->master->frontsector->lightlevel);
colormap = rover->master->frontsector->extra_colormap;
lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, vs.x, vs.y, ve.x, ve.y);
@ -2442,7 +2480,7 @@ static void HWR_Subsector(size_t num)
rover; rover = rover->next)
{
fixed_t bottomCullHeight, topCullHeight, centerHeight;
if (!(rover->fofflags & FOF_EXISTS) || !(rover->fofflags & FOF_RENDERPLANES))
continue;
if (sub->validcount == validcount)
@ -2471,13 +2509,13 @@ static void HWR_Subsector(size_t num)
UINT8 alpha;
light = R_GetPlaneLight(gl_frontsector, centerHeight, viewz < bottomCullHeight ? true : false);
alpha = HWR_FogBlockAlpha(*gl_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap);
alpha = HWR_FogBlockAlpha(HWR_FloorLightLevel(rover->master->frontsector, *gl_frontsector->lightlist[light].lightlevel), rover->master->frontsector->extra_colormap);
HWR_AddTransparentFloor(0,
&extrasubsectors[num],
false,
*rover->bottomheight,
*gl_frontsector->lightlist[light].lightlevel,
HWR_FloorLightLevel(rover->master->frontsector, *gl_frontsector->lightlist[light].lightlevel),
alpha, rover->master->frontsector, PF_Fog|PF_NoTexture,
true, false, rover->master->frontsector->extra_colormap);
}
@ -2489,7 +2527,7 @@ static void HWR_Subsector(size_t num)
&extrasubsectors[num],
false,
*rover->bottomheight,
*gl_frontsector->lightlist[light].lightlevel,
HWR_FloorLightLevel(rover->master->frontsector, *gl_frontsector->lightlist[light].lightlevel),
max(0, min(rover->alpha, 255)), rover->master->frontsector,
HWR_RippleBlend(gl_frontsector, rover, false) | (rover->blend ? HWR_GetBlendModeFlag(rover->blend) : PF_Translucent),
false, rover->fofflags & FOF_SPLAT, *gl_frontsector->lightlist[light].extra_colormap);
@ -2498,8 +2536,9 @@ static void HWR_Subsector(size_t num)
{
HWR_GetLevelFlat(&levelflats[*rover->bottompic], rover->fofflags & FOF_SPLAT);
light = R_GetPlaneLight(gl_frontsector, centerHeight, viewz < bottomCullHeight ? true : false);
HWR_RenderPlane(sub, &extrasubsectors[num], false, *rover->bottomheight, HWR_RippleBlend(gl_frontsector, rover, false)|PF_Occlude, *gl_frontsector->lightlist[light].lightlevel, &levelflats[*rover->bottompic],
rover->master->frontsector, 255, *gl_frontsector->lightlist[light].extra_colormap);
HWR_RenderPlane(sub, &extrasubsectors[num], false, *rover->bottomheight, HWR_RippleBlend(gl_frontsector, rover, false)|PF_Occlude,
HWR_FloorLightLevel(rover->master->frontsector, *gl_frontsector->lightlist[light].lightlevel),
&levelflats[*rover->bottompic], rover->master->frontsector, 255, *gl_frontsector->lightlist[light].extra_colormap);
}
}
@ -2516,13 +2555,13 @@ static void HWR_Subsector(size_t num)
UINT8 alpha;
light = R_GetPlaneLight(gl_frontsector, centerHeight, viewz < topCullHeight ? true : false);
alpha = HWR_FogBlockAlpha(*gl_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap);
alpha = HWR_FogBlockAlpha(HWR_CeilingLightLevel(rover->master->frontsector, *gl_frontsector->lightlist[light].lightlevel), rover->master->frontsector->extra_colormap);
HWR_AddTransparentFloor(0,
&extrasubsectors[num],
true,
*rover->topheight,
*gl_frontsector->lightlist[light].lightlevel,
HWR_CeilingLightLevel(rover->master->frontsector, *gl_frontsector->lightlist[light].lightlevel),
alpha, rover->master->frontsector, PF_Fog|PF_NoTexture,
true, false, rover->master->frontsector->extra_colormap);
}
@ -2534,7 +2573,7 @@ static void HWR_Subsector(size_t num)
&extrasubsectors[num],
true,
*rover->topheight,
*gl_frontsector->lightlist[light].lightlevel,
HWR_CeilingLightLevel(rover->master->frontsector, *gl_frontsector->lightlist[light].lightlevel),
max(0, min(rover->alpha, 255)), rover->master->frontsector,
HWR_RippleBlend(gl_frontsector, rover, false) | (rover->blend ? HWR_GetBlendModeFlag(rover->blend) : PF_Translucent),
false, rover->fofflags & FOF_SPLAT, *gl_frontsector->lightlist[light].extra_colormap);
@ -2543,8 +2582,9 @@ static void HWR_Subsector(size_t num)
{
HWR_GetLevelFlat(&levelflats[*rover->toppic], rover->fofflags & FOF_SPLAT);
light = R_GetPlaneLight(gl_frontsector, centerHeight, viewz < topCullHeight ? true : false);
HWR_RenderPlane(sub, &extrasubsectors[num], true, *rover->topheight, HWR_RippleBlend(gl_frontsector, rover, false)|PF_Occlude, *gl_frontsector->lightlist[light].lightlevel, &levelflats[*rover->toppic],
rover->master->frontsector, 255, *gl_frontsector->lightlist[light].extra_colormap);
HWR_RenderPlane(sub, &extrasubsectors[num], true, *rover->topheight, HWR_RippleBlend(gl_frontsector, rover, false)|PF_Occlude,
HWR_CeilingLightLevel(rover->master->frontsector, *gl_frontsector->lightlist[light].lightlevel),
&levelflats[*rover->toppic], rover->master->frontsector, 255, *gl_frontsector->lightlist[light].extra_colormap);
}
}
}
@ -2880,7 +2920,7 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale)
}
HWR_Lighting(&sSurf, 0, colormap);
sSurf.PolyColor.s.alpha = alpha;
sSurf.PolyColor.s.alpha = FixedMul(thing->alpha, alpha);
if (HWR_UseShader())
{
@ -3054,11 +3094,16 @@ static void HWR_SplitSprite(gl_vissprite_t *spr)
// baseWallVerts is used to know the final shape to easily get the vertex
// co-ordinates
memcpy(wallVerts, baseWallVerts, sizeof(baseWallVerts));
fixed_t newalpha = spr->mobj->alpha;
// if sprite has linkdraw, then dont write to z-buffer (by not using PF_Occlude)
// this will result in sprites drawn afterwards to be drawn on top like intended when using linkdraw.
if ((spr->mobj->flags2 & MF2_LINKDRAW) && spr->mobj->tracer)
{
newalpha = spr->mobj->tracer->alpha;
occlusion = 0;
}
else
occlusion = PF_Occlude;
@ -3094,6 +3139,8 @@ static void HWR_SplitSprite(gl_vissprite_t *spr)
blend = HWR_GetBlendModeFlag(blendmode)|occlusion;
if (!occlusion) use_linkdraw_hack = true;
}
Surf.PolyColor.s.alpha = FixedMul(newalpha, Surf.PolyColor.s.alpha);
if (HWR_UseShader())
{
@ -3543,11 +3590,15 @@ static void HWR_DrawSprite(gl_vissprite_t *spr)
FBITFIELD blend = 0;
FBITFIELD occlusion;
boolean use_linkdraw_hack = false;
fixed_t newalpha = spr->mobj->alpha;
// if sprite has linkdraw, then dont write to z-buffer (by not using PF_Occlude)
// this will result in sprites drawn afterwards to be drawn on top like intended when using linkdraw.
if ((spr->mobj->flags2 & MF2_LINKDRAW) && spr->mobj->tracer)
{
occlusion = 0;
newalpha = spr->mobj->tracer->alpha;
}
else
occlusion = PF_Occlude;
@ -3583,6 +3634,8 @@ static void HWR_DrawSprite(gl_vissprite_t *spr)
blend = HWR_GetBlendModeFlag(blendmode)|occlusion;
if (!occlusion) use_linkdraw_hack = true;
}
Surf.PolyColor.s.alpha = FixedMul(newalpha, Surf.PolyColor.s.alpha);
if (spr->renderflags & RF_SHADOWEFFECTS)
{
@ -3893,7 +3946,7 @@ void HWR_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boo
planeinfo[numplanes].isceiling = isceiling;
planeinfo[numplanes].fixedheight = fixedheight;
planeinfo[numplanes].lightlevel = (planecolormap && (planecolormap->flags & CMF_FOG)) ? 255 : lightlevel;
planeinfo[numplanes].lightlevel = (planecolormap && (planecolormap->flags & CMF_FOG)) ? lightlevel : 255; // TODO: 2.3: Make transparent FOF planes always use light level
planeinfo[numplanes].levelflat = levelflat;
planeinfo[numplanes].xsub = xsub;
planeinfo[numplanes].alpha = alpha;
@ -3925,7 +3978,7 @@ void HWR_AddTransparentPolyobjectFloor(levelflat_t *levelflat, polyobj_t *polyse
polyplaneinfo[numpolyplanes].isceiling = isceiling;
polyplaneinfo[numpolyplanes].fixedheight = fixedheight;
polyplaneinfo[numpolyplanes].lightlevel = (planecolormap && (planecolormap->flags & CMF_FOG)) ? 255 : lightlevel;
polyplaneinfo[numpolyplanes].lightlevel = (planecolormap && (planecolormap->flags & CMF_FOG)) ? lightlevel : 255; // TODO: 2.3: Make transparent polyobject planes always use light level
polyplaneinfo[numpolyplanes].levelflat = levelflat;
polyplaneinfo[numpolyplanes].polysector = polysector;
polyplaneinfo[numpolyplanes].alpha = alpha;
@ -4086,7 +4139,7 @@ static void HWR_CreateDrawNodes(void)
else if (sortnode[sortindex[i]].wall)
{
if (!(sortnode[sortindex[i]].wall->blend & PF_NoTexture))
HWR_GetTexture(sortnode[sortindex[i]].wall->texnum);
HWR_GetTexture(sortnode[sortindex[i]].wall->texnum, true);
HWR_RenderWall(sortnode[sortindex[i]].wall->wallVerts, &sortnode[sortindex[i]].wall->Surf, sortnode[sortindex[i]].wall->blend, sortnode[sortindex[i]].wall->fogwall,
sortnode[sortindex[i]].wall->lightlevel, sortnode[sortindex[i]].wall->wallcolormap);
}
@ -5066,6 +5119,8 @@ static void HWR_DrawSkyBackground(player_t *player)
HWD.pfnSetBlend(PF_Translucent|PF_NoDepthTest|PF_Modulated);
HWR_GetTexture(texturetranslation[skytexture], false);
if (cv_glskydome.value)
{
FTransform dometransform;
@ -5081,8 +5136,6 @@ static void HWR_DrawSkyBackground(player_t *player)
HWR_SetTransformAiming(&dometransform, player, false);
dometransform.angley = (float)((viewangle-ANGLE_270)>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES);
HWR_GetTexture(texturetranslation[skytexture]);
if (gl_sky.texture != texturetranslation[skytexture])
{
HWR_ClearSkyDome();
@ -5102,7 +5155,6 @@ static void HWR_DrawSkyBackground(player_t *player)
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

View file

@ -1154,6 +1154,9 @@ static void adjustTextureCoords(model_t *model, patch_t *patch)
int i;
GLPatch_t *gpatch = ((GLPatch_t *)patch->hardware);
if (!gpatch)
return;
for (i = 0; i < model->numMeshes; i++)
{
int j;
@ -1286,6 +1289,11 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
// Apparently people don't like jump frames like that, so back it goes
//if (tics > durs)
//durs = tics;
// Make linkdraw objects use their tracer's alpha value
fixed_t newalpha = spr->mobj->alpha;
if ((spr->mobj->flags2 & MF2_LINKDRAW) && spr->mobj->tracer)
newalpha = spr->mobj->tracer->alpha;
INT32 blendmode;
if (spr->mobj->frame & FF_BLENDMASK)
@ -1300,6 +1308,8 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
Surf.PolyColor.s.alpha = (spr->mobj->flags2 & MF2_SHADOW) ? 0x40 : 0xff;
Surf.PolyFlags = HWR_GetBlendModeFlag(blendmode);
}
Surf.PolyColor.s.alpha = FixedMul(newalpha, Surf.PolyColor.s.alpha);
// don't forget to enable the depth test because we can't do this
// like before: model polygons are not sorted

View file

@ -448,6 +448,101 @@ void HWR_LoadAllCustomShaders(void)
HWR_LoadCustomShadersFromFile(i, W_FileHasFolders(wadfiles[i]));
}
static const char version_directives[][14] = {
"#version 330\n",
"#version 150\n",
"#version 140\n",
"#version 130\n",
"#version 120\n",
"#version 110\n",
};
static boolean HWR_VersionDirectiveExists(const char* source)
{
return strncmp(source, "#version", 8) == 0;
}
static char* HWR_PrependVersionDirective(const char* source, UINT32 version_index)
{
const UINT32 version_len = sizeof(version_directives[version_index]) - 1;
const UINT32 source_len = strlen(source);
char* result = Z_Malloc(source_len + version_len + 1, PU_STATIC, NULL);
strcpy(result, version_directives[version_index]);
strcpy(result + version_len, source);
return result;
}
static void HWR_ReplaceVersionInplace(char* shader, UINT32 version_index)
{
shader[9] = version_directives[version_index][9];
shader[10] = version_directives[version_index][10];
shader[11] = version_directives[version_index][11];
}
static boolean HWR_CheckVersionDirectives(const char* vert, const char* frag)
{
return HWR_VersionDirectiveExists(vert) && HWR_VersionDirectiveExists(frag);
}
static void HWR_TryToCompileShaderWithImplicitVersion(INT32 shader_index, INT32 shaderxlat_id)
{
char* vert_shader = gl_shaders[shader_index].vertex;
char* frag_shader = gl_shaders[shader_index].fragment;
boolean vert_shader_version_exists = HWR_VersionDirectiveExists(vert_shader);
boolean frag_shader_version_exists = HWR_VersionDirectiveExists(frag_shader);
if(!vert_shader_version_exists) {
CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: vertex shader '%s' is missing a #version directive\n", HWR_GetShaderName(shaderxlat_id));
}
if(!frag_shader_version_exists) {
CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: fragment shader '%s' is missing a #version directive\n", HWR_GetShaderName(shaderxlat_id));
}
// try to compile as is
HWR_CompileShader(shader_index);
if (gl_shaders[shader_index].compiled)
return;
// try each version directive
for(UINT32 i = 0; i < sizeof(version_directives) / sizeof(version_directives[0]); ++i) {
CONS_Alert(CONS_NOTICE, "HWR_TryToCompileShaderWithImplicitVersion: Trying %s\n", version_directives[i]);
if(!vert_shader_version_exists) {
// first time reallocation would have to be made
if(i == 0) {
void* old = (void*)gl_shaders[shader_index].vertex;
vert_shader = gl_shaders[shader_index].vertex = HWR_PrependVersionDirective(vert_shader, i);
Z_Free(old);
} else {
HWR_ReplaceVersionInplace(vert_shader, i);
}
}
if(!frag_shader_version_exists) {
if(i == 0) {
void* old = (void*)gl_shaders[shader_index].fragment;
frag_shader = gl_shaders[shader_index].fragment = HWR_PrependVersionDirective(frag_shader, i);
Z_Free(old);
} else {
HWR_ReplaceVersionInplace(frag_shader, i);
}
}
HWR_CompileShader(shader_index);
if (gl_shaders[shader_index].compiled) {
CONS_Alert(CONS_NOTICE, "HWR_TryToCompileShaderWithImplicitVersion: Compiled with %s\n",
version_directives[i]);
CONS_Alert(CONS_WARNING, "Implicit GLSL version is used. Correct behavior is not guaranteed\n");
return;
}
}
}
void HWR_LoadCustomShadersFromFile(UINT16 wadnum, boolean PK3)
{
UINT16 lump;
@ -610,7 +705,13 @@ skip_field:
gl_shaders[shader_index].fragment = Z_StrDup(gl_shadersources[i].fragment);
if (!gl_shaders[shader_index].vertex)
gl_shaders[shader_index].vertex = Z_StrDup(gl_shadersources[i].vertex);
HWR_CompileShader(shader_index);
if(!HWR_CheckVersionDirectives(gl_shaders[shader_index].vertex, gl_shaders[shader_index].fragment)) {
HWR_TryToCompileShaderWithImplicitVersion(shader_index, i);
} else {
HWR_CompileShader(shader_index);
}
if (!gl_shaders[shader_index].compiled)
CONS_Alert(CONS_ERROR, "HWR_LoadCustomShadersFromFile: A compilation error occured for the %s shader in file %s. See the console messages above for more information.\n", shaderxlat[i].type, wadfiles[wadnum]->filename);
}

View file

@ -29,7 +29,7 @@
#include "i_video.h"
#include "i_system.h"
#include "st_stuff.h" // ST_HEIGHT
#include "st_stuff.h"
#include "r_local.h"
#include "keys.h"
@ -204,7 +204,7 @@ void HU_LoadGraphics(void)
HU_SetFontProperties(&hu_font, 0, 4, 8, 12);
HU_SetFontProperties(&tny_font, 0, 2, 4, 12);
HU_SetFontProperties(&cred_font, 0, 16, 16, 16);
HU_SetFontProperties(&lt_font, 0, 16, 20, 20);
HU_SetFontProperties(&lt_font, 0, 16, 20, 16);
HU_SetFontProperties(&ntb_font, 2, 4, 20, 21);
HU_SetFontProperties(&nto_font, 0, 4, 20, 21);
@ -1218,27 +1218,36 @@ static void HU_drawMiniChat(void)
INT32 charwidth = 4, charheight = 6;
INT32 boxw = cv_chatwidth.value;
INT32 dx = 0, dy = 0;
boolean prev_linereturn = false;
if (!chat_nummsg_min)
return; // needless to say it's useless to do anything if we don't have anything to draw.
for (size_t i = chat_nummsg_min; i > 0; i--)
{
char *msg = V_ChatWordWrap(chatx, boxw-charwidth, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i-1]);
char *msg = V_ChatWordWrap(0, boxw-charwidth-2, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE|V_MONOSPACE, chat_mini[i-1]);
for(size_t j = 0; msg[j]; j++) // iterate through msg
{
if (msg[j] == '\n') // get back down.
{
chatheight += charheight;
dx = 0;
if (!prev_linereturn)
{
chatheight += charheight;
dx = 0;
}
prev_linereturn = true;
}
else if (msg[j] >= FONTSTART)
{
prev_linereturn = false;
dx += charwidth;
if (dx >= boxw)
if (dx >= boxw-charwidth-2)
{
dx = 0;
chatheight += charheight;
prev_linereturn = true;
}
}
}
@ -1250,35 +1259,43 @@ static void HU_drawMiniChat(void)
}
y = chaty - (chatheight + charheight);
prev_linereturn = false;
for (size_t i = 0; i < chat_nummsg_min; i++) // iterate through our hot messages
{
INT32 timer = ((cv_chattime.value*TICRATE)-chat_timers[i]) - cv_chattime.value*TICRATE+9; // see below...
INT32 transflag = (timer >= 0 && timer <= 9) ? (timer*V_10TRANS) : 0; // you can make bad jokes out of this one.
char *msg = V_ChatWordWrap(chatx, boxw-charwidth, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i]); // get the current message, and word wrap it.
char *msg = V_ChatWordWrap(0, boxw-charwidth-2, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE|V_MONOSPACE, chat_mini[i]); // get the current message, and word wrap it.
UINT8 *colormap = NULL;
for(size_t j = 0; msg[j]; j++) // iterate through msg
{
if (msg[j] == '\n') // get back down.
{
dy += charheight;
dx = 0;
if (!prev_linereturn)
{
dy += charheight;
dx = 0;
}
prev_linereturn = true;
}
else if (msg[j] & 0x80) // get colormap
colormap = V_GetStringColormap(((msg[j] & 0x7f) << V_CHARCOLORSHIFT) & V_CHARCOLORMASK);
else if (msg[j] >= FONTSTART)
{
prev_linereturn = false;
if (cv_chatbacktint.value) // on request of wolfy
V_DrawFillConsoleMap(x + dx + 2, y+dy, charwidth, charheight, 239|V_SNAPTOBOTTOM|V_SNAPTOLEFT);
V_DrawChatCharacter(x + dx + 2, y+dy, msg[j] |V_SNAPTOBOTTOM|V_SNAPTOLEFT|transflag, true, colormap);
V_DrawChatCharacter(x + dx + 2, y+dy, msg[j] |V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_MONOSPACE|transflag, true, colormap);
dx += charwidth;
if (dx >= boxw)
if (dx >= boxw-charwidth-2)
{
dx = 0;
dy += charheight;
prev_linereturn = true;
}
}
}
@ -1303,6 +1320,7 @@ static void HU_drawChatLog(INT32 offset)
UINT32 i = 0;
INT32 chat_topy, chat_bottomy;
boolean atbottom = false;
boolean prev_linereturn = false;
// make sure that our scroll position isn't "illegal";
if (chat_scroll > chat_maxscroll)
@ -1335,27 +1353,38 @@ static void HU_drawChatLog(INT32 offset)
for (i=0; i<chat_nummsg_log; i++) // iterate through our chatlog
{
char *msg = V_ChatWordWrap(chatx, boxw-charwidth, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_log[i]); // get the current message, and word wrap it.
char *msg = V_ChatWordWrap(0, boxw-charwidth-2, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE|V_MONOSPACE, chat_log[i]); // get the current message, and word wrap it.
UINT8 *colormap = NULL;
for(size_t j = 0; msg[j]; j++) // iterate through msg
{
if (msg[j] == '\n') // get back down.
{
dy += charheight;
dx = 0;
if (!prev_linereturn)
{
dy += charheight;
dx = 0;
}
prev_linereturn = true;
}
else if (msg[j] & 0x80) // get colormap
colormap = V_GetStringColormap(((msg[j] & 0x7f) << V_CHARCOLORSHIFT) & V_CHARCOLORMASK);
else if (msg[j] >= FONTSTART)
else
{
if ((y+dy+2 >= chat_topy) && (y+dy < (chat_bottomy)))
V_DrawChatCharacter(x + dx + 2, y+dy+2, msg[j] |V_SNAPTOBOTTOM|V_SNAPTOLEFT, true, colormap);
prev_linereturn = false;
dx += charwidth;
if (dx >= boxw-charwidth-2 && i<chat_nummsg_log) // end of message shouldn't count, nor should invisible characters!!!!
if (msg[j] >= FONTSTART)
{
if ((y+dy+2 >= chat_topy) && (y+dy < (chat_bottomy)))
V_DrawChatCharacter(x + dx + 2, y+dy+2, msg[j] |V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_MONOSPACE, true, colormap);
dx += charwidth;
}
if (dx >= boxw-charwidth-2 && i < chat_nummsg_log) // end of message shouldn't count, nor should invisible characters!!!!
{
dx = 0;
dy += charheight;
prev_linereturn = true;
}
}
}
@ -2463,53 +2492,20 @@ static inline void HU_DrawSpectatorTicker(void)
{
int i;
int length = 0, height = 174;
int totallength = 0, templength = 0;
int totallength = 0;
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].spectator)
totallength += (signed)strlen(player_names[i]) * 8 + 16;
length -= (leveltime % (totallength + BASEVIDWIDTH));
length += BASEVIDWIDTH;
length -= (leveltime % (totallength + (vid.width / vid.dup)));
length += (vid.width / vid.dup);
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].spectator)
{
char *pos;
char initial[MAXPLAYERNAME+1];
char current[MAXPLAYERNAME+1];
strcpy(initial, player_names[i]);
pos = initial;
if (length >= -((signed)strlen(player_names[i]) * 8 + 16) && length <= BASEVIDWIDTH)
{
if (length < 0)
{
UINT8 eatenchars = (UINT8)(abs(length) / 8 + 1);
if (eatenchars <= strlen(initial))
{
// Eat one letter off the left side,
// then compensate the drawing position.
pos += eatenchars;
strcpy(current, pos);
templength = length % 8 + 8;
}
else
{
strcpy(current, " ");
templength = length;
}
}
else
{
strcpy(current, initial);
templength = length;
}
V_DrawString(templength, height + 8, V_TRANSLUCENT|V_ALLOWLOWERCASE, current);
}
if (length >= -((signed)strlen(player_names[i]) * 8 + 16) && length <= (vid.width / vid.dup))
V_DrawString(length, height + 8, V_TRANSLUCENT|V_ALLOWLOWERCASE|V_SNAPTOLEFT, player_names[i]);
length += (signed)strlen(player_names[i]) * 8 + 16;
}

View file

@ -298,276 +298,278 @@ enum actionnum
NUMACTIONS
};
struct mobj_s;
// IMPORTANT NOTE: If you add/remove from this list of action
// functions, don't forget to update them in deh_tables.c!
void A_Explode();
void A_Pain();
void A_Fall();
void A_MonitorPop();
void A_GoldMonitorPop();
void A_GoldMonitorRestore();
void A_GoldMonitorSparkle();
void A_Look();
void A_Chase();
void A_FaceStabChase();
void A_FaceStabRev();
void A_FaceStabHurl();
void A_FaceStabMiss();
void A_StatueBurst();
void A_FaceTarget();
void A_FaceTracer();
void A_Scream();
void A_BossDeath();
void A_SetShadowScale();
void A_ShadowScream(); // MARIA!!!!!!
void A_CustomPower(); // Use this for a custom power
void A_GiveWeapon(); // Gives the player weapon(s)
void A_RingBox(); // Obtained Ring Box Tails
void A_Invincibility(); // Obtained Invincibility Box
void A_SuperSneakers(); // Obtained Super Sneakers Box
void A_BunnyHop(); // have bunny hop tails
void A_BubbleSpawn(); // Randomly spawn bubbles
void A_FanBubbleSpawn();
void A_BubbleRise(); // Bubbles float to surface
void A_BubbleCheck(); // Don't draw if not underwater
void A_AwardScore();
void A_ExtraLife(); // Extra Life
void A_GiveShield(); // Obtained Shield
void A_GravityBox();
void A_ScoreRise(); // Rise the score logo
void A_AttractChase(); // Ring Chase
void A_DropMine(); // Drop Mine from Skim or Jetty-Syn Bomber
void A_FishJump(); // Fish Jump
void A_ThrownRing(); // Sparkle trail for red ring
void A_SetSolidSteam();
void A_UnsetSolidSteam();
void A_SignSpin();
void A_SignPlayer();
void A_OverlayThink();
void A_JetChase();
void A_JetbThink(); // Jetty-Syn Bomber Thinker
void A_JetgThink(); // Jetty-Syn Gunner Thinker
void A_JetgShoot(); // Jetty-Syn Shoot Function
void A_ShootBullet(); // JetgShoot without reactiontime setting
void A_MinusDigging();
void A_MinusPopup();
void A_MinusCheck();
void A_ChickenCheck();
void A_MouseThink(); // Mouse Thinker
void A_DetonChase(); // Deton Chaser
void A_CapeChase(); // Fake little Super Sonic cape
void A_RotateSpikeBall(); // Spike ball rotation
void A_SlingAppear();
void A_UnidusBall();
void A_RockSpawn();
void A_SetFuse();
void A_CrawlaCommanderThink(); // Crawla Commander
void A_SmokeTrailer();
void A_RingExplode();
void A_OldRingExplode();
void A_MixUp();
void A_RecyclePowers();
void A_BossScream();
void A_Boss2TakeDamage();
void A_GoopSplat();
void A_Boss2PogoSFX();
void A_Boss2PogoTarget();
void A_EggmanBox();
void A_TurretFire();
void A_SuperTurretFire();
void A_TurretStop();
void A_JetJawRoam();
void A_JetJawChomp();
void A_PointyThink();
void A_CheckBuddy();
void A_HoodFire();
void A_HoodThink();
void A_HoodFall();
void A_ArrowBonks();
void A_SnailerThink();
void A_SharpChase();
void A_SharpSpin();
void A_SharpDecel();
void A_CrushstaceanWalk();
void A_CrushstaceanPunch();
void A_CrushclawAim();
void A_CrushclawLaunch();
void A_VultureVtol();
void A_VultureCheck();
void A_VultureHover();
void A_VultureBlast();
void A_VultureFly();
void A_SkimChase();
void A_SkullAttack();
void A_LobShot();
void A_FireShot();
void A_SuperFireShot();
void A_BossFireShot();
void A_Boss7FireMissiles();
void A_Boss1Laser();
void A_FocusTarget();
void A_Boss4Reverse();
void A_Boss4SpeedUp();
void A_Boss4Raise();
void A_SparkFollow();
void A_BuzzFly();
void A_GuardChase();
void A_EggShield();
void A_SetReactionTime();
void A_Boss1Spikeballs();
void A_Boss3TakeDamage();
void A_Boss3Path();
void A_Boss3ShockThink();
void A_Shockwave();
void A_LinedefExecute();
void A_LinedefExecuteFromArg();
void A_PlaySeeSound();
void A_PlayAttackSound();
void A_PlayActiveSound();
void A_1upThinker();
void A_BossZoom(); //Unused
void A_Boss1Chase();
void A_Boss2Chase();
void A_Boss2Pogo();
void A_Boss7Chase();
void A_BossJetFume();
void A_SpawnObjectAbsolute();
void A_SpawnObjectRelative();
void A_ChangeAngleRelative();
void A_ChangeAngleAbsolute();
void A_RollAngle();
void A_ChangeRollAngleRelative();
void A_ChangeRollAngleAbsolute();
void A_PlaySound();
void A_FindTarget();
void A_FindTracer();
void A_SetTics();
void A_SetRandomTics();
void A_ChangeColorRelative();
void A_ChangeColorAbsolute();
void A_Dye();
void A_SetTranslation();
void A_MoveRelative();
void A_MoveAbsolute();
void A_Thrust();
void A_ZThrust();
void A_SetTargetsTarget();
void A_SetObjectFlags();
void A_SetObjectFlags2();
void A_RandomState();
void A_RandomStateRange();
void A_StateRangeByAngle();
void A_StateRangeByParameter();
void A_DualAction();
void A_RemoteAction();
void A_ToggleFlameJet();
void A_OrbitNights();
void A_GhostMe();
void A_SetObjectState();
void A_SetObjectTypeState();
void A_KnockBack();
void A_PushAway();
void A_RingDrain();
void A_SplitShot();
void A_MissileSplit();
void A_MultiShot();
void A_InstaLoop();
void A_Custom3DRotate();
void A_SearchForPlayers();
void A_CheckRandom();
void A_CheckTargetRings();
void A_CheckRings();
void A_CheckTotalRings();
void A_CheckHealth();
void A_CheckRange();
void A_CheckHeight();
void A_CheckTrueRange();
void A_CheckThingCount();
void A_CheckAmbush();
void A_CheckCustomValue();
void A_CheckCusValMemo();
void A_SetCustomValue();
void A_UseCusValMemo();
void A_RelayCustomValue();
void A_CusValAction();
void A_ForceStop();
void A_ForceWin();
void A_SpikeRetract();
void A_InfoState();
void A_Repeat();
void A_SetScale();
void A_RemoteDamage();
void A_HomingChase();
void A_TrapShot();
void A_VileTarget();
void A_VileAttack();
void A_VileFire();
void A_BrakChase();
void A_BrakFireShot();
void A_BrakLobShot();
void A_NapalmScatter();
void A_SpawnFreshCopy();
void A_FlickySpawn();
void A_FlickyCenter();
void A_FlickyAim();
void A_FlickyFly();
void A_FlickySoar();
void A_FlickyCoast();
void A_FlickyHop();
void A_FlickyFlounder();
void A_FlickyCheck();
void A_FlickyHeightCheck();
void A_FlickyFlutter();
void A_FlameParticle();
void A_FadeOverlay();
void A_Boss5Jump();
void A_LightBeamReset();
void A_MineExplode();
void A_MineRange();
void A_ConnectToGround();
void A_SpawnParticleRelative();
void A_MultiShotDist();
void A_WhoCaresIfYourSonIsABee();
void A_ParentTriesToSleep();
void A_CryingToMomma();
void A_CheckFlags2();
void A_Boss5FindWaypoint();
void A_DoNPCSkid();
void A_DoNPCPain();
void A_PrepareRepeat();
void A_Boss5ExtraRepeat();
void A_Boss5Calm();
void A_Boss5CheckOnGround();
void A_Boss5CheckFalling();
void A_Boss5PinchShot();
void A_Boss5MakeItRain();
void A_Boss5MakeJunk();
void A_LookForBetter();
void A_Boss5BombExplode();
void A_DustDevilThink();
void A_TNTExplode();
void A_DebrisRandom();
void A_TrainCameo();
void A_TrainCameo2();
void A_CanarivoreGas();
void A_KillSegments();
void A_SnapperSpawn();
void A_SnapperThinker();
void A_SaloonDoorSpawn();
void A_MinecartSparkThink();
void A_ModuloToState();
void A_LavafallRocks();
void A_LavafallLava();
void A_FallingLavaCheck();
void A_FireShrink();
void A_SpawnPterabytes();
void A_PterabyteHover();
void A_RolloutSpawn();
void A_RolloutRock();
void A_DragonbomberSpawn();
void A_DragonWing();
void A_DragonSegment();
void A_ChangeHeight();
void A_Explode(struct mobj_s *actor);
void A_Pain(struct mobj_s *actor);
void A_Fall(struct mobj_s *actor);
void A_MonitorPop(struct mobj_s *actor);
void A_GoldMonitorPop(struct mobj_s *actor);
void A_GoldMonitorRestore(struct mobj_s *actor);
void A_GoldMonitorSparkle(struct mobj_s *actor);
void A_Look(struct mobj_s *actor);
void A_Chase(struct mobj_s *actor);
void A_FaceStabChase(struct mobj_s *actor);
void A_FaceStabRev(struct mobj_s *actor);
void A_FaceStabHurl(struct mobj_s *actor);
void A_FaceStabMiss(struct mobj_s *actor);
void A_StatueBurst(struct mobj_s *actor);
void A_FaceTarget(struct mobj_s *actor);
void A_FaceTracer(struct mobj_s *actor);
void A_Scream(struct mobj_s *actor);
void A_BossDeath(struct mobj_s *actor);
void A_SetShadowScale(struct mobj_s *actor);
void A_ShadowScream(struct mobj_s *actor); // MARIA!!!!!!
void A_CustomPower(struct mobj_s *actor); // Use this for a custom power
void A_GiveWeapon(struct mobj_s *actor); // Gives the player weapon(s)
void A_RingBox(struct mobj_s *actor); // Obtained Ring Box Tails
void A_Invincibility(struct mobj_s *actor); // Obtained Invincibility Box
void A_SuperSneakers(struct mobj_s *actor); // Obtained Super Sneakers Box
void A_BunnyHop(struct mobj_s *actor); // have bunny hop tails
void A_BubbleSpawn(struct mobj_s *actor); // Randomly spawn bubbles
void A_FanBubbleSpawn(struct mobj_s *actor);
void A_BubbleRise(struct mobj_s *actor); // Bubbles float to surface
void A_BubbleCheck(struct mobj_s *actor); // Don't draw if not underwater
void A_AwardScore(struct mobj_s *actor);
void A_ExtraLife(struct mobj_s *actor); // Extra Life
void A_GiveShield(struct mobj_s *actor); // Obtained Shield
void A_GravityBox(struct mobj_s *actor);
void A_ScoreRise(struct mobj_s *actor); // Rise the score logo
void A_AttractChase(struct mobj_s *actor); // Ring Chase
void A_DropMine(struct mobj_s *actor); // Drop Mine from Skim or Jetty-Syn Bomber
void A_FishJump(struct mobj_s *actor); // Fish Jump
void A_ThrownRing(struct mobj_s *actor); // Sparkle trail for red ring
void A_SetSolidSteam(struct mobj_s *actor);
void A_UnsetSolidSteam(struct mobj_s *actor);
void A_SignSpin(struct mobj_s *actor);
void A_SignPlayer(struct mobj_s *actor);
void A_OverlayThink(struct mobj_s *actor);
void A_JetChase(struct mobj_s *actor);
void A_JetbThink(struct mobj_s *actor); // Jetty-Syn Bomber Thinker
void A_JetgThink(struct mobj_s *actor); // Jetty-Syn Gunner Thinker
void A_JetgShoot(struct mobj_s *actor); // Jetty-Syn Shoot Function
void A_ShootBullet(struct mobj_s *actor); // JetgShoot without reactiontime setting
void A_MinusDigging(struct mobj_s *actor);
void A_MinusPopup(struct mobj_s *actor);
void A_MinusCheck(struct mobj_s *actor);
void A_ChickenCheck(struct mobj_s *actor);
void A_MouseThink(struct mobj_s *actor); // Mouse Thinker
void A_DetonChase(struct mobj_s *actor); // Deton Chaser
void A_CapeChase(struct mobj_s *actor); // Fake little Super Sonic cape
void A_RotateSpikeBall(struct mobj_s *actor); // Spike ball rotation
void A_SlingAppear(struct mobj_s *actor);
void A_UnidusBall(struct mobj_s *actor);
void A_RockSpawn(struct mobj_s *actor);
void A_SetFuse(struct mobj_s *actor);
void A_CrawlaCommanderThink(struct mobj_s *actor); // Crawla Commander
void A_SmokeTrailer(struct mobj_s *actor);
void A_RingExplode(struct mobj_s *actor);
void A_OldRingExplode(struct mobj_s *actor);
void A_MixUp(struct mobj_s *actor);
void A_RecyclePowers(struct mobj_s *actor);
void A_BossScream(struct mobj_s *actor);
void A_Boss2TakeDamage(struct mobj_s *actor);
void A_GoopSplat(struct mobj_s *actor);
void A_Boss2PogoSFX(struct mobj_s *actor);
void A_Boss2PogoTarget(struct mobj_s *actor);
void A_EggmanBox(struct mobj_s *actor);
void A_TurretFire(struct mobj_s *actor);
void A_SuperTurretFire(struct mobj_s *actor);
void A_TurretStop(struct mobj_s *actor);
void A_JetJawRoam(struct mobj_s *actor);
void A_JetJawChomp(struct mobj_s *actor);
void A_PointyThink(struct mobj_s *actor);
void A_CheckBuddy(struct mobj_s *actor);
void A_HoodFire(struct mobj_s *actor);
void A_HoodThink(struct mobj_s *actor);
void A_HoodFall(struct mobj_s *actor);
void A_ArrowBonks(struct mobj_s *actor);
void A_SnailerThink(struct mobj_s *actor);
void A_SharpChase(struct mobj_s *actor);
void A_SharpSpin(struct mobj_s *actor);
void A_SharpDecel(struct mobj_s *actor);
void A_CrushstaceanWalk(struct mobj_s *actor);
void A_CrushstaceanPunch(struct mobj_s *actor);
void A_CrushclawAim(struct mobj_s *actor);
void A_CrushclawLaunch(struct mobj_s *actor);
void A_VultureVtol(struct mobj_s *actor);
void A_VultureCheck(struct mobj_s *actor);
void A_VultureHover(struct mobj_s *actor);
void A_VultureBlast(struct mobj_s *actor);
void A_VultureFly(struct mobj_s *actor);
void A_SkimChase(struct mobj_s *actor);
void A_SkullAttack(struct mobj_s *actor);
void A_LobShot(struct mobj_s *actor);
void A_FireShot(struct mobj_s *actor);
void A_SuperFireShot(struct mobj_s *actor);
void A_BossFireShot(struct mobj_s *actor);
void A_Boss7FireMissiles(struct mobj_s *actor);
void A_Boss1Laser(struct mobj_s *actor);
void A_FocusTarget(struct mobj_s *actor);
void A_Boss4Reverse(struct mobj_s *actor);
void A_Boss4SpeedUp(struct mobj_s *actor);
void A_Boss4Raise(struct mobj_s *actor);
void A_SparkFollow(struct mobj_s *actor);
void A_BuzzFly(struct mobj_s *actor);
void A_GuardChase(struct mobj_s *actor);
void A_EggShield(struct mobj_s *actor);
void A_SetReactionTime(struct mobj_s *actor);
void A_Boss1Spikeballs(struct mobj_s *actor);
void A_Boss3TakeDamage(struct mobj_s *actor);
void A_Boss3Path(struct mobj_s *actor);
void A_Boss3ShockThink(struct mobj_s *actor);
void A_Shockwave(struct mobj_s *actor);
void A_LinedefExecute(struct mobj_s *actor);
void A_LinedefExecuteFromArg(struct mobj_s *actor);
void A_PlaySeeSound(struct mobj_s *actor);
void A_PlayAttackSound(struct mobj_s *actor);
void A_PlayActiveSound(struct mobj_s *actor);
void A_1upThinker(struct mobj_s *actor);
void A_BossZoom(struct mobj_s *actor); //Unused
void A_Boss1Chase(struct mobj_s *actor);
void A_Boss2Chase(struct mobj_s *actor);
void A_Boss2Pogo(struct mobj_s *actor);
void A_Boss7Chase(struct mobj_s *actor);
void A_BossJetFume(struct mobj_s *actor);
void A_SpawnObjectAbsolute(struct mobj_s *actor);
void A_SpawnObjectRelative(struct mobj_s *actor);
void A_ChangeAngleRelative(struct mobj_s *actor);
void A_ChangeAngleAbsolute(struct mobj_s *actor);
void A_RollAngle(struct mobj_s *actor);
void A_ChangeRollAngleRelative(struct mobj_s *actor);
void A_ChangeRollAngleAbsolute(struct mobj_s *actor);
void A_PlaySound(struct mobj_s *actor);
void A_FindTarget(struct mobj_s *actor);
void A_FindTracer(struct mobj_s *actor);
void A_SetTics(struct mobj_s *actor);
void A_SetRandomTics(struct mobj_s *actor);
void A_ChangeColorRelative(struct mobj_s *actor);
void A_ChangeColorAbsolute(struct mobj_s *actor);
void A_Dye(struct mobj_s *actor);
void A_SetTranslation(struct mobj_s *actor);
void A_MoveRelative(struct mobj_s *actor);
void A_MoveAbsolute(struct mobj_s *actor);
void A_Thrust(struct mobj_s *actor);
void A_ZThrust(struct mobj_s *actor);
void A_SetTargetsTarget(struct mobj_s *actor);
void A_SetObjectFlags(struct mobj_s *actor);
void A_SetObjectFlags2(struct mobj_s *actor);
void A_RandomState(struct mobj_s *actor);
void A_RandomStateRange(struct mobj_s *actor);
void A_StateRangeByAngle(struct mobj_s *actor);
void A_StateRangeByParameter(struct mobj_s *actor);
void A_DualAction(struct mobj_s *actor);
void A_RemoteAction(struct mobj_s *actor);
void A_ToggleFlameJet(struct mobj_s *actor);
void A_OrbitNights(struct mobj_s *actor);
void A_GhostMe(struct mobj_s *actor);
void A_SetObjectState(struct mobj_s *actor);
void A_SetObjectTypeState(struct mobj_s *actor);
void A_KnockBack(struct mobj_s *actor);
void A_PushAway(struct mobj_s *actor);
void A_RingDrain(struct mobj_s *actor);
void A_SplitShot(struct mobj_s *actor);
void A_MissileSplit(struct mobj_s *actor);
void A_MultiShot(struct mobj_s *actor);
void A_InstaLoop(struct mobj_s *actor);
void A_Custom3DRotate(struct mobj_s *actor);
void A_SearchForPlayers(struct mobj_s *actor);
void A_CheckRandom(struct mobj_s *actor);
void A_CheckTargetRings(struct mobj_s *actor);
void A_CheckRings(struct mobj_s *actor);
void A_CheckTotalRings(struct mobj_s *actor);
void A_CheckHealth(struct mobj_s *actor);
void A_CheckRange(struct mobj_s *actor);
void A_CheckHeight(struct mobj_s *actor);
void A_CheckTrueRange(struct mobj_s *actor);
void A_CheckThingCount(struct mobj_s *actor);
void A_CheckAmbush(struct mobj_s *actor);
void A_CheckCustomValue(struct mobj_s *actor);
void A_CheckCusValMemo(struct mobj_s *actor);
void A_SetCustomValue(struct mobj_s *actor);
void A_UseCusValMemo(struct mobj_s *actor);
void A_RelayCustomValue(struct mobj_s *actor);
void A_CusValAction(struct mobj_s *actor);
void A_ForceStop(struct mobj_s *actor);
void A_ForceWin(struct mobj_s *actor);
void A_SpikeRetract(struct mobj_s *actor);
void A_InfoState(struct mobj_s *actor);
void A_Repeat(struct mobj_s *actor);
void A_SetScale(struct mobj_s *actor);
void A_RemoteDamage(struct mobj_s *actor);
void A_HomingChase(struct mobj_s *actor);
void A_TrapShot(struct mobj_s *actor);
void A_VileTarget(struct mobj_s *actor);
void A_VileAttack(struct mobj_s *actor);
void A_VileFire(struct mobj_s *actor);
void A_BrakChase(struct mobj_s *actor);
void A_BrakFireShot(struct mobj_s *actor);
void A_BrakLobShot(struct mobj_s *actor);
void A_NapalmScatter(struct mobj_s *actor);
void A_SpawnFreshCopy(struct mobj_s *actor);
void A_FlickySpawn(struct mobj_s *actor);
void A_FlickyCenter(struct mobj_s *actor);
void A_FlickyAim(struct mobj_s *actor);
void A_FlickyFly(struct mobj_s *actor);
void A_FlickySoar(struct mobj_s *actor);
void A_FlickyCoast(struct mobj_s *actor);
void A_FlickyHop(struct mobj_s *actor);
void A_FlickyFlounder(struct mobj_s *actor);
void A_FlickyCheck(struct mobj_s *actor);
void A_FlickyHeightCheck(struct mobj_s *actor);
void A_FlickyFlutter(struct mobj_s *actor);
void A_FlameParticle(struct mobj_s *actor);
void A_FadeOverlay(struct mobj_s *actor);
void A_Boss5Jump(struct mobj_s *actor);
void A_LightBeamReset(struct mobj_s *actor);
void A_MineExplode(struct mobj_s *actor);
void A_MineRange(struct mobj_s *actor);
void A_ConnectToGround(struct mobj_s *actor);
void A_SpawnParticleRelative(struct mobj_s *actor);
void A_MultiShotDist(struct mobj_s *actor);
void A_WhoCaresIfYourSonIsABee(struct mobj_s *actor);
void A_ParentTriesToSleep(struct mobj_s *actor);
void A_CryingToMomma(struct mobj_s *actor);
void A_CheckFlags2(struct mobj_s *actor);
void A_Boss5FindWaypoint(struct mobj_s *actor);
void A_DoNPCSkid(struct mobj_s *actor);
void A_DoNPCPain(struct mobj_s *actor);
void A_PrepareRepeat(struct mobj_s *actor);
void A_Boss5ExtraRepeat(struct mobj_s *actor);
void A_Boss5Calm(struct mobj_s *actor);
void A_Boss5CheckOnGround(struct mobj_s *actor);
void A_Boss5CheckFalling(struct mobj_s *actor);
void A_Boss5PinchShot(struct mobj_s *actor);
void A_Boss5MakeItRain(struct mobj_s *actor);
void A_Boss5MakeJunk(struct mobj_s *actor);
void A_LookForBetter(struct mobj_s *actor);
void A_Boss5BombExplode(struct mobj_s *actor);
void A_DustDevilThink(struct mobj_s *actor);
void A_TNTExplode(struct mobj_s *actor);
void A_DebrisRandom(struct mobj_s *actor);
void A_TrainCameo(struct mobj_s *actor);
void A_TrainCameo2(struct mobj_s *actor);
void A_CanarivoreGas(struct mobj_s *actor);
void A_KillSegments(struct mobj_s *actor);
void A_SnapperSpawn(struct mobj_s *actor);
void A_SnapperThinker(struct mobj_s *actor);
void A_SaloonDoorSpawn(struct mobj_s *actor);
void A_MinecartSparkThink(struct mobj_s *actor);
void A_ModuloToState(struct mobj_s *actor);
void A_LavafallRocks(struct mobj_s *actor);
void A_LavafallLava(struct mobj_s *actor);
void A_FallingLavaCheck(struct mobj_s *actor);
void A_FireShrink(struct mobj_s *actor);
void A_SpawnPterabytes(struct mobj_s *actor);
void A_PterabyteHover(struct mobj_s *actor);
void A_RolloutSpawn(struct mobj_s *actor);
void A_RolloutRock(struct mobj_s *actor);
void A_DragonbomberSpawn(struct mobj_s *actor);
void A_DragonWing(struct mobj_s *actor);
void A_DragonSegment(struct mobj_s *actor);
void A_ChangeHeight(struct mobj_s *actor);
extern int actionsoverridden[NUMACTIONS][MAX_ACTION_RECURSION];

View file

@ -184,8 +184,10 @@ static const struct {
{META_SKIN, "skin_t"},
{META_POWERS, "player_t.powers"},
{META_SOUNDSID, "skin_t.soundsid"},
{META_SKINSPRITES, "skin_t.sprites"},
{META_SKINSPRITESLIST, "skin_t.sprites[]"},
{META_SKINSPRITES, "skin_t.skinsprites"},
{META_SKINSPRITESLIST, "skin_t.skinsprites[]"},
{META_SKINSPRITESCOMPAT, "skin_t.sprites"}, // TODO: 2.3: Delete
{META_VERTEX, "vertex_t"},
{META_LINE, "line_t"},
@ -653,7 +655,7 @@ static int lib_pSpawnMobj(lua_State *L)
NOHUD
INLEVEL
NOSPAWNNULL
LUA_PushUserdata(L, P_SpawnMobj(x, y, z, type), META_MOBJ);
LUA_PushUserdata(L, P_SpawnMobj(x, y, z, type, NULL), META_MOBJ);
return 1;
}
@ -3876,7 +3878,7 @@ static int lib_gAddPlayer(lua_State *L)
player_t *newplayer;
SINT8 skinnum = 0, bot;
for (i = 0; i < MAXPLAYERS; i++)
for (i = 1; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
break;

View file

@ -42,8 +42,9 @@ extern boolean ignoregameinputs;
#define META_SKIN "SKIN_T*"
#define META_POWERS "PLAYER_T*POWERS"
#define META_SOUNDSID "SKIN_T*SOUNDSID"
#define META_SKINSPRITES "SKIN_T*SPRITES"
#define META_SKINSPRITESLIST "SKIN_T*SPRITES[]"
#define META_SKINSPRITES "SKIN_T*SKINSPRITES"
#define META_SKINSPRITESLIST "SKIN_T*SKINSPRITES[]"
#define META_SKINSPRITESCOMPAT "SKIN_T*SPRITES" // TODO: 2.3: Delete
#define META_VERTEX "VERTEX_T*"
#define META_LINE "LINE_T*"

View file

@ -213,6 +213,14 @@ enum side_e {
side_sector,
side_special,
side_repeatcnt,
side_light,
side_light_top,
side_light_mid,
side_light_bottom,
side_lightabsolute,
side_lightabsolute_top,
side_lightabsolute_mid,
side_lightabsolute_bottom,
side_text
};
@ -241,6 +249,14 @@ static const char *const side_opt[] = {
"sector",
"special",
"repeatcnt",
"light",
"light_top",
"light_mid",
"light_bottom",
"lightabsolute",
"lightabsolute_top",
"lightabsolute_mid",
"lightabsolute_bottom",
"text",
NULL};
@ -1311,6 +1327,30 @@ static int side_get(lua_State *L)
case side_repeatcnt:
lua_pushinteger(L, side->repeatcnt);
return 1;
case side_light:
lua_pushinteger(L, side->light);
return 1;
case side_light_top:
lua_pushinteger(L, side->light_top);
return 1;
case side_light_mid:
lua_pushinteger(L, side->light_mid);
return 1;
case side_light_bottom:
lua_pushinteger(L, side->light_bottom);
return 1;
case side_lightabsolute:
lua_pushboolean(L, side->lightabsolute);
return 1;
case side_lightabsolute_top:
lua_pushboolean(L, side->lightabsolute_top);
return 1;
case side_lightabsolute_mid:
lua_pushboolean(L, side->lightabsolute_mid);
return 1;
case side_lightabsolute_bottom:
lua_pushboolean(L, side->lightabsolute_bottom);
return 1;
// TODO: 2.3: Delete
case side_text:
{
@ -1413,6 +1453,30 @@ static int side_set(lua_State *L)
case side_repeatcnt:
side->repeatcnt = luaL_checkinteger(L, 3);
break;
case side_light:
side->light = luaL_checkinteger(L, 3);
break;
case side_light_top:
side->light_top = luaL_checkinteger(L, 3);
break;
case side_light_mid:
side->light_mid = luaL_checkinteger(L, 3);
break;
case side_light_bottom:
side->light_bottom = luaL_checkinteger(L, 3);
break;
case side_lightabsolute:
side->lightabsolute = luaL_checkboolean(L, 3);
break;
case side_lightabsolute_top:
side->lightabsolute_top = luaL_checkboolean(L, 3);
break;
case side_lightabsolute_mid:
side->lightabsolute_mid = luaL_checkboolean(L, 3);
break;
case side_lightabsolute_bottom:
side->lightabsolute_bottom = luaL_checkboolean(L, 3);
break;
}
return 0;
}

View file

@ -69,6 +69,7 @@ enum mobj_e {
mobj_color,
mobj_translation,
mobj_blendmode,
mobj_alpha,
mobj_bnext,
mobj_bprev,
mobj_hnext,
@ -150,6 +151,7 @@ static const char *const mobj_opt[] = {
"color",
"translation",
"blendmode",
"alpha",
"bnext",
"bprev",
"hnext",
@ -354,6 +356,9 @@ static int mobj_get(lua_State *L)
case mobj_blendmode:
lua_pushinteger(L, mo->blendmode);
break;
case mobj_alpha:
lua_pushfixed(L, mo->alpha);
break;
case mobj_bnext:
if (mo->blocknode && mo->blocknode->bnext) {
LUA_PushUserdata(L, mo->blocknode->bnext->mobj, META_MOBJ);
@ -733,6 +738,16 @@ static int mobj_set(lua_State *L)
mo->blendmode = blendmode;
break;
}
case mobj_alpha:
{
fixed_t alpha = luaL_checkfixed(L, 3);
if (alpha < 0)
alpha = 0;
else if (alpha > FRACUNIT)
alpha = FRACUNIT;
mo->alpha = alpha;
break;
}
case mobj_bnext:
return NOSETPOS;
case mobj_bprev:

View file

@ -54,7 +54,8 @@ enum skin {
skin_contspeed,
skin_contangle,
skin_soundsid,
skin_sprites,
skin_sprites, // TODO: 2.3: Delete
skin_skinsprites,
skin_supersprites,
skin_natkcolor
};
@ -95,7 +96,8 @@ static const char *const skin_opt[] = {
"contspeed",
"contangle",
"soundsid",
"sprites",
"sprites", // TODO: 2.3: Delete
"skinsprites",
"supersprites",
"natkcolor",
NULL};
@ -219,7 +221,10 @@ static int skin_get(lua_State *L)
case skin_soundsid:
LUA_PushUserdata(L, skin->soundsid, META_SOUNDSID);
break;
case skin_sprites:
case skin_sprites: // TODO: 2.3: Delete
LUA_PushUserdata(L, skin->sprites_compat, META_SKINSPRITESCOMPAT);
break;
case skin_skinsprites:
LUA_PushUserdata(L, skin->sprites, META_SKINSPRITES);
break;
case skin_supersprites:
@ -338,15 +343,7 @@ static int soundsid_num(lua_State *L)
return 1;
}
enum spritesopt {
numframes = 0
};
static const char *const sprites_opt[] = {
"numframes",
NULL};
// skin.sprites[i] -> sprites[i]
// skin.skinsprites[i] -> sprites[i]
static int lib_getSkinSprite(lua_State *L)
{
spritedef_t *sksprites = *(spritedef_t **)luaL_checkudata(L, 1, META_SKINSPRITES);
@ -359,13 +356,43 @@ static int lib_getSkinSprite(lua_State *L)
return 1;
}
// #skin.sprites -> NUMPLAYERSPRITES
// #skin.skinsprites -> NUMPLAYERSPRITES
static int lib_numSkinsSprites(lua_State *L)
{
lua_pushinteger(L, NUMPLAYERSPRITES);
return 1;
}
// TODO: 2.3: Delete
// skin.sprites[i] -> sprites[i]
static int lib_getSkinSpriteCompat(lua_State *L)
{
spritedef_t *sksprites = *(spritedef_t **)luaL_checkudata(L, 1, META_SKINSPRITESCOMPAT);
playersprite_t i = luaL_checkinteger(L, 2);
if (i < 0 || i >= NUMPLAYERSPRITES*2)
return luaL_error(L, "skin sprites index %d out of range (0 - %d)", i, (NUMPLAYERSPRITES*2)-1);
LUA_PushUserdata(L, &sksprites[i], META_SKINSPRITESLIST);
return 1;
}
// TODO: 2.3: Delete
// #skin.sprites -> NUMPLAYERSPRITES*2
static int lib_numSkinsSpritesCompat(lua_State *L)
{
lua_pushinteger(L, NUMPLAYERSPRITES*2);
return 1;
}
enum spritesopt {
numframes = 0
};
static const char *const sprites_opt[] = {
"numframes",
NULL};
static int sprite_get(lua_State *L)
{
spritedef_t *sprite = *(spritedef_t **)luaL_checkudata(L, 1, META_SKINSPRITESLIST);
@ -387,6 +414,7 @@ int LUA_SkinLib(lua_State *L)
LUA_RegisterUserdataMetatable(L, META_SOUNDSID, soundsid_get, NULL, soundsid_num);
LUA_RegisterUserdataMetatable(L, META_SKINSPRITES, lib_getSkinSprite, NULL, lib_numSkinsSprites);
LUA_RegisterUserdataMetatable(L, META_SKINSPRITESLIST, sprite_get, NULL, NULL);
LUA_RegisterUserdataMetatable(L, META_SKINSPRITESCOMPAT, lib_getSkinSpriteCompat, NULL, lib_numSkinsSpritesCompat); // TODO: 2.3: Delete
skin_fields_ref = Lua_CreateFieldTable(L, skin_opt);

View file

@ -494,6 +494,12 @@ UINT8 M_MapLocked(INT32 mapnum, gamedata_t *data)
UINT8 M_CampaignWarpIsCheat(INT32 gt, INT32 mapnum, gamedata_t *data)
{
if (dedicated)
{
// See M_MapLocked; don't make dedicated servers annoying.
return false;
}
if (M_MapLocked(mapnum, data) == true)
{
// Warping to locked maps is definitely always a cheat

View file

@ -140,6 +140,7 @@ static char *char_notes = NULL;
boolean menuactive = false;
boolean fromlevelselect = false;
tic_t shieldprompt_timer = 0; // Show a prompt about the new Shield button for old configs // TODO: 2.3: Remove
typedef enum
{
@ -3161,6 +3162,7 @@ static void Command_Manual_f(void)
if (modeattacking)
return;
M_StartControlPanel();
if (shieldprompt_timer) return; // TODO: 2.3: Delete this line
currentMenu = &MISC_HelpDef;
itemOn = 0;
}
@ -3340,6 +3342,7 @@ boolean M_Responder(event_t *ev)
if (modeattacking)
return true;
M_StartControlPanel();
if (shieldprompt_timer) return true; // TODO: 2.3: Delete this line
M_Options(0);
// Uncomment the below if you want the menu to reset to the top each time like before. M_SetupNextMenu will fix it automatically.
//OP_SoundOptionsDef.lastOn = 0;
@ -3350,6 +3353,7 @@ boolean M_Responder(event_t *ev)
if (modeattacking)
return true;
M_StartControlPanel();
if (shieldprompt_timer) return true; // TODO: 2.3: Delete this line
M_Options(0);
M_VideoModeMenu(0);
return true;
@ -3361,6 +3365,7 @@ boolean M_Responder(event_t *ev)
if (modeattacking)
return true;
M_StartControlPanel();
if (shieldprompt_timer) return true; // TODO: 2.3: Delete this line
M_Options(0);
M_SetupNextMenu(&OP_MainDef);
return true;
@ -3631,6 +3636,230 @@ void M_Drawer(void)
}
}
// Handle the "Do you want to assign Shield Ability now?" pop-up for old configs // TODO: 2.3: Remove this line...
static UINT8 shieldprompt_currentchoice = 0; // ...and this line...
static void M_ShieldPromptUseDefaults(void) // ...and this function
{
// With a default config from v2.2.10 to v2.2.13, the B button will be set to Custom 1,
// and Controls per Key defaults to "One", so it will override the default Shield button.
// A default config from v2.2.0 to v2.2.9 has Next Weapon on B, so it suffers from this too.
// So for "Use default Shield Ability buttons", we should update old configs to mitigate gamepad conflicts
// (even with "Several" Controls per Key!), and show a message with the default bindings
for (setupcontrols = gamecontrol; true; setupcontrols = gamecontrolbis) // Do stuff for both P1 and P2
{
INT32 JOY1 = (setupcontrols == gamecontrol) ? KEY_JOY1 : KEY_2JOY1; // Is this for P1 or for P2?
if ((setupcontrols[GC_CUSTOM1][0] == JOY1+1 || setupcontrols[GC_CUSTOM1][1] == JOY1+1)
&& (setupcontrols[GC_CUSTOM2][0] == JOY1+3 || setupcontrols[GC_CUSTOM2][1] == JOY1+3)
&& (setupcontrols[GC_CUSTOM3][0] == JOY1+8 || setupcontrols[GC_CUSTOM3][1] == JOY1+8))
{
// If the player has v2.2.13's default gamepad Custom 1/2/3 buttons,
// shuffle Custom 1/2/3 around to make room for Shield Ability on B
UINT8 shield_slot = (setupcontrols[GC_SHIELD ][0] == KEY_NULL ) ? 0 : 1;
UINT8 custom1_slot = (setupcontrols[GC_CUSTOM1][0] == JOY1+1) ? 0 : 1;
UINT8 custom2_slot = (setupcontrols[GC_CUSTOM2][0] == JOY1+3) ? 0 : 1;
UINT8 custom3_slot = (setupcontrols[GC_CUSTOM3][0] == JOY1+8) ? 0 : 1;
setupcontrols[GC_SHIELD ][shield_slot ] = JOY1+1; // Assign Shield Ability to B
setupcontrols[GC_CUSTOM1][custom1_slot] = JOY1+3; // Move Custom 1 from B to Y
setupcontrols[GC_CUSTOM2][custom2_slot] = JOY1+8; // Move Custom 2 from Y to LS
setupcontrols[GC_CUSTOM3][custom3_slot] = KEY_NULL; // Unassign Custom 3 from LS...
// (The alternative would be to check and update the ENTIRE gamepad layout.
// That'd be nice, but it would mess with people that are used to the old defaults.)
}
else if ((setupcontrols[GC_WEAPONNEXT][0] == JOY1+1 || setupcontrols[GC_WEAPONNEXT][1] == JOY1+1)
&& (setupcontrols[GC_WEAPONPREV][0] == JOY1+2 || setupcontrols[GC_WEAPONPREV][1] == JOY1+2))
{
// Or if the user has a default config from v2.2.0 to v2.2.9,
// the B button will be Next Weapon, and X will be Previous Weapon.
// It's "safe" to discard one of them, you just have to press X multiple times to select in the other direction
UINT8 shield_slot = (setupcontrols[GC_SHIELD ][0] == KEY_NULL ) ? 0 : 1;
UINT8 nweapon_slot = (setupcontrols[GC_WEAPONNEXT][0] == JOY1+1) ? 0 : 1;
UINT8 pweapon_slot = (setupcontrols[GC_WEAPONPREV][0] == JOY1+2) ? 0 : 1;
setupcontrols[GC_SHIELD ][shield_slot ] = JOY1+1; // Assign Shield Ability to B
setupcontrols[GC_WEAPONNEXT][nweapon_slot] = JOY1+3; // Move Next Weapon from B to X
setupcontrols[GC_WEAPONPREV][pweapon_slot] = KEY_NULL; // Unassign Previous Weapon from X
}
if (setupcontrols == gamecontrolbis) // If we've already updated both players, break out
break;
}
// Now, show a message about the default Shield Ability bindings
if ((gamecontrol[GC_SHIELD][0] == KEY_LALT && gamecontrol[GC_SHIELD][1] == KEY_JOY1+1)
|| (gamecontrol[GC_SHIELD][0] == KEY_JOY1+1 && gamecontrol[GC_SHIELD][1] == KEY_LALT))
{
// Left Alt and the B button are both assigned
M_StartMessage(M_GetText("Shield Ability defaults to\nthe \x82""Left Alt\x80"" key on keyboard,\nand the \x85""B button\x80"" on gamepads."
"\n\nYou can always reassign it\nin the Options menu later."
"\n\n\nPress 'Enter' to continue\n"),
NULL, MM_NOTHING);
MessageDef.x = 43; // Change the pop-up message's background position/width
MessageDef.lastOn = (MessageDef.lastOn & ~0xFF) | 27;
}
else if (gamecontrol[GC_SHIELD][0] == KEY_LALT || gamecontrol[GC_SHIELD][1] == KEY_LALT)
{
// Left Alt is assigned, but the B button isn't.
M_StartMessage(M_GetText("Shield Ability defaults to\nthe \x82""Left Alt\x80"" key on keyboard.\nThe \x85""B button\x80"" on gamepads was taken."
"\n\nYou can always reassign it\nin the Options menu later."
"\n\n\nPress 'Enter' to continue\n"),
NULL, MM_NOTHING);
MessageDef.x = 24; // Change the pop-up message's background position/width
MessageDef.lastOn = (MessageDef.lastOn & ~0xFF) | 32;
}
else if (gamecontrol[GC_SHIELD][0] == KEY_JOY1+1 || gamecontrol[GC_SHIELD][1] == KEY_JOY1+1)
{
// The B button is assigned, but Left Alt isn't
M_StartMessage(M_GetText("Shield Ability defaults to\nthe \x85""B button\x80"" on gamepads.\nThe \x82""Left Alt\x80"" key on keyboard was taken."
"\n\nYou can always reassign it\nin the Options menu later."
"\n\n\nPress 'Enter' to continue\n"),
NULL, MM_NOTHING);
MessageDef.x = 8; // Change the pop-up message's background position/width
MessageDef.lastOn = (MessageDef.lastOn & ~0xFF) | 36;
}
else if (gamecontrol[GC_SHIELD][0] == KEY_NULL && gamecontrol[GC_SHIELD][1] == KEY_NULL)
{
// Neither Left Alt nor the B button are assigned
M_StartMessage(M_GetText("Shield Ability is unassigned!\nThe \x82""Left Alt\x80"" key on keyboard and\nthe \x85""B button\x80"" on gamepads were taken."
"\n\nYou should assign Shield Ability\nin the Options menu later."
"\n\n\nPress 'Enter' to continue\n"),
NULL, MM_NOTHING);
MessageDef.x = 19; // Change the pop-up message's background position/width
MessageDef.lastOn = (MessageDef.lastOn & ~0xFF) | 33;
}
else
{
// Neither Left Alt nor the B button are assigned... but something else is???
// (This can technically happen if you edit your config or use setcontrol in the console before opening the menu)
char keystr[16+16+2+7+1]; // Two 16-char keys + two colour codes + "' and '" + null
if (gamecontrol[GC_SHIELD][0] != KEY_NULL && gamecontrol[GC_SHIELD][1] != KEY_NULL)
STRBUFCPY(keystr, va("%s\x80""' and '\x82""%s",
G_KeyNumToName(gamecontrol[GC_SHIELD][0]),
G_KeyNumToName(gamecontrol[GC_SHIELD][1])));
else if (gamecontrol[GC_SHIELD][0] != KEY_NULL)
STRBUFCPY(keystr, G_KeyNumToName(gamecontrol[GC_SHIELD][0]));
else //if (gamecontrol[GC_SHIELD][1] != KEY_NULL)
STRBUFCPY(keystr, G_KeyNumToName(gamecontrol[GC_SHIELD][1]));
M_StartMessage(va("Shield Ability is assigned to\n'\x82""%s\x80""'."
"\n\nYou can always reassign it\nin the Options menu later."
"\n\n\nPress 'Enter' to continue\n",
keystr), NULL, MM_NOTHING);
MessageDef.x = 23; // Change the pop-up message's background position/width
MessageDef.lastOn = (MessageDef.lastOn & ~0xFF) | 32;
}
}
static void M_HandleShieldPromptMenu(INT32 choice) // TODO: 2.3: Remove
{
switch (choice)
{
case KEY_ESCAPE:
if (I_GetTime() <= shieldprompt_timer) // Don't mash past the pop-up by accident!
break;
S_StartSound(NULL, sfx_menu1);
noFurtherInput = true;
shieldprompt_timer = 0;
M_ShieldPromptUseDefaults();
break;
case KEY_ENTER:
if (I_GetTime() <= shieldprompt_timer) // Don't mash past the pop-up by accident!
break;
S_StartSound(NULL, sfx_menu1);
noFurtherInput = true;
shieldprompt_timer = 0;
if (shieldprompt_currentchoice == 0)
{
OP_ChangeControlsDef.lastOn = 8; // Highlight Shield Ability in the controls menu
M_Setup1PControlsMenu(0); // Set up P1's controls menu and call M_SetupNextMenu
}
else if (shieldprompt_currentchoice == 1) // Copy the Spin buttons to the Shield buttons
{
CV_SetValue(&cv_controlperkey, 2); // Make sure that Controls per Key is "Several"
gamecontrol [GC_SHIELD][0] = gamecontrol [GC_SPIN][0];
gamecontrol [GC_SHIELD][1] = gamecontrol [GC_SPIN][1];
gamecontrolbis[GC_SHIELD][0] = gamecontrolbis[GC_SPIN][0];
gamecontrolbis[GC_SHIELD][1] = gamecontrolbis[GC_SPIN][1];
CV_SetValue(&cv_shieldaxis, cv_spinaxis.value);
CV_SetValue(&cv_shieldaxis2, cv_spinaxis2.value);
M_StartMessage(M_GetText("Spin and Shield Ability are now\nthe same button."
"\n\nYou can always reassign them\nin the Options menu later."
"\n\n\nPress 'Enter' to continue\n"),
NULL, MM_NOTHING);
MessageDef.x = 36; // Change the pop-up message's background position/width
MessageDef.lastOn = (MessageDef.lastOn & ~0xFF) | 29;
}
else
M_ShieldPromptUseDefaults();
break;
case KEY_UPARROW:
S_StartSound(NULL, sfx_menu1);
shieldprompt_currentchoice = (shieldprompt_currentchoice+2)%3;
break;
case KEY_DOWNARROW:
S_StartSound(NULL, sfx_menu1);
shieldprompt_currentchoice = (shieldprompt_currentchoice+1)%3;
break;
}
MessageDef.prevMenu = &MainDef;
}
static void M_DrawShieldPromptMenu(void) // TODO: 2.3: Remove
{
INT16 cursorx = (BASEVIDWIDTH/2) - 24;
V_DrawFill(10-3, 68-3, 300+6, 40+6, 159);
// V_DrawCenteredString doesn't centre newlines, so we have to draw each line separately
V_DrawCenteredString(BASEVIDWIDTH/2, 68, V_ALLOWLOWERCASE, "Welcome back! Since you last played,");
V_DrawCenteredString(BASEVIDWIDTH/2, 76, V_ALLOWLOWERCASE, "Spin has been split into separate");
V_DrawCenteredString(BASEVIDWIDTH/2, 84, V_ALLOWLOWERCASE, "\"Spin\" and \"Shield Ability\" controls.");
V_DrawCenteredString(BASEVIDWIDTH/2, 98, V_ALLOWLOWERCASE, "Do you want to assign Shield Ability now?");
V_DrawCenteredString(BASEVIDWIDTH/2, 164,
(shieldprompt_currentchoice == 0) ? V_YELLOWMAP : 0, "Open Control Setup");
V_DrawCenteredString(BASEVIDWIDTH/2, 172,
(shieldprompt_currentchoice == 1) ? V_YELLOWMAP : 0, "Keep the old behaviour");
V_DrawCenteredString(BASEVIDWIDTH/2, 180,
(shieldprompt_currentchoice == 2) ? V_YELLOWMAP : 0, "Use default Shield Ability buttons");
switch (shieldprompt_currentchoice)
{
case 0: cursorx -= V_StringWidth("Open Control Setup", 0)/2; break;
case 1: cursorx -= V_StringWidth("Keep the old behaviour", 0)/2; break;
default: cursorx -= V_StringWidth("Use default Shield Ability buttons", 0)/2; break;
}
V_DrawScaledPatch(cursorx, 164 + (shieldprompt_currentchoice*8), 0, W_CachePatchName("M_CURSOR", PU_PATCH));
}
static menuitem_t OP_ShieldPromptMenu[] = {{IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleShieldPromptMenu, 0}}; // TODO: 2.3: Remove
menu_t OP_ShieldPromptDef = { // TODO: 2.3: Remove
MN_SPECIAL,
NULL,
1,
&MainDef,
OP_ShieldPromptMenu,
M_DrawShieldPromptMenu,
0, 0, 0, NULL
};
//
// M_StartControlPanel
//
@ -3662,6 +3891,15 @@ void M_StartControlPanel(void)
currentMenu = &MainDef;
itemOn = singleplr;
M_UpdateItemOn();
if (shieldprompt_timer) // For old configs, show a pop-up about the new Shield button // TODO: 2.3: Remove
{
S_StartSound(NULL, sfx_strpst);
noFurtherInput = true;
shieldprompt_timer = I_GetTime() + TICRATE; // Don't mash past the pop-up by accident!
M_SetupNextMenu(&OP_ShieldPromptDef);
}
}
else if (modeattacking)
{
@ -8372,7 +8610,7 @@ static void M_DrawLoadGameData(void)
if (savegameinfo[savetodraw].lives == -42)
col = 26;
else if (savegameinfo[savetodraw].botskin == 3) // & knuckles
col = 105;
col = 106;
else if (savegameinfo[savetodraw].botskin) // tailsbot or custom
col = 134;
else
@ -8432,7 +8670,17 @@ static void M_DrawLoadGameData(void)
if (savegameinfo[savetodraw].lives == -42)
V_DrawRightAlignedThinString(x + 79, y, V_GRAYMAP, "NEW GAME");
else if (savegameinfo[savetodraw].lives == -666)
V_DrawRightAlignedThinString(x + 79, y, V_REDMAP, "CAN'T LOAD!");
{
if (savegameinfo[savetodraw].continuescore == -62)
{
V_DrawRightAlignedThinString(x + 79, y, V_REDMAP, "ADDON NOT LOADED");
V_DrawRightAlignedThinString(x + 79, y-10, V_REDMAP, savegameinfo[savetodraw].skinname);
}
else
{
V_DrawRightAlignedThinString(x + 79, y, V_REDMAP, "CAN'T LOAD!");
}
}
else if (savegameinfo[savetodraw].gamemap & 8192)
V_DrawRightAlignedThinString(x + 79, y, V_GREENMAP, "CLEAR!");
else
@ -8665,6 +8913,7 @@ static void M_LoadSelect(INT32 choice)
}
#define VERSIONSIZE 16
#define MISSING { savegameinfo[slot].continuescore = -62; savegameinfo[slot].lives = -666; Z_Free(savebuffer); return; }
#define BADSAVE { savegameinfo[slot].lives = -666; Z_Free(savebuffer); return; }
#define CHECKPOS if (sav_p >= end_p) BADSAVE
// Reads the save file to list lives, level, player, etc.
@ -8761,10 +9010,11 @@ static void M_ReadSavegameInfo(UINT32 slot)
CHECKPOS
READSTRINGN(sav_p, ourSkinName, SKINNAMESIZE);
savegameinfo[slot].skinnum = R_SkinAvailable(ourSkinName);
STRBUFCPY(savegameinfo[slot].skinname, ourSkinName);
if (savegameinfo[slot].skinnum >= numskins
|| !R_SkinUsable(-1, savegameinfo[slot].skinnum))
BADSAVE
MISSING
CHECKPOS
READSTRINGN(sav_p, botSkinName, SKINNAMESIZE);
@ -8772,7 +9022,7 @@ static void M_ReadSavegameInfo(UINT32 slot)
if (savegameinfo[slot].botskin-1 >= numskins
|| !R_SkinUsable(-1, savegameinfo[slot].botskin-1))
BADSAVE
MISSING
}
CHECKPOS
@ -8817,6 +9067,7 @@ static void M_ReadSavegameInfo(UINT32 slot)
}
#undef CHECKPOS
#undef BADSAVE
#undef MISSING
//
// M_ReadSaveStrings

View file

@ -176,6 +176,7 @@ typedef struct
extern menupres_t menupres[NUMMENUTYPES];
extern UINT32 prevMenuId;
extern UINT32 activeMenuId;
extern tic_t shieldprompt_timer; // Show a prompt about the new Shield button for old configs // TODO: 2.3: Remove
void M_InitMenuPresTables(void);
UINT8 M_GetYoungestChildMenu(void);
@ -421,6 +422,7 @@ typedef struct
{
char levelname[32];
UINT8 skinnum;
char skinname [SKINNAMESIZE+1];
UINT8 botskin;
UINT8 numemeralds;
UINT8 numgameovers;

View file

@ -560,6 +560,11 @@ void M_FirstLoadConfig(void)
COM_BufInsertText(va("exec \"%s\"\n", configfile));
// no COM_BufExecute() needed; that does it right away
// For configs loaded at startup only, check for pre-Shield-button configs // TODO: 2.3: Remove
if (GETMAJOREXECVERSION(cv_execversion.value) < 55 // Pre-v2.2.14 configs
&& cv_execversion.value != 25) // Make sure that the config exists, too
shieldprompt_timer = 1;
// don't filter anymore vars and don't let this convsvar be changed
COM_BufInsertText(va("%s \"%d\"\n", cv_execversion.name, EXECVERSION));
CV_ToggleExecVersion(false);

View file

@ -21,6 +21,32 @@ void DVector3_Load(dvector3_t *vec, double x, double y, double z)
vec->z = z;
}
void DVector3_Copy(dvector3_t *a_o, const dvector3_t *a_i)
{
memcpy(a_o, a_i, sizeof(dvector3_t));
}
void DVector3_Add(const dvector3_t *a_i, const dvector3_t *a_c, dvector3_t *a_o)
{
a_o->x = a_i->x + a_c->x;
a_o->y = a_i->y + a_c->y;
a_o->z = a_i->z + a_c->z;
}
void DVector3_Subtract(const dvector3_t *a_i, const dvector3_t *a_c, dvector3_t *a_o)
{
a_o->x = a_i->x - a_c->x;
a_o->y = a_i->y - a_c->y;
a_o->z = a_i->z - a_c->z;
}
void DVector3_Multiply(const dvector3_t *a_i, double a_c, dvector3_t *a_o)
{
a_o->x = a_i->x * a_c;
a_o->y = a_i->y * a_c;
a_o->z = a_i->z * a_c;
}
double DVector3_Magnitude(const dvector3_t *a_normal)
{
double xs = a_normal->x * a_normal->x;

View file

@ -19,6 +19,10 @@ typedef struct
} dvector3_t;
void DVector3_Load(dvector3_t *vec, double x, double y, double z);
void DVector3_Copy(dvector3_t *a_o, const dvector3_t *a_i);
void DVector3_Add(const dvector3_t *a_i, const dvector3_t *a_c, dvector3_t *a_o);
void DVector3_Subtract(const dvector3_t *a_i, const dvector3_t *a_c, dvector3_t *a_o);
void DVector3_Multiply(const dvector3_t *a_i, double a_c, dvector3_t *a_o);
double DVector3_Magnitude(const dvector3_t *a_normal);
double DVector3_Normalize(dvector3_t *a_normal);
void DVector3_Negate(dvector3_t *a_o);

View file

@ -114,6 +114,7 @@ static CV_PossibleValue_t playbackspeed_cons_t[] = {{1, "MIN"}, {10, "MAX"}, {0,
consvar_t cv_playbackspeed = CVAR_INIT ("playbackspeed", "1", 0, playbackspeed_cons_t, NULL);
consvar_t cv_idletime = CVAR_INIT ("idletime", "0", CV_SAVE, CV_Unsigned, NULL);
consvar_t cv_idlespectate = CVAR_INIT ("idlespectate", "On", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_dedicatedidletime = CVAR_INIT ("dedicatedidletime", "10", CV_SAVE, CV_Unsigned, NULL);
consvar_t cv_httpsource = CVAR_INIT ("http_source", "", CV_SAVE, NULL, NULL);
@ -1360,19 +1361,33 @@ static void IdleUpdate(void)
if (!server || !netgame)
return;
for (i = 1; i < MAXPLAYERS; i++)
for (i = 0; i < MAXPLAYERS; i++)
{
if (cv_idletime.value && playeringame[i] && playernode[i] != UINT8_MAX && !players[i].quittime && !players[i].spectator && !players[i].bot && !IsPlayerAdmin(i) && i != serverplayer && gamestate == GS_LEVEL)
if (playeringame[i] && playernode[i] != UINT8_MAX && !players[i].quittime && !players[i].spectator && !players[i].bot && gamestate == GS_LEVEL)
{
if (players[i].cmd.forwardmove || players[i].cmd.sidemove || players[i].cmd.buttons)
players[i].lastinputtime = 0;
else
players[i].lastinputtime++;
if (players[i].lastinputtime > (tic_t)cv_idletime.value * TICRATE * 60)
if (cv_idletime.value && !IsPlayerAdmin(i) && i != serverplayer && !(players[i].pflags & PF_FINISHED) && players[i].lastinputtime > (tic_t)cv_idletime.value * TICRATE * 60)
{
players[i].lastinputtime = 0;
SendKick(i, KICK_MSG_IDLE | KICK_MSG_KEEP_BODY);
if (cv_idlespectate.value && G_GametypeHasSpectators())
{
changeteam_union NetPacket;
UINT16 usvalue;
NetPacket.value.l = NetPacket.value.b = 0;
NetPacket.packet.newteam = 0;
NetPacket.packet.playernum = i;
NetPacket.packet.verification = true; // This signals that it's a server change
usvalue = SHORT(NetPacket.value.l|NetPacket.value.b);
SendNetXCmd(XD_TEAMCHANGE, &usvalue, sizeof(usvalue));
}
else
{
SendKick(i, KICK_MSG_IDLE | KICK_MSG_KEEP_BODY);
}
}
}
else

View file

@ -73,7 +73,7 @@ extern UINT32 realpingtable[MAXPLAYERS];
extern UINT32 playerpingtable[MAXPLAYERS];
extern tic_t servermaxping;
extern consvar_t cv_netticbuffer, cv_resynchattempts, cv_blamecfail, cv_playbackspeed, cv_idletime, cv_dedicatedidletime;
extern consvar_t cv_netticbuffer, cv_resynchattempts, cv_blamecfail, cv_playbackspeed, cv_idletime, cv_idlespectate, cv_dedicatedidletime;
extern consvar_t cv_httpsource;
// Used in d_net, the only dependence

View file

@ -620,6 +620,7 @@ void D_RegisterServerCommands(void)
CV_RegisterVar(&cv_blamecfail);
CV_RegisterVar(&cv_dedicatedidletime);
CV_RegisterVar(&cv_idletime);
CV_RegisterVar(&cv_idlespectate);
CV_RegisterVar(&cv_httpsource);
COM_AddCommand("ping", Command_Ping_f, COM_LUA);
@ -2510,11 +2511,11 @@ static void MutePlayer(boolean mute)
if (COM_Argc() < 2)
{
CONS_Printf(M_GetText("muteplayer <playernum>: mute a player\n"));
CONS_Printf(M_GetText("muteplayer <playername/playernum>: mute a player\n"));
return;
}
data[0] = atoi(COM_Argv(1));
data[0] = nametonum(COM_Argv(1));
if (data[0] >= MAXPLAYERS || !playeringame[data[0]])
{
CONS_Alert(CONS_NOTICE, M_GetText("There is no player %u!\n"), (unsigned int)data[0]);
@ -2603,11 +2604,11 @@ static void Command_ServerTeamChange_f(void)
if (COM_Argc() < 3)
{
if (G_TagGametype())
CONS_Printf(M_GetText("serverchangeteam <playernum> <team>: switch player to a new team (%s)\n"), "it, notit, playing, or spectator");
CONS_Printf(M_GetText("serverchangeteam <playername/playernum> <team>: switch player to a new team (%s)\n"), "it, notit, playing, or spectator");
else if (G_GametypeHasTeams())
CONS_Printf(M_GetText("serverchangeteam <playernum> <team>: switch player to a new team (%s)\n"), "red, blue or spectator");
CONS_Printf(M_GetText("serverchangeteam <playername/playernum> <team>: switch player to a new team (%s)\n"), "red, blue or spectator");
else if (G_GametypeHasSpectators())
CONS_Printf(M_GetText("serverchangeteam <playernum> <team>: switch player to a new team (%s)\n"), "spectator or playing");
CONS_Printf(M_GetText("serverchangeteam <playername/playernum> <team>: switch player to a new team (%s)\n"), "spectator or playing");
else
CONS_Alert(CONS_NOTICE, M_GetText("This command cannot be used in this gametype.\n"));
return;
@ -2655,19 +2656,19 @@ static void Command_ServerTeamChange_f(void)
if (error)
{
if (G_TagGametype())
CONS_Printf(M_GetText("serverchangeteam <playernum> <team>: switch player to a new team (%s)\n"), "it, notit, playing, or spectator");
CONS_Printf(M_GetText("serverchangeteam <playername/playernum> <team>: switch player to a new team (%s)\n"), "it, notit, playing, or spectator");
else if (G_GametypeHasTeams())
CONS_Printf(M_GetText("serverchangeteam <playernum> <team>: switch player to a new team (%s)\n"), "red, blue or spectator");
CONS_Printf(M_GetText("serverchangeteam <playername/playernum> <team>: switch player to a new team (%s)\n"), "red, blue or spectator");
else if (G_GametypeHasSpectators())
CONS_Printf(M_GetText("serverchangeteam <playernum> <team>: switch player to a new team (%s)\n"), "spectator or playing");
CONS_Printf(M_GetText("serverchangeteam <playername/playernum> <team>: switch player to a new team (%s)\n"), "spectator or playing");
return;
}
NetPacket.packet.playernum = atoi(COM_Argv(1));
NetPacket.packet.playernum = nametonum(COM_Argv(1));
if (!playeringame[NetPacket.packet.playernum])
if (NetPacket.packet.playernum == -1 || !playeringame[NetPacket.packet.playernum])
{
CONS_Alert(CONS_NOTICE, M_GetText("There is no player %d!\n"), NetPacket.packet.playernum);
CONS_Alert(CONS_NOTICE, M_GetText("There is no player %s!\n"), COM_Argv(1));
return;
}
@ -3106,13 +3107,16 @@ static void Command_Verify_f(void)
if (COM_Argc() != 2)
{
CONS_Printf(M_GetText("promote <playernum>: give admin privileges to a player\n"));
CONS_Printf(M_GetText("promote <playername/playernum>: give admin privileges to a player\n"));
return;
}
strlcpy(buf, COM_Argv(1), sizeof (buf));
playernum = atoi(buf);
playernum = nametonum(COM_Argv(1));
if (playernum == -1)
{
CONS_Alert(CONS_NOTICE, M_GetText("There is no player %s!\n"), COM_Argv(1));
return;
}
temp = buf;
@ -3156,13 +3160,16 @@ static void Command_RemoveAdmin_f(void)
if (COM_Argc() != 2)
{
CONS_Printf(M_GetText("demote <playernum>: remove admin privileges from a player\n"));
CONS_Printf(M_GetText("demote <playername/playernum>: remove admin privileges from a player\n"));
return;
}
strlcpy(buf, COM_Argv(1), sizeof(buf));
playernum = atoi(buf);
playernum = nametonum(COM_Argv(1));
if (playernum == -1)
{
CONS_Alert(CONS_NOTICE, M_GetText("There is no player %s!\n"), COM_Argv(1));
return;
}
temp = buf;

View file

@ -317,7 +317,11 @@ init_upnpc_once(struct upnpdata *upnpuserdata)
I_OutputMsg(M_GetText("Found UPnP device:\n desc: %s\n st: %s\n"),
dev->descURL, dev->st);
#if (MINIUPNPC_API_VERSION >= 18)
UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr), NULL, 0);
#else
UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
#endif
I_OutputMsg(M_GetText("Local LAN IP address: %s\n"), lanaddr);
descXML = miniwget(dev->descURL, &descXMLsize, scope_id, &status_code);
if (descXML)

View file

@ -50,6 +50,8 @@ static void Command_Listserv_f(void);
#endif/*MASTERSERVER*/
static boolean ServerName_CanChange (const char*);
static void Update_parameters (void);
static void MasterServer_OnChange(void);
@ -61,7 +63,7 @@ static CV_PossibleValue_t masterserver_update_rate_cons_t[] = {
};
consvar_t cv_masterserver = CVAR_INIT ("masterserver", "https://ds.ms.srb2.org/MS/0", CV_SAVE|CV_CALL, NULL, MasterServer_OnChange);
consvar_t cv_servername = CVAR_INIT ("servername", "SRB2 server", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT|CV_ALLOWLUA, NULL, Update_parameters);
consvar_t cv_servername = CVAR_INIT_WITH_CALLBACKS ("servername", "SRB2 server", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT|CV_ALLOWLUA, NULL, Update_parameters, ServerName_CanChange);
consvar_t cv_masterserver_update_rate = CVAR_INIT ("masterserver_update_rate", "15", CV_SAVE|CV_CALL|CV_NOINIT, masterserver_update_rate_cons_t, Update_parameters);
@ -497,6 +499,15 @@ Set_api (const char *api)
#endif/*MASTERSERVER*/
static boolean ServerName_CanChange(const char* newvalue)
{
if (strlen(newvalue) < MAXSERVERNAME)
return true;
CONS_Alert(CONS_NOTICE, "The server name must be shorter than %d characters\n", MAXSERVERNAME);
return false;
}
static void
Update_parameters (void)
{

View file

@ -54,276 +54,6 @@ static dirtype_t diags[] =
DI_NORTHWEST, DI_NORTHEAST, DI_SOUTHWEST, DI_SOUTHEAST
};
//Real Prototypes to A_*
void A_Fall(mobj_t *actor);
void A_Look(mobj_t *actor);
void A_Chase(mobj_t *actor);
void A_FaceStabChase(mobj_t *actor);
void A_FaceStabRev(mobj_t *actor);
void A_FaceStabHurl(mobj_t *actor);
void A_FaceStabMiss(mobj_t *actor);
void A_StatueBurst(mobj_t *actor);
void A_JetJawRoam(mobj_t *actor);
void A_JetJawChomp(mobj_t *actor);
void A_PointyThink(mobj_t *actor);
void A_CheckBuddy(mobj_t *actor);
void A_HoodFire(mobj_t *actor);
void A_HoodThink(mobj_t *actor);
void A_HoodFall(mobj_t *actor);
void A_ArrowBonks(mobj_t *actor);
void A_SnailerThink(mobj_t *actor);
void A_SharpChase(mobj_t *actor);
void A_SharpSpin(mobj_t *actor);
void A_SharpDecel(mobj_t *actor);
void A_CrushstaceanWalk(mobj_t *actor);
void A_CrushstaceanPunch(mobj_t *actor);
void A_CrushclawAim(mobj_t *actor);
void A_CrushclawLaunch(mobj_t *actor);
void A_VultureVtol(mobj_t *actor);
void A_VultureCheck(mobj_t *actor);
void A_VultureHover(mobj_t *actor);
void A_VultureBlast(mobj_t *actor);
void A_VultureFly(mobj_t *actor);
void A_SkimChase(mobj_t *actor);
void A_FaceTarget(mobj_t *actor);
void A_FaceTracer(mobj_t *actor);
void A_LobShot(mobj_t *actor);
void A_FireShot(mobj_t *actor);
void A_SuperFireShot(mobj_t *actor);
void A_BossFireShot(mobj_t *actor);
void A_Boss7FireMissiles(mobj_t *actor);
void A_Boss1Laser(mobj_t *actor);
void A_FocusTarget(mobj_t *actor);
void A_Boss4Reverse(mobj_t *actor);
void A_Boss4SpeedUp(mobj_t *actor);
void A_Boss4Raise(mobj_t *actor);
void A_SkullAttack(mobj_t *actor);
void A_BossZoom(mobj_t *actor);
void A_BossScream(mobj_t *actor);
void A_Scream(mobj_t *actor);
void A_Pain(mobj_t *actor);
void A_1upThinker(mobj_t *actor);
void A_MonitorPop(mobj_t *actor);
void A_GoldMonitorPop(mobj_t *actor);
void A_GoldMonitorRestore(mobj_t *actor);
void A_GoldMonitorSparkle(mobj_t *actor);
void A_Explode(mobj_t *actor);
void A_BossDeath(mobj_t *actor);
void A_SetShadowScale(mobj_t *actor);
void A_ShadowScream(mobj_t *actor);
void A_CustomPower(mobj_t *actor);
void A_GiveWeapon(mobj_t *actor);
void A_RingBox(mobj_t *actor);
void A_Invincibility(mobj_t *actor);
void A_SuperSneakers(mobj_t *actor);
void A_AwardScore(mobj_t *actor);
void A_ExtraLife(mobj_t *actor);
void A_GiveShield(mobj_t *actor);
void A_GravityBox(mobj_t *actor);
void A_ScoreRise(mobj_t *actor);
void A_BunnyHop(mobj_t *actor);
void A_BubbleSpawn(mobj_t *actor);
void A_FanBubbleSpawn(mobj_t *actor);
void A_BubbleRise(mobj_t *actor);
void A_BubbleCheck(mobj_t *actor);
void A_AttractChase(mobj_t *actor);
void A_DropMine(mobj_t *actor);
void A_FishJump(mobj_t *actor);
void A_ThrownRing(mobj_t *actor);
void A_SetSolidSteam(mobj_t *actor);
void A_UnsetSolidSteam(mobj_t *actor);
void A_SignSpin(mobj_t *actor);
void A_SignPlayer(mobj_t *actor);
void A_OverlayThink(mobj_t *actor);
void A_JetChase(mobj_t *actor);
void A_JetbThink(mobj_t *actor);
void A_JetgShoot(mobj_t *actor);
void A_JetgThink(mobj_t *actor);
void A_ShootBullet(mobj_t *actor);
void A_MinusDigging(mobj_t *actor);
void A_MinusPopup(mobj_t *actor);
void A_MinusCheck(mobj_t *actor);
void A_ChickenCheck(mobj_t *actor);
void A_MouseThink(mobj_t *actor);
void A_DetonChase(mobj_t *actor);
void A_CapeChase(mobj_t *actor);
void A_RotateSpikeBall(mobj_t *actor);
void A_SlingAppear(mobj_t *actor);
void A_UnidusBall(mobj_t *actor);
void A_RockSpawn(mobj_t *actor);
void A_SetFuse(mobj_t *actor);
void A_CrawlaCommanderThink(mobj_t *actor);
void A_RingExplode(mobj_t *actor);
void A_OldRingExplode(mobj_t *actor);
void A_MixUp(mobj_t *actor);
void A_RecyclePowers(mobj_t *actor);
void A_Boss2TakeDamage(mobj_t *actor);
void A_Boss7Chase(mobj_t *actor);
void A_GoopSplat(mobj_t *actor);
void A_Boss2PogoSFX(mobj_t *actor);
void A_Boss2PogoTarget(mobj_t *actor);
void A_EggmanBox(mobj_t *actor);
void A_TurretFire(mobj_t *actor);
void A_SuperTurretFire(mobj_t *actor);
void A_TurretStop(mobj_t *actor);
void A_SparkFollow(mobj_t *actor);
void A_BuzzFly(mobj_t *actor);
void A_GuardChase(mobj_t *actor);
void A_EggShield(mobj_t *actor);
void A_SetReactionTime(mobj_t *actor);
void A_Boss1Spikeballs(mobj_t *actor);
void A_Boss3TakeDamage(mobj_t *actor);
void A_Boss3Path(mobj_t *actor);
void A_Boss3ShockThink(mobj_t *actor);
void A_Shockwave(mobj_t *actor);
void A_LinedefExecute(mobj_t *actor);
void A_LinedefExecuteFromArg(mobj_t *actor);
void A_PlaySeeSound(mobj_t *actor);
void A_PlayAttackSound(mobj_t *actor);
void A_PlayActiveSound(mobj_t *actor);
void A_SmokeTrailer(mobj_t *actor);
void A_SpawnObjectAbsolute(mobj_t *actor);
void A_SpawnObjectRelative(mobj_t *actor);
void A_ChangeAngleRelative(mobj_t *actor);
void A_ChangeAngleAbsolute(mobj_t *actor);
void A_RollAngle(mobj_t *actor);
void A_ChangeRollAngleRelative(mobj_t *actor);
void A_ChangeRollAngleAbsolute(mobj_t *actor);
void A_PlaySound(mobj_t *actor);
void A_FindTarget(mobj_t *actor);
void A_FindTracer(mobj_t *actor);
void A_SetTics(mobj_t *actor);
void A_SetRandomTics(mobj_t *actor);
void A_ChangeColorRelative(mobj_t *actor);
void A_ChangeColorAbsolute(mobj_t *actor);
void A_Dye(mobj_t *actor);
void A_SetTranslation(mobj_t *actor);
void A_MoveRelative(mobj_t *actor);
void A_MoveAbsolute(mobj_t *actor);
void A_Thrust(mobj_t *actor);
void A_ZThrust(mobj_t *actor);
void A_SetTargetsTarget(mobj_t *actor);
void A_SetObjectFlags(mobj_t *actor);
void A_SetObjectFlags2(mobj_t *actor);
void A_RandomState(mobj_t *actor);
void A_RandomStateRange(mobj_t *actor);
void A_StateRangeByAngle(mobj_t *actor);
void A_StateRangeByParameter(mobj_t *actor);
void A_DualAction(mobj_t *actor);
void A_RemoteAction(mobj_t *actor);
void A_ToggleFlameJet(mobj_t *actor);
void A_OrbitNights(mobj_t *actor);
void A_GhostMe(mobj_t *actor);
void A_SetObjectState(mobj_t *actor);
void A_SetObjectTypeState(mobj_t *actor);
void A_KnockBack(mobj_t *actor);
void A_PushAway(mobj_t *actor);
void A_RingDrain(mobj_t *actor);
void A_SplitShot(mobj_t *actor);
void A_MissileSplit(mobj_t *actor);
void A_MultiShot(mobj_t *actor);
void A_InstaLoop(mobj_t *actor);
void A_Custom3DRotate(mobj_t *actor);
void A_SearchForPlayers(mobj_t *actor);
void A_CheckRandom(mobj_t *actor);
void A_CheckTargetRings(mobj_t *actor);
void A_CheckRings(mobj_t *actor);
void A_CheckTotalRings(mobj_t *actor);
void A_CheckHealth(mobj_t *actor);
void A_CheckRange(mobj_t *actor);
void A_CheckHeight(mobj_t *actor);
void A_CheckTrueRange(mobj_t *actor);
void A_CheckThingCount(mobj_t *actor);
void A_CheckAmbush(mobj_t *actor);
void A_CheckCustomValue(mobj_t *actor);
void A_CheckCusValMemo(mobj_t *actor);
void A_SetCustomValue(mobj_t *actor);
void A_UseCusValMemo(mobj_t *actor);
void A_RelayCustomValue(mobj_t *actor);
void A_CusValAction(mobj_t *actor);
void A_ForceStop(mobj_t *actor);
void A_ForceWin(mobj_t *actor);
void A_SpikeRetract(mobj_t *actor);
void A_InfoState(mobj_t *actor);
void A_Repeat(mobj_t *actor);
void A_SetScale(mobj_t *actor);
void A_RemoteDamage(mobj_t *actor);
void A_HomingChase(mobj_t *actor);
void A_TrapShot(mobj_t *actor);
void A_Boss1Chase(mobj_t *actor);
void A_Boss2Chase(mobj_t *actor);
void A_Boss2Pogo(mobj_t *actor);
void A_BossJetFume(mobj_t *actor);
void A_VileTarget(mobj_t *actor);
void A_VileAttack(mobj_t *actor);
void A_VileFire(mobj_t *actor);
void A_BrakChase(mobj_t *actor);
void A_BrakFireShot(mobj_t *actor);
void A_BrakLobShot(mobj_t *actor);
void A_NapalmScatter(mobj_t *actor);
void A_SpawnFreshCopy(mobj_t *actor);
void A_FlickySpawn(mobj_t *actor);
void A_FlickyCenter(mobj_t *actor);
void A_FlickyAim(mobj_t *actor);
void A_FlickyFly(mobj_t *actor);
void A_FlickySoar(mobj_t *actor);
void A_FlickyCoast(mobj_t *actor);
void A_FlickyHop(mobj_t *actor);
void A_FlickyFlounder(mobj_t *actor);
void A_FlickyCheck(mobj_t *actor);
void A_FlickyHeightCheck(mobj_t *actor);
void A_FlickyFlutter(mobj_t *actor);
void A_FlameParticle(mobj_t *actor);
void A_FadeOverlay(mobj_t *actor);
void A_Boss5Jump(mobj_t *actor);
void A_LightBeamReset(mobj_t *actor);
void A_MineExplode(mobj_t *actor);
void A_MineRange(mobj_t *actor);
void A_ConnectToGround(mobj_t *actor);
void A_SpawnParticleRelative(mobj_t *actor);
void A_MultiShotDist(mobj_t *actor);
void A_WhoCaresIfYourSonIsABee(mobj_t *actor);
void A_ParentTriesToSleep(mobj_t *actor);
void A_CryingToMomma(mobj_t *actor);
void A_CheckFlags2(mobj_t *actor);
void A_Boss5FindWaypoint(mobj_t *actor);
void A_DoNPCSkid(mobj_t *actor);
void A_DoNPCPain(mobj_t *actor);
void A_PrepareRepeat(mobj_t *actor);
void A_Boss5ExtraRepeat(mobj_t *actor);
void A_Boss5Calm(mobj_t *actor);
void A_Boss5CheckOnGround(mobj_t *actor);
void A_Boss5CheckFalling(mobj_t *actor);
void A_Boss5PinchShot(mobj_t *actor);
void A_Boss5MakeItRain(mobj_t *actor);
void A_Boss5MakeJunk(mobj_t *actor);
void A_LookForBetter(mobj_t *actor);
void A_Boss5BombExplode(mobj_t *actor);
void A_DustDevilThink(mobj_t *actor);
void A_TNTExplode(mobj_t *actor);
void A_DebrisRandom(mobj_t *actor);
void A_TrainCameo(mobj_t *actor);
void A_TrainCameo2(mobj_t *actor);
void A_CanarivoreGas(mobj_t *actor);
void A_KillSegments(mobj_t *actor);
void A_SnapperSpawn(mobj_t *actor);
void A_SnapperThinker(mobj_t *actor);
void A_SaloonDoorSpawn(mobj_t *actor);
void A_MinecartSparkThink(mobj_t *actor);
void A_ModuloToState(mobj_t *actor);
void A_LavafallRocks(mobj_t *actor);
void A_LavafallLava(mobj_t *actor);
void A_FallingLavaCheck(mobj_t *actor);
void A_FireShrink(mobj_t *actor);
void A_SpawnPterabytes(mobj_t *actor);
void A_PterabyteHover(mobj_t *actor);
void A_RolloutSpawn(mobj_t *actor);
void A_RolloutRock(mobj_t *actor);
void A_DragonbomberSpawn(mobj_t *actor);
void A_DragonWing(mobj_t *actor);
void A_DragonSegment(mobj_t *actor);
void A_ChangeHeight(mobj_t *actor);
//for p_enemy.c
//

View file

@ -3786,6 +3786,8 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
if (player->powers[pw_carry] == CR_NIGHTSMODE) // NiGHTS damage handling
{
if (player->powers[pw_flashing])
return false;
if (!force)
{
if (source == target)
@ -3803,6 +3805,10 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
if (G_IsSpecialStage(gamemap) && !(damagetype & DMG_DEATHMASK))
{
if (player->powers[pw_flashing])
return false;
if (LUA_HookMobjDamage(target, inflictor, source, damage, damagetype))
return true;
P_SpecialStageDamage(player, inflictor, source);
return true;
}

View file

@ -1258,8 +1258,9 @@ static unsigned PIT_DoCheckThing(mobj_t *thing)
if (tmthing->type != MT_SHELL && tmthing->target && tmthing->target->type == thing->type)
{
// Don't hit same species as originator.
if (thing == tmthing->target)
// Don't hit yourself, and if a player, don't hit bots
if (thing == tmthing->target
|| (thing->player && tmthing->target->player && (thing->player->bot == BOT_2PAI || thing->player->bot == BOT_2PHUMAN)))
return CHECKTHING_IGNORE;
if (thing->type != MT_PLAYER)
@ -2501,6 +2502,9 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam)
floatok = false;
if (dedicated) // this crashes so don't even try it
return false;
if (twodlevel
|| (thiscam == &camera && players[displayplayer].mo && (players[displayplayer].mo->flags2 & MF2_TWOD))
|| (thiscam == &camera2 && players[secondarydisplayplayer].mo && (players[secondarydisplayplayer].mo->flags2 & MF2_TWOD)))
@ -3960,23 +3964,25 @@ papercollision:
mo->momy = tmymove;
}
const fixed_t tmradius = mo->radius > 8 ? mo->radius : 8;
do {
if (tmxmove > mo->radius) {
newx = mo->x + mo->radius;
tmxmove -= mo->radius;
} else if (tmxmove < -mo->radius) {
newx = mo->x - mo->radius;
tmxmove += mo->radius;
if (tmxmove > tmradius) {
newx = mo->x + tmradius;
tmxmove -= tmradius;
} else if (tmxmove < -tmradius) {
newx = mo->x - tmradius;
tmxmove += tmradius;
} else {
newx = mo->x + tmxmove;
tmxmove = 0;
}
if (tmymove > mo->radius) {
newy = mo->y + mo->radius;
tmymove -= mo->radius;
} else if (tmymove < -mo->radius) {
newy = mo->y - mo->radius;
tmymove += mo->radius;
if (tmymove > tmradius) {
newy = mo->y + tmradius;
tmymove -= tmradius;
} else if (tmymove < -tmradius) {
newy = mo->y - tmradius;
tmymove += tmradius;
} else {
newy = mo->y + tmymove;
tmymove = 0;

View file

@ -2246,7 +2246,7 @@ boolean P_ZMovement(mobj_t *mo)
else if (!onground)
P_SlopeLaunch(mo);
}
if (!mo->player && P_CheckDeathPitCollide(mo) && mo->health
&& !(mo->flags & MF_NOCLIPHEIGHT) && !(mo->flags2 & MF2_BOSSDEAD))
{
@ -2939,7 +2939,7 @@ boolean P_SceneryZMovement(mobj_t *mo)
mo->eflags &= ~MFE_APPLYPMOMZ;
}
mo->z += mo->momz;
if (!mo->player && P_CheckDeathPitCollide(mo) && mo->health
&& !(mo->flags & MF_NOCLIPHEIGHT) && !(mo->flags2 & MF2_BOSSDEAD))
{
@ -3782,7 +3782,7 @@ static void P_PlayerMobjThinker(mobj_t *mobj)
// always do the gravity bit now, that's simpler
// BUT CheckPosition only if wasn't done before.
if (!(mobj->eflags & MFE_ONGROUND) || mobj->momz
if (mobj->momz
|| ((mobj->eflags & MFE_VERTICALFLIP) && mobj->z + mobj->height != mobj->ceilingz)
|| (!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z != mobj->floorz)
|| P_IsObjectInGoop(mobj))
@ -3795,17 +3795,6 @@ static void P_PlayerMobjThinker(mobj_t *mobj)
}
else
{
#if 0 // i don't know why this is here, it's causing a few undesired state glitches, and disabling it doesn't appear to negatively affect the game, but i don't want it gone permanently just in case some obscure bug crops up
if (!(mobj->player->powers[pw_carry] == CR_NIGHTSMODE)) // used for drilling
mobj->player->pflags &= ~PF_STARTJUMP;
mobj->player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE);
if (mobj->player->secondjump || mobj->player->powers[pw_tailsfly])
{
mobj->player->secondjump = 0;
mobj->player->powers[pw_tailsfly] = 0;
P_SetMobjState(mobj, S_PLAY_WALK);
}
#endif
mobj->eflags &= ~MFE_JUSTHITFLOOR;
}
@ -10355,6 +10344,7 @@ void P_MobjThinker(mobj_t *mobj)
case MT_GRENADEPICKUP:
if (mobj->health == 0) // Fading tile
{
// TODO: Maybe use mobj->alpha instead of messing with frame flags
INT32 value = mobj->info->damage/10;
value = mobj->fuse/value;
value = 10-value;
@ -10700,6 +10690,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...)
// Sprite rendering
mobj->blendmode = AST_TRANSLUCENT;
mobj->alpha = FRACUNIT;
mobj->spritexscale = mobj->spriteyscale = mobj->scale;
mobj->spritexoffset = mobj->spriteyoffset = 0;
mobj->floorspriteslope = NULL;
@ -10744,7 +10735,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...)
// Set shadowscale here, before spawn hook so that Lua can change it
mobj->shadowscale = P_DefaultMobjShadowScale(mobj);
// A monitor can't respawn if we're not in multiplayer,
// or if we're in co-op and it's score or a 1up
if (mobj->flags & MF_MONITOR && (!(netgame || multiplayer)
@ -10760,7 +10751,8 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...)
// when spawning MT_PLAYER, set mobj->player before calling MobjSpawn hook to prevent P_RemoveMobj from succeeding on player mobj.
va_start(args, type);
mobj->player = va_arg(args, player_t *);
mobj->player->mo = mobj;
if (mobj->player)
mobj->player->mo = mobj;
va_end(args);
}
@ -14302,7 +14294,8 @@ mobj_t *P_SpawnMobjFromMobj(mobj_t *mobj, fixed_t xofs, fixed_t yofs, fixed_t zo
yofs = FixedMul(yofs, mobj->scale);
zofs = FixedMul(zofs, mobj->scale);
newmobj = P_SpawnMobj(mobj->x + xofs, mobj->y + yofs, mobj->z + zofs, type);
newmobj = P_SpawnMobj(mobj->x + xofs, mobj->y + yofs, mobj->z + zofs, type, NULL);
if (!newmobj)
return NULL;

View file

@ -313,6 +313,7 @@ typedef struct mobj_s
UINT32 renderflags; // render flags
INT32 blendmode; // blend mode
fixed_t alpha; // alpha
fixed_t spritexscale, spriteyscale;
fixed_t spritexoffset, spriteyoffset;
fixed_t old_spritexscale, old_spriteyscale, old_spritexscale2, old_spriteyscale2;
@ -456,6 +457,7 @@ typedef struct precipmobj_s
UINT32 renderflags; // render flags
INT32 blendmode; // blend mode
fixed_t alpha; // alpha
fixed_t spritexscale, spriteyscale;
fixed_t spritexoffset, spriteyoffset;
fixed_t old_spritexscale, old_spriteyscale, old_spritexscale2, old_spriteyscale2;

View file

@ -919,7 +919,11 @@ enum
LD_SDMIDLIGHT = 1<<19,
LD_SDBOTLIGHT = 1<<20,
LD_SDREPEATCNT = 1<<21,
LD_SDFLAGS = 1<<22
LD_SDFLAGS = 1<<22,
LD_SDLIGHTABS = 1<<23,
LD_SDTOPLIGHTABS = 1<<24,
LD_SDMIDLIGHTABS = 1<<25,
LD_SDBOTLIGHTABS = 1<<26
};
static boolean P_AreArgsEqual(const line_t *li, const line_t *spawnli)
@ -1393,6 +1397,22 @@ static UINT32 GetSideDiff(const side_t *si, const side_t *spawnsi)
diff |= LD_SDBOTSCALEY;
if (si->repeatcnt != spawnsi->repeatcnt)
diff |= LD_SDREPEATCNT;
if (si->light != spawnsi->light)
diff |= LD_SDLIGHT;
if (si->light_top != spawnsi->light_top)
diff |= LD_SDTOPLIGHT;
if (si->light_mid != spawnsi->light_mid)
diff |= LD_SDMIDLIGHT;
if (si->light_bottom != spawnsi->light_bottom)
diff |= LD_SDBOTLIGHT;
if (si->lightabsolute != spawnsi->lightabsolute)
diff |= LD_SDLIGHTABS;
if (si->lightabsolute_top != spawnsi->lightabsolute_top)
diff |= LD_SDTOPLIGHTABS;
if (si->lightabsolute_mid != spawnsi->lightabsolute_mid)
diff |= LD_SDMIDLIGHTABS;
if (si->lightabsolute_bottom != spawnsi->lightabsolute_bottom)
diff |= LD_SDBOTLIGHTABS;
return diff;
}
@ -1436,6 +1456,22 @@ static void ArchiveSide(const side_t *si, UINT32 diff)
WRITEFIXED(save_p, si->scaley_bottom);
if (diff & LD_SDREPEATCNT)
WRITEINT16(save_p, si->repeatcnt);
if (diff & LD_SDLIGHT)
WRITEINT16(save_p, si->light);
if (diff & LD_SDTOPLIGHT)
WRITEINT16(save_p, si->light_top);
if (diff & LD_SDMIDLIGHT)
WRITEINT16(save_p, si->light_mid);
if (diff & LD_SDBOTLIGHT)
WRITEINT16(save_p, si->light_bottom);
if (diff & LD_SDLIGHTABS)
WRITEUINT8(save_p, si->lightabsolute);
if (diff & LD_SDTOPLIGHTABS)
WRITEUINT8(save_p, si->lightabsolute_top);
if (diff & LD_SDMIDLIGHTABS)
WRITEUINT8(save_p, si->lightabsolute_mid);
if (diff & LD_SDBOTLIGHTABS)
WRITEUINT8(save_p, si->lightabsolute_bottom);
}
static void ArchiveLines(void)
@ -1576,6 +1612,22 @@ static void UnArchiveSide(side_t *si)
si->scaley_bottom = READFIXED(save_p);
if (diff & LD_SDREPEATCNT)
si->repeatcnt = READINT16(save_p);
if (diff & LD_SDLIGHT)
si->light = READINT16(save_p);
if (diff & LD_SDTOPLIGHT)
si->light_top = READINT16(save_p);
if (diff & LD_SDMIDLIGHT)
si->light_mid = READINT16(save_p);
if (diff & LD_SDBOTLIGHT)
si->light_bottom = READINT16(save_p);
if (diff & LD_SDLIGHTABS)
si->lightabsolute = READUINT8(save_p);
if (diff & LD_SDTOPLIGHTABS)
si->lightabsolute_top = READUINT8(save_p);
if (diff & LD_SDMIDLIGHTABS)
si->lightabsolute_mid = READUINT8(save_p);
if (diff & LD_SDBOTLIGHTABS)
si->lightabsolute_bottom = READUINT8(save_p);
}
static void UnArchiveLines(void)
@ -1746,7 +1798,8 @@ typedef enum
MD2_DISPOFFSET = 1<<23,
MD2_DRAWONLYFORPLAYER = 1<<24,
MD2_DONTDRAWFORVIEWMOBJ = 1<<25,
MD2_TRANSLATION = 1<<26
MD2_TRANSLATION = 1<<26,
MD2_ALPHA = 1<<27
} mobj_diff2_t;
typedef enum
@ -1989,6 +2042,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
diff2 |= MD2_DONTDRAWFORVIEWMOBJ;
if (mobj->dispoffset != mobj->info->dispoffset)
diff2 |= MD2_DISPOFFSET;
if (mobj->alpha != FRACUNIT)
diff2 |= MD2_ALPHA;
if (diff2 != 0)
diff |= MD_MORE;
@ -2172,6 +2227,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
WRITEINT32(save_p, mobj->dispoffset);
if (diff2 & MD2_TRANSLATION)
WRITEUINT16(save_p, mobj->translation);
if (diff2 & MD2_ALPHA)
WRITEFIXED(save_p, mobj->alpha);
WRITEUINT32(save_p, mobj->mobjnum);
}
@ -3238,6 +3295,10 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
mobj->dispoffset = mobj->info->dispoffset;
if (diff2 & MD2_TRANSLATION)
mobj->translation = READUINT16(save_p);
if (diff2 & MD2_ALPHA)
mobj->alpha = READFIXED(save_p);
else
mobj->alpha = FRACUNIT;
if (diff & MD_REDFLAG)
{

View file

@ -1367,6 +1367,9 @@ static void P_LoadSidedefs(UINT8 *data)
sd->scalex_top = sd->scalex_mid = sd->scalex_bottom = FRACUNIT;
sd->scaley_top = sd->scaley_mid = sd->scaley_bottom = FRACUNIT;
sd->light = sd->light_top = sd->light_mid = sd->light_bottom = 0;
sd->lightabsolute = sd->lightabsolute_top = sd->lightabsolute_mid = sd->lightabsolute_bottom = false;
P_SetSidedefSector(i, (UINT16)SHORT(msd->sector));
// Special info stored in texture fields!
@ -1554,11 +1557,41 @@ static void P_LoadThings(UINT8 *data)
}
// Stores positions for relevant map data spread through a TEXTMAP.
UINT32 mapthingsPos[UINT16_MAX];
UINT32 linesPos[UINT16_MAX];
UINT32 sidesPos[UINT16_MAX];
UINT32 vertexesPos[UINT16_MAX];
UINT32 sectorsPos[UINT16_MAX];
typedef struct textmap_block_s
{
UINT32 *pos;
size_t capacity;
} textmap_block_t;
static textmap_block_t mapthingBlocks;
static textmap_block_t linedefBlocks;
static textmap_block_t sidedefBlocks;
static textmap_block_t vertexBlocks;
static textmap_block_t sectorBlocks;
static void TextmapStorePos(textmap_block_t *blocks, size_t *count)
{
size_t locCount = (*count) + 1;
if (blocks->pos == NULL)
{
// Initial capacity (half of the former one.)
blocks->capacity = UINT16_MAX / 2;
Z_Calloc(sizeof(blocks->pos) * blocks->capacity, PU_LEVEL, &blocks->pos);
}
else if (locCount >= blocks->capacity)
{
// If we hit the list's capacity, make space for 1024 more blocks
blocks->capacity += 1024;
Z_Realloc(blocks->pos, sizeof(blocks->pos) * blocks->capacity, PU_LEVEL, &blocks->pos);
}
blocks->pos[locCount - 1] = M_TokenizerGetEndPos();
(*count) = locCount;
}
// Determine total amount of map data in TEXTMAP.
static boolean TextmapCount(size_t size)
@ -1602,15 +1635,15 @@ static boolean TextmapCount(size_t size)
brackets++;
// Check for valid fields.
else if (fastcmp(tkn, "thing"))
mapthingsPos[nummapthings++] = M_TokenizerGetEndPos();
TextmapStorePos(&mapthingBlocks, &nummapthings);
else if (fastcmp(tkn, "linedef"))
linesPos[numlines++] = M_TokenizerGetEndPos();
TextmapStorePos(&linedefBlocks, &numlines);
else if (fastcmp(tkn, "sidedef"))
sidesPos[numsides++] = M_TokenizerGetEndPos();
TextmapStorePos(&sidedefBlocks, &numsides);
else if (fastcmp(tkn, "vertex"))
vertexesPos[numvertexes++] = M_TokenizerGetEndPos();
TextmapStorePos(&vertexBlocks, &numvertexes);
else if (fastcmp(tkn, "sector"))
sectorsPos[numsectors++] = M_TokenizerGetEndPos();
TextmapStorePos(&sectorBlocks, &numsectors);
else
CONS_Alert(CONS_NOTICE, "Unknown field '%s'.\n", tkn);
}
@ -1947,6 +1980,22 @@ static void ParseTextmapSidedefParameter(UINT32 i, const char *param, const char
P_SetSidedefSector(i, atol(val));
else if (fastcmp(param, "repeatcnt"))
sides[i].repeatcnt = atol(val);
else if (fastcmp(param, "light"))
sides[i].light = atol(val);
else if (fastcmp(param, "light_top"))
sides[i].light_top = atol(val);
else if (fastcmp(param, "light_mid"))
sides[i].light_mid = atol(val);
else if (fastcmp(param, "light_bottom"))
sides[i].light_bottom = atol(val);
else if (fastcmp(param, "lightabsolute") && fastcmp("true", val))
sides[i].lightabsolute = true;
else if (fastcmp(param, "lightabsolute_top") && fastcmp("true", val))
sides[i].lightabsolute_top = true;
else if (fastcmp(param, "lightabsolute_mid") && fastcmp("true", val))
sides[i].lightabsolute_mid = true;
else if (fastcmp(param, "lightabsolute_bottom") && fastcmp("true", val))
sides[i].lightabsolute_bottom = true;
}
static void ParseTextmapLinedefParameter(UINT32 i, const char *param, const char *val)
@ -2674,6 +2723,22 @@ static void P_WriteTextmap(void)
fprintf(f, "texturemiddle = \"%.*s\";\n", 8, textures[wsides[i].midtexture]->name);
if (wsides[i].repeatcnt != 0)
fprintf(f, "repeatcnt = %d;\n", wsides[i].repeatcnt);
if (wsides[i].light != 0)
fprintf(f, "light = %d;\n", wsides[i].light);
if (wsides[i].light_top != 0)
fprintf(f, "light_top = %d;\n", wsides[i].light_top);
if (wsides[i].light_mid != 0)
fprintf(f, "light_mid = %d;\n", wsides[i].light_mid);
if (wsides[i].light_bottom != 0)
fprintf(f, "light_bottom = %d;\n", wsides[i].light_bottom);
if (wsides[i].lightabsolute)
fprintf(f, "lightabsolute = true;\n");
if (wsides[i].lightabsolute_top)
fprintf(f, "lightabsolute_top = true;\n");
if (wsides[i].lightabsolute_mid)
fprintf(f, "lightabsolute_mid = true;\n");
if (wsides[i].lightabsolute_bottom)
fprintf(f, "lightabsolute_bottom = true;\n");
fprintf(f, "}\n");
fprintf(f, "\n");
}
@ -2944,7 +3009,7 @@ static void P_LoadTextmap(void)
vt->floorzset = vt->ceilingzset = false;
vt->floorz = vt->ceilingz = 0;
TextmapParse(vertexesPos[i], i, ParseTextmapVertexParameter);
TextmapParse(vertexBlocks.pos[i], i, ParseTextmapVertexParameter);
if (vt->x == INT32_MAX)
I_Error("P_LoadTextmap: vertex %s has no x value set!\n", sizeu1(i));
@ -3001,7 +3066,7 @@ static void P_LoadTextmap(void)
textmap_planefloor.defined = 0;
textmap_planeceiling.defined = 0;
TextmapParse(sectorsPos[i], i, ParseTextmapSectorParameter);
TextmapParse(sectorBlocks.pos[i], i, ParseTextmapSectorParameter);
P_InitializeSector(sc);
if (textmap_colormap.used)
@ -3050,7 +3115,7 @@ static void P_LoadTextmap(void)
ld->sidenum[0] = NO_SIDEDEF;
ld->sidenum[1] = NO_SIDEDEF;
TextmapParse(linesPos[i], i, ParseTextmapLinedefParameter);
TextmapParse(linedefBlocks.pos[i], i, ParseTextmapLinedefParameter);
if (!ld->v1)
I_Error("P_LoadTextmap: linedef %s has no v1 value set!\n", sizeu1(i));
@ -3076,8 +3141,10 @@ static void P_LoadTextmap(void)
sd->bottomtexture = R_TextureNumForName("-");
sd->sector = NULL;
sd->repeatcnt = 0;
sd->light = sd->light_top = sd->light_mid = sd->light_bottom = 0;
sd->lightabsolute = sd->lightabsolute_top = sd->lightabsolute_mid = sd->lightabsolute_bottom = false;
TextmapParse(sidesPos[i], i, ParseTextmapSidedefParameter);
TextmapParse(sidedefBlocks.pos[i], i, ParseTextmapSidedefParameter);
if (!sd->sector)
I_Error("P_LoadTextmap: sidedef %s has no sector value set!\n", sizeu1(i));
@ -3101,7 +3168,7 @@ static void P_LoadTextmap(void)
memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs));
mt->mobj = NULL;
TextmapParse(mapthingsPos[i], i, ParseTextmapThingParameter);
TextmapParse(mapthingBlocks.pos[i], i, ParseTextmapThingParameter);
}
}
@ -3419,13 +3486,13 @@ typedef enum {
} nodetype_t;
// Find out the BSP format.
static nodetype_t P_GetNodetype(const virtres_t *virt, UINT8 **nodedata)
static nodetype_t P_GetNodetype(const virtres_t *virt, UINT8 **nodedata, char signature[4 + 1])
{
boolean supported[NUMNODETYPES] = {0};
nodetype_t nodetype = NT_UNSUPPORTED;
char signature[4 + 1];
*nodedata = NULL;
signature[0] = signature[4] = '\0';
if (udmf)
{
@ -3434,7 +3501,7 @@ static nodetype_t P_GetNodetype(const virtres_t *virt, UINT8 **nodedata)
if (virtznodes && virtznodes->size)
{
*nodedata = virtznodes->data;
supported[NT_XGLN] = supported[NT_XGL3] = true;
supported[NT_XGLN] = supported[NT_XGL2] = supported[NT_XGL3] = true;
}
}
else
@ -3456,9 +3523,9 @@ static nodetype_t P_GetNodetype(const virtres_t *virt, UINT8 **nodedata)
virtssectors = vres_Find(virt, "SSECTORS");
if (virtssectors && virtssectors->size)
{ // Possibly GL nodes: NODES ignored, SSECTORS takes precedence as nodes lump, (It is confusing yeah) and has a signature.
{ // Possibly GL nodes: NODES ignored, SSECTORS takes precedence as nodes lump (it is confusing, yeah), and has a signature.
*nodedata = virtssectors->data;
supported[NT_XGLN] = supported[NT_ZGLN] = supported[NT_XGL3] = true;
supported[NT_XGLN] = supported[NT_ZGLN] = supported[NT_XGL2] = supported[NT_XGL3] = true;
}
else
{ // Possibly ZDoom extended nodes: SSECTORS is empty, NODES has a signature.
@ -3478,19 +3545,42 @@ static nodetype_t P_GetNodetype(const virtres_t *virt, UINT8 **nodedata)
}
M_Memcpy(signature, *nodedata, 4);
signature[4] = '\0';
(*nodedata) += 4;
if (!strcmp(signature, "XNOD"))
nodetype = NT_XNOD;
else if (!strcmp(signature, "ZNOD"))
nodetype = NT_ZNOD;
else if (!strcmp(signature, "XGLN"))
nodetype = NT_XGLN;
else if (!strcmp(signature, "ZGLN"))
nodetype = NT_ZGLN;
else if (!strcmp(signature, "XGL3"))
nodetype = NT_XGL3;
// Identify node format from its starting signature.
if (memcmp(&signature[1], "NOD", 3) == 0) // ZDoom extended nodes
{
if (signature[0] == 'X')
{
nodetype = NT_XNOD; // Uncompressed
}
else if (signature[0] == 'Z')
{
nodetype = NT_ZNOD; // Compressed
}
}
else if (memcmp(&signature[1], "GL", 2) == 0) // GL nodes
{
switch (signature[0])
{
case 'X': // Uncompressed
switch (signature[3])
{
case 'N': nodetype = NT_XGLN; break; // GL nodes
case '2': nodetype = NT_XGL2; break; // Version 2 GL nodes
case '3': nodetype = NT_XGL3; break; // Version 3 GL nodes
}
break;
case 'Z': // Compressed
switch (signature[3])
{
case 'N': nodetype = NT_ZGLN; break; // GL nodes (compressed)
case '2': nodetype = NT_ZGL2; break; // Version 2 GL nodes (compressed)
case '3': nodetype = NT_ZGL3; break; // Version 3 GL nodes (compressed)
}
break;
}
}
return supported[nodetype] ? nodetype : NT_UNSUPPORTED;
}
@ -3502,7 +3592,6 @@ static boolean P_LoadExtraVertices(UINT8 **data)
UINT32 xtrvrtx = READUINT32((*data));
line_t* ld = lines;
vertex_t *oldpos = vertexes;
ssize_t offset;
size_t i;
if (numvertexes != origvrtx) // If native vertex count doesn't match node original vertex count, bail out (broken data?).
@ -3517,12 +3606,11 @@ static boolean P_LoadExtraVertices(UINT8 **data)
// If extra vertexes were generated, reallocate the vertex array and fix the pointers.
numvertexes += xtrvrtx;
vertexes = Z_Realloc(vertexes, numvertexes*sizeof(*vertexes), PU_LEVEL, NULL);
offset = (size_t)(vertexes - oldpos);
for (i = 0, ld = lines; i < numlines; i++, ld++)
{
ld->v1 += offset;
ld->v2 += offset;
ld->v1 = &vertexes[ld->v1 - oldpos];
ld->v2 = &vertexes[ld->v2 - oldpos];
}
// Read extra vertex data.
@ -3560,6 +3648,7 @@ static boolean P_LoadExtendedSubsectorsAndSegs(UINT8 **data, nodetype_t nodetype
switch (nodetype)
{
case NT_XGLN:
case NT_XGL2:
case NT_XGL3:
for (m = 0; m < (size_t)subsectors[i].numlines; m++, k++)
{
@ -3571,7 +3660,7 @@ static boolean P_LoadExtendedSubsectorsAndSegs(UINT8 **data, nodetype_t nodetype
READUINT32((*data)); // partner, can be ignored by software renderer
if (nodetype == NT_XGL3)
if (nodetype != NT_XGLN)
{
UINT32 linenum = READUINT32((*data));
if (linenum != 0xFFFFFFFF && linenum >= numlines)
@ -3682,8 +3771,9 @@ static void P_LoadExtendedNodes(UINT8 **data, nodetype_t nodetype)
static void P_LoadMapBSP(const virtres_t *virt)
{
char signature[4 + 1];
UINT8 *nodedata = NULL;
nodetype_t nodetype = P_GetNodetype(virt, &nodedata);
nodetype_t nodetype = P_GetNodetype(virt, &nodedata, signature);
switch (nodetype)
{
@ -3715,6 +3805,7 @@ static void P_LoadMapBSP(const virtres_t *virt)
}
case NT_XNOD:
case NT_XGLN:
case NT_XGL2:
case NT_XGL3:
if (!P_LoadExtraVertices(&nodedata))
return;
@ -3723,10 +3814,13 @@ static void P_LoadMapBSP(const virtres_t *virt)
P_LoadExtendedNodes(&nodedata, nodetype);
break;
default:
CONS_Alert(CONS_WARNING, "Unsupported BSP format detected.\n");
return;
if (isprint(signature[0]) && isprint(signature[1]) && isprint(signature[2]) && isprint(signature[3]))
{
I_Error("Unsupported BSP format '%s' detected!\n", signature);
return;
}
I_Error("Unknown BSP format detected!\n");
}
return;
}
// Split from P_LoadBlockMap for convenience

View file

@ -181,8 +181,8 @@ void T_DynamicSlopeLine (dynlineplanethink_t* th)
{
pslope_t* slope = th->slope;
line_t* srcline = th->sourceline;
fixed_t zdelta;
fixed_t zdelta, oldoz = slope->o.z;
switch(th->type) {
case DP_FRONTFLOOR:
@ -209,7 +209,7 @@ void T_DynamicSlopeLine (dynlineplanethink_t* th)
return;
}
if (slope->zdelta != FixedDiv(zdelta, th->extent)) {
if (slope->zdelta != FixedDiv(zdelta, th->extent) || oldoz != slope->o.z) {
slope->zdelta = FixedDiv(zdelta, th->extent);
slope->zangle = R_PointToAngle2(0, 0, th->extent, -zdelta);
slope->moved = true;

View file

@ -2405,18 +2405,15 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
y = line->args[3] << FRACBITS;
z = line->args[4] << FRACBITS;
P_UnsetThingPosition(mo);
mo->x += x;
mo->y += y;
mo->z += z;
P_SetThingPosition(mo);
P_SetOrigin(mo, mo->x + x, mo->y + y, mo->z + z);
if (mo->player)
{
if (bot) // This might put poor Tails in a wall if he's too far behind! D: But okay, whatever! >:3
P_SetOrigin(bot, bot->x + x, bot->y + y, bot->z + z);
if (splitscreen && mo->player == &players[secondarydisplayplayer] && camera2.chase)
{
camera2.reset = true;
camera2.x += x;
camera2.y += y;
camera2.z += z;
@ -2424,6 +2421,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
}
else if (camera.chase && mo->player == &players[displayplayer])
{
camera.reset = true;
camera.x += x;
camera.y += y;
camera.z += z;

View file

@ -976,6 +976,9 @@ pflags_t P_GetJumpFlags(player_t *player)
//
boolean P_PlayerInPain(player_t *player)
{
if (P_MobjWasRemoved(player->mo))
return false;
// no silly, sliding isn't pain
if (!(player->pflags & PF_SLIDING) && player->mo->state == &states[player->mo->info->painstate] && player->powers[pw_flashing])
return true;
@ -2078,6 +2081,7 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj)
ghost->renderflags = mobj->renderflags;
ghost->blendmode = mobj->blendmode;
ghost->alpha = mobj->alpha;
ghost->spritexscale = mobj->spritexscale;
ghost->spriteyscale = mobj->spriteyscale;
@ -8825,6 +8829,8 @@ void P_MovePlayer(player_t *player)
player->mo->height = P_GetPlayerSpinHeight(player);
atspinheight = true;
}
else if (player->powers[pw_carry] == CR_PLAYER || player->powers[pw_carry] == CR_PTERABYTE) // You're slightly shorter while being carried
player->mo->height = FixedDiv(P_GetPlayerHeight(player), FixedDiv(14*FRACUNIT,10*FRACUNIT));
else
player->mo->height = P_GetPlayerHeight(player);
@ -12846,9 +12852,9 @@ void P_PlayerAfterThink(player_t *player)
else
{
if (tails->player)
P_TryMove(player->mo, tails->x + P_ReturnThrustX(tails, tails->player->drawangle, 4*FRACUNIT), tails->y + P_ReturnThrustY(tails, tails->player->drawangle, 4*FRACUNIT), true);
P_TryMove(player->mo, tails->x + P_ReturnThrustX(tails, tails->player->drawangle, 4*tails->scale), tails->y + P_ReturnThrustY(tails, tails->player->drawangle, 4*tails->scale), true);
else
P_TryMove(player->mo, tails->x + P_ReturnThrustX(tails, tails->angle, 4*FRACUNIT), tails->y + P_ReturnThrustY(tails, tails->angle, 4*FRACUNIT), true);
P_TryMove(player->mo, tails->x + P_ReturnThrustX(tails, tails->angle, 4*tails->scale), tails->y + P_ReturnThrustY(tails, tails->angle, 4*tails->scale), true);
player->mo->momx = tails->momx;
player->mo->momy = tails->momy;
player->mo->momz = tails->momz;
@ -12862,7 +12868,7 @@ void P_PlayerAfterThink(player_t *player)
P_SetPlayerAngle(player, player->mo->angle);
}
if (P_AproxDistance(player->mo->x - tails->x, player->mo->y - tails->y) > player->mo->radius)
if (P_AproxDistance(player->mo->x - tails->x, player->mo->y - tails->y) > tails->radius)
player->powers[pw_carry] = CR_NONE;
if (player->powers[pw_carry] == CR_PLAYER)
@ -13083,7 +13089,7 @@ void P_PlayerAfterThink(player_t *player)
player->mo->momy = ptera->momy;
player->mo->momz = ptera->momz;
if (P_AproxDistance(player->mo->x - ptera->x - ptera->watertop, player->mo->y - ptera->y - ptera->waterbottom) > player->mo->radius)
if (P_AproxDistance(player->mo->x - ptera->x - ptera->watertop, player->mo->y - ptera->y - ptera->waterbottom) > ptera->radius)
goto dropoff;
ptera->watertop >>= 1;

View file

@ -230,6 +230,18 @@ static INT32 R_DoorClosed(void)
&& (backsector->floorheight <= frontsector->floorheight || curline->sidedef->bottomtexture);
}
static UINT8 R_FloorLightLevel(sector_t *sector, INT16 base_lightlevel)
{
return max(0, min(255, sector->floorlightlevel +
((sector->floorlightabsolute) ? 0 : base_lightlevel)));
}
static UINT8 R_CeilingLightLevel(sector_t *sector, INT16 base_lightlevel)
{
return max(0, min(255, sector->ceilinglightlevel +
((sector->ceilinglightabsolute) ? 0 : base_lightlevel)));
}
//
// If player's view height is underneath fake floor, lower the
// drawn ceiling to be just under the floor height, and replace
@ -312,11 +324,11 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel,
tempsec->lightlevel = s->lightlevel;
if (floorlightlevel)
*floorlightlevel = s->floorlightsec == -1 ? (s->floorlightabsolute ? s->floorlightlevel : max(0, min(255, s->lightlevel + s->floorlightlevel)))
*floorlightlevel = s->floorlightsec == -1 ? (s->floorlightabsolute ? s->floorlightlevel : max(0, min(255, s->lightlevel + s->floorlightlevel)))
: sectors[s->floorlightsec].lightlevel;
if (ceilinglightlevel)
*ceilinglightlevel = s->ceilinglightsec == -1 ? (s->ceilinglightabsolute ? s->ceilinglightlevel : max(0, min(255, s->lightlevel + s->ceilinglightlevel)))
*ceilinglightlevel = s->ceilinglightsec == -1 ? (s->ceilinglightabsolute ? s->ceilinglightlevel : max(0, min(255, s->lightlevel + s->ceilinglightlevel)))
: sectors[s->ceilinglightsec].lightlevel;
}
else if (heightsec != -1 && viewz >= sectors[heightsec].ceilingheight
@ -356,11 +368,11 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel,
tempsec->lightlevel = s->lightlevel;
if (floorlightlevel)
*floorlightlevel = s->floorlightsec == -1 ? (s->floorlightabsolute ? s->floorlightlevel : max(0, min(255, s->lightlevel + s->floorlightlevel)))
*floorlightlevel = s->floorlightsec == -1 ? (s->floorlightabsolute ? s->floorlightlevel : max(0, min(255, s->lightlevel + s->floorlightlevel)))
: sectors[s->floorlightsec].lightlevel;
if (ceilinglightlevel)
*ceilinglightlevel = s->ceilinglightsec == -1 ? (s->ceilinglightabsolute ? s->ceilinglightlevel : max(0, min(255, s->lightlevel + s->ceilinglightlevel)))
*ceilinglightlevel = s->ceilinglightsec == -1 ? (s->ceilinglightabsolute ? s->ceilinglightlevel : max(0, min(255, s->lightlevel + s->ceilinglightlevel)))
: sectors[s->ceilinglightsec].lightlevel;
}
sec = tempsec;
@ -968,11 +980,10 @@ static void R_Subsector(size_t num)
&& ((viewz < heightcheck && (rover->fofflags & FOF_BOTHPLANES || !(rover->fofflags & FOF_INVERTPLANES)))
|| (viewz > heightcheck && (rover->fofflags & FOF_BOTHPLANES || rover->fofflags & FOF_INVERTPLANES))))
{
light = R_GetPlaneLight(frontsector, planecenterz,
viewz < heightcheck);
light = R_GetPlaneLight(frontsector, planecenterz, viewz < heightcheck);
ffloor[numffloors].plane = R_FindPlane(rover->master->frontsector, *rover->bottomheight, *rover->bottompic,
*frontsector->lightlist[light].lightlevel, *rover->bottomxoffs, *rover->bottomyoffs,
R_FloorLightLevel(rover->master->frontsector, *frontsector->lightlist[light].lightlevel), *rover->bottomxoffs, *rover->bottomyoffs,
*rover->bottomxscale, *rover->bottomyscale, *rover->bottomangle,
*frontsector->lightlist[light].extra_colormap, rover, NULL, *rover->b_slope, NULL);
@ -1002,7 +1013,7 @@ static void R_Subsector(size_t num)
light = R_GetPlaneLight(frontsector, planecenterz, viewz < heightcheck);
ffloor[numffloors].plane = R_FindPlane(rover->master->frontsector, *rover->topheight, *rover->toppic,
*frontsector->lightlist[light].lightlevel, *rover->topxoffs, *rover->topyoffs,
R_CeilingLightLevel(rover->master->frontsector, *frontsector->lightlist[light].lightlevel), *rover->topxoffs, *rover->topyoffs,
*rover->topxscale, *rover->topyscale, *rover->topangle,
*frontsector->lightlist[light].extra_colormap, rover, NULL, *rover->t_slope, NULL);

View file

@ -60,6 +60,8 @@ typedef UINT8 lighttable_t;
#define CMF_FADEFULLBRIGHTSPRITES 1
#define CMF_FOG 4
#define TEXTURE_255_IS_TRANSPARENT
// ExtraColormap type. Use for extra_colormaps from now on.
typedef struct extracolormap_s
{
@ -358,7 +360,7 @@ typedef struct pslope_s
double dzdelta;
boolean moved : 1;
boolean moved;
UINT8 flags; // Slope options
} pslope_t;
@ -631,6 +633,11 @@ typedef struct
fixed_t scalex_top, scalex_mid, scalex_bottom;
fixed_t scaley_top, scaley_mid, scaley_bottom;
// per-wall lighting for UDMF
// TODO: implement per-texture lighting
INT16 light, light_top, light_mid, light_bottom;
boolean lightabsolute, lightabsolute_top, lightabsolute_mid, lightabsolute_bottom;
// Texture indices.
// We do not maintain names here.
INT32 toptexture, bottomtexture, midtexture;

View file

@ -19,7 +19,6 @@
#include "doomstat.h"
#include "r_local.h"
#include "r_translation.h"
#include "st_stuff.h" // need ST_HEIGHT
#include "i_video.h"
#include "v_video.h"
#include "m_misc.h"

View file

@ -154,9 +154,11 @@ void R_VideoErase(size_t ofs, INT32 count);
void R_DrawColumn_8(void);
void R_DrawColumnClamped_8(void);
void R_Draw2sMultiPatchColumn_8(void);
void R_DrawShadeColumn_8(void);
void R_DrawTranslucentColumn_8(void);
void R_DrawTranslucentColumnClamped_8(void);
void R_Draw2sMultiPatchTranslucentColumn_8(void);
void R_DrawDropShadowColumn_8(void);
void R_DrawTranslatedColumn_8(void);
void R_DrawTranslatedTranslucentColumn_8(void);

View file

@ -192,6 +192,189 @@ void R_DrawColumnClamped_8(void)
}
}
void R_Draw2sMultiPatchColumn_8(void)
{
INT32 count;
register UINT8 *dest;
register fixed_t frac;
fixed_t fracstep;
count = dc_yh - dc_yl;
if (count < 0) // Zero length, column does not exceed a pixel.
return;
#ifdef RANGECHECK
if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height)
return;
#endif
// Framebuffer destination address.
dest = &topleft[dc_yl*vid.width + dc_x];
count++;
// Determine scaling, which is the only mapping to be done.
fracstep = dc_iscale;
frac = dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep);
// Inner loop that does the actual texture mapping, e.g. a DDA-like scaling.
// This is as fast as it gets.
{
register const UINT8 *source = dc_source;
register const lighttable_t *colormap = dc_colormap;
register INT32 heightmask = dc_texheight-1;
register UINT8 val;
if (dc_texheight & heightmask) // not a power of 2 -- killough
{
heightmask++;
heightmask <<= FRACBITS;
if (frac < 0)
while ((frac += heightmask) < 0);
else
while (frac >= heightmask)
frac -= heightmask;
do
{
// Re-map color indices from wall texture column
// using a lighting/special effects LUT.
// heightmask is the Tutti-Frutti fix
val = source[frac>>FRACBITS];
if (val != TRANSPARENTPIXEL)
*dest = colormap[val];
dest += vid.width;
// Avoid overflow.
if (fracstep > 0x7FFFFFFF - frac)
frac += fracstep - heightmask;
else
frac += fracstep;
while (frac >= heightmask)
frac -= heightmask;
} while (--count);
}
else
{
while ((count -= 2) >= 0) // texture height is a power of 2
{
val = source[(frac>>FRACBITS) & heightmask];
if (val != TRANSPARENTPIXEL)
*dest = colormap[val];
dest += vid.width;
frac += fracstep;
val = source[(frac>>FRACBITS) & heightmask];
if (val != TRANSPARENTPIXEL)
*dest = colormap[val];
dest += vid.width;
frac += fracstep;
}
if (count & 1)
{
val = source[(frac>>FRACBITS) & heightmask];
if (val != TRANSPARENTPIXEL)
*dest = colormap[val];
}
}
}
}
void R_Draw2sMultiPatchTranslucentColumn_8(void)
{
INT32 count;
register UINT8 *dest;
register fixed_t frac;
fixed_t fracstep;
count = dc_yh - dc_yl;
if (count < 0) // Zero length, column does not exceed a pixel.
return;
#ifdef RANGECHECK
if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height)
return;
#endif
// Framebuffer destination address.
dest = &topleft[dc_yl*vid.width + dc_x];
count++;
// Determine scaling, which is the only mapping to be done.
fracstep = dc_iscale;
frac = dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep);
// Inner loop that does the actual texture mapping, e.g. a DDA-like scaling.
// This is as fast as it gets.
{
register const UINT8 *source = dc_source;
register const UINT8 *transmap = dc_transmap;
register const lighttable_t *colormap = dc_colormap;
register INT32 heightmask = dc_texheight-1;
register UINT8 val;
if (dc_texheight & heightmask) // not a power of 2 -- killough
{
heightmask++;
heightmask <<= FRACBITS;
if (frac < 0)
while ((frac += heightmask) < 0);
else
while (frac >= heightmask)
frac -= heightmask;
do
{
// Re-map color indices from wall texture column
// using a lighting/special effects LUT.
// heightmask is the Tutti-Frutti fix
val = source[frac>>FRACBITS];
if (val != TRANSPARENTPIXEL)
*dest = *(transmap + (colormap[val]<<8) + (*dest));
dest += vid.width;
// Avoid overflow.
if (fracstep > 0x7FFFFFFF - frac)
frac += fracstep - heightmask;
else
frac += fracstep;
while (frac >= heightmask)
frac -= heightmask;
} while (--count);
}
else
{
while ((count -= 2) >= 0) // texture height is a power of 2
{
val = source[(frac>>FRACBITS) & heightmask];
if (val != TRANSPARENTPIXEL)
*dest = *(transmap + (colormap[val]<<8) + (*dest));
dest += vid.width;
frac += fracstep;
val = source[(frac>>FRACBITS) & heightmask];
if (val != TRANSPARENTPIXEL)
*dest = *(transmap + (colormap[val]<<8) + (*dest));
dest += vid.width;
frac += fracstep;
}
if (count & 1)
{
val = source[(frac>>FRACBITS) & heightmask];
if (val != TRANSPARENTPIXEL)
*dest = *(transmap + (colormap[val]<<8) + (*dest));
}
}
}
}
/** \brief The R_DrawShadeColumn_8 function
Experiment to make software go faster. Taken from the Boom source
*/

View file

@ -120,6 +120,19 @@ static vector3_t *R_LerpVector3(const vector3_t *from, const vector3_t *to, fixe
return out;
}
static double R_LerpDouble(double from, double to, double frac)
{
return from + (frac * (to - from));
}
static dvector3_t *R_LerpDVector3(const dvector3_t *from, const dvector3_t *to, double frac, dvector3_t *out)
{
DVector3_Subtract(to, from, out);
DVector3_Multiply(out, frac, out);
DVector3_Add(from, out, out);
return out;
}
// recalc necessary stuff for mouseaiming
// slopes are already calculated for the full possible view (which is 4*viewheight).
// 18/08/18: (No it's actually 16*viewheight, thanks Jimita for finding this out)
@ -497,6 +510,14 @@ void R_CreateInterpolator_DynSlope(thinker_t *thinker, pslope_t *slope)
FV2_Copy(&interp->dynslope.bakd, &slope->d);
interp->dynslope.oldzdelta = interp->dynslope.bakzdelta = slope->zdelta;
DVector3_Copy(&interp->dynslope.oldorigin, &slope->dorigin);
DVector3_Copy(&interp->dynslope.bakorigin, &slope->dorigin);
DVector3_Copy(&interp->dynslope.oldnormdir, &slope->dnormdir);
DVector3_Copy(&interp->dynslope.baknormdir, &slope->dnormdir);
interp->dynslope.olddzdelta = interp->dynslope.bakdzdelta = slope->dzdelta;
}
void R_InitializeLevelInterpolators(void)
@ -561,6 +582,21 @@ static void UpdateLevelInterpolatorState(levelinterpolator_t *interp)
FV3_Copy(&interp->dynslope.bako, &interp->dynslope.slope->o);
FV2_Copy(&interp->dynslope.bakd, &interp->dynslope.slope->d);
interp->dynslope.bakzdelta = interp->dynslope.slope->zdelta;
DVector3_Copy(&interp->dynslope.oldorigin, &interp->dynslope.bakorigin);
DVector3_Copy(&interp->dynslope.oldnormdir, &interp->dynslope.baknormdir);
interp->dynslope.olddzdelta = interp->dynslope.bakdzdelta;
if (interp->dynslope.slope->moved)
{
P_CalculateSlopeVectors(interp->dynslope.slope);
interp->dynslope.slope->moved = false;
}
DVector3_Copy(&interp->dynslope.bakorigin, &interp->dynslope.slope->dorigin);
DVector3_Copy(&interp->dynslope.baknormdir, &interp->dynslope.slope->dnormdir);
interp->dynslope.bakdzdelta = interp->dynslope.slope->dzdelta;
break;
}
}
@ -646,7 +682,13 @@ void R_ApplyLevelInterpolators(fixed_t frac)
R_LerpVector3(&interp->dynslope.oldo, &interp->dynslope.bako, frac, &interp->dynslope.slope->o);
R_LerpVector2(&interp->dynslope.oldd, &interp->dynslope.bakd, frac, &interp->dynslope.slope->d);
interp->dynslope.slope->zdelta = R_LerpFixed(interp->dynslope.oldzdelta, interp->dynslope.bakzdelta, frac);
interp->dynslope.slope->moved = true;
if (rendermode == render_soft)
{
double dfrac = FixedToDouble(frac);
R_LerpDVector3(&interp->dynslope.oldorigin, &interp->dynslope.bakorigin, dfrac, &interp->dynslope.slope->dorigin);
R_LerpDVector3(&interp->dynslope.oldnormdir, &interp->dynslope.baknormdir, dfrac, &interp->dynslope.slope->dnormdir);
interp->dynslope.slope->dzdelta = R_LerpDouble(interp->dynslope.olddzdelta, interp->dynslope.bakdzdelta, dfrac);
}
break;
}
}
@ -704,6 +746,10 @@ void R_RestoreLevelInterpolators(void)
FV3_Copy(&interp->dynslope.slope->o, &interp->dynslope.bako);
FV2_Copy(&interp->dynslope.slope->d, &interp->dynslope.bakd);
interp->dynslope.slope->zdelta = interp->dynslope.bakzdelta;
DVector3_Copy(&interp->dynslope.slope->dorigin, &interp->dynslope.bakorigin);
DVector3_Copy(&interp->dynslope.slope->dnormdir, &interp->dynslope.baknormdir);
interp->dynslope.slope->dzdelta = interp->dynslope.bakdzdelta;
break;
}
}

View file

@ -115,6 +115,9 @@ typedef struct levelinterpolator_s {
vector3_t oldo, bako;
vector2_t oldd, bakd;
fixed_t oldzdelta, bakzdelta;
dvector3_t oldorigin, bakorigin;
dvector3_t oldnormdir, baknormdir;
double olddzdelta, bakdzdelta;
} dynslope;
};
} levelinterpolator_t;

View file

@ -910,7 +910,7 @@ void R_DrawSinglePlane(visplane_t *pl)
if (pl->polyobj->translucency == 0 || (pl->extra_colormap && (pl->extra_colormap->flags & CMF_FOG)))
light = (pl->lightlevel >> LIGHTSEGSHIFT);
else
else // TODO: 2.3: Make transparent polyobject planes always use light level
light = LIGHTLEVELS-1;
}
else
@ -952,7 +952,7 @@ void R_DrawSinglePlane(visplane_t *pl)
if ((spanfunctype == SPANDRAWFUNC_SPLAT) || (pl->extra_colormap && (pl->extra_colormap->flags & CMF_FOG)))
light = (pl->lightlevel >> LIGHTSEGSHIFT);
else
else // TODO: 2.3: Make transparent FOF planes use light level instead of always being fullbright
light = LIGHTLEVELS-1;
}
else if (pl->ffloor->fofflags & FOF_FOG)

View file

@ -94,6 +94,124 @@ transnum_t R_GetLinedefTransTable(fixed_t alpha)
return (20*(FRACUNIT - alpha - 1) + FRACUNIT) >> (FRACBITS+1);
}
static UINT8 R_SideLightLevel(side_t *side, INT16 base_lightlevel)
{
return max(0, min(255, side->light +
((side->lightabsolute) ? 0 : base_lightlevel)));
}
/* TODO: implement per-texture lighting
static UINT8 R_TopLightLevel(side_t *side, INT16 base_lightlevel)
{
return max(0, min(255, side->light_top +
((side->lightabsolute_top) ? 0 : R_SideLightLevel(side, base_lightlevel))));
}
static UINT8 R_MidLightLevel(side_t *side, INT16 base_lightlevel)
{
return max(0, min(255, side->light_mid +
((side->lightabsolute_mid) ? 0 : R_SideLightLevel(side, base_lightlevel))));
}
static UINT8 R_BottomLightLevel(side_t *side, INT16 base_lightlevel)
{
return max(0, min(255, side->light_bottom +
((side->lightabsolute_bottom) ? 0 : R_SideLightLevel(side, base_lightlevel))));
}
*/
// If we have a multi-patch texture on a 2sided wall (rare) then we draw
// it using R_DrawColumn, else we draw it using R_DrawMaskedColumn, this
// way we don't have to store extra post_t info with each column for
// multi-patch textures. They are not normally needed as multi-patch
// textures don't have holes in it. At least not for now.
static void R_Render2sidedMultiPatchColumn(column_t *column, unsigned lengthcol)
{
INT32 topscreen, bottomscreen;
post_t *post = &column->posts[0];
if (!post->length)
return;
topscreen = sprtopscreen;
bottomscreen = topscreen + spryscale * lengthcol;
dc_yl = (sprtopscreen+FRACUNIT-1)>>FRACBITS;
dc_yh = (bottomscreen-1)>>FRACBITS;
if (windowtop != INT32_MAX && windowbottom != INT32_MAX)
{
dc_yl = ((windowtop + FRACUNIT)>>FRACBITS);
dc_yh = (windowbottom - 1)>>FRACBITS;
}
if (dc_yh >= mfloorclip[dc_x])
dc_yh = mfloorclip[dc_x] - 1;
if (dc_yl <= mceilingclip[dc_x])
dc_yl = mceilingclip[dc_x] + 1;
if (dc_yl >= vid.height || dc_yh < 0)
return;
if (dc_yl <= dc_yh && dc_yh < vid.height && dc_yh > 0)
{
dc_source = column->pixels + post->data_offset;
dc_postlength = post->length;
if (colfunc == colfuncs[BASEDRAWFUNC])
(colfuncs[COLDRAWFUNC_TWOSMULTIPATCH])();
else if (colfunc == colfuncs[COLDRAWFUNC_FUZZY])
(colfuncs[COLDRAWFUNC_TWOSMULTIPATCHTRANS])();
else
colfunc();
}
}
static void R_RenderFlipped2sidedMultiPatchColumn(column_t *column, unsigned lengthcol)
{
INT32 topscreen, bottomscreen;
void (*localcolfunc)(void);
post_t *post = &column->posts[0];
if (!post->length)
return;
topscreen = sprtopscreen;
bottomscreen = topscreen + spryscale * lengthcol;
dc_yl = (sprtopscreen+FRACUNIT-1)>>FRACBITS;
dc_yh = (bottomscreen-1)>>FRACBITS;
if (windowtop != INT32_MAX && windowbottom != INT32_MAX)
{
dc_yl = ((windowtop + FRACUNIT)>>FRACBITS);
dc_yh = (windowbottom - 1)>>FRACBITS;
}
if (dc_yh >= mfloorclip[dc_x])
dc_yh = mfloorclip[dc_x] - 1;
if (dc_yl <= mceilingclip[dc_x])
dc_yl = mceilingclip[dc_x] + 1;
if (dc_yl >= vid.height || dc_yh < 0)
return;
if (dc_yl <= dc_yh && dc_yh < vid.height && dc_yh > 0)
{
dc_postlength = post->length;
if (colfunc == colfuncs[BASEDRAWFUNC])
localcolfunc = colfuncs[COLDRAWFUNC_TWOSMULTIPATCH];
else if (colfunc == colfuncs[COLDRAWFUNC_FUZZY])
localcolfunc = colfuncs[COLDRAWFUNC_TWOSMULTIPATCHTRANS];
else
localcolfunc = colfunc;
R_DrawFlippedPost(column->pixels + post->data_offset, post->length, localcolfunc);
}
}
void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
{
size_t pindex;
@ -181,7 +299,16 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
// Texture must be cached
R_CheckTextureCache(texnum);
if (vertflip) // vertically flipped?
// handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures
// are not stored per-column with post info in SRB2
if (!textures[texnum]->transparency)
{
if (vertflip) // vertically flipped?
colfunc_2s = R_RenderFlipped2sidedMultiPatchColumn;
else
colfunc_2s = R_Render2sidedMultiPatchColumn;
}
else if (vertflip) // vertically flipped?
colfunc_2s = R_DrawFlippedMaskedColumn;
else
colfunc_2s = R_DrawMaskedColumn; // render the usual 2sided single-patch packed texture
@ -223,7 +350,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
if ((colfunc != colfuncs[COLDRAWFUNC_FUZZY])
|| (rlight->flags & FOF_FOG)
|| (rlight->extra_colormap && (rlight->extra_colormap->flags & CMF_FOG)))
lightnum = (rlight->lightlevel >> LIGHTSEGSHIFT);
lightnum = R_SideLightLevel(curline->sidedef, rlight->lightlevel) >> LIGHTSEGSHIFT;
else
lightnum = LIGHTLEVELS - 1;
@ -241,7 +368,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
{
if ((colfunc != colfuncs[COLDRAWFUNC_FUZZY])
|| (frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG)))
lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT);
lightnum = R_SideLightLevel(curline->sidedef, frontsector->lightlevel) >> LIGHTSEGSHIFT;
else
lightnum = LIGHTLEVELS - 1;
@ -697,9 +824,9 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
// Check if the current light effects the colormap/lightlevel
if (pfloor->fofflags & FOF_FOG)
rlight->lightnum = (pfloor->master->frontsector->lightlevel >> LIGHTSEGSHIFT);
rlight->lightnum = R_SideLightLevel(curline->sidedef, pfloor->master->frontsector->lightlevel) >> LIGHTSEGSHIFT;
else
rlight->lightnum = (rlight->lightlevel >> LIGHTSEGSHIFT);
rlight->lightnum = R_SideLightLevel(curline->sidedef, rlight->lightlevel) >> LIGHTSEGSHIFT;
if (pfloor->fofflags & FOF_FOG || rlight->flags & FOF_FOG || (rlight->extra_colormap && (rlight->extra_colormap->flags & CMF_FOG)))
;
@ -717,18 +844,17 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
{
// Get correct light level!
if ((frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG)))
lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT);
lightnum = R_SideLightLevel(curline->sidedef, frontsector->lightlevel) >> LIGHTSEGSHIFT;
else if (fog)
lightnum = (pfloor->master->frontsector->lightlevel >> LIGHTSEGSHIFT);
lightnum = R_SideLightLevel(curline->sidedef, pfloor->master->frontsector->lightlevel) >> LIGHTSEGSHIFT;
else if (fuzzy)
lightnum = LIGHTLEVELS-1;
else
lightnum = R_FakeFlat(frontsector, &tempsec, &templight, &templight, false)
->lightlevel >> LIGHTSEGSHIFT;
lightnum = R_SideLightLevel(curline->sidedef, R_FakeFlat(frontsector, &tempsec, &templight, &templight, false)->lightlevel) >> LIGHTSEGSHIFT;
if (pfloor->fofflags & FOF_FOG || (frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG)));
else if (curline->v1->y == curline->v2->y)
lightnum--;
lightnum--;
else if (curline->v1->x == curline->v2->x)
lightnum++;
@ -811,7 +937,16 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
// Texture must be cached
R_CheckTextureCache(texnum);
if (vertflip) // vertically flipped?
// handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures
// are not stored per-column with post info in SRB2
if (!textures[texnum]->transparency)
{
if (vertflip) // vertically flipped?
colfunc_2s = R_RenderFlipped2sidedMultiPatchColumn;
else
colfunc_2s = R_Render2sidedMultiPatchColumn;
}
else if (vertflip) // vertically flipped?
colfunc_2s = R_DrawRepeatFlippedMaskedColumn;
else
colfunc_2s = R_DrawRepeatMaskedColumn;
@ -906,9 +1041,9 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
{
// Otherwise use column drawers with extra checks
if (fuzzy)
colfunc = R_DrawTranslucentColumnClamped_8;
colfunc = colfuncs[COLDRAWFUNC_CLAMPEDTRANS];
else
colfunc = R_DrawColumnClamped_8;
colfunc = colfuncs[COLDRAWFUNC_CLAMPED];
}
}
@ -1353,7 +1488,7 @@ static void R_RenderSegLoop (void)
for (i = 0; i < dc_numlights; i++)
{
INT32 lightnum;
lightnum = (dc_lightlist[i].lightlevel >> LIGHTSEGSHIFT);
lightnum = R_SideLightLevel(curline->sidedef, dc_lightlist[i].lightlevel) >> LIGHTSEGSHIFT;
if (dc_lightlist[i].extra_colormap)
;
@ -2540,7 +2675,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
// use different light tables
// for horizontal / vertical / diagonal
// OPTIMIZE: get rid of LIGHTSEGSHIFT globally
lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT);
lightnum = R_SideLightLevel(curline->sidedef, frontsector->lightlevel) >> LIGHTSEGSHIFT;
if (curline->v1->y == curline->v2->y)
lightnum--;

View file

@ -636,6 +636,14 @@ static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, ski
if (skin->sprites[0].numframes == 0)
CONS_Alert(CONS_ERROR, M_GetText("No frames found for sprite SPR2_%s\n"), spr2names[0]);
// TODO: 2.3: Delete
memcpy(&skin->sprites_compat[start_spr2],
&skin->sprites[start_spr2],
sizeof(spritedef_t) * (free_spr2 - start_spr2));
memcpy(&skin->sprites_compat[start_spr2 + NUMPLAYERSPRITES],
&skin->super.sprites[start_spr2],
sizeof(spritedef_t) * (free_spr2 - start_spr2));
}
// returns whether found appropriate property

View file

@ -88,6 +88,9 @@ typedef struct
spritedef_t sprites[NUMPLAYERSPRITES];
spriteinfo_t sprinfo[NUMPLAYERSPRITES];
} super;
// TODO: 2.3: Delete
spritedef_t sprites_compat[NUMPLAYERSPRITES * 2];
} skin_t;
/// Externs

View file

@ -147,9 +147,9 @@ static void R_DrawFlippedColumnInCache(column_t *column, UINT8 *cache, texpatch_
if (count > 0)
{
for (; dest < cache + position + count; --source, is_opaque++)
for (; dest < cache + position + count; --source, dest++, is_opaque++)
{
*dest++ = *source;
*dest = *source;
*is_opaque = true;
}
}
@ -295,7 +295,6 @@ UINT8 *R_GenerateTexture(size_t texnum)
UINT16 lumpnum = patch->lump;
UINT8 *pdata;
softwarepatch_t *realpatch;
boolean holey = false;
#ifndef NO_PNG_LUMPS
UINT8 header[PNG_HEADER_SIZE];
@ -310,9 +309,11 @@ UINT8 *R_GenerateTexture(size_t texnum)
pdata = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE);
realpatch = (softwarepatch_t *)pdata;
texture->transparency = false;
// Check the patch for holes.
if (texture->width > SHORT(realpatch->width) || texture->height > SHORT(realpatch->height))
holey = true;
texture->transparency = true;
else
{
UINT8 *colofs = (UINT8 *)realpatch->columnofs;
@ -332,12 +333,12 @@ UINT8 *R_GenerateTexture(size_t texnum)
col = (doompost_t *)((UINT8 *)col + col->length + 4);
}
if (y < texture->height)
holey = true; // this texture is HOLEy! D:
texture->transparency = true; // this texture is HOLEy! D:
}
}
// If the patch uses transparency, we have to save it this way.
if (holey)
if (texture->transparency)
{
texture->flip = patch->flip;
@ -378,6 +379,15 @@ UINT8 *R_GenerateTexture(size_t texnum)
temp_columns = Z_Calloc(sizeof(column_t) * texture->width, PU_STATIC, NULL);
temp_block = Z_Calloc(total_pixels, PU_STATIC, NULL);
#ifdef TEXTURE_255_IS_TRANSPARENT
texture->transparency = false;
// Transparency hack
memset(temp_block, TRANSPARENTPIXEL, total_pixels);
#else
texture->transparency = true;
#endif
for (x = 0; x < texture->width; x++)
{
column_t *column = &temp_columns[x];
@ -474,13 +484,27 @@ UINT8 *R_GenerateTexture(size_t texnum)
// Now write the columns
column_posts = Z_Calloc(sizeof(unsigned) * texture->width, PU_STATIC, NULL);
#ifdef TEXTURE_255_IS_TRANSPARENT
total_posts = texture->width;
temp_posts = Z_Realloc(temp_posts, sizeof(post_t) * total_posts, PU_CACHE, NULL);
#endif
for (x = 0; x < texture->width; x++)
{
post_t *post = NULL;
boolean was_opaque = false;
column_t *column = &temp_columns[x];
#ifdef TEXTURE_255_IS_TRANSPARENT
post = &temp_posts[x];
post->topdelta = 0;
post->length = texture->height;
post->data_offset = 0;
column_posts[x] = x;
column->num_posts = 1;
#else
boolean was_opaque = false;
column_posts[x] = (unsigned)-1;
for (INT32 y = 0; y < texture->height; y++)
@ -510,6 +534,7 @@ UINT8 *R_GenerateTexture(size_t texnum)
post->length++;
}
#endif
}
blocksize = (sizeof(column_t) * texture->width) + (sizeof(post_t) * total_posts) + (sizeof(UINT8) * total_pixels);
@ -1154,7 +1179,7 @@ static lumpnum_t W_GetTexPatchLumpNum(const char *name)
if (lump == LUMPERROR)
{
// Use whatever else you can find.
return W_GetNumForName(name);
return W_CheckNumForPatchName(name);
}
return lump;

View file

@ -54,6 +54,7 @@ typedef struct
char name[8];
UINT32 hash;
UINT8 type; // TEXTURETYPE_*
boolean transparency;
INT16 width, height;
UINT8 flip; // 1 = flipx, 2 = flipy, 3 = both
void *flat; // The texture, as a flat.

View file

@ -996,6 +996,12 @@ UINT8 *R_GetTranslationForThing(mobj_t *mobj, skincolornum_t color, UINT16 trans
return NULL;
}
// Based off of R_GetLinedefTransTable
transnum_t R_GetThingTransTable(fixed_t alpha, transnum_t transmap)
{
return (20*(FRACUNIT - ((alpha * (10 - transmap))/10) - 1) + FRACUNIT) >> (FRACBITS+1);
}
//
// R_DrawVisSprite
// mfloorclip and mceilingclip should also be set.
@ -1501,6 +1507,7 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale,
floordiff = abs((isflipped ? interp.height : 0) + interp.z - groundz);
trans = floordiff / (100*FRACUNIT) + 3;
trans = R_GetThingTransTable(thing->alpha, trans);
if (trans >= 9) return;
scalemul = FixedMul(FRACUNIT - floordiff/640, scale);
@ -2191,6 +2198,11 @@ static void R_ProjectSprite(mobj_t *thing)
}
else
trans = 0;
if ((oldthing->flags2 & MF2_LINKDRAW) && oldthing->tracer)
trans = R_GetThingTransTable(oldthing->tracer->alpha, trans);
else
trans = R_GetThingTransTable(oldthing->alpha, trans);
// Check if this sprite needs to be rendered like a shadow
shadowdraw = (!!(thing->renderflags & RF_SHADOWDRAW) && !(papersprite || splat));
@ -3652,6 +3664,7 @@ boolean R_ThingVisible (mobj_t *thing)
(thing->sprite == SPR_NULL) || // Don't draw null-sprites
(thing->flags2 & MF2_DONTDRAW) || // Don't draw MF2_LINKDRAW objects
(thing->drawonlyforplayer && thing->drawonlyforplayer != viewplayer) || // Don't draw other players' personal objects
(!R_BlendLevelVisible(thing->blendmode, R_GetThingTransTable(thing->alpha, 0))) ||
(!P_MobjWasRemoved(r_viewmobj) && (
(r_viewmobj == thing) || // Don't draw first-person players or awayviewmobj objects
(r_viewmobj->player && r_viewmobj->player->followmobj == thing) || // Don't draw first-person players' followmobj

View file

@ -93,6 +93,7 @@ boolean R_ThingIsFullDark (mobj_t *thing);
boolean R_ThingIsFlashing (mobj_t *thing);
UINT8 *R_GetTranslationForThing(mobj_t *mobj, skincolornum_t color, UINT16 translation);
transnum_t R_GetThingTransTable(fixed_t alpha, transnum_t transmap);
void R_ThingOffsetOverlay (mobj_t *thing, fixed_t *outx, fixed_t *outy);

View file

@ -112,6 +112,10 @@ void SCR_SetDrawFuncs(void)
colfuncs[COLDRAWFUNC_SHADE] = R_DrawShadeColumn_8;
colfuncs[COLDRAWFUNC_SHADOWED] = R_DrawColumnShadowed_8;
colfuncs[COLDRAWFUNC_TRANSTRANS] = R_DrawTranslatedTranslucentColumn_8;
colfuncs[COLDRAWFUNC_CLAMPED] = R_DrawColumnClamped_8;
colfuncs[COLDRAWFUNC_CLAMPEDTRANS] = R_DrawTranslucentColumnClamped_8;
colfuncs[COLDRAWFUNC_TWOSMULTIPATCH] = R_Draw2sMultiPatchColumn_8;
colfuncs[COLDRAWFUNC_TWOSMULTIPATCHTRANS] = R_Draw2sMultiPatchTranslucentColumn_8;
colfuncs[COLDRAWFUNC_FOG] = R_DrawFogColumn_8;
spanfuncs[SPANDRAWFUNC_TRANS] = R_DrawTranslucentSpan_8;

View file

@ -30,10 +30,6 @@
#define NUMSCREENS 5
#endif
// Size of statusbar.
#define ST_HEIGHT 32
#define ST_WIDTH 320
// used now as a maximum video mode size for extra vesa modes.
// we try to re-allocate a minimum of buffers for stability of the memory,
@ -97,6 +93,10 @@ enum
COLDRAWFUNC_SHADE,
COLDRAWFUNC_SHADOWED,
COLDRAWFUNC_TRANSTRANS,
COLDRAWFUNC_CLAMPED,
COLDRAWFUNC_CLAMPEDTRANS,
COLDRAWFUNC_TWOSMULTIPATCH,
COLDRAWFUNC_TWOSMULTIPATCHTRANS,
COLDRAWFUNC_FOG,
COLDRAWFUNC_MAX

View file

@ -33,8 +33,6 @@ target_compile_options(SRB2SDL2 PRIVATE
-Wall
-Wno-trigraphs
-W # Was controlled by RELAXWARNINGS
-pedantic
-Wpedantic
-Wfloat-equal
-Wundef
-Wpointer-arith

View file

@ -2987,7 +2987,7 @@ static void pathonly(char *s)
*/
static const char *searchWad(const char *searchDir)
{
static char tempsw[256] = "";
static char tempsw[MAX_WADPATH] = "";
filestatus_t fstemp;
strcpy(tempsw, WADKEYWORD1);
@ -3003,8 +3003,8 @@ static const char *searchWad(const char *searchDir)
#define CHECKWADPATH(ret) \
do { \
I_OutputMsg(",%s", returnWadPath); \
if (isWadPathOk(returnWadPath)) \
I_OutputMsg(",%s", ret); \
if (isWadPathOk(ret)) \
return ret; \
} while (0)
@ -3033,7 +3033,9 @@ static const char *locateWad(void)
#ifndef NOCWD
// examine current dir
strcpy(returnWadPath, ".");
CHECKWADPATH(NULL);
I_OutputMsg(",%s", returnWadPath);
if (isWadPathOk(returnWadPath))
return NULL;
#endif
#ifdef __APPLE__
@ -3050,9 +3052,16 @@ static const char *locateWad(void)
#ifndef NOHOME
// find in $HOME
I_OutputMsg(",HOME");
I_OutputMsg(",HOME/" DEFAULTDIR);
if ((envstr = I_GetEnv("HOME")) != NULL)
SEARCHWAD(envstr);
{
char *tmp = malloc(strlen(envstr) + 1 + sizeof(DEFAULTDIR));
strcpy(tmp, envstr);
strcat(tmp, "/");
strcat(tmp, DEFAULTDIR);
CHECKWADPATH(tmp);
free(tmp);
}
#endif
// search paths

View file

@ -1706,7 +1706,7 @@ static void Impl_VideoSetupBuffer(void)
vid.direct = NULL;
if (vid.buffer)
free(vid.buffer);
vid.buffer = calloc(vid.rowbytes*vid.height, NUMSCREENS);
vid.buffer = calloc(NUMSCREENS, vid.rowbytes*vid.height);
if (!vid.buffer)
{
I_Error("%s", M_GetText("Not enough memory for video buffer\n"));

View file

@ -582,7 +582,7 @@ boolean Snake_JoyGrabber(void *opaque, event_t *ev)
{
snake_t *snake = opaque;
if (ev->type == ev_joystick && ev->key == 0)
if (snake != NULL && ev->type == ev_joystick && ev->key == 0)
{
snake->joyevents[snake->joyeventcount] = ev;
snake->joyeventcount++;