Merge remote-tracking branch 'origin/next' into pitch-roll

This commit is contained in:
lachablock 2022-03-28 20:58:35 +11:00
commit f126ceb878
23 changed files with 477 additions and 217 deletions

View file

@ -91,6 +91,8 @@ actionpointer_t actionpointers[] =
{{A_FaceTracer}, "A_FACETRACER"},
{{A_Scream}, "A_SCREAM"},
{{A_BossDeath}, "A_BOSSDEATH"},
{{A_SetShadowScale}, "A_SETSHADOWSCALE"},
{{A_ShadowScream}, "A_SHADOWSCREAM"},
{{A_CustomPower}, "A_CUSTOMPOWER"},
{{A_GiveWeapon}, "A_GIVEWEAPON"},
{{A_RingBox}, "A_RINGBOX"},

View file

@ -530,6 +530,22 @@ extern boolean capslock;
// i_system.c, replace getchar() once the keyboard has been appropriated
INT32 I_GetKey(void);
/* http://www.cse.yorku.ca/~oz/hash.html */
static inline
UINT32 quickncasehash (const char *p, size_t n)
{
size_t i = 0;
UINT32 x = 5381;
while (i < n && p[i])
{
x = (x * 33) ^ tolower(p[i]);
i++;
}
return x;
}
#ifndef min // Double-Check with WATTCP-32's cdefs.h
#define min(x, y) (((x) < (y)) ? (x) : (y))
#endif

View file

@ -3632,6 +3632,7 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale)
FBITFIELD blendmode = PF_Translucent|PF_Modulated;
INT32 shader = SHADER_DEFAULT;
UINT8 i;
INT32 heightsec, phs;
SINT8 flip = P_MobjFlip(thing);
INT32 light;
@ -3644,7 +3645,23 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale)
groundz = R_GetShadowZ(thing, &groundslope);
//if (abs(groundz - gl_viewz) / tz > 4) return; // Prevent stretchy shadows and possible crashes
heightsec = thing->subsector->sector->heightsec;
if (viewplayer->mo && viewplayer->mo->subsector)
phs = viewplayer->mo->subsector->sector->heightsec;
else
phs = -1;
if (heightsec != -1 && phs != -1) // only clip things which are in special sectors
{
if (gl_viewz < FIXED_TO_FLOAT(sectors[phs].floorheight) ?
thing->z >= sectors[heightsec].floorheight :
thing->z < sectors[heightsec].floorheight)
return;
if (gl_viewz > FIXED_TO_FLOAT(sectors[phs].ceilingheight) ?
thing->z < sectors[heightsec].ceilingheight && gl_viewz >= FIXED_TO_FLOAT(sectors[heightsec].ceilingheight) :
thing->z >= sectors[heightsec].ceilingheight)
return;
}
floordiff = abs((flip < 0 ? thing->height : 0) + thing->z - groundz);
@ -5179,8 +5196,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
#ifdef ROTSPRITE
if (papersprite)
rollangle = thing->pitch // pitch should flip the sprite rotation on one side of the papersprite (OpenGL does this by default)
+ (ang >= ANGLE_180 ? -1 : 1) * thing->rollangle; // rollangle should use the same rotation for both sides of a papersprite (Software behavior parity)
rollangle = thing->rollangle;
else
{
rollangle = FixedMul(FINECOSINE((ang) >> ANGLETOFINESHIFT), thing->roll)
@ -5310,13 +5326,19 @@ static void HWR_ProjectSprite(mobj_t *thing)
if (heightsec != -1 && phs != -1) // only clip things which are in special sectors
{
float top = gzt;
float bottom = FIXED_TO_FLOAT(thing->z);
if (R_ThingIsFloorSprite(thing))
top = bottom;
if (gl_viewz < FIXED_TO_FLOAT(sectors[phs].floorheight) ?
FIXED_TO_FLOAT(thing->z) >= FIXED_TO_FLOAT(sectors[heightsec].floorheight) :
gzt < FIXED_TO_FLOAT(sectors[heightsec].floorheight))
bottom >= FIXED_TO_FLOAT(sectors[heightsec].floorheight) :
top < FIXED_TO_FLOAT(sectors[heightsec].floorheight))
return;
if (gl_viewz > FIXED_TO_FLOAT(sectors[phs].ceilingheight) ?
gzt < FIXED_TO_FLOAT(sectors[heightsec].ceilingheight) && gl_viewz >= FIXED_TO_FLOAT(sectors[heightsec].ceilingheight) :
FIXED_TO_FLOAT(thing->z) >= FIXED_TO_FLOAT(sectors[heightsec].ceilingheight))
top < FIXED_TO_FLOAT(sectors[heightsec].ceilingheight) && gl_viewz >= FIXED_TO_FLOAT(sectors[heightsec].ceilingheight) :
bottom >= FIXED_TO_FLOAT(sectors[heightsec].ceilingheight))
return;
}

View file

@ -2992,10 +2992,10 @@ state_t states[NUMSTATES] =
{SPR_NULL, 0, 15*2, {NULL}, 0, 0, S_ZAPSB2 }, // S_ZAPSB11
// Thunder spark
{SPR_SSPK, FF_ANIMATE, -1, {NULL}, 1, 2, S_NULL}, // S_THUNDERCOIN_SPARK
{SPR_SSPK, FF_ANIMATE|FF_FULLBRIGHT, -1, {NULL}, 1, 2, S_NULL}, // S_THUNDERCOIN_SPARK
// Invincibility Sparkles
{SPR_IVSP, FF_ANIMATE, 32, {NULL}, 31, 1, S_NULL}, // S_IVSP
{SPR_IVSP, FF_ANIMATE|FF_FULLBRIGHT, 32, {NULL}, 31, 1, S_NULL}, // S_IVSP
// Super Sonic Spark
{SPR_SSPK, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_SSPK2}, // S_SSPK1
@ -3936,23 +3936,23 @@ state_t states[NUMSTATES] =
{SPR_SPRK, FF_TRANS20|FF_ANIMATE|9, 18, {NULL}, 8, 2, S_NULL}, // S_SPRK3
// Robot Explosion
{SPR_BOM1, 0, 0, {A_FlickySpawn}, 0, 0, S_XPLD1}, // S_XPLD_FLICKY
{SPR_BOM1, 0, 2, {A_Scream}, 0, 0, S_XPLD2}, // S_XPLD1
{SPR_BOM1, 1, 2, {NULL}, 0, 0, S_XPLD3}, // S_XPLD2
{SPR_BOM1, 2, 3, {NULL}, 0, 0, S_XPLD4}, // S_XPLD3
{SPR_BOM1, 3, 3, {NULL}, 0, 0, S_XPLD5}, // S_XPLD4
{SPR_BOM1, 4, 4, {NULL}, 0, 0, S_XPLD6}, // S_XPLD5
{SPR_BOM1, 5, 4, {NULL}, 0, 0, S_NULL}, // S_XPLD6
{SPR_BOM1, 0, 0, {A_FlickySpawn}, 0, 0, S_XPLD1}, // S_XPLD_FLICKY
{SPR_BOM1, 0, 2, {A_ShadowScream}, 0, 0, S_XPLD2}, // S_XPLD1
{SPR_BOM1, 1, 2, {NULL}, 0, 0, S_XPLD3}, // S_XPLD2
{SPR_BOM1, 2, 3, {NULL}, 0, 0, S_XPLD4}, // S_XPLD3
{SPR_BOM1, 3, 3, {NULL}, 0, 0, S_XPLD5}, // S_XPLD4
{SPR_BOM1, 4, 4, {NULL}, 0, 0, S_XPLD6}, // S_XPLD5
{SPR_BOM1, 5, 4, {NULL}, 0, 0, S_NULL}, // S_XPLD6
{SPR_BOM1, FF_ANIMATE, 21, {NULL}, 5, 4, S_INVISIBLE}, // S_XPLD_EGGTRAP
// Underwater Explosion
{SPR_BOM4, 0, 3, {A_Scream}, 0, 0, S_WPLD2}, // S_WPLD1
{SPR_BOM4, 1, 3, {NULL}, 0, 0, S_WPLD3}, // S_WPLD2
{SPR_BOM4, 2, 3, {NULL}, 0, 0, S_WPLD4}, // S_WPLD3
{SPR_BOM4, 3, 3, {NULL}, 0, 0, S_WPLD5}, // S_WPLD4
{SPR_BOM4, 4, 3, {NULL}, 0, 0, S_WPLD6}, // S_WPLD5
{SPR_BOM4, 5, 3, {NULL}, 0, 0, S_NULL}, // S_WPLD6
{SPR_BOM4, 0, 3, {A_ShadowScream}, 0, 0, S_WPLD2}, // S_WPLD1
{SPR_BOM4, 1, 3, {NULL}, 0, 0, S_WPLD3}, // S_WPLD2
{SPR_BOM4, 2, 3, {NULL}, 0, 0, S_WPLD4}, // S_WPLD3
{SPR_BOM4, 3, 3, {NULL}, 0, 0, S_WPLD5}, // S_WPLD4
{SPR_BOM4, 4, 3, {NULL}, 0, 0, S_WPLD6}, // S_WPLD5
{SPR_BOM4, 5, 3, {NULL}, 0, 0, S_NULL}, // S_WPLD6
{SPR_DUST, FF_TRANS40, 4, {NULL}, 0, 0, S_DUST2}, // S_DUST1
{SPR_DUST, 1|FF_TRANS50, 5, {NULL}, 0, 0, S_DUST3}, // S_DUST2

View file

@ -44,6 +44,8 @@ enum actionnum
A_FACETRACER,
A_SCREAM,
A_BOSSDEATH,
A_SETSHADOWSCALE,
A_SHADOWSCREAM,
A_CUSTOMPOWER,
A_GIVEWEAPON,
A_RINGBOX,
@ -312,6 +314,8 @@ 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

View file

@ -88,6 +88,7 @@ enum line_e {
line_v2,
line_dx,
line_dy,
line_angle,
line_flags,
line_special,
line_tag,
@ -113,6 +114,7 @@ static const char *const line_opt[] = {
"v2",
"dx",
"dy",
"angle",
"flags",
"special",
"tag",
@ -823,6 +825,9 @@ static int line_get(lua_State *L)
case line_dy:
lua_pushfixed(L, line->dy);
return 1;
case line_angle:
lua_pushangle(L, line->angle);
return 1;
case line_flags:
lua_pushinteger(L, line->flags);
return 1;

View file

@ -4751,7 +4751,7 @@ static void M_DrawPauseMenu(void)
emblemslot = 2;
break;
case ET_NGRADE:
snprintf(targettext, 9, "%u", P_GetScoreForGrade(gamemap, 0, emblem->var));
snprintf(targettext, 9, "%u", P_GetScoreForGradeOverall(gamemap, emblem->var));
snprintf(currenttext, 9, "%u", G_GetBestNightsScore(gamemap, 0));
targettext[8] = 0;
@ -5408,11 +5408,13 @@ static boolean M_PrepareLevelPlatter(INT32 gt, boolean nextmappick)
if (actnum)
sprintf(mapname, "%s %d", mapheaderinfo[headingIterate]->lvlttl, actnum);
else if (V_ThinStringWidth(mapheaderinfo[headingIterate]->lvlttl, 0) <= 80)
strlcpy(mapname, mapheaderinfo[headingIterate]->lvlttl, 22);
else
strcpy(mapname, mapheaderinfo[headingIterate]->lvlttl);
if (strlen(mapname) >= 17)
strcpy(mapname+17-3, "...");
{
strlcpy(mapname, mapheaderinfo[headingIterate]->lvlttl, 15);
strcat(mapname, "...");
}
strcpy(levelselect.rows[row].mapnames[col], (const char *)mapname);
}
@ -5747,7 +5749,7 @@ static void M_DrawLevelPlatterMap(UINT8 row, UINT8 col, INT32 x, INT32 y, boolea
? 159 : 63));
if (strlen(levelselect.rows[row].mapnames[col]) > 6) // "AERIAL GARDEN" vs "ACT 18" - "THE ACT" intentionally compressed
V_DrawThinString(x, y+50, (highlight ? V_YELLOWMAP : 0), levelselect.rows[row].mapnames[col]);
V_DrawThinString(x, y+50+1, (highlight ? V_YELLOWMAP : 0), levelselect.rows[row].mapnames[col]);
else
V_DrawString(x, y+50, (highlight ? V_YELLOWMAP : 0), levelselect.rows[row].mapnames[col]);
}
@ -8748,12 +8750,12 @@ static void M_ReadSavegameInfo(UINT32 slot)
if(!mapheaderinfo[(fake-1) & 8191])
savegameinfo[slot].levelname[0] = '\0';
else if (V_ThinStringWidth(mapheaderinfo[(fake-1) & 8191]->lvlttl, 0) <= 78)
strlcpy(savegameinfo[slot].levelname, mapheaderinfo[(fake-1) & 8191]->lvlttl, 22);
else
{
strlcpy(savegameinfo[slot].levelname, mapheaderinfo[(fake-1) & 8191]->lvlttl, 17+1);
if (strlen(mapheaderinfo[(fake-1) & 8191]->lvlttl) >= 17)
strcpy(savegameinfo[slot].levelname+17-3, "...");
strlcpy(savegameinfo[slot].levelname, mapheaderinfo[(fake-1) & 8191]->lvlttl, 15);
strcat(savegameinfo[slot].levelname, "...");
}
savegameinfo[slot].gamemap = fake;

View file

@ -389,9 +389,9 @@ typedef struct
// level select platter
typedef struct
{
char header[22+5]; // mapheader_t lvltttl max length + " ZONE"
char header[22+5]; // mapheader_t lvlttl max length + " ZONE"
INT32 maplist[3];
char mapnames[3][17+1];
char mapnames[3][22]; // lvlttl max length
boolean mapavailable[4]; // mapavailable[3] == wide or not
} levelselectrow_t;

View file

@ -107,6 +107,8 @@ 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);
@ -4169,6 +4171,41 @@ bossjustdie:
}
}
// Function: A_SetShadowScale
//
// Description: Sets the target's shadowscale.
//
// var1 = new fixed_t shadowscale (default = FRACUNIT)
// var2 = unused
//
void A_SetShadowScale(mobj_t *actor)
{
INT32 locvar1 = var1;
if (LUA_CallAction(A_SETSHADOWSCALE, actor))
return;
actor->shadowscale = locvar1;
}
// Function: A_ShadowScream
//
// Description: Sets the target's shadowscale and starts the death sound of the object.
//
// var1 = new fixed_t shadowscale (default = FRACUNIT)
// var2 = unused
//
void A_ShadowScream(mobj_t *actor)
{
if (LUA_CallAction(A_SHADOWSCREAM, actor))
return;
A_SetShadowScale(actor);
A_Scream(actor);
}
// Function: A_CustomPower
//
// Description: Provides a custom powerup. Target (must be a player) is awarded the powerup. Reactiontime of the object is used as an index to the powers array.

View file

@ -3101,7 +3101,7 @@ static void P_HitCameraSlideLine(line_t *ld, camera_t *thiscam)
}
side = P_PointOnLineSide(thiscam->x, thiscam->y, ld);
lineangle = R_PointToAngle2(0, 0, ld->dx, ld->dy);
lineangle = ld->angle;
if (side == 1)
lineangle += ANGLE_180;
@ -3147,7 +3147,7 @@ static void P_HitSlideLine(line_t *ld)
side = P_PointOnLineSide(slidemo->x, slidemo->y, ld);
lineangle = R_PointToAngle2(0, 0, ld->dx, ld->dy);
lineangle = ld->angle;
if (side == 1)
lineangle += ANGLE_180;
@ -3190,7 +3190,7 @@ static void P_HitBounceLine(line_t *ld)
return;
}
lineangle = R_PointToAngle2(0, 0, ld->dx, ld->dy);
lineangle = ld->angle;
if (lineangle >= ANGLE_180)
lineangle -= ANGLE_180;

View file

@ -7864,7 +7864,8 @@ static void P_MobjSceneryThink(mobj_t *mobj)
case MT_WOODDEBRIS:
case MT_BRICKDEBRIS:
case MT_BROKENROBOT:
if (mobj->z <= P_FloorzAtPos(mobj->x, mobj->y, mobj->z, mobj->height)
if (((!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z <= P_FloorzAtPos(mobj->x, mobj->y, mobj->z, mobj->height))
|| (mobj->eflags & MFE_VERTICALFLIP && mobj->z + mobj->height >= P_CeilingzAtPos(mobj->x, mobj->y, mobj->z, mobj->height)))
&& mobj->state != &states[mobj->info->deathstate])
{
P_SetMobjState(mobj, mobj->info->deathstate);
@ -8433,7 +8434,10 @@ static boolean P_HangsterThink(mobj_t *mobj)
}
//after swooping back up, check for ceiling
else if ((st == S_HANGSTER_RETURN1 || st == S_HANGSTER_RETURN2) && mobj->momz == 0 && mobj->ceilingz == (mobj->z + mobj->height))
{
P_SetMobjState(mobj, (st = S_HANGSTER_RETURN3));
mobj->momx = mobj->momy = 0;
}
//should you roost on a ceiling with F_SKY1 as its flat, disappear forever
if (st == S_HANGSTER_RETURN3 && mobj->momz == 0 && mobj->ceilingz == (mobj->z + mobj->height)
@ -9723,7 +9727,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
if (P_IsObjectOnGround(mobj))
mobj->rollangle = 0;
else
mobj->rollangle = R_PointToAngle2(0, 0, mobj->momz, (mobj->scale << 1) - min(abs(mobj->momz), mobj->scale << 1));
mobj->rollangle = R_PointToAngle2(0, 0, P_MobjFlip(mobj)*mobj->momz, (mobj->scale << 1) - min(abs(mobj->momz), mobj->scale << 1));
break;
case MT_SPINFIRE:
if (mobj->flags & MF_NOGRAVITY)
@ -10412,6 +10416,7 @@ static fixed_t P_DefaultMobjShadowScale (mobj_t *thing)
switch (thing->type)
{
case MT_PLAYER:
case MT_METALSONIC_RACE:
case MT_ROLLOUTROCK:
case MT_EGGMOBILE4_MACE:
@ -10456,6 +10461,27 @@ static fixed_t P_DefaultMobjShadowScale (mobj_t *thing)
return 2*FRACUNIT/3;
case MT_FLICKY_01:
case MT_FLICKY_02:
case MT_FLICKY_03:
case MT_FLICKY_04:
case MT_FLICKY_05:
case MT_FLICKY_06:
case MT_FLICKY_07:
case MT_FLICKY_08:
case MT_FLICKY_09:
case MT_FLICKY_10:
case MT_FLICKY_11:
case MT_FLICKY_12:
case MT_FLICKY_13:
case MT_FLICKY_14:
case MT_FLICKY_15:
case MT_FLICKY_16:
case MT_SECRETFLICKY_01:
case MT_SECRETFLICKY_02:
return FRACUNIT;
default:
if (thing->flags & (MF_ENEMY|MF_BOSS))
@ -10477,7 +10503,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
if (type == MT_NULL)
{
#if 0
#if 0
#ifdef PARANOIA
I_Error("Tried to spawn MT_NULL\n");
#endif

View file

@ -785,7 +785,7 @@ static void Polyobj_pushThing(polyobj_t *po, line_t *line, mobj_t *mo)
vertex_t closest;
// calculate angle of line and subtract 90 degrees to get normal
lineangle = R_PointToAngle2(0, 0, line->dx, line->dy) - ANGLE_90;
lineangle = line->angle - ANGLE_90;
lineangle >>= ANGLETOFINESHIFT;
momx = FixedMul(po->thrust, FINECOSINE(lineangle));
momy = FixedMul(po->thrust, FINESINE(lineangle));
@ -1060,6 +1060,8 @@ static void Polyobj_rotateLine(line_t *ld)
ld->dx = v2->x - v1->x;
ld->dy = v2->y - v1->y;
ld->angle = R_PointToAngle2(0, 0, ld->dx, ld->dy);
// determine slopetype
ld->slopetype = !ld->dx ? ST_VERTICAL : !ld->dy ? ST_HORIZONTAL :
((ld->dy > 0) == (ld->dx > 0)) ? ST_POSITIVE : ST_NEGATIVE;

View file

@ -508,6 +508,17 @@ UINT32 P_GetScoreForGrade(INT16 map, UINT8 mare, UINT8 grade)
return mapheaderinfo[map-1]->grades[mare].grade[grade-1];
}
UINT32 P_GetScoreForGradeOverall(INT16 map, UINT8 grade)
{
UINT8 mares;
INT32 i;
UINT32 score = 0;
mares = mapheaderinfo[map-1]->numGradedMares;
for (i = 0; i < mares; ++i)
score += P_GetScoreForGrade(map, i, grade);
return score;
}
//
// levelflats
//
@ -1058,6 +1069,8 @@ static void P_InitializeLinedef(line_t *ld)
ld->dx = v2->x - v1->x;
ld->dy = v2->y - v1->y;
ld->angle = R_PointToAngle2(0, 0, ld->dx, ld->dy);
ld->bbox[BOXLEFT] = min(v1->x, v2->x);
ld->bbox[BOXRIGHT] = max(v1->x, v2->x);
ld->bbox[BOXBOTTOM] = min(v1->y, v2->y);
@ -4725,7 +4738,7 @@ static boolean P_LoadAddon(UINT16 wadnum, UINT16 numlumps)
// Reload it all anyway, just in case they
// added some textures but didn't insert a
// TEXTURES/etc. list.
R_LoadTextures(); // numtexture changes
R_LoadTexturesPwad(wadnum); // numtexture changes
// Reload ANIMDEFS
P_InitPicAnims();

View file

@ -122,5 +122,6 @@ void P_AddGradesForMare(INT16 i, UINT8 mare, char *gtext);
UINT8 P_GetGrade(UINT32 pscore, INT16 map, UINT8 mare);
UINT8 P_HasGrades(INT16 map, UINT8 mare);
UINT32 P_GetScoreForGrade(INT16 map, UINT8 mare, UINT8 grade);
UINT32 P_GetScoreForGradeOverall(INT16 map, UINT8 grade);
#endif

View file

@ -1241,7 +1241,7 @@ static boolean PolyFlag(line_t *line)
pfd.polyObjNum = Tag_FGet(&line->tags);
pfd.speed = P_AproxDistance(line->dx, line->dy) >> FRACBITS;
pfd.angle = R_PointToAngle2(line->v1->x, line->v1->y, line->v2->x, line->v2->y) >> ANGLETOFINESHIFT;
pfd.angle = line->angle >> ANGLETOFINESHIFT;
pfd.momx = sides[line->sidenum[0]].textureoffset >> FRACBITS;
return EV_DoPolyObjFlag(&pfd);

View file

@ -2054,12 +2054,22 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj)
ghost->angle = (mobj->player ? mobj->player->drawangle : mobj->angle);
ghost->rollangle = mobj->rollangle;
ghost->sprite = mobj->sprite;
ghost->sprite2 = mobj->sprite2;
ghost->frame = mobj->frame;
ghost->tics = -1;
ghost->frame &= ~FF_TRANSMASK;
ghost->frame |= tr_trans50<<FF_TRANSSHIFT;
ghost->renderflags = mobj->renderflags;
ghost->blendmode = mobj->blendmode;
ghost->spritexscale = mobj->spritexscale;
ghost->spriteyscale = mobj->spriteyscale;
ghost->spritexoffset = mobj->spritexoffset;
ghost->spriteyoffset = mobj->spriteyoffset;
ghost->fuse = ghost->info->damage;
ghost->skin = mobj->skin;
@ -6695,7 +6705,7 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad
//
static void P_DoNiGHTSCapsule(player_t *player)
{
INT32 i, spherecount, totalduration, popduration, deductinterval, deductquantity, sphereresult, firstpoptic, startingspheres;
INT32 i, spherecount, totalduration, popduration, deductinterval, deductquantity, sphereresult, firstpoptic;
INT32 tictimer = ++player->capsule->extravalue2;
if (abs(player->mo->x-player->capsule->x) <= 3*FRACUNIT)
@ -6818,15 +6828,20 @@ static void P_DoNiGHTSCapsule(player_t *player)
if (player->capsule->health > sphereresult && player->spheres > 0)
{
// If spherecount isn't a multiple of deductquantity, the final deduction might steal too many spheres from the player
// E.g. with 80 capsule health, deductquantity is 3, 3*26 is 78, 78+3=81, and then it'll have stolen more than the 80 that it was meant to!
// So let's adjust deductquantity accordingly for the final deduction
deductquantity = min(deductquantity, player->capsule->health - sphereresult);
player->spheres -= deductquantity;
player->capsule->health -= deductquantity;
if (player->spheres < 0) // This can't happen... without Lua, setrings, et cetera
player->spheres = 0;
//if (player->capsule->health < sphereresult) // This can't happen
//player->capsule->health = sphereresult;
}
if (player->spheres < 0)
player->spheres = 0;
if (player->capsule->health < sphereresult)
player->capsule->health = sphereresult;
}
// Spawn a 'pop' for every 2 tics
@ -6847,9 +6862,8 @@ static void P_DoNiGHTSCapsule(player_t *player)
}
else
{
startingspheres = player->spheres - player->capsule->health;
player->spheres -= player->capsule->health;
player->capsule->health = 0;
player->spheres = startingspheres;
}
}

View file

@ -387,6 +387,7 @@ typedef struct line_s
vertex_t *v2;
fixed_t dx, dy; // Precalculated v2 - v1 for side checking.
angle_t angle; // Precalculated angle between dx and dy
// Animation related.
INT16 flags;

View file

@ -105,6 +105,7 @@ typedef struct
} spriteinfo_t;
// Portable Network Graphics
#define PNG_HEADER_SIZE (8)
boolean Picture_IsLumpPNG(const UINT8 *d, size_t s);
#define Picture_ThrowPNGError(lumpname, wadfilename) I_Error("W_Wad: Lump \"%s\" in file \"%s\" is a .png - please convert to either Doom or Flat (raw) image format.", lumpname, wadfilename); // Fears Of LJ Sonic

View file

@ -59,6 +59,7 @@ INT32 *texturetranslation;
// Painfully simple texture id cacheing to make maps load faster. :3
static struct {
char name[9];
UINT32 hash;
INT32 id;
} *tidcache = NULL;
static INT32 tidcachelen = 0;
@ -725,6 +726,7 @@ Rloadflats (INT32 i, INT32 w)
UINT16 texstart, texend;
texture_t *texture;
texpatch_t *patch;
UINT8 header[PNG_HEADER_SIZE];
// Yes
if (W_FileHasFolders(wadfiles[w]))
@ -743,7 +745,6 @@ Rloadflats (INT32 i, INT32 w)
// Work through each lump between the markers in the WAD.
for (j = 0; j < (texend - texstart); j++)
{
UINT8 *flatlump;
UINT16 wadnum = (UINT16)w;
lumpnum_t lumpnum = texstart + j;
size_t lumplength;
@ -755,7 +756,7 @@ Rloadflats (INT32 i, INT32 w)
continue; // If it is then SKIP IT
}
flatlump = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE);
W_ReadLumpHeaderPwad(wadnum, lumpnum, header, sizeof header, 0);
lumplength = W_LumpLengthPwad(wadnum, lumpnum);
switch (lumplength)
@ -788,14 +789,17 @@ Rloadflats (INT32 i, INT32 w)
// Set texture properties.
M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name));
texture->hash = quickncasehash(texture->name, 8);
#ifndef NO_PNG_LUMPS
if (Picture_IsLumpPNG((UINT8 *)flatlump, lumplength))
if (Picture_IsLumpPNG(header, lumplength))
{
UINT8 *flatlump = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE);
INT32 width, height;
Picture_PNGDimensions((UINT8 *)flatlump, &width, &height, NULL, NULL, lumplength);
texture->width = (INT16)width;
texture->height = (INT16)height;
Z_Free(flatlump);
}
else
#endif
@ -814,8 +818,6 @@ Rloadflats (INT32 i, INT32 w)
patch->lump = texstart + j;
patch->flip = 0;
Z_Unlock(flatlump);
texturewidth[i] = texture->width;
textureheight[i] = texture->height << FRACBITS;
i++;
@ -835,8 +837,8 @@ Rloadtextures (INT32 i, INT32 w)
UINT16 j;
UINT16 texstart, texend, texturesLumpPos;
texture_t *texture;
softwarepatch_t *patchlump;
texpatch_t *patch;
softwarepatch_t patchlump;
// Get the lump numbers for the markers in the WAD, if they exist.
if (W_FileHasFolders(wadfiles[w]))
@ -876,7 +878,7 @@ Rloadtextures (INT32 i, INT32 w)
continue; // If it is then SKIP IT
}
patchlump = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE);
W_ReadLumpHeaderPwad(wadnum, lumpnum, &patchlump, PNG_HEADER_SIZE, 0);
#ifndef NO_PNG_LUMPS
lumplength = W_LumpLengthPwad(wadnum, lumpnum);
#endif
@ -886,20 +888,23 @@ Rloadtextures (INT32 i, INT32 w)
// Set texture properties.
M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name));
texture->hash = quickncasehash(texture->name, 8);
#ifndef NO_PNG_LUMPS
if (Picture_IsLumpPNG((UINT8 *)patchlump, lumplength))
if (Picture_IsLumpPNG((UINT8 *)&patchlump, lumplength))
{
UINT8 *png = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE);
INT32 width, height;
Picture_PNGDimensions((UINT8 *)patchlump, &width, &height, NULL, NULL, lumplength);
Picture_PNGDimensions(png, &width, &height, NULL, NULL, lumplength);
texture->width = (INT16)width;
texture->height = (INT16)height;
Z_Free(png);
}
else
#endif
{
texture->width = SHORT(patchlump->width);
texture->height = SHORT(patchlump->height);
texture->width = SHORT(patchlump.width);
texture->height = SHORT(patchlump.height);
}
texture->type = TEXTURETYPE_SINGLEPATCH;
@ -915,8 +920,6 @@ Rloadtextures (INT32 i, INT32 w)
patch->lump = texstart + j;
patch->flip = 0;
Z_Unlock(patchlump);
texturewidth[i] = texture->width;
textureheight[i] = texture->height << FRACBITS;
i++;
@ -926,27 +929,53 @@ Rloadtextures (INT32 i, INT32 w)
return i;
}
//
// R_LoadTextures
// Initializes the texture list with the textures from the world map.
//
void R_LoadTextures(void)
static INT32
count_range
( const char * marker_start,
const char * marker_end,
const char * folder,
UINT16 wadnum)
{
INT32 i, w;
UINT16 j;
UINT16 texstart, texend, texturesLumpPos;
UINT16 texstart, texend;
INT32 count = 0;
// Free previous memory before numtextures change.
if (numtextures)
// Count flats
if (W_FileHasFolders(wadfiles[wadnum]))
{
for (i = 0; i < numtextures; i++)
{
Z_Free(textures[i]);
Z_Free(texturecache[i]);
}
Z_Free(texturetranslation);
Z_Free(textures);
texstart = W_CheckNumForFolderStartPK3(folder, wadnum, 0);
texend = W_CheckNumForFolderEndPK3(folder, wadnum, texstart);
}
else
{
texstart = W_CheckNumForMarkerStartPwad(marker_start, wadnum, 0);
texend = W_CheckNumForNamePwad(marker_end, wadnum, texstart);
}
if (texstart != INT16_MAX && texend != INT16_MAX)
{
// PK3s have subfolders, so we can't just make a simple sum
if (W_FileHasFolders(wadfiles[wadnum]))
{
for (j = texstart; j < texend; j++)
{
if (!W_IsLumpFolder(wadnum, j)) // Check if lump is a folder; if not, then count it
count++;
}
}
else // Add all the textures between markers
{
count += (texend - texstart);
}
}
return count;
}
static INT32 R_CountTextures(UINT16 wadnum)
{
UINT16 texturesLumpPos;
INT32 count = 0;
// Load patches and textures.
@ -955,113 +984,132 @@ void R_LoadTextures(void)
// the markers.
// This system will allocate memory for all duplicate/patched textures even if it never uses them,
// but the alternative is to spend a ton of time checking and re-checking all previous entries just to skip any potentially patched textures.
for (w = 0, numtextures = 0; w < numwadfiles; w++)
{
#ifdef WALLFLATS
// Count flats
if (W_FileHasFolders(wadfiles[w]))
{
texstart = W_CheckNumForFolderStartPK3("flats/", (UINT16)w, 0);
texend = W_CheckNumForFolderEndPK3("flats/", (UINT16)w, texstart);
}
else
{
texstart = W_CheckNumForMarkerStartPwad("F_START", (UINT16)w, 0);
texend = W_CheckNumForNamePwad("F_END", (UINT16)w, texstart);
}
count += count_range("F_START", "F_END", "flats/", wadnum);
#endif
if (!( texstart == INT16_MAX || texend == INT16_MAX ))
{
// PK3s have subfolders, so we can't just make a simple sum
if (W_FileHasFolders(wadfiles[w]))
{
for (j = texstart; j < texend; j++)
{
if (!W_IsLumpFolder((UINT16)w, j)) // Check if lump is a folder; if not, then count it
numtextures++;
}
}
else // Add all the textures between F_START and F_END
{
numtextures += (UINT32)(texend - texstart);
}
}
#endif/*WALLFLATS*/
// Count the textures from TEXTURES lumps
texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", wadnum, 0);
// Count the textures from TEXTURES lumps
texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0);
while (texturesLumpPos != INT16_MAX)
{
numtextures += R_CountTexturesInTEXTURESLump((UINT16)w, (UINT16)texturesLumpPos);
texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, texturesLumpPos + 1);
}
// Count single-patch textures
if (W_FileHasFolders(wadfiles[w]))
{
texstart = W_CheckNumForFolderStartPK3("textures/", (UINT16)w, 0);
texend = W_CheckNumForFolderEndPK3("textures/", (UINT16)w, texstart);
}
else
{
texstart = W_CheckNumForMarkerStartPwad(TX_START, (UINT16)w, 0);
texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0);
}
if (texstart == INT16_MAX || texend == INT16_MAX)
continue;
// PK3s have subfolders, so we can't just make a simple sum
if (W_FileHasFolders(wadfiles[w]))
{
for (j = texstart; j < texend; j++)
{
if (!W_IsLumpFolder((UINT16)w, j)) // Check if lump is a folder; if not, then count it
numtextures++;
}
}
else // Add all the textures between TX_START and TX_END
{
numtextures += (UINT32)(texend - texstart);
}
while (texturesLumpPos != INT16_MAX)
{
count += R_CountTexturesInTEXTURESLump(wadnum, texturesLumpPos);
texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", wadnum, texturesLumpPos + 1);
}
// If no textures found by this point, bomb out
if (!numtextures)
I_Error("No textures detected in any WADs!\n");
// Count single-patch textures
count += count_range(TX_START, TX_END, "textures/", wadnum);
return count;
}
static void
recallocuser
( void * user,
size_t old,
size_t new)
{
char *p = Z_Realloc(*(void**)user,
new, PU_STATIC, user);
if (new > old)
memset(&p[old], 0, (new - old));
}
static void R_AllocateTextures(INT32 add)
{
const INT32 newtextures = (numtextures + add);
const size_t newsize = newtextures * sizeof (void*);
const size_t oldsize = numtextures * sizeof (void*);
INT32 i;
// Allocate memory and initialize to 0 for all the textures we are initialising.
// There are actually 5 buffers allocated in one for convenience.
textures = Z_Calloc((numtextures * sizeof(void *)) * 5, PU_STATIC, NULL);
recallocuser(&textures, oldsize, newsize);
// Allocate texture column offset table.
texturecolumnofs = (void *)((UINT8 *)textures + (numtextures * sizeof(void *)));
recallocuser(&texturecolumnofs, oldsize, newsize);
// Allocate texture referencing cache.
texturecache = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 2));
recallocuser(&texturecache, oldsize, newsize);
// Allocate texture width table.
texturewidth = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 3));
recallocuser(&texturewidth, oldsize, newsize);
// Allocate texture height table.
textureheight = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 4));
recallocuser(&textureheight, oldsize, newsize);
// Create translation table for global animation.
texturetranslation = Z_Malloc((numtextures + 1) * sizeof(*texturetranslation), PU_STATIC, NULL);
Z_Realloc(texturetranslation, (newtextures + 1) * sizeof(*texturetranslation), PU_STATIC, &texturetranslation);
for (i = 0; i < numtextures; i++)
texturetranslation[i] = i;
for (i = 0, w = 0; w < numwadfiles; w++)
for (i = 0; i < numtextures; ++i)
{
#ifdef WALLFLATS
i = Rloadflats(i, w);
#endif
i = Rloadtextures(i, w);
// R_FlushTextureCache relies on the user for
// Z_Free, texturecache has been reallocated so the
// user is now garbage memory.
Z_SetUser(texturecache[i],
(void**)&texturecache[i]);
}
while (i < newtextures)
{
texturetranslation[i] = i;
i++;
}
}
static INT32 R_DefineTextures(INT32 i, UINT16 w)
{
#ifdef WALLFLATS
i = Rloadflats(i, w);
#endif
return Rloadtextures(i, w);
}
static void R_FinishLoadingTextures(INT32 add)
{
numtextures += add;
#ifdef HWRENDER
if (rendermode == render_opengl)
HWR_LoadMapTextures(numtextures);
#endif
}
//
// R_LoadTextures
// Initializes the texture list with the textures from the world map.
//
void R_LoadTextures(void)
{
INT32 i, w;
INT32 newtextures = 0;
for (w = 0; w < numwadfiles; w++)
{
newtextures += R_CountTextures((UINT16)w);
}
// If no textures found by this point, bomb out
if (!newtextures)
I_Error("No textures detected in any WADs!\n");
R_AllocateTextures(newtextures);
for (i = 0, w = 0; w < numwadfiles; w++)
{
i = R_DefineTextures(i, w);
}
R_FinishLoadingTextures(newtextures);
}
void R_LoadTexturesPwad(UINT16 wadnum)
{
INT32 newtextures = R_CountTextures(wadnum);
R_AllocateTextures(newtextures);
R_DefineTextures(numtextures, wadnum);
R_FinishLoadingTextures(newtextures);
}
static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch)
{
char *texturesToken;
@ -1368,6 +1416,7 @@ static texture_t *R_ParseTexture(boolean actuallyLoadTexture)
// Allocate memory for a zero-patch texture. Obviously, we'll be adding patches momentarily.
resultTexture = (texture_t *)Z_Calloc(sizeof(texture_t),PU_STATIC,NULL);
M_Memcpy(resultTexture->name, newTextureName, 8);
resultTexture->hash = quickncasehash(newTextureName, 8);
resultTexture->width = newTextureWidth;
resultTexture->height = newTextureHeight;
resultTexture->type = TEXTURETYPE_COMPOSITE;
@ -1594,19 +1643,22 @@ void R_ClearTextureNumCache(boolean btell)
INT32 R_CheckTextureNumForName(const char *name)
{
INT32 i;
UINT32 hash;
// "NoTexture" marker.
if (name[0] == '-')
return 0;
hash = quickncasehash(name, 8);
for (i = 0; i < tidcachelen; i++)
if (!strncasecmp(tidcache[i].name, name, 8))
if (tidcache[i].hash == hash && !strncasecmp(tidcache[i].name, name, 8))
return tidcache[i].id;
// Need to parse the list backwards, so textures loaded more recently are used in lieu of ones loaded earlier
//for (i = 0; i < numtextures; i++) <- old
for (i = (numtextures - 1); i >= 0; i--) // <- new
if (!strncasecmp(textures[i]->name, name, 8))
if (textures[i]->hash == hash && !strncasecmp(textures[i]->name, name, 8))
{
tidcachelen++;
Z_Realloc(tidcache, tidcachelen * sizeof(*tidcache), PU_STATIC, &tidcache);
@ -1615,6 +1667,7 @@ INT32 R_CheckTextureNumForName(const char *name)
#ifndef ZDEBUG
CONS_Debug(DBG_SETUP, "texture #%s: %s\n", sizeu1(tidcachelen), tidcache[tidcachelen-1].name);
#endif
tidcache[tidcachelen-1].hash = hash;
tidcache[tidcachelen-1].id = i;
return i;
}

View file

@ -54,6 +54,7 @@ typedef struct
{
// Keep name for switch changing, etc.
char name[8];
UINT32 hash;
UINT8 type; // TEXTURETYPE_
INT16 width, height;
boolean holes;
@ -76,6 +77,7 @@ extern UINT8 **texturecache; // graphics data for each generated full-size textu
// Load TEXTURES definitions, create lookup tables
void R_LoadTextures(void);
void R_LoadTexturesPwad(UINT16 wadnum);
void R_FlushTextureCache(void);
// Texture generation

View file

@ -1275,6 +1275,7 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale,
vissprite_t *shadow;
patch_t *patch;
fixed_t xscale, yscale, shadowxscale, shadowyscale, shadowskew, x1, x2;
INT32 heightsec, phs;
INT32 light = 0;
fixed_t scalemul; UINT8 trans;
fixed_t floordiff;
@ -1286,6 +1287,24 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale,
if (abs(groundz-viewz)/tz > 4) return; // Prevent stretchy shadows and possible crashes
heightsec = thing->subsector->sector->heightsec;
if (viewplayer->mo && viewplayer->mo->subsector)
phs = viewplayer->mo->subsector->sector->heightsec;
else
phs = -1;
if (heightsec != -1 && phs != -1) // only clip things which are in special sectors
{
if (viewz < sectors[phs].floorheight ?
groundz >= sectors[heightsec].floorheight :
groundz < sectors[heightsec].floorheight)
return;
if (viewz > sectors[phs].ceilingheight ?
groundz < sectors[heightsec].ceilingheight && viewz >= sectors[heightsec].ceilingheight :
groundz >= sectors[heightsec].ceilingheight)
return;
}
floordiff = abs((isflipped ? thing->height : 0) + thing->z - groundz);
trans = floordiff / (100*FRACUNIT) + 3;
@ -1591,8 +1610,17 @@ static void R_ProjectSprite(mobj_t *thing)
#ifdef ROTSPRITE
if (papersprite)
rollangle = (ang >= ANGLE_180 ? -1 : 1) * thing->pitch // pitch should flip the sprite rotation on one side of the papersprite
+ thing->rollangle; // rollangle should use the same rotation for both sides of a papersprite
{
if (ang >= ANGLE_180)
{
// Makes Software act much more sane like OpenGL
rollangle = InvAngle(thing->rollangle);
}
else
{
rollangle = thing->rollangle;
}
}
else
{
rollangle = FixedMul(FINECOSINE((ang) >> ANGLETOFINESHIFT), thing->roll)
@ -1952,13 +1980,19 @@ static void R_ProjectSprite(mobj_t *thing)
if (heightsec != -1 && phs != -1) // only clip things which are in special sectors
{
fixed_t top = gzt;
fixed_t bottom = thing->z;
if (splat)
top = bottom;
if (viewz < sectors[phs].floorheight ?
thing->z >= sectors[heightsec].floorheight :
gzt < sectors[heightsec].floorheight)
bottom >= sectors[heightsec].floorheight :
top < sectors[heightsec].floorheight)
return;
if (viewz > sectors[phs].ceilingheight ?
gzt < sectors[heightsec].ceilingheight && viewz >= sectors[heightsec].ceilingheight :
thing->z >= sectors[heightsec].ceilingheight)
top < sectors[heightsec].ceilingheight && viewz >= sectors[heightsec].ceilingheight :
bottom >= sectors[heightsec].ceilingheight)
return;
}
@ -2832,6 +2866,57 @@ static void R_DrawPrecipitationSprite(vissprite_t *spr)
R_DrawPrecipitationVisSprite(spr);
}
//SoM: 3/17/2000: Clip sprites in water.
static void R_HeightSecClip(vissprite_t *spr, INT32 x1, INT32 x2)
{
fixed_t mh, h;
INT32 x, phs;
if (spr->heightsec == -1)
return;
if (spr->cut & (SC_SPLAT | SC_SHADOW) || spr->renderflags & RF_SHADOWDRAW)
return;
phs = viewplayer->mo->subsector->sector->heightsec;
if ((mh = sectors[spr->heightsec].floorheight) > spr->gz &&
(h = centeryfrac - FixedMul(mh -= viewz, spr->sortscale)) >= 0 &&
(h >>= FRACBITS) < viewheight)
{
if (mh <= 0 || (phs != -1 && viewz > sectors[phs].floorheight))
{ // clip bottom
for (x = x1; x <= x2; x++)
if (spr->clipbot[x] == -2 || h < spr->clipbot[x])
spr->clipbot[x] = (INT16)h;
}
else // clip top
{
for (x = x1; x <= x2; x++)
if (spr->cliptop[x] == -2 || h > spr->cliptop[x])
spr->cliptop[x] = (INT16)h;
}
}
if ((mh = sectors[spr->heightsec].ceilingheight) < spr->gzt &&
(h = centeryfrac - FixedMul(mh-viewz, spr->sortscale)) >= 0 &&
(h >>= FRACBITS) < viewheight)
{
if (phs != -1 && viewz >= sectors[phs].ceilingheight)
{ // clip bottom
for (x = x1; x <= x2; x++)
if (spr->clipbot[x] == -2 || h < spr->clipbot[x])
spr->clipbot[x] = (INT16)h;
}
else // clip top
{
for (x = x1; x <= x2; x++)
if (spr->cliptop[x] == -2 || h > spr->cliptop[x])
spr->cliptop[x] = (INT16)h;
}
}
}
// R_ClipVisSprite
// Clips vissprites without drawing, so that portals can work. -Red
void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, drawseg_t* dsstart, portal_t* portal)
@ -2933,47 +3018,9 @@ void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, drawseg_t* dsstart, p
}
}
}
//SoM: 3/17/2000: Clip sprites in water.
if (spr->heightsec != -1) // only things in specially marked sectors
{
fixed_t mh, h;
INT32 phs = viewplayer->mo->subsector->sector->heightsec;
if ((mh = sectors[spr->heightsec].floorheight) > spr->gz &&
(h = centeryfrac - FixedMul(mh -= viewz, spr->sortscale)) >= 0 &&
(h >>= FRACBITS) < viewheight)
{
if (mh <= 0 || (phs != -1 && viewz > sectors[phs].floorheight))
{ // clip bottom
for (x = x1; x <= x2; x++)
if (spr->clipbot[x] == -2 || h < spr->clipbot[x])
spr->clipbot[x] = (INT16)h;
}
else // clip top
{
for (x = x1; x <= x2; x++)
if (spr->cliptop[x] == -2 || h > spr->cliptop[x])
spr->cliptop[x] = (INT16)h;
}
}
if ((mh = sectors[spr->heightsec].ceilingheight) < spr->gzt &&
(h = centeryfrac - FixedMul(mh-viewz, spr->sortscale)) >= 0 &&
(h >>= FRACBITS) < viewheight)
{
if (phs != -1 && viewz >= sectors[phs].ceilingheight)
{ // clip bottom
for (x = x1; x <= x2; x++)
if (spr->clipbot[x] == -2 || h < spr->clipbot[x])
spr->clipbot[x] = (INT16)h;
}
else // clip top
{
for (x = x1; x <= x2; x++)
if (spr->cliptop[x] == -2 || h > spr->cliptop[x])
spr->cliptop[x] = (INT16)h;
}
}
}
R_HeightSecClip(spr, x1, x2);
if (spr->cut & SC_TOP && spr->cut & SC_BOTTOM)
{
for (x = x1; x <= x2; x++)

View file

@ -361,6 +361,7 @@ static lumpinfo_t* ResGetLumpsStandalone (FILE* handle, UINT16* numlumps, const
lumpinfo->size = ftell(handle);
fseek(handle, 0, SEEK_SET);
strcpy(lumpinfo->name, lumpname);
lumpinfo->hash = quickncasehash(lumpname, 8);
// Allocate the lump's long name.
lumpinfo->longname = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL);
@ -459,6 +460,7 @@ static lumpinfo_t* ResGetLumpsWad (FILE* handle, UINT16* nlmp, const char* filen
lump_p->compression = CM_NOCOMPRESSION;
memset(lump_p->name, 0x00, 9);
strncpy(lump_p->name, fileinfo->name, 8);
lump_p->hash = quickncasehash(lump_p->name, 8);
// Allocate the lump's long name.
lump_p->longname = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL);
@ -634,6 +636,7 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp)
memset(lump_p->name, '\0', 9); // Making sure they're initialized to 0. Is it necessary?
strncpy(lump_p->name, trimname, min(8, dotpos - trimname));
lump_p->hash = quickncasehash(lump_p->name, 8);
lump_p->longname = Z_Calloc(dotpos - trimname + 1, PU_STATIC, NULL);
strlcpy(lump_p->longname, trimname, dotpos - trimname + 1);
@ -1225,12 +1228,14 @@ UINT16 W_CheckNumForNamePwad(const char *name, UINT16 wad, UINT16 startlump)
{
UINT16 i;
static char uname[8 + 1];
UINT32 hash;
if (!TestValidLump(wad,0))
return INT16_MAX;
strlcpy(uname, name, sizeof uname);
strupr(uname);
hash = quickncasehash(uname, 8);
//
// scan forward
@ -1241,7 +1246,7 @@ UINT16 W_CheckNumForNamePwad(const char *name, UINT16 wad, UINT16 startlump)
{
lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump;
for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++)
if (!strncmp(lump_p->name, uname, sizeof(uname) - 1))
if (lump_p->hash == hash && !strncmp(lump_p->name, uname, sizeof(uname) - 1))
return i;
}
@ -1444,15 +1449,20 @@ lumpnum_t W_CheckNumForLongName(const char *name)
// TODO: Make it search through cache first, maybe...?
lumpnum_t W_CheckNumForMap(const char *name)
{
UINT32 hash = quickncasehash(name, 8);
UINT16 lumpNum, end;
UINT32 i;
lumpinfo_t *p;
for (i = numwadfiles - 1; i < numwadfiles; i--)
{
if (wadfiles[i]->type == RET_WAD)
{
for (lumpNum = 0; lumpNum < wadfiles[i]->numlumps; lumpNum++)
if (!strncmp(name, (wadfiles[i]->lumpinfo + lumpNum)->name, 8))
{
p = wadfiles[i]->lumpinfo + lumpNum;
if (p->hash == hash && !strncmp(name, p->name, 8))
return (i<<16) + lumpNum;
}
}
else if (W_FileHasFolders(wadfiles[i]))
{
@ -1464,9 +1474,10 @@ lumpnum_t W_CheckNumForMap(const char *name)
// Now look for the specified map.
for (; lumpNum < end; lumpNum++)
{
if (!strnicmp(name, wadfiles[i]->lumpinfo[lumpNum].name, 8))
p = wadfiles[i]->lumpinfo + lumpNum;
if (p->hash == hash && !strnicmp(name, p->name, 8))
{
const char *extension = strrchr(wadfiles[i]->lumpinfo[lumpNum].fullname, '.');
const char *extension = strrchr(p->fullname, '.');
if (!(extension && stricmp(extension, ".wad")))
return (i<<16) + lumpNum;
}

View file

@ -67,6 +67,7 @@ typedef struct
unsigned long position; // filelump_t filepos
unsigned long disksize; // filelump_t size
char name[9]; // filelump_t name[] e.g. "LongEntr"
UINT32 hash;
char *longname; // e.g. "LongEntryName"
char *fullname; // e.g. "Folder/Subfolder/LongEntryName.extension"
char *diskpath; // path to the file e.g. "/usr/games/srb2/Addon/Folder/Subfolder/LongEntryName.extension"