Merge branch 'next' into udmf-fofs-mkii

This commit is contained in:
MascaraSnake 2022-04-19 21:59:31 +02:00
commit 0b4bbacec0
24 changed files with 483 additions and 216 deletions

View file

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

View file

@ -530,6 +530,22 @@ extern boolean capslock;
// i_system.c, replace getchar() once the keyboard has been appropriated // i_system.c, replace getchar() once the keyboard has been appropriated
INT32 I_GetKey(void); 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 #ifndef min // Double-Check with WATTCP-32's cdefs.h
#define min(x, y) (((x) < (y)) ? (x) : (y)) #define min(x, y) (((x) < (y)) ? (x) : (y))
#endif #endif

View file

@ -3605,6 +3605,7 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale)
FBITFIELD blendmode = PF_Translucent|PF_Modulated; FBITFIELD blendmode = PF_Translucent|PF_Modulated;
INT32 shader = SHADER_DEFAULT; INT32 shader = SHADER_DEFAULT;
UINT8 i; UINT8 i;
INT32 heightsec, phs;
SINT8 flip = P_MobjFlip(thing); SINT8 flip = P_MobjFlip(thing);
INT32 light; INT32 light;
@ -3617,7 +3618,23 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale)
groundz = R_GetShadowZ(thing, &groundslope); 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); floordiff = abs((flip < 0 ? thing->height : 0) + thing->z - groundz);
@ -5274,13 +5291,19 @@ static void HWR_ProjectSprite(mobj_t *thing)
if (heightsec != -1 && phs != -1) // only clip things which are in special sectors 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) ? if (gl_viewz < FIXED_TO_FLOAT(sectors[phs].floorheight) ?
FIXED_TO_FLOAT(thing->z) >= FIXED_TO_FLOAT(sectors[heightsec].floorheight) : bottom >= FIXED_TO_FLOAT(sectors[heightsec].floorheight) :
gzt < FIXED_TO_FLOAT(sectors[heightsec].floorheight)) top < FIXED_TO_FLOAT(sectors[heightsec].floorheight))
return; return;
if (gl_viewz > FIXED_TO_FLOAT(sectors[phs].ceilingheight) ? if (gl_viewz > FIXED_TO_FLOAT(sectors[phs].ceilingheight) ?
gzt < FIXED_TO_FLOAT(sectors[heightsec].ceilingheight) && gl_viewz >= FIXED_TO_FLOAT(sectors[heightsec].ceilingheight) : top < 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)) bottom >= FIXED_TO_FLOAT(sectors[heightsec].ceilingheight))
return; return;
} }

View file

@ -1346,12 +1346,18 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
//if (tics > durs) //if (tics > durs)
//durs = tics; //durs = tics;
INT32 blendmode;
if (spr->mobj->frame & FF_BLENDMASK)
blendmode = ((spr->mobj->frame & FF_BLENDMASK) >> FF_BLENDSHIFT) + 1;
else
blendmode = spr->mobj->blendmode;
if (spr->mobj->frame & FF_TRANSMASK) if (spr->mobj->frame & FF_TRANSMASK)
Surf.PolyFlags = HWR_SurfaceBlend(spr->mobj->blendmode, (spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf); Surf.PolyFlags = HWR_SurfaceBlend(blendmode, (spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf);
else else
{ {
Surf.PolyColor.s.alpha = (spr->mobj->flags2 & MF2_SHADOW) ? 0x40 : 0xff; Surf.PolyColor.s.alpha = (spr->mobj->flags2 & MF2_SHADOW) ? 0x40 : 0xff;
Surf.PolyFlags = HWR_GetBlendModeFlag(spr->mobj->blendmode); Surf.PolyFlags = HWR_GetBlendModeFlag(blendmode);
} }
// don't forget to enable the depth test because we can't do this // don't forget to enable the depth test because we can't do this

View file

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

View file

@ -44,6 +44,8 @@ enum actionnum
A_FACETRACER, A_FACETRACER,
A_SCREAM, A_SCREAM,
A_BOSSDEATH, A_BOSSDEATH,
A_SETSHADOWSCALE,
A_SHADOWSCREAM,
A_CUSTOMPOWER, A_CUSTOMPOWER,
A_GIVEWEAPON, A_GIVEWEAPON,
A_RINGBOX, A_RINGBOX,
@ -312,6 +314,8 @@ void A_FaceTarget();
void A_FaceTracer(); void A_FaceTracer();
void A_Scream(); void A_Scream();
void A_BossDeath(); void A_BossDeath();
void A_SetShadowScale();
void A_ShadowScream(); // MARIA!!!!!!
void A_CustomPower(); // Use this for a custom power void A_CustomPower(); // Use this for a custom power
void A_GiveWeapon(); // Gives the player weapon(s) void A_GiveWeapon(); // Gives the player weapon(s)
void A_RingBox(); // Obtained Ring Box Tails void A_RingBox(); // Obtained Ring Box Tails

View file

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

View file

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

View file

@ -389,9 +389,9 @@ typedef struct
// level select platter // level select platter
typedef struct 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]; INT32 maplist[3];
char mapnames[3][17+1]; char mapnames[3][22]; // lvlttl max length
boolean mapavailable[4]; // mapavailable[3] == wide or not boolean mapavailable[4]; // mapavailable[3] == wide or not
} levelselectrow_t; } levelselectrow_t;

View file

@ -107,6 +107,8 @@ void A_GoldMonitorRestore(mobj_t *actor);
void A_GoldMonitorSparkle(mobj_t *actor); void A_GoldMonitorSparkle(mobj_t *actor);
void A_Explode(mobj_t *actor); void A_Explode(mobj_t *actor);
void A_BossDeath(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_CustomPower(mobj_t *actor);
void A_GiveWeapon(mobj_t *actor); void A_GiveWeapon(mobj_t *actor);
void A_RingBox(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 // 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. // 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); side = P_PointOnLineSide(thiscam->x, thiscam->y, ld);
lineangle = R_PointToAngle2(0, 0, ld->dx, ld->dy); lineangle = ld->angle;
if (side == 1) if (side == 1)
lineangle += ANGLE_180; lineangle += ANGLE_180;
@ -3147,7 +3147,7 @@ static void P_HitSlideLine(line_t *ld)
side = P_PointOnLineSide(slidemo->x, slidemo->y, ld); side = P_PointOnLineSide(slidemo->x, slidemo->y, ld);
lineangle = R_PointToAngle2(0, 0, ld->dx, ld->dy); lineangle = ld->angle;
if (side == 1) if (side == 1)
lineangle += ANGLE_180; lineangle += ANGLE_180;
@ -3190,7 +3190,7 @@ static void P_HitBounceLine(line_t *ld)
return; return;
} }
lineangle = R_PointToAngle2(0, 0, ld->dx, ld->dy); lineangle = ld->angle;
if (lineangle >= ANGLE_180) if (lineangle >= ANGLE_180)
lineangle -= ANGLE_180; lineangle -= ANGLE_180;

View file

@ -7869,7 +7869,8 @@ static void P_MobjSceneryThink(mobj_t *mobj)
case MT_WOODDEBRIS: case MT_WOODDEBRIS:
case MT_BRICKDEBRIS: case MT_BRICKDEBRIS:
case MT_BROKENROBOT: 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]) && mobj->state != &states[mobj->info->deathstate])
{ {
P_SetMobjState(mobj, mobj->info->deathstate); P_SetMobjState(mobj, mobj->info->deathstate);
@ -8438,7 +8439,10 @@ static boolean P_HangsterThink(mobj_t *mobj)
} }
//after swooping back up, check for ceiling //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)) 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)); 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 //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) if (st == S_HANGSTER_RETURN3 && mobj->momz == 0 && mobj->ceilingz == (mobj->z + mobj->height)
@ -9728,7 +9732,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
if (P_IsObjectOnGround(mobj)) if (P_IsObjectOnGround(mobj))
mobj->rollangle = 0; mobj->rollangle = 0;
else 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; break;
case MT_SPINFIRE: case MT_SPINFIRE:
if (mobj->flags & MF_NOGRAVITY) if (mobj->flags & MF_NOGRAVITY)
@ -10417,6 +10421,7 @@ static fixed_t P_DefaultMobjShadowScale (mobj_t *thing)
switch (thing->type) switch (thing->type)
{ {
case MT_PLAYER: case MT_PLAYER:
case MT_METALSONIC_RACE:
case MT_ROLLOUTROCK: case MT_ROLLOUTROCK:
case MT_EGGMOBILE4_MACE: case MT_EGGMOBILE4_MACE:
@ -10461,6 +10466,27 @@ static fixed_t P_DefaultMobjShadowScale (mobj_t *thing)
return 2*FRACUNIT/3; 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: default:
if (thing->flags & (MF_ENEMY|MF_BOSS)) if (thing->flags & (MF_ENEMY|MF_BOSS))
@ -10482,7 +10508,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
if (type == MT_NULL) if (type == MT_NULL)
{ {
#if 0 #if 0
#ifdef PARANOIA #ifdef PARANOIA
I_Error("Tried to spawn MT_NULL\n"); I_Error("Tried to spawn MT_NULL\n");
#endif #endif

View file

@ -785,7 +785,7 @@ static void Polyobj_pushThing(polyobj_t *po, line_t *line, mobj_t *mo)
vertex_t closest; vertex_t closest;
// calculate angle of line and subtract 90 degrees to get normal // 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; lineangle >>= ANGLETOFINESHIFT;
momx = FixedMul(po->thrust, FINECOSINE(lineangle)); momx = FixedMul(po->thrust, FINECOSINE(lineangle));
momy = FixedMul(po->thrust, FINESINE(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->dx = v2->x - v1->x;
ld->dy = v2->y - v1->y; ld->dy = v2->y - v1->y;
ld->angle = R_PointToAngle2(0, 0, ld->dx, ld->dy);
// determine slopetype // determine slopetype
ld->slopetype = !ld->dx ? ST_VERTICAL : !ld->dy ? ST_HORIZONTAL : ld->slopetype = !ld->dx ? ST_VERTICAL : !ld->dy ? ST_HORIZONTAL :
((ld->dy > 0) == (ld->dx > 0)) ? ST_POSITIVE : ST_NEGATIVE; ((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]; 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 // levelflats
// //
@ -1058,6 +1069,8 @@ static void P_InitializeLinedef(line_t *ld)
ld->dx = v2->x - v1->x; ld->dx = v2->x - v1->x;
ld->dy = v2->y - v1->y; 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[BOXLEFT] = min(v1->x, v2->x);
ld->bbox[BOXRIGHT] = max(v1->x, v2->x); ld->bbox[BOXRIGHT] = max(v1->x, v2->x);
ld->bbox[BOXBOTTOM] = min(v1->y, v2->y); ld->bbox[BOXBOTTOM] = min(v1->y, v2->y);
@ -5146,7 +5159,7 @@ static boolean P_LoadAddon(UINT16 wadnum, UINT16 numlumps)
// Reload it all anyway, just in case they // Reload it all anyway, just in case they
// added some textures but didn't insert a // added some textures but didn't insert a
// TEXTURES/etc. list. // TEXTURES/etc. list.
R_LoadTextures(); // numtexture changes R_LoadTexturesPwad(wadnum); // numtexture changes
// Reload ANIMDEFS // Reload ANIMDEFS
P_InitPicAnims(); 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_GetGrade(UINT32 pscore, INT16 map, UINT8 mare);
UINT8 P_HasGrades(INT16 map, UINT8 mare); UINT8 P_HasGrades(INT16 map, UINT8 mare);
UINT32 P_GetScoreForGrade(INT16 map, UINT8 mare, UINT8 grade); UINT32 P_GetScoreForGrade(INT16 map, UINT8 mare, UINT8 grade);
UINT32 P_GetScoreForGradeOverall(INT16 map, UINT8 grade);
#endif #endif

View file

@ -1242,7 +1242,7 @@ static boolean PolyFlag(line_t *line)
pfd.polyObjNum = Tag_FGet(&line->tags); pfd.polyObjNum = Tag_FGet(&line->tags);
pfd.speed = P_AproxDistance(line->dx, line->dy) >> FRACBITS; 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; pfd.momx = sides[line->sidenum[0]].textureoffset >> FRACBITS;
return EV_DoPolyObjFlag(&pfd); return EV_DoPolyObjFlag(&pfd);

View file

@ -2051,12 +2051,22 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj)
ghost->angle = (mobj->player ? mobj->player->drawangle : mobj->angle); ghost->angle = (mobj->player ? mobj->player->drawangle : mobj->angle);
ghost->rollangle = mobj->rollangle; ghost->rollangle = mobj->rollangle;
ghost->sprite = mobj->sprite; ghost->sprite = mobj->sprite;
ghost->sprite2 = mobj->sprite2; ghost->sprite2 = mobj->sprite2;
ghost->frame = mobj->frame; ghost->frame = mobj->frame;
ghost->tics = -1; ghost->tics = -1;
ghost->frame &= ~FF_TRANSMASK; ghost->frame &= ~FF_TRANSMASK;
ghost->frame |= tr_trans50<<FF_TRANSSHIFT; 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->fuse = ghost->info->damage;
ghost->skin = mobj->skin; ghost->skin = mobj->skin;
@ -6699,7 +6709,7 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad
// //
static void P_DoNiGHTSCapsule(player_t *player) 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; INT32 tictimer = ++player->capsule->extravalue2;
if (abs(player->mo->x-player->capsule->x) <= 3*FRACUNIT) if (abs(player->mo->x-player->capsule->x) <= 3*FRACUNIT)
@ -6822,15 +6832,20 @@ static void P_DoNiGHTSCapsule(player_t *player)
if (player->capsule->health > sphereresult && player->spheres > 0) 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->spheres -= deductquantity;
player->capsule->health -= 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 // Spawn a 'pop' for every 2 tics
@ -6851,9 +6866,8 @@ static void P_DoNiGHTSCapsule(player_t *player)
} }
else else
{ {
startingspheres = player->spheres - player->capsule->health; player->spheres -= player->capsule->health;
player->capsule->health = 0; player->capsule->health = 0;
player->spheres = startingspheres;
} }
} }

View file

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

View file

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

View file

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

View file

@ -1275,6 +1275,7 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale,
vissprite_t *shadow; vissprite_t *shadow;
patch_t *patch; patch_t *patch;
fixed_t xscale, yscale, shadowxscale, shadowyscale, shadowskew, x1, x2; fixed_t xscale, yscale, shadowxscale, shadowyscale, shadowskew, x1, x2;
INT32 heightsec, phs;
INT32 light = 0; INT32 light = 0;
fixed_t scalemul; UINT8 trans; fixed_t scalemul; UINT8 trans;
fixed_t floordiff; 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 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); floordiff = abs((isflipped ? thing->height : 0) + thing->z - groundz);
trans = floordiff / (100*FRACUNIT) + 3; trans = floordiff / (100*FRACUNIT) + 3;
@ -1592,7 +1611,16 @@ static void R_ProjectSprite(mobj_t *thing)
if (thing->rollangle if (thing->rollangle
&& !(splat && !(thing->renderflags & RF_NOSPLATROLLANGLE))) && !(splat && !(thing->renderflags & RF_NOSPLATROLLANGLE)))
{ {
rollangle = R_GetRollAngle(thing->rollangle); if (papersprite && ang >= ANGLE_180)
{
// Makes Software act much more sane like OpenGL
rollangle = R_GetRollAngle(InvAngle(thing->rollangle));
}
else
{
rollangle = R_GetRollAngle(thing->rollangle);
}
rotsprite = Patch_GetRotatedSprite(sprframe, (thing->frame & FF_FRAMEMASK), rot, flip, false, sprinfo, rollangle); rotsprite = Patch_GetRotatedSprite(sprframe, (thing->frame & FF_FRAMEMASK), rot, flip, false, sprinfo, rollangle);
if (rotsprite != NULL) if (rotsprite != NULL)
@ -1942,13 +1970,19 @@ static void R_ProjectSprite(mobj_t *thing)
if (heightsec != -1 && phs != -1) // only clip things which are in special sectors 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 ? if (viewz < sectors[phs].floorheight ?
thing->z >= sectors[heightsec].floorheight : bottom >= sectors[heightsec].floorheight :
gzt < sectors[heightsec].floorheight) top < sectors[heightsec].floorheight)
return; return;
if (viewz > sectors[phs].ceilingheight ? if (viewz > sectors[phs].ceilingheight ?
gzt < sectors[heightsec].ceilingheight && viewz >= sectors[heightsec].ceilingheight : top < sectors[heightsec].ceilingheight && viewz >= sectors[heightsec].ceilingheight :
thing->z >= sectors[heightsec].ceilingheight) bottom >= sectors[heightsec].ceilingheight)
return; return;
} }
@ -2822,6 +2856,57 @@ static void R_DrawPrecipitationSprite(vissprite_t *spr)
R_DrawPrecipitationVisSprite(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 // R_ClipVisSprite
// Clips vissprites without drawing, so that portals can work. -Red // 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) void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, drawseg_t* dsstart, portal_t* portal)
@ -2923,47 +3008,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 && R_HeightSecClip(spr, x1, x2);
(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;
}
}
}
if (spr->cut & SC_TOP && spr->cut & SC_BOTTOM) if (spr->cut & SC_TOP && spr->cut & SC_BOTTOM)
{ {
for (x = x1; x <= x2; x++) 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); lumpinfo->size = ftell(handle);
fseek(handle, 0, SEEK_SET); fseek(handle, 0, SEEK_SET);
strcpy(lumpinfo->name, lumpname); strcpy(lumpinfo->name, lumpname);
lumpinfo->hash = quickncasehash(lumpname, 8);
// Allocate the lump's long name. // Allocate the lump's long name.
lumpinfo->longname = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL); 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; lump_p->compression = CM_NOCOMPRESSION;
memset(lump_p->name, 0x00, 9); memset(lump_p->name, 0x00, 9);
strncpy(lump_p->name, fileinfo->name, 8); strncpy(lump_p->name, fileinfo->name, 8);
lump_p->hash = quickncasehash(lump_p->name, 8);
// Allocate the lump's long name. // Allocate the lump's long name.
lump_p->longname = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL); 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? 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)); 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); lump_p->longname = Z_Calloc(dotpos - trimname + 1, PU_STATIC, NULL);
strlcpy(lump_p->longname, trimname, dotpos - trimname + 1); strlcpy(lump_p->longname, trimname, dotpos - trimname + 1);
@ -1225,12 +1228,14 @@ UINT16 W_CheckNumForNamePwad(const char *name, UINT16 wad, UINT16 startlump)
{ {
UINT16 i; UINT16 i;
static char uname[8 + 1]; static char uname[8 + 1];
UINT32 hash;
if (!TestValidLump(wad,0)) if (!TestValidLump(wad,0))
return INT16_MAX; return INT16_MAX;
strlcpy(uname, name, sizeof uname); strlcpy(uname, name, sizeof uname);
strupr(uname); strupr(uname);
hash = quickncasehash(uname, 8);
// //
// scan forward // scan forward
@ -1241,7 +1246,7 @@ UINT16 W_CheckNumForNamePwad(const char *name, UINT16 wad, UINT16 startlump)
{ {
lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump; lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump;
for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++) 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; return i;
} }
@ -1444,15 +1449,20 @@ lumpnum_t W_CheckNumForLongName(const char *name)
// TODO: Make it search through cache first, maybe...? // TODO: Make it search through cache first, maybe...?
lumpnum_t W_CheckNumForMap(const char *name) lumpnum_t W_CheckNumForMap(const char *name)
{ {
UINT32 hash = quickncasehash(name, 8);
UINT16 lumpNum, end; UINT16 lumpNum, end;
UINT32 i; UINT32 i;
lumpinfo_t *p;
for (i = numwadfiles - 1; i < numwadfiles; i--) for (i = numwadfiles - 1; i < numwadfiles; i--)
{ {
if (wadfiles[i]->type == RET_WAD) if (wadfiles[i]->type == RET_WAD)
{ {
for (lumpNum = 0; lumpNum < wadfiles[i]->numlumps; lumpNum++) 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; return (i<<16) + lumpNum;
}
} }
else if (W_FileHasFolders(wadfiles[i])) else if (W_FileHasFolders(wadfiles[i]))
{ {
@ -1464,9 +1474,10 @@ lumpnum_t W_CheckNumForMap(const char *name)
// Now look for the specified map. // Now look for the specified map.
for (; lumpNum < end; lumpNum++) 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"))) if (!(extension && stricmp(extension, ".wad")))
return (i<<16) + lumpNum; return (i<<16) + lumpNum;
} }

View file

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