Merge branch 'musicplus-core' into musicplus-feature-postboss

This commit is contained in:
mazmazz 2018-09-18 15:35:02 -04:00
commit b55191f09a
30 changed files with 1976 additions and 433 deletions

View file

@ -1126,7 +1126,7 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum,
else else
{ {
lightnum = *list[i].lightlevel; lightnum = *list[i].lightlevel;
colormap = list[i].extra_colormap; colormap = *list[i].extra_colormap;
} }
} }
@ -3486,12 +3486,12 @@ static void HWR_Subsector(size_t num)
light = R_GetPlaneLight(gr_frontsector, locFloorHeight, false); light = R_GetPlaneLight(gr_frontsector, locFloorHeight, false);
if (gr_frontsector->floorlightsec == -1) if (gr_frontsector->floorlightsec == -1)
floorlightlevel = *gr_frontsector->lightlist[light].lightlevel; floorlightlevel = *gr_frontsector->lightlist[light].lightlevel;
floorcolormap = gr_frontsector->lightlist[light].extra_colormap; floorcolormap = *gr_frontsector->lightlist[light].extra_colormap;
light = R_GetPlaneLight(gr_frontsector, locCeilingHeight, false); light = R_GetPlaneLight(gr_frontsector, locCeilingHeight, false);
if (gr_frontsector->ceilinglightsec == -1) if (gr_frontsector->ceilinglightsec == -1)
ceilinglightlevel = *gr_frontsector->lightlist[light].lightlevel; ceilinglightlevel = *gr_frontsector->lightlist[light].lightlevel;
ceilingcolormap = gr_frontsector->lightlist[light].extra_colormap; ceilingcolormap = *gr_frontsector->lightlist[light].extra_colormap;
} }
sub->sector->extra_colormap = gr_frontsector->extra_colormap; sub->sector->extra_colormap = gr_frontsector->extra_colormap;
@ -3617,7 +3617,7 @@ static void HWR_Subsector(size_t num)
*rover->bottomheight, *rover->bottomheight,
*gr_frontsector->lightlist[light].lightlevel, *gr_frontsector->lightlist[light].lightlevel,
rover->alpha-1 > 255 ? 255 : rover->alpha-1, rover->master->frontsector, PF_Translucent, rover->alpha-1 > 255 ? 255 : rover->alpha-1, rover->master->frontsector, PF_Translucent,
false, gr_frontsector->lightlist[light].extra_colormap); false, *gr_frontsector->lightlist[light].extra_colormap);
#endif #endif
} }
else else
@ -3625,7 +3625,7 @@ static void HWR_Subsector(size_t num)
HWR_GetFlat(levelflats[*rover->bottompic].lumpnum); HWR_GetFlat(levelflats[*rover->bottompic].lumpnum);
light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
HWR_RenderPlane(NULL, &extrasubsectors[num], false, *rover->bottomheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->bottompic].lumpnum, HWR_RenderPlane(NULL, &extrasubsectors[num], false, *rover->bottomheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->bottompic].lumpnum,
rover->master->frontsector, 255, false, gr_frontsector->lightlist[light].extra_colormap); rover->master->frontsector, 255, false, *gr_frontsector->lightlist[light].extra_colormap);
} }
} }
@ -3680,7 +3680,7 @@ static void HWR_Subsector(size_t num)
*rover->topheight, *rover->topheight,
*gr_frontsector->lightlist[light].lightlevel, *gr_frontsector->lightlist[light].lightlevel,
rover->alpha-1 > 255 ? 255 : rover->alpha-1, rover->master->frontsector, PF_Translucent, rover->alpha-1 > 255 ? 255 : rover->alpha-1, rover->master->frontsector, PF_Translucent,
false, gr_frontsector->lightlist[light].extra_colormap); false, *gr_frontsector->lightlist[light].extra_colormap);
#endif #endif
} }
@ -3689,7 +3689,7 @@ static void HWR_Subsector(size_t num)
HWR_GetFlat(levelflats[*rover->toppic].lumpnum); HWR_GetFlat(levelflats[*rover->toppic].lumpnum);
light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
HWR_RenderPlane(NULL, &extrasubsectors[num], true, *rover->topheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->toppic].lumpnum, HWR_RenderPlane(NULL, &extrasubsectors[num], true, *rover->topheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->toppic].lumpnum,
rover->master->frontsector, 255, false, gr_frontsector->lightlist[light].extra_colormap); rover->master->frontsector, 255, false, *gr_frontsector->lightlist[light].extra_colormap);
} }
} }
} }
@ -4200,8 +4200,8 @@ static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float t
if (!(spr->mobj->frame & FF_FULLBRIGHT)) if (!(spr->mobj->frame & FF_FULLBRIGHT))
lightlevel = *sector->lightlist[light].lightlevel; lightlevel = *sector->lightlist[light].lightlevel;
if (sector->lightlist[light].extra_colormap) if (*sector->lightlist[light].extra_colormap)
colormap = sector->lightlist[light].extra_colormap; colormap = *sector->lightlist[light].extra_colormap;
} }
else else
{ {
@ -4362,7 +4362,7 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
// Start with the lightlevel and colormap from the top of the sprite // Start with the lightlevel and colormap from the top of the sprite
lightlevel = *list[sector->numlights - 1].lightlevel; lightlevel = *list[sector->numlights - 1].lightlevel;
colormap = list[sector->numlights - 1].extra_colormap; colormap = *list[sector->numlights - 1].extra_colormap;
i = 0; i = 0;
temp = FLOAT_TO_FIXED(realtop); temp = FLOAT_TO_FIXED(realtop);
@ -4378,7 +4378,7 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
{ {
if (!(spr->mobj->frame & FF_FULLBRIGHT)) if (!(spr->mobj->frame & FF_FULLBRIGHT))
lightlevel = *list[i-1].lightlevel; lightlevel = *list[i-1].lightlevel;
colormap = list[i-1].extra_colormap; colormap = *list[i-1].extra_colormap;
break; break;
} }
} }
@ -4386,7 +4386,7 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
i = R_GetPlaneLight(sector, temp, false); i = R_GetPlaneLight(sector, temp, false);
if (!(spr->mobj->frame & FF_FULLBRIGHT)) if (!(spr->mobj->frame & FF_FULLBRIGHT))
lightlevel = *list[i].lightlevel; lightlevel = *list[i].lightlevel;
colormap = list[i].extra_colormap; colormap = *list[i].extra_colormap;
#endif #endif
for (i = 0; i < sector->numlights; i++) for (i = 0; i < sector->numlights; i++)
@ -4402,7 +4402,7 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
{ {
if (!(spr->mobj->frame & FF_FULLBRIGHT)) if (!(spr->mobj->frame & FF_FULLBRIGHT))
lightlevel = *list[i].lightlevel; lightlevel = *list[i].lightlevel;
colormap = list[i].extra_colormap; colormap = *list[i].extra_colormap;
} }
#ifdef ESLOPE #ifdef ESLOPE
@ -4734,8 +4734,8 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr)
if (!(spr->mobj->frame & FF_FULLBRIGHT)) if (!(spr->mobj->frame & FF_FULLBRIGHT))
lightlevel = *sector->lightlist[light].lightlevel; lightlevel = *sector->lightlist[light].lightlevel;
if (sector->lightlist[light].extra_colormap) if (*sector->lightlist[light].extra_colormap)
colormap = sector->lightlist[light].extra_colormap; colormap = *sector->lightlist[light].extra_colormap;
} }
else else
{ {

View file

@ -1194,8 +1194,8 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
if (!(spr->mobj->frame & FF_FULLBRIGHT)) if (!(spr->mobj->frame & FF_FULLBRIGHT))
lightlevel = *sector->lightlist[light].lightlevel; lightlevel = *sector->lightlist[light].lightlevel;
if (sector->lightlist[light].extra_colormap) if (*sector->lightlist[light].extra_colormap)
colormap = sector->lightlist[light].extra_colormap; colormap = *sector->lightlist[light].extra_colormap;
} }
else else
{ {

View file

@ -954,14 +954,9 @@ static int lib_pRestoreMusic(lua_State *L)
INLEVEL INLEVEL
if (!player) if (!player)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
if (!player || P_IsLocalPlayer(player)) if (P_IsLocalPlayer(player))
{
P_RestoreMusic(player); P_RestoreMusic(player);
lua_pushboolean(L, true); return 0;
}
else
lua_pushnil(L);
return 1;
} }
static int lib_pSpawnShieldOrb(lua_State *L) static int lib_pSpawnShieldOrb(lua_State *L)
@ -1815,9 +1810,11 @@ static int lib_pFadeLight(lua_State *L)
INT16 tag = (INT16)luaL_checkinteger(L, 1); INT16 tag = (INT16)luaL_checkinteger(L, 1);
INT32 destvalue = (INT32)luaL_checkinteger(L, 2); INT32 destvalue = (INT32)luaL_checkinteger(L, 2);
INT32 speed = (INT32)luaL_checkinteger(L, 3); INT32 speed = (INT32)luaL_checkinteger(L, 3);
boolean ticbased = lua_optboolean(L, 4);
boolean force = lua_optboolean(L, 5);
NOHUD NOHUD
INLEVEL INLEVEL
P_FadeLight(tag, destvalue, speed); P_FadeLight(tag, destvalue, speed, ticbased, force);
return 0; return 0;
} }
@ -2241,13 +2238,8 @@ static int lib_sChangeMusic(lua_State *L)
fadeinms = (UINT32)luaL_optinteger(L, 7, 0); fadeinms = (UINT32)luaL_optinteger(L, 7, 0);
if (!player || P_IsLocalPlayer(player)) if (!player || P_IsLocalPlayer(player))
{
S_ChangeMusicEx(music_name, music_flags, looping, position, prefadems, fadeinms); S_ChangeMusicEx(music_name, music_flags, looping, position, prefadems, fadeinms);
lua_pushboolean(L, true); return 0;
}
else
lua_pushnil(L);
return 1;
} }
static int lib_sSpeedMusic(lua_State *L) static int lib_sSpeedMusic(lua_State *L)
@ -2263,10 +2255,23 @@ static int lib_sSpeedMusic(lua_State *L)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
} }
if (!player || P_IsLocalPlayer(player)) if (!player || P_IsLocalPlayer(player))
lua_pushboolean(L, S_SpeedMusic(speed)); S_SpeedMusic(speed);
else return 0;
lua_pushnil(L); }
return 1;
static int lib_sStopMusic(lua_State *L)
{
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
{
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
S_StopMusic();
return 0;
} }
static int lib_sOriginPlaying(lua_State *L) static int lib_sOriginPlaying(lua_State *L)
@ -2646,6 +2651,7 @@ static luaL_Reg lib[] = {
{"S_StopSound",lib_sStopSound}, {"S_StopSound",lib_sStopSound},
{"S_ChangeMusic",lib_sChangeMusic}, {"S_ChangeMusic",lib_sChangeMusic},
{"S_SpeedMusic",lib_sSpeedMusic}, {"S_SpeedMusic",lib_sSpeedMusic},
{"S_StopMusic",lib_sStopMusic},
{"S_OriginPlaying",lib_sOriginPlaying}, {"S_OriginPlaying",lib_sOriginPlaying},
{"S_IdPlaying",lib_sIdPlaying}, {"S_IdPlaying",lib_sIdPlaying},
{"S_SoundPlaying",lib_sSoundPlaying}, {"S_SoundPlaying",lib_sSoundPlaying},

View file

@ -48,7 +48,6 @@ enum hook {
hook_MobjMoveBlocked, hook_MobjMoveBlocked,
hook_MapThingSpawn, hook_MapThingSpawn,
hook_FollowMobj, hook_FollowMobj,
hook_MusicChange,
hook_MAX // last hook hook_MAX // last hook
}; };

View file

@ -59,7 +59,6 @@ const char *const hookNames[hook_MAX+1] = {
"MobjMoveBlocked", "MobjMoveBlocked",
"MapThingSpawn", "MapThingSpawn",
"FollowMobj", "FollowMobj",
"MusicChange",
NULL NULL
}; };

View file

@ -40,6 +40,8 @@ enum mobj_e {
mobj_subsector, mobj_subsector,
mobj_floorz, mobj_floorz,
mobj_ceilingz, mobj_ceilingz,
mobj_floorrover,
mobj_ceilingrover,
mobj_radius, mobj_radius,
mobj_height, mobj_height,
mobj_momx, mobj_momx,
@ -100,6 +102,8 @@ static const char *const mobj_opt[] = {
"subsector", "subsector",
"floorz", "floorz",
"ceilingz", "ceilingz",
"floorrover",
"ceilingrover",
"radius", "radius",
"height", "height",
"momx", "momx",
@ -208,6 +212,12 @@ static int mobj_get(lua_State *L)
case mobj_ceilingz: case mobj_ceilingz:
lua_pushfixed(L, mo->ceilingz); lua_pushfixed(L, mo->ceilingz);
break; break;
case mobj_floorrover:
LUA_PushUserdata(L, mo->floorrover, META_FFLOOR);
break;
case mobj_ceilingrover:
LUA_PushUserdata(L, mo->ceilingrover, META_FFLOOR);
break;
case mobj_radius: case mobj_radius:
lua_pushfixed(L, mo->radius); lua_pushfixed(L, mo->radius);
break; break;
@ -396,6 +406,8 @@ static int mobj_set(lua_State *L)
P_CheckPosition(mo, mo->x, mo->y); P_CheckPosition(mo, mo->x, mo->y);
mo->floorz = tmfloorz; mo->floorz = tmfloorz;
mo->ceilingz = tmceilingz; mo->ceilingz = tmceilingz;
mo->floorrover = tmfloorrover;
mo->ceilingrover = tmceilingrover;
P_SetTarget(&tmthing, ptmthing); P_SetTarget(&tmthing, ptmthing);
break; break;
} }
@ -430,6 +442,10 @@ static int mobj_set(lua_State *L)
return NOSETPOS; return NOSETPOS;
case mobj_ceilingz: case mobj_ceilingz:
return NOSETPOS; return NOSETPOS;
case mobj_floorrover:
return NOSET;
case mobj_ceilingrover:
return NOSET;
case mobj_radius: case mobj_radius:
{ {
mobj_t *ptmthing = tmthing; mobj_t *ptmthing = tmthing;
@ -439,6 +455,8 @@ static int mobj_set(lua_State *L)
P_CheckPosition(mo, mo->x, mo->y); P_CheckPosition(mo, mo->x, mo->y);
mo->floorz = tmfloorz; mo->floorz = tmfloorz;
mo->ceilingz = tmceilingz; mo->ceilingz = tmceilingz;
mo->floorrover = tmfloorrover;
mo->ceilingrover = tmceilingrover;
P_SetTarget(&tmthing, ptmthing); P_SetTarget(&tmthing, ptmthing);
break; break;
} }
@ -451,6 +469,8 @@ static int mobj_set(lua_State *L)
P_CheckPosition(mo, mo->x, mo->y); P_CheckPosition(mo, mo->x, mo->y);
mo->floorz = tmfloorz; mo->floorz = tmfloorz;
mo->ceilingz = tmceilingz; mo->ceilingz = tmceilingz;
mo->floorrover = tmfloorrover;
mo->ceilingrover = tmceilingrover;
P_SetTarget(&tmthing, ptmthing); P_SetTarget(&tmthing, ptmthing);
break; break;
} }

View file

@ -1839,6 +1839,7 @@ void T_ThwompSector(levelspecthink_t *thwomp)
#define ceilingwasheight vars[5] #define ceilingwasheight vars[5]
fixed_t thwompx, thwompy; fixed_t thwompx, thwompy;
sector_t *actionsector; sector_t *actionsector;
ffloor_t *rover = NULL;
INT32 secnum; INT32 secnum;
// If you just crashed down, wait a second before coming back up. // If you just crashed down, wait a second before coming back up.
@ -1853,7 +1854,16 @@ void T_ThwompSector(levelspecthink_t *thwomp)
secnum = P_FindSectorFromTag((INT16)thwomp->vars[0], -1); secnum = P_FindSectorFromTag((INT16)thwomp->vars[0], -1);
if (secnum > 0) if (secnum > 0)
{
actionsector = &sectors[secnum]; actionsector = &sectors[secnum];
// Look for thwomp FFloor
for (rover = actionsector->ffloors; rover; rover = rover->next)
{
if (rover->master == thwomp->sourceline)
break;
}
}
else else
return; // Bad bad bad! return; // Bad bad bad!
@ -1942,10 +1952,13 @@ void T_ThwompSector(levelspecthink_t *thwomp)
{ {
mobj_t *mp = (void *)&actionsector->soundorg; mobj_t *mp = (void *)&actionsector->soundorg;
if (thwomp->sourceline->flags & ML_EFFECT4) if (!rover || (rover->flags & FF_EXISTS))
S_StartSound(mp, sides[thwomp->sourceline->sidenum[0]].textureoffset>>FRACBITS); {
else if (thwomp->sourceline->flags & ML_EFFECT4)
S_StartSound(mp, sfx_thwomp); S_StartSound(mp, sides[thwomp->sourceline->sidenum[0]].textureoffset>>FRACBITS);
else
S_StartSound(mp, sfx_thwomp);
}
thwomp->direction = 1; // start heading back up thwomp->direction = 1; // start heading back up
thwomp->distance = TICRATE; // but only after a small delay thwomp->distance = TICRATE; // but only after a small delay
@ -1959,18 +1972,22 @@ void T_ThwompSector(levelspecthink_t *thwomp)
thinker_t *th; thinker_t *th;
mobj_t *mo; mobj_t *mo;
// scan the thinkers to find players! if (!rover || (rover->flags & FF_EXISTS))
for (th = thinkercap.next; th != &thinkercap; th = th->next)
{ {
if (th->function.acp1 != (actionf_p1)P_MobjThinker) // scan the thinkers to find players!
continue; for (th = thinkercap.next; th != &thinkercap; th = th->next)
mo = (mobj_t *)th;
if (mo->type == MT_PLAYER && mo->health && mo->z <= thwomp->sector->ceilingheight
&& P_AproxDistance(thwompx - mo->x, thwompy - mo->y) <= 96*FRACUNIT)
{ {
thwomp->direction = -1; if (th->function.acp1 != (actionf_p1)P_MobjThinker)
break; continue;
mo = (mobj_t *)th;
if (mo->type == MT_PLAYER && mo->health && mo->player && !mo->player->spectator
&& mo->z <= thwomp->sector->ceilingheight
&& P_AproxDistance(thwompx - mo->x, thwompy - mo->y) <= 96*FRACUNIT)
{
thwomp->direction = -1;
break;
}
} }
} }

View file

@ -322,39 +322,70 @@ glow_t *P_SpawnAdjustableGlowingLight(sector_t *minsector, sector_t *maxsector,
return g; return g;
} }
/** Fades all the lights in sectors with a particular tag to a new /** Fades all the lights in specified sector to a new
* value. * value.
* *
* \param tag Tag to look for sectors by. * \param sector Target sector
* \param destvalue The final light value in these sectors. * \param destvalue The final light value in these sectors.
* \param speed Speed of the fade; the change to the ligh * \param speed If tic-based: total duration of effect.
* If speed-based: Speed of the fade; the change to the ligh
* level in each sector per tic. * level in each sector per tic.
* \todo Calculate speed better so that it is possible to specify * \param ticbased Use a specific duration for the fade, defined by speed
* the time for completion of the fade, and all lights fade
* in this time regardless of initial values.
* \sa T_LightFade * \sa T_LightFade
*/ */
void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed) void P_FadeLightBySector(sector_t *sector, INT32 destvalue, INT32 speed, boolean ticbased)
{
lightlevel_t *ll;
P_RemoveLighting(sector); // remove the old lighting effect first
if ((ticbased && !speed) || sector->lightlevel == destvalue) // set immediately
{
sector->lightlevel = destvalue;
return;
}
ll = Z_Calloc(sizeof (*ll), PU_LEVSPEC, NULL);
ll->thinker.function.acp1 = (actionf_p1)T_LightFade;
sector->lightingdata = ll; // set it to the lightlevel_t
P_AddThinker(&ll->thinker); // add thinker
ll->sector = sector;
ll->sourcelevel = sector->lightlevel;
ll->destlevel = destvalue;
ll->fixedcurlevel = sector->lightlevel<<FRACBITS;
if (ticbased)
{
// Speed means duration.
ll->timer = abs(speed);
ll->fixedpertic = FixedDiv((destvalue<<FRACBITS) - ll->fixedcurlevel, speed<<FRACBITS);
}
else
{
// Speed means increment per tic (literally speed).
ll->timer = FixedDiv((destvalue<<FRACBITS) - ll->fixedcurlevel, speed<<FRACBITS)>>FRACBITS;
ll->fixedpertic = speed<<FRACBITS;
}
}
void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased, boolean force)
{ {
INT32 i; INT32 i;
lightlevel_t *ll;
sector_t *sector;
// search all sectors for ones with tag // search all sectors for ones with tag
for (i = -1; (i = P_FindSectorFromTag(tag, i)) >= 0 ;) for (i = -1; (i = P_FindSectorFromTag(tag, i)) >= 0 ;)
{ {
sector = &sectors[i]; if (!force && ticbased // always let speed fader execute
&& sectors[i].lightingdata
P_RemoveLighting(sector); // remove the old lighting effect first && ((lightlevel_t*)sectors[i].lightingdata)->thinker.function.acp1 == (actionf_p1)T_LightFade)
ll = Z_Calloc(sizeof (*ll), PU_LEVSPEC, NULL); // && ((lightlevel_t*)sectors[i].lightingdata)->timer > 2)
ll->thinker.function.acp1 = (actionf_p1)T_LightFade; {
sector->lightingdata = ll; // set it to the lightlevel_t CONS_Debug(DBG_GAMELOGIC, "Line type 420 Executor: Fade light thinker already exists, timer: %d\n", ((lightlevel_t*)sectors[i].lightingdata)->timer);
continue;
P_AddThinker(&ll->thinker); // add thinker }
P_FadeLightBySector(&sectors[i], destvalue, speed, ticbased);
ll->sector = sector;
ll->destlevel = destvalue;
ll->speed = speed;
} }
} }
@ -365,30 +396,13 @@ void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed)
*/ */
void T_LightFade(lightlevel_t *ll) void T_LightFade(lightlevel_t *ll)
{ {
if (ll->sector->lightlevel < ll->destlevel) if (--ll->timer <= 0)
{ {
// increase the lightlevel ll->sector->lightlevel = ll->destlevel; // set to dest lightlevel
if (ll->sector->lightlevel + ll->speed >= ll->destlevel) P_RemoveLighting(ll->sector); // clear lightingdata, remove thinker
{ return;
// stop changing light level
ll->sector->lightlevel = (INT16)ll->destlevel; // set to dest lightlevel
P_RemoveLighting(ll->sector); // clear lightingdata, remove thinker
}
else
ll->sector->lightlevel = (INT16)(ll->sector->lightlevel + (INT16)ll->speed); // move lightlevel
} }
else
{
// decrease lightlevel
if (ll->sector->lightlevel - ll->speed <= ll->destlevel)
{
// stop changing light level
ll->sector->lightlevel = (INT16)ll->destlevel; // set to dest lightlevel
P_RemoveLighting(ll->sector); // clear lightingdata, remove thinker ll->fixedcurlevel = ll->fixedcurlevel + ll->fixedpertic;
} ll->sector->lightlevel = (ll->fixedcurlevel)>>FRACBITS;
else
ll->sector->lightlevel = (INT16)(ll->sector->lightlevel - (INT16)ll->speed); // move lightlevel
}
} }

View file

@ -326,6 +326,7 @@ void P_InternalFlickyHop(mobj_t *actor, fixed_t momz, fixed_t momh, angle_t angl
extern boolean floatok; extern boolean floatok;
extern fixed_t tmfloorz; extern fixed_t tmfloorz;
extern fixed_t tmceilingz; extern fixed_t tmceilingz;
extern ffloor_t *tmfloorrover, *tmceilingrover;
extern mobj_t *tmfloorthing, *tmhitthing, *tmthing; extern mobj_t *tmfloorthing, *tmhitthing, *tmthing;
extern camera_t *mapcampointer; extern camera_t *mapcampointer;
extern fixed_t tmx; extern fixed_t tmx;

View file

@ -52,6 +52,7 @@ fixed_t tmfloorz, tmceilingz;
static fixed_t tmdropoffz, tmdrpoffceilz; // drop-off floor/ceiling heights static fixed_t tmdropoffz, tmdrpoffceilz; // drop-off floor/ceiling heights
mobj_t *tmfloorthing; // the thing corresponding to tmfloorz or NULL if tmfloorz is from a sector mobj_t *tmfloorthing; // the thing corresponding to tmfloorz or NULL if tmfloorz is from a sector
mobj_t *tmhitthing; // the solid thing you bumped into (for collisions) mobj_t *tmhitthing; // the solid thing you bumped into (for collisions)
ffloor_t *tmfloorrover, *tmceilingrover;
#ifdef ESLOPE #ifdef ESLOPE
pslope_t *tmfloorslope, *tmceilingslope; pslope_t *tmfloorslope, *tmceilingslope;
#endif #endif
@ -101,6 +102,8 @@ boolean P_TeleportMove(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z)
thing->floorz = tmfloorz; thing->floorz = tmfloorz;
thing->ceilingz = tmceilingz; thing->ceilingz = tmceilingz;
thing->floorrover = tmfloorrover;
thing->ceilingrover = tmceilingrover;
return true; return true;
} }
@ -1417,6 +1420,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (thing->z + thing->height > tmfloorz) if (thing->z + thing->height > tmfloorz)
{ {
tmfloorz = thing->z + thing->height; tmfloorz = thing->z + thing->height;
tmfloorrover = NULL;
#ifdef ESLOPE #ifdef ESLOPE
tmfloorslope = NULL; tmfloorslope = NULL;
#endif #endif
@ -1437,6 +1441,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
return false; return false;
tmfloorz = tmceilingz = topz; // block while in air tmfloorz = tmceilingz = topz; // block while in air
tmceilingrover = NULL;
#ifdef ESLOPE #ifdef ESLOPE
tmceilingslope = NULL; tmceilingslope = NULL;
#endif #endif
@ -1445,6 +1450,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
else if (topz < tmceilingz && tmthing->z <= thing->z+thing->height) else if (topz < tmceilingz && tmthing->z <= thing->z+thing->height)
{ {
tmceilingz = topz; tmceilingz = topz;
tmceilingrover = NULL;
#ifdef ESLOPE #ifdef ESLOPE
tmceilingslope = NULL; tmceilingslope = NULL;
#endif #endif
@ -1461,6 +1467,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (thing->z < tmceilingz) if (thing->z < tmceilingz)
{ {
tmceilingz = thing->z; tmceilingz = thing->z;
tmceilingrover = NULL;
#ifdef ESLOPE #ifdef ESLOPE
tmceilingslope = NULL; tmceilingslope = NULL;
#endif #endif
@ -1481,6 +1488,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
return false; return false;
tmfloorz = tmceilingz = topz; // block while in air tmfloorz = tmceilingz = topz; // block while in air
tmfloorrover = NULL;
#ifdef ESLOPE #ifdef ESLOPE
tmfloorslope = NULL; tmfloorslope = NULL;
#endif #endif
@ -1489,6 +1497,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
else if (topz > tmfloorz && tmthing->z+tmthing->height >= thing->z) else if (topz > tmfloorz && tmthing->z+tmthing->height >= thing->z)
{ {
tmfloorz = topz; tmfloorz = topz;
tmfloorrover = NULL;
#ifdef ESLOPE #ifdef ESLOPE
tmfloorslope = NULL; tmfloorslope = NULL;
#endif #endif
@ -1640,6 +1649,7 @@ static boolean PIT_CheckLine(line_t *ld)
{ {
tmceilingz = opentop; tmceilingz = opentop;
ceilingline = ld; ceilingline = ld;
tmceilingrover = NULL;
#ifdef ESLOPE #ifdef ESLOPE
tmceilingslope = opentopslope; tmceilingslope = opentopslope;
#endif #endif
@ -1648,6 +1658,7 @@ static boolean PIT_CheckLine(line_t *ld)
if (openbottom > tmfloorz) if (openbottom > tmfloorz)
{ {
tmfloorz = openbottom; tmfloorz = openbottom;
tmfloorrover = NULL;
#ifdef ESLOPE #ifdef ESLOPE
tmfloorslope = openbottomslope; tmfloorslope = openbottomslope;
#endif #endif
@ -1729,6 +1740,8 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
// will adjust them. // will adjust them.
tmfloorz = tmdropoffz = P_GetFloorZ(thing, newsubsec->sector, x, y, NULL); //newsubsec->sector->floorheight; tmfloorz = tmdropoffz = P_GetFloorZ(thing, newsubsec->sector, x, y, NULL); //newsubsec->sector->floorheight;
tmceilingz = P_GetCeilingZ(thing, newsubsec->sector, x, y, NULL); //newsubsec->sector->ceilingheight; tmceilingz = P_GetCeilingZ(thing, newsubsec->sector, x, y, NULL); //newsubsec->sector->ceilingheight;
tmfloorrover = NULL;
tmceilingrover = NULL;
#ifdef ESLOPE #ifdef ESLOPE
tmfloorslope = newsubsec->sector->f_slope; tmfloorslope = newsubsec->sector->f_slope;
tmceilingslope = newsubsec->sector->c_slope; tmceilingslope = newsubsec->sector->c_slope;
@ -1772,6 +1785,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
{ {
if (tmfloorz < topheight - sinklevel) { if (tmfloorz < topheight - sinklevel) {
tmfloorz = topheight - sinklevel; tmfloorz = topheight - sinklevel;
tmfloorrover = rover;
#ifdef ESLOPE #ifdef ESLOPE
tmfloorslope = *rover->t_slope; tmfloorslope = *rover->t_slope;
#endif #endif
@ -1781,6 +1795,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
{ {
if (tmceilingz > bottomheight + sinklevel) { if (tmceilingz > bottomheight + sinklevel) {
tmceilingz = bottomheight + sinklevel; tmceilingz = bottomheight + sinklevel;
tmceilingrover = rover;
#ifdef ESLOPE #ifdef ESLOPE
tmceilingslope = *rover->b_slope; tmceilingslope = *rover->b_slope;
#endif #endif
@ -1805,6 +1820,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
{ {
if (tmfloorz < thing->z) { if (tmfloorz < thing->z) {
tmfloorz = thing->z; tmfloorz = thing->z;
tmfloorrover = rover;
#ifdef ESLOPE #ifdef ESLOPE
tmfloorslope = NULL; tmfloorslope = NULL;
#endif #endif
@ -1823,6 +1839,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
&& !(rover->flags & FF_REVERSEPLATFORM)) && !(rover->flags & FF_REVERSEPLATFORM))
{ {
tmfloorz = tmdropoffz = topheight; tmfloorz = tmdropoffz = topheight;
tmfloorrover = rover;
#ifdef ESLOPE #ifdef ESLOPE
tmfloorslope = *rover->t_slope; tmfloorslope = *rover->t_slope;
#endif #endif
@ -1832,6 +1849,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
&& !(thing->type == MT_SKIM && (rover->flags & FF_SWIMMABLE))) && !(thing->type == MT_SKIM && (rover->flags & FF_SWIMMABLE)))
{ {
tmceilingz = tmdrpoffceilz = bottomheight; tmceilingz = tmdrpoffceilz = bottomheight;
tmceilingrover = rover;
#ifdef ESLOPE #ifdef ESLOPE
tmceilingslope = *rover->b_slope; tmceilingslope = *rover->b_slope;
#endif #endif
@ -2328,6 +2346,8 @@ boolean PIT_PushableMoved(mobj_t *thing)
mobj_t *oldthing = tmthing; mobj_t *oldthing = tmthing;
line_t *oldceilline = ceilingline; line_t *oldceilline = ceilingline;
line_t *oldblockline = blockingline; line_t *oldblockline = blockingline;
ffloor_t *oldflrrover = tmfloorrover;
ffloor_t *oldceilrover = tmceilingrover;
#ifdef ESLOPE #ifdef ESLOPE
pslope_t *oldfslope = tmfloorslope; pslope_t *oldfslope = tmfloorslope;
pslope_t *oldcslope = tmceilingslope; pslope_t *oldcslope = tmceilingslope;
@ -2344,6 +2364,8 @@ boolean PIT_PushableMoved(mobj_t *thing)
P_SetTarget(&tmthing, oldthing); P_SetTarget(&tmthing, oldthing);
ceilingline = oldceilline; ceilingline = oldceilline;
blockingline = oldblockline; blockingline = oldblockline;
tmfloorrover = oldflrrover;
tmceilingrover = oldceilrover;
#ifdef ESLOPE #ifdef ESLOPE
tmfloorslope = oldfslope; tmfloorslope = oldfslope;
tmceilingslope = oldcslope; tmceilingslope = oldcslope;
@ -2465,6 +2487,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
if (thingtop == thing->ceilingz && tmceilingz > thingtop && tmceilingz - thingtop <= maxstep) if (thingtop == thing->ceilingz && tmceilingz > thingtop && tmceilingz - thingtop <= maxstep)
{ {
thing->z = (thing->ceilingz = thingtop = tmceilingz) - thing->height; thing->z = (thing->ceilingz = thingtop = tmceilingz) - thing->height;
thing->ceilingrover = tmceilingrover;
thing->eflags |= MFE_JUSTSTEPPEDDOWN; thing->eflags |= MFE_JUSTSTEPPEDDOWN;
} }
#ifdef ESLOPE #ifdef ESLOPE
@ -2472,6 +2495,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
else if (tmceilingslope && tmceilingz < thingtop && thingtop - tmceilingz <= maxstep) else if (tmceilingslope && tmceilingz < thingtop && thingtop - tmceilingz <= maxstep)
{ {
thing->z = (thing->ceilingz = thingtop = tmceilingz) - thing->height; thing->z = (thing->ceilingz = thingtop = tmceilingz) - thing->height;
thing->ceilingrover = tmceilingrover;
thing->eflags |= MFE_JUSTSTEPPEDDOWN; thing->eflags |= MFE_JUSTSTEPPEDDOWN;
} }
#endif #endif
@ -2479,6 +2503,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
else if (thing->z == thing->floorz && tmfloorz < thing->z && thing->z - tmfloorz <= maxstep) else if (thing->z == thing->floorz && tmfloorz < thing->z && thing->z - tmfloorz <= maxstep)
{ {
thing->z = thing->floorz = tmfloorz; thing->z = thing->floorz = tmfloorz;
thing->floorrover = tmfloorrover;
thing->eflags |= MFE_JUSTSTEPPEDDOWN; thing->eflags |= MFE_JUSTSTEPPEDDOWN;
} }
#ifdef ESLOPE #ifdef ESLOPE
@ -2486,6 +2511,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
else if (tmfloorslope && tmfloorz > thing->z && tmfloorz - thing->z <= maxstep) else if (tmfloorslope && tmfloorz > thing->z && tmfloorz - thing->z <= maxstep)
{ {
thing->z = thing->floorz = tmfloorz; thing->z = thing->floorz = tmfloorz;
thing->floorrover = tmfloorrover;
thing->eflags |= MFE_JUSTSTEPPEDDOWN; thing->eflags |= MFE_JUSTSTEPPEDDOWN;
} }
#endif #endif
@ -2557,6 +2583,8 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
thing->floorz = tmfloorz; thing->floorz = tmfloorz;
thing->ceilingz = tmceilingz; thing->ceilingz = tmceilingz;
thing->floorrover = tmfloorrover;
thing->ceilingrover = tmceilingrover;
#ifdef ESLOPE #ifdef ESLOPE
if (!(thing->flags & MF_NOCLIPHEIGHT)) if (!(thing->flags & MF_NOCLIPHEIGHT))
@ -2637,6 +2665,8 @@ boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y)
thing->floorz = tmfloorz; thing->floorz = tmfloorz;
thing->ceilingz = tmceilingz; thing->ceilingz = tmceilingz;
thing->floorrover = tmfloorrover;
thing->ceilingrover = tmceilingrover;
thing->x = x; thing->x = x;
thing->y = y; thing->y = y;
@ -2663,7 +2693,10 @@ static boolean P_ThingHeightClip(mobj_t *thing)
{ {
boolean floormoved; boolean floormoved;
fixed_t oldfloorz = thing->floorz; fixed_t oldfloorz = thing->floorz;
ffloor_t *oldfloorrover = thing->floorrover;
ffloor_t *oldceilingrover = thing->ceilingrover;
boolean onfloor = P_IsObjectOnGround(thing);//(thing->z <= thing->floorz); boolean onfloor = P_IsObjectOnGround(thing);//(thing->z <= thing->floorz);
ffloor_t *rover = NULL;
if (thing->flags & MF_NOCLIPHEIGHT) if (thing->flags & MF_NOCLIPHEIGHT)
return true; return true;
@ -2678,6 +2711,8 @@ static boolean P_ThingHeightClip(mobj_t *thing)
thing->floorz = tmfloorz; thing->floorz = tmfloorz;
thing->ceilingz = tmceilingz; thing->ceilingz = tmceilingz;
thing->floorrover = tmfloorrover;
thing->ceilingrover = tmceilingrover;
// Ugly hack?!?! As long as just ceilingz is the lowest, // Ugly hack?!?! As long as just ceilingz is the lowest,
// you'll still get crushed, right? // you'll still get crushed, right?
@ -2686,16 +2721,23 @@ static boolean P_ThingHeightClip(mobj_t *thing)
if (onfloor && !(thing->flags & MF_NOGRAVITY) && floormoved) if (onfloor && !(thing->flags & MF_NOGRAVITY) && floormoved)
{ {
if (thing->eflags & MFE_VERTICALFLIP) rover = (thing->eflags & MFE_VERTICALFLIP) ? oldceilingrover : oldfloorrover;
thing->pmomz = thing->ceilingz - (thing->z + thing->height);
else
thing->pmomz = thing->floorz - thing->z;
thing->eflags |= MFE_APPLYPMOMZ;
if (thing->eflags & MFE_VERTICALFLIP) // Match the Thing's old floorz to an FOF and check for FF_EXISTS
thing->z = thing->ceilingz - thing->height; // If ~FF_EXISTS, don't set mobj Z.
else if (!rover || ((rover->flags & FF_EXISTS) && (rover->flags & FF_SOLID)))
thing->z = thing->floorz; {
if (thing->eflags & MFE_VERTICALFLIP)
thing->pmomz = thing->ceilingz - (thing->z + thing->height);
else
thing->pmomz = thing->floorz - thing->z;
thing->eflags |= MFE_APPLYPMOMZ;
if (thing->eflags & MFE_VERTICALFLIP)
thing->z = thing->ceilingz - thing->height;
else
thing->z = thing->floorz;
}
} }
else if (!tmfloorthing) else if (!tmfloorthing)
{ {

View file

@ -8027,6 +8027,8 @@ void P_MobjThinker(mobj_t *mobj)
return; return;
mobj->floorz = tmfloorz; mobj->floorz = tmfloorz;
mobj->ceilingz = tmceilingz; mobj->ceilingz = tmceilingz;
mobj->floorrover = tmfloorrover;
mobj->ceilingrover = tmceilingrover;
if ((mobj->eflags & MFE_UNDERWATER) && mobj->health > 0) if ((mobj->eflags & MFE_UNDERWATER) && mobj->health > 0)
{ {
@ -8545,6 +8547,8 @@ void P_SceneryThinker(mobj_t *mobj)
return; return;
mobj->floorz = tmfloorz; mobj->floorz = tmfloorz;
mobj->ceilingz = tmceilingz; mobj->ceilingz = tmceilingz;
mobj->floorrover = tmfloorrover;
mobj->ceilingrover = tmceilingrover;
} }
else else
{ {
@ -8627,6 +8631,9 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
#endif #endif
mobj->subsector->sector->ceilingheight; mobj->subsector->sector->ceilingheight;
mobj->floorrover = NULL;
mobj->ceilingrover = NULL;
// Tells MobjCheckWater that the water height was not set. // Tells MobjCheckWater that the water height was not set.
mobj->watertop = INT32_MAX; mobj->watertop = INT32_MAX;
@ -8890,6 +8897,9 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype
#endif #endif
mobj->subsector->sector->ceilingheight; mobj->subsector->sector->ceilingheight;
mobj->floorrover = NULL;
mobj->ceilingrover = NULL;
mobj->z = z; mobj->z = z;
mobj->momz = mobjinfo[type].speed; mobj->momz = mobjinfo[type].speed;

View file

@ -282,6 +282,8 @@ typedef struct mobj_s
// The closest interval over all contacted sectors (or things). // The closest interval over all contacted sectors (or things).
fixed_t floorz; // Nearest floor below. fixed_t floorz; // Nearest floor below.
fixed_t ceilingz; // Nearest ceiling above. fixed_t ceilingz; // Nearest ceiling above.
struct ffloor_s *floorrover; // FOF referred by floorz
struct ffloor_s *ceilingrover; // FOF referred by ceilingz
// For movement checking. // For movement checking.
fixed_t radius; fixed_t radius;
@ -398,6 +400,8 @@ typedef struct precipmobj_s
// The closest interval over all contacted sectors (or things). // The closest interval over all contacted sectors (or things).
fixed_t floorz; // Nearest floor below. fixed_t floorz; // Nearest floor below.
fixed_t ceilingz; // Nearest ceiling above. fixed_t ceilingz; // Nearest ceiling above.
struct ffloor_s *floorrover; // FOF referred by floorz
struct ffloor_s *ceilingrover; // FOF referred by ceilingz
// For movement checking. // For movement checking.
fixed_t radius; // Fixed at 2*FRACUNIT fixed_t radius; // Fixed at 2*FRACUNIT

View file

@ -985,6 +985,8 @@ static void Polyobj_pushThing(polyobj_t *po, line_t *line, mobj_t *mo)
P_CheckPosition(mo, mo->x + momx, mo->y + momy); P_CheckPosition(mo, mo->x + momx, mo->y + momy);
mo->floorz = tmfloorz; mo->floorz = tmfloorz;
mo->ceilingz = tmceilingz; mo->ceilingz = tmceilingz;
mo->floorrover = tmfloorrover;
mo->ceilingrover = tmceilingrover;
} }
} }
@ -2853,6 +2855,165 @@ INT32 EV_DoPolyObjFlag(line_t *pfdata)
return 1; return 1;
} }
void T_PolyObjFade(polyfade_t *th)
{
boolean stillfading = false;
polyobj_t *po = Polyobj_GetForNum(th->polyObjNum);
if (!po)
#ifdef RANGECHECK
I_Error("T_PolyObjFade: thinker has invalid id %d\n", th->polyObjNum);
#else
{
CONS_Debug(DBG_POLYOBJ, "T_PolyObjFade: thinker with invalid id %d removed.\n", th->polyObjNum);
P_RemoveThinkerDelayed(&th->thinker);
return;
}
#endif
// check for displacement due to override and reattach when possible
if (po->thinker == NULL)
po->thinker = &th->thinker;
stillfading = th->ticbased ? !(--(th->timer) <= 0)
: !((th->timer -= th->duration) <= 0);
if (th->timer <= 0)
{
po->translucency = max(min(th->destvalue, NUMTRANSMAPS), 0);
// remove thinker
if (po->thinker == &th->thinker)
po->thinker = NULL;
P_RemoveThinker(&th->thinker);
}
else
{
INT16 delta = abs(th->destvalue - th->sourcevalue);
INT32 duration = th->ticbased ? th->duration
: abs(FixedMul(FixedDiv(256, NUMTRANSMAPS), NUMTRANSMAPS - th->destvalue)
- FixedMul(FixedDiv(256, NUMTRANSMAPS), NUMTRANSMAPS - th->sourcevalue)); // speed-based internal counter duration: delta in 256 scale
fixed_t factor = min(FixedDiv(duration - th->timer, duration), 1*FRACUNIT);
if (th->destvalue < th->sourcevalue)
po->translucency = max(min(po->translucency, th->sourcevalue - (INT16)FixedMul(delta, factor)), th->destvalue);
else if (th->destvalue > th->sourcevalue)
po->translucency = min(max(po->translucency, th->sourcevalue + (INT16)FixedMul(delta, factor)), th->destvalue);
}
if (!stillfading)
{
// set render flags
if (po->translucency >= NUMTRANSMAPS) // invisible
po->flags &= ~POF_RENDERALL;
else
po->flags |= (po->spawnflags & POF_RENDERALL);
// set collision
if (th->docollision)
{
if (th->destvalue > th->sourcevalue) // faded out
{
po->flags &= ~POF_SOLID;
po->flags |= POF_NOSPECIALS;
}
else
{
po->flags |= (po->spawnflags & POF_SOLID);
if (!(po->spawnflags & POF_NOSPECIALS))
po->flags &= ~POF_NOSPECIALS;
}
}
}
else
{
if (po->translucency >= NUMTRANSMAPS)
// HACK: OpenGL renders fully opaque when >= NUMTRANSMAPS
po->translucency = NUMTRANSMAPS-1;
po->flags |= (po->spawnflags & POF_RENDERALL);
// set collision
if (th->docollision)
{
if (th->doghostfade)
{
po->flags &= ~POF_SOLID;
po->flags |= POF_NOSPECIALS;
}
else
{
po->flags |= (po->spawnflags & POF_SOLID);
if (!(po->spawnflags & POF_NOSPECIALS))
po->flags &= ~POF_NOSPECIALS;
}
}
}
}
INT32 EV_DoPolyObjFade(polyfadedata_t *pfdata)
{
polyobj_t *po;
polyobj_t *oldpo;
polyfade_t *th;
INT32 start;
if (!(po = Polyobj_GetForNum(pfdata->polyObjNum)))
{
CONS_Debug(DBG_POLYOBJ, "EV_DoPolyObjFade: bad polyobj %d\n", pfdata->polyObjNum);
return 0;
}
// don't allow line actions to affect bad polyobjects
if (po->isBad)
return 0;
// already equal, nothing to do
if (po->translucency == pfdata->destvalue)
return 1;
if (po->thinker && po->thinker->function.acp1 == (actionf_p1)T_PolyObjFade)
P_RemoveThinker(po->thinker);
// create a new thinker
th = Z_Malloc(sizeof(polyfade_t), PU_LEVSPEC, NULL);
th->thinker.function.acp1 = (actionf_p1)T_PolyObjFade;
PolyObj_AddThinker(&th->thinker);
po->thinker = &th->thinker;
// set fields
th->polyObjNum = pfdata->polyObjNum;
th->sourcevalue = po->translucency;
th->destvalue = pfdata->destvalue;
th->docollision = pfdata->docollision;
th->doghostfade = pfdata->doghostfade;
if (pfdata->ticbased)
{
th->ticbased = true;
th->timer = th->duration = abs(pfdata->speed); // pfdata->speed is duration
}
else
{
th->ticbased = false;
th->timer = abs(FixedMul(FixedDiv(256, NUMTRANSMAPS), NUMTRANSMAPS - th->destvalue)
- FixedMul(FixedDiv(256, NUMTRANSMAPS), NUMTRANSMAPS - th->sourcevalue)); // delta converted to 256 scale, use as internal counter
th->duration = abs(pfdata->speed); // use th->duration as speed decrement
}
oldpo = po;
// apply action to mirroring polyobjects as well
start = 0;
while ((po = Polyobj_GetChild(oldpo, &start)))
{
pfdata->polyObjNum = po->id;
EV_DoPolyObjFade(pfdata);
}
// action was successful
return 1;
}
#endif // ifdef POLYOBJECTS #endif // ifdef POLYOBJECTS
// EOF // EOF

View file

@ -207,6 +207,20 @@ typedef struct polydisplace_s
fixed_t oldHeights; fixed_t oldHeights;
} polydisplace_t; } polydisplace_t;
typedef struct polyfade_s
{
thinker_t thinker; // must be first
INT32 polyObjNum;
INT32 sourcevalue;
INT32 destvalue;
boolean docollision;
boolean doghostfade;
boolean ticbased;
INT32 duration;
INT32 timer;
} polyfade_t;
// //
// Line Activation Data Structures // Line Activation Data Structures
// //
@ -266,6 +280,16 @@ typedef struct polydisplacedata_s
fixed_t dy; fixed_t dy;
} polydisplacedata_t; } polydisplacedata_t;
typedef struct polyfadedata_s
{
INT32 polyObjNum;
INT32 destvalue;
boolean docollision;
boolean doghostfade;
boolean ticbased;
INT32 speed;
} polyfadedata_t;
// //
// Functions // Functions
// //
@ -287,6 +311,7 @@ void T_PolyDoorSlide(polyslidedoor_t *);
void T_PolyDoorSwing(polyswingdoor_t *); void T_PolyDoorSwing(polyswingdoor_t *);
void T_PolyObjDisplace (polydisplace_t *); void T_PolyObjDisplace (polydisplace_t *);
void T_PolyObjFlag (polymove_t *); void T_PolyObjFlag (polymove_t *);
void T_PolyObjFade (polyfade_t *);
INT32 EV_DoPolyDoor(polydoordata_t *); INT32 EV_DoPolyDoor(polydoordata_t *);
INT32 EV_DoPolyObjMove(polymovedata_t *); INT32 EV_DoPolyObjMove(polymovedata_t *);
@ -294,6 +319,7 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *);
INT32 EV_DoPolyObjRotate(polyrotdata_t *); INT32 EV_DoPolyObjRotate(polyrotdata_t *);
INT32 EV_DoPolyObjDisplace(polydisplacedata_t *); INT32 EV_DoPolyObjDisplace(polydisplacedata_t *);
INT32 EV_DoPolyObjFlag(struct line_s *); INT32 EV_DoPolyObjFlag(struct line_s *);
INT32 EV_DoPolyObjFade(polyfadedata_t *);
// //

View file

@ -21,6 +21,7 @@
#include "p_local.h" #include "p_local.h"
#include "p_setup.h" #include "p_setup.h"
#include "p_saveg.h" #include "p_saveg.h"
#include "r_data.h"
#include "r_things.h" #include "r_things.h"
#include "r_state.h" #include "r_state.h"
#include "w_wad.h" #include "w_wad.h"
@ -473,6 +474,243 @@ static void P_NetUnArchivePlayers(void)
} }
} }
///
/// Colormaps
///
static extracolormap_t *net_colormaps = NULL;
static UINT32 num_net_colormaps = 0;
static UINT32 num_ffloors = 0; // for loading
// Copypasta from r_data.c AddColormapToList
// But also check for equality and return the matching index
static UINT32 CheckAddNetColormapToList(extracolormap_t *extra_colormap)
{
extracolormap_t *exc, *exc_prev;
UINT32 i = 0;
if (!net_colormaps)
{
net_colormaps = R_CopyColormap(extra_colormap, false);
net_colormaps->next = 0;
net_colormaps->prev = 0;
num_net_colormaps = i+1;
return i;
}
for (exc = net_colormaps; exc; exc_prev = exc, exc = exc->next)
{
if (R_CheckEqualColormaps(exc, extra_colormap, true, true, true))
return i;
i++;
}
exc_prev->next = R_CopyColormap(extra_colormap, false);
extra_colormap->prev = exc_prev;
extra_colormap->next = 0;
num_net_colormaps = i+1;
return i;
}
static extracolormap_t *GetNetColormapFromList(UINT32 index)
{
// For loading, we have to be tricky:
// We load the sectors BEFORE knowing the colormap values
// So if an index doesn't exist, fill our list with dummy colormaps
// until we get the index we want
// Then when we load the color data, we set up the dummy colormaps
extracolormap_t *exc, *last_exc = NULL;
UINT32 i = 0;
if (!net_colormaps) // initialize our list
net_colormaps = R_CreateDefaultColormap(false);
for (exc = net_colormaps; exc; last_exc = exc, exc = exc->next)
{
if (i++ == index)
return exc;
}
// LET'S HOPE that index is a sane value, because we create up to [index]
// entries in net_colormaps. At this point, we don't know
// what the total colormap count is
if (index >= numsectors*3 + num_ffloors)
// if every sector had a unique colormap change AND a fade color thinker which has two colormap entries
// AND every ffloor had a fade FOF thinker with one colormap entry
I_Error("Colormap %d from server is too high for sectors %d", index, (UINT32)numsectors);
// our index doesn't exist, so just make the entry
for (; i <= index; i++)
{
exc = R_CreateDefaultColormap(false);
if (last_exc)
last_exc->next = exc;
exc->prev = last_exc;
exc->next = NULL;
last_exc = exc;
}
return exc;
}
static void ClearNetColormaps(void)
{
// We're actually Z_Freeing each entry here,
// so don't call this in P_NetUnArchiveColormaps (where entries will be used in-game)
extracolormap_t *exc, *exc_next;
for (exc = net_colormaps; exc; exc = exc_next)
{
exc_next = exc->next;
Z_Free(exc);
}
num_net_colormaps = 0;
num_ffloors = 0;
net_colormaps = NULL;
}
static void P_NetArchiveColormaps(void)
{
// We save and then we clean up our colormap mess
extracolormap_t *exc, *exc_next;
UINT32 i = 0;
WRITEUINT32(save_p, num_net_colormaps); // save for safety
for (exc = net_colormaps; i < num_net_colormaps; i++, exc = exc_next)
{
// We must save num_net_colormaps worth of data
// So fill non-existent entries with default.
if (!exc)
exc = R_CreateDefaultColormap(false);
WRITEUINT8(save_p, exc->fadestart);
WRITEUINT8(save_p, exc->fadeend);
WRITEUINT8(save_p, exc->fog);
WRITEINT32(save_p, exc->rgba);
WRITEINT32(save_p, exc->fadergba);
#ifdef EXTRACOLORMAPLUMPS
WRITESTRINGN(save_p, exc->lumpname, 9);
#endif
exc_next = exc->next;
Z_Free(exc); // don't need anymore
}
num_net_colormaps = 0;
num_ffloors = 0;
net_colormaps = NULL;
}
static void P_NetUnArchiveColormaps(void)
{
// When we reach this point, we already populated our list with
// dummy colormaps. Now that we are loading the color data,
// set up the dummies.
extracolormap_t *exc, *existing_exc, *exc_next = NULL;
UINT32 i = 0;
num_net_colormaps = READUINT32(save_p);
for (exc = net_colormaps; i < num_net_colormaps; i++, exc = exc_next)
{
UINT8 fadestart, fadeend, fog;
INT32 rgba, fadergba;
#ifdef EXTRACOLORMAPLUMPS
char lumpname[9];
#endif
fadestart = READUINT8(save_p);
fadeend = READUINT8(save_p);
fog = READUINT8(save_p);
rgba = READINT32(save_p);
fadergba = READINT32(save_p);
#ifdef EXTRACOLORMAPLUMPS
READSTRINGN(save_p, lumpname, 9);
if (lumpname[0])
{
if (!exc)
// no point making a new entry since nothing points to it,
// but we needed to read the data so now continue
continue;
exc_next = exc->next; // this gets overwritten during our operations here, so get it now
existing_exc = R_ColormapForName(lumpname);
*exc = *existing_exc;
R_AddColormapToList(exc); // see HACK note below on why we're adding duplicates
continue;
}
#endif
if (!exc)
// no point making a new entry since nothing points to it,
// but we needed to read the data so now continue
continue;
exc_next = exc->next; // this gets overwritten during our operations here, so get it now
exc->fadestart = fadestart;
exc->fadeend = fadeend;
exc->fog = fog;
exc->rgba = rgba;
exc->fadergba = fadergba;
#ifdef EXTRACOLORMAPLUMPS
exc->lump = LUMPERROR;
exc->lumpname[0] = 0;
#endif
existing_exc = R_GetColormapFromListByValues(rgba, fadergba, fadestart, fadeend, fog);
if (existing_exc)
exc->colormap = existing_exc->colormap;
else
// CONS_Debug(DBG_RENDER, "Creating Colormap: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n",
// R_GetRgbaR(rgba), R_GetRgbaG(rgba), R_GetRgbaB(rgba), R_GetRgbaA(rgba),
// R_GetRgbaR(fadergba), R_GetRgbaG(fadergba), R_GetRgbaB(fadergba), R_GetRgbaA(fadergba));
exc->colormap = R_CreateLightTable(exc);
// HACK: If this dummy is a duplicate, we're going to add it
// to the extra_colormaps list anyway. I think this is faster
// than going through every loaded sector and correcting their
// colormap address to the pre-existing one, PER net_colormap entry
R_AddColormapToList(exc);
if (i < num_net_colormaps-1 && !exc_next)
exc_next = R_CreateDefaultColormap(false);
}
// if we still have a valid net_colormap after iterating up to num_net_colormaps,
// some sector had a colormap index higher than num_net_colormaps. We done goofed or $$$ was corrupted.
// In any case, add them to the colormap list too so that at least the sectors' colormap
// addresses are valid and accounted properly
if (exc_next)
{
existing_exc = R_GetDefaultColormap();
for (exc = exc_next; exc; exc = exc->next)
{
exc->colormap = existing_exc->colormap; // all our dummies are default values
R_AddColormapToList(exc);
}
}
// Don't need these anymore
num_net_colormaps = 0;
num_ffloors = 0;
net_colormaps = NULL;
}
///
/// World Archiving
///
#define SD_FLOORHT 0x01 #define SD_FLOORHT 0x01
#define SD_CEILHT 0x02 #define SD_CEILHT 0x02
#define SD_FLOORPIC 0x04 #define SD_FLOORPIC 0x04
@ -494,7 +732,7 @@ static void P_NetUnArchivePlayers(void)
// diff3 flags // diff3 flags
#define SD_TAGLIST 0x01 #define SD_TAGLIST 0x01
#define SD_MIDMAP 0x02 #define SD_COLORMAP 0x02
#define LD_FLAG 0x01 #define LD_FLAG 0x01
#define LD_SPECIAL 0x02 #define LD_SPECIAL 0x02
@ -529,6 +767,9 @@ static void P_NetArchiveWorld(void)
const sector_t *ss = sectors; const sector_t *ss = sectors;
UINT8 diff, diff2, diff3; UINT8 diff, diff2, diff3;
// initialize colormap vars because paranoia
ClearNetColormaps();
WRITEUINT32(save_p, ARCHIVEBLOCK_WORLD); WRITEUINT32(save_p, ARCHIVEBLOCK_WORLD);
put = save_p; put = save_p;
@ -589,8 +830,9 @@ static void P_NetArchiveWorld(void)
diff2 |= SD_TAG; diff2 |= SD_TAG;
if (ss->nexttag != ss->spawn_nexttag || ss->firsttag != ss->spawn_firsttag) if (ss->nexttag != ss->spawn_nexttag || ss->firsttag != ss->spawn_firsttag)
diff3 |= SD_TAGLIST; diff3 |= SD_TAGLIST;
if (ss->midmap != ss->spawn_midmap)
diff3 |= SD_MIDMAP; if (ss->extra_colormap != ss->spawn_extra_colormap)
diff3 |= SD_COLORMAP;
// Check if any of the sector's FOFs differ from how they spawned // Check if any of the sector's FOFs differ from how they spawned
if (ss->ffloors) if (ss->ffloors)
@ -654,8 +896,10 @@ static void P_NetArchiveWorld(void)
WRITEINT32(put, ss->firsttag); WRITEINT32(put, ss->firsttag);
WRITEINT32(put, ss->nexttag); WRITEINT32(put, ss->nexttag);
} }
if (diff3 & SD_MIDMAP)
WRITEINT32(put, ss->midmap); if (diff3 & SD_COLORMAP)
WRITEUINT32(put, CheckAddNetColormapToList(ss->extra_colormap));
// returns existing index if already added, or appends to net_colormaps and returns new index
// Special case: save the stats of all modified ffloors along with their ffloor "number"s // Special case: save the stats of all modified ffloors along with their ffloor "number"s
// we don't bother with ffloors that haven't changed, that would just add to savegame even more than is really needed // we don't bother with ffloors that haven't changed, that would just add to savegame even more than is really needed
@ -790,6 +1034,17 @@ static void P_NetUnArchiveWorld(void)
if (READUINT32(save_p) != ARCHIVEBLOCK_WORLD) if (READUINT32(save_p) != ARCHIVEBLOCK_WORLD)
I_Error("Bad $$$.sav at archive block World"); I_Error("Bad $$$.sav at archive block World");
// initialize colormap vars because paranoia
ClearNetColormaps();
// count the level's ffloors so that colormap loading can have an upper limit
for (i = 0; i < numsectors; i++)
{
ffloor_t *rover;
for (rover = sectors[i].ffloors; rover; rover = rover->next)
num_ffloors++;
}
get = save_p; get = save_p;
for (;;) for (;;)
@ -850,8 +1105,9 @@ static void P_NetUnArchiveWorld(void)
sectors[i].firsttag = READINT32(get); sectors[i].firsttag = READINT32(get);
sectors[i].nexttag = READINT32(get); sectors[i].nexttag = READINT32(get);
} }
if (diff3 & SD_MIDMAP)
sectors[i].midmap = READINT32(get); if (diff3 & SD_COLORMAP)
sectors[i].extra_colormap = GetNetColormapFromList(READUINT32(get));
if (diff & SD_FFLOORS) if (diff & SD_FFLOORS)
{ {
@ -994,11 +1250,13 @@ typedef enum
MD2_EXTVAL1 = 1<<5, MD2_EXTVAL1 = 1<<5,
MD2_EXTVAL2 = 1<<6, MD2_EXTVAL2 = 1<<6,
MD2_HNEXT = 1<<7, MD2_HNEXT = 1<<7,
#ifdef ESLOPE
MD2_HPREV = 1<<8, MD2_HPREV = 1<<8,
MD2_SLOPE = 1<<9 MD2_FLOORROVER = 1<<9,
#ifdef ESLOPE
MD2_CEILINGROVER = 1<<10,
MD2_SLOPE = 1<<11
#else #else
MD2_HPREV = 1<<8 MD2_CEILINGROVER = 1<<10
#endif #endif
} mobj_diff2_t; } mobj_diff2_t;
@ -1018,6 +1276,7 @@ typedef enum
tc_bouncecheese, tc_bouncecheese,
tc_startcrumble, tc_startcrumble,
tc_marioblock, tc_marioblock,
tc_marioblockchecker,
tc_spikesector, tc_spikesector,
tc_floatsector, tc_floatsector,
tc_bridgethinker, tc_bridgethinker,
@ -1032,6 +1291,7 @@ typedef enum
tc_noenemies, tc_noenemies,
tc_eachtime, tc_eachtime,
tc_disappear, tc_disappear,
tc_fadecolormap,
tc_planedisplace, tc_planedisplace,
#ifdef POLYOBJECTS #ifdef POLYOBJECTS
tc_polyrotate, // haleyjd 03/26/06: polyobjects tc_polyrotate, // haleyjd 03/26/06: polyobjects
@ -1041,6 +1301,7 @@ typedef enum
tc_polyswingdoor, tc_polyswingdoor,
tc_polyflag, tc_polyflag,
tc_polydisplace, tc_polydisplace,
tc_polyfade,
#endif #endif
tc_end tc_end
} specials_e; } specials_e;
@ -1192,6 +1453,10 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
diff2 |= MD2_HNEXT; diff2 |= MD2_HNEXT;
if (mobj->hprev) if (mobj->hprev)
diff2 |= MD2_HPREV; diff2 |= MD2_HPREV;
if (mobj->floorrover)
diff2 |= MD2_FLOORROVER;
if (mobj->ceilingrover)
diff2 |= MD2_CEILINGROVER;
#ifdef ESLOPE #ifdef ESLOPE
if (mobj->standingslope) if (mobj->standingslope)
diff2 |= MD2_SLOPE; diff2 |= MD2_SLOPE;
@ -1215,6 +1480,46 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
WRITEFIXED(save_p, mobj->floorz); WRITEFIXED(save_p, mobj->floorz);
WRITEFIXED(save_p, mobj->ceilingz); WRITEFIXED(save_p, mobj->ceilingz);
if (diff2 & MD2_FLOORROVER)
{
ffloor_t *rover;
size_t i = 0;
UINT32 roverindex = 0;
for (rover = mobj->floorrover->target->ffloors; rover; rover = rover->next)
{
if (rover == mobj->floorrover)
{
roverindex = i;
break;
}
i++;
}
WRITEUINT32(save_p, (UINT32)(mobj->floorrover->target - sectors));
WRITEUINT32(save_p, rover ? roverindex : i); // store max index to denote invalid ffloor ref
}
if (diff2 & MD2_CEILINGROVER)
{
ffloor_t *rover;
size_t i = 0;
UINT32 roverindex = 0;
for (rover = mobj->ceilingrover->target->ffloors; rover; rover = rover->next)
{
if (rover == mobj->ceilingrover)
{
roverindex = i;
break;
}
i++;
}
WRITEUINT32(save_p, (UINT32)(mobj->ceilingrover->target - sectors));
WRITEUINT32(save_p, rover ? roverindex : i); // store max index to denote invalid ffloor ref
}
if (diff & MD_SPAWNPOINT) if (diff & MD_SPAWNPOINT)
{ {
size_t z; size_t z;
@ -1333,7 +1638,10 @@ static void SaveSpecialLevelThinker(const thinker_t *th, const UINT8 type)
size_t i; size_t i;
WRITEUINT8(save_p, type); WRITEUINT8(save_p, type);
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)
{
WRITEFIXED(save_p, ht->vars[i]); //var[16] WRITEFIXED(save_p, ht->vars[i]); //var[16]
WRITEFIXED(save_p, ht->var2s[i]); //var[16]
}
WRITEUINT32(save_p, SaveLine(ht->sourceline)); WRITEUINT32(save_p, SaveLine(ht->sourceline));
WRITEUINT32(save_p, SaveSector(ht->sector)); WRITEUINT32(save_p, SaveSector(ht->sector));
} }
@ -1559,8 +1867,11 @@ static void SaveLightlevelThinker(const thinker_t *th, const UINT8 type)
const lightlevel_t *ht = (const void *)th; const lightlevel_t *ht = (const void *)th;
WRITEUINT8(save_p, type); WRITEUINT8(save_p, type);
WRITEUINT32(save_p, SaveSector(ht->sector)); WRITEUINT32(save_p, SaveSector(ht->sector));
WRITEINT32(save_p, ht->destlevel); WRITEINT16(save_p, ht->sourcelevel);
WRITEINT32(save_p, ht->speed); WRITEINT16(save_p, ht->destlevel);
WRITEFIXED(save_p, ht->fixedcurlevel);
WRITEFIXED(save_p, ht->fixedpertic);
WRITEINT32(save_p, ht->timer);
} }
// //
@ -1596,6 +1907,23 @@ static void SaveDisappearThinker(const thinker_t *th, const UINT8 type)
WRITEINT32(save_p, ht->exists); WRITEINT32(save_p, ht->exists);
} }
//
// SaveFadeColormapThinker
//
// Saves a fadecolormap_t thinker
//
static void SaveFadeColormapThinker(const thinker_t *th, const UINT8 type)
{
const fadecolormap_t *ht = (const void *)th;
WRITEUINT8(save_p, type);
WRITEUINT32(save_p, SaveSector(ht->sector));
WRITEUINT32(save_p, CheckAddNetColormapToList(ht->source_exc));
WRITEUINT32(save_p, CheckAddNetColormapToList(ht->dest_exc));
WRITEUINT8(save_p, (UINT8)ht->ticbased);
WRITEINT32(save_p, ht->duration);
WRITEINT32(save_p, ht->timer);
}
// //
// SavePlaneDisplaceThinker // SavePlaneDisplaceThinker
// //
@ -1721,6 +2049,20 @@ static void SavePolydisplaceThinker(const thinker_t *th, const UINT8 type)
WRITEFIXED(save_p, ht->oldHeights); WRITEFIXED(save_p, ht->oldHeights);
} }
static void SavePolyfadeThinker(const thinker_t *th, const UINT8 type)
{
const polyfade_t *ht = (const void *)th;
WRITEUINT8(save_p, type);
WRITEINT32(save_p, ht->polyObjNum);
WRITEINT32(save_p, ht->sourcevalue);
WRITEINT32(save_p, ht->destvalue);
WRITEUINT8(save_p, (UINT8)ht->docollision);
WRITEUINT8(save_p, (UINT8)ht->doghostfade);
WRITEUINT8(save_p, (UINT8)ht->ticbased);
WRITEINT32(save_p, ht->duration);
WRITEINT32(save_p, ht->timer);
}
#endif #endif
/* /*
// //
@ -1863,6 +2205,11 @@ static void P_NetArchiveThinkers(void)
SaveSpecialLevelThinker(th, tc_marioblock); SaveSpecialLevelThinker(th, tc_marioblock);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_MarioBlockChecker)
{
SaveSpecialLevelThinker(th, tc_marioblockchecker);
continue;
}
else if (th->function.acp1 == (actionf_p1)T_SpikeSector) else if (th->function.acp1 == (actionf_p1)T_SpikeSector)
{ {
SaveSpecialLevelThinker(th, tc_spikesector); SaveSpecialLevelThinker(th, tc_spikesector);
@ -1898,6 +2245,11 @@ static void P_NetArchiveThinkers(void)
SaveDisappearThinker(th, tc_disappear); SaveDisappearThinker(th, tc_disappear);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_FadeColormap)
{
SaveFadeColormapThinker(th, tc_fadecolormap);
continue;
}
else if (th->function.acp1 == (actionf_p1)T_PlaneDisplace) else if (th->function.acp1 == (actionf_p1)T_PlaneDisplace)
{ {
@ -1940,6 +2292,11 @@ static void P_NetArchiveThinkers(void)
SavePolydisplaceThinker(th, tc_polydisplace); SavePolydisplaceThinker(th, tc_polydisplace);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_PolyObjFade)
{
SavePolyfadeThinker(th, tc_polyfade);
continue;
}
#endif #endif
#ifdef PARANOIA #ifdef PARANOIA
else if (th->function.acv != P_RemoveThinkerDelayed) // wait garbage collection else if (th->function.acv != P_RemoveThinkerDelayed) // wait garbage collection
@ -2011,6 +2368,7 @@ static void LoadMobjThinker(actionf_p1 thinker)
UINT16 diff2; UINT16 diff2;
INT32 i; INT32 i;
fixed_t z, floorz, ceilingz; fixed_t z, floorz, ceilingz;
ffloor_t *floorrover = NULL, *ceilingrover = NULL;
diff = READUINT32(save_p); diff = READUINT32(save_p);
if (diff & MD_MORE) if (diff & MD_MORE)
@ -2024,6 +2382,38 @@ static void LoadMobjThinker(actionf_p1 thinker)
floorz = READFIXED(save_p); floorz = READFIXED(save_p);
ceilingz = READFIXED(save_p); ceilingz = READFIXED(save_p);
if (diff2 & MD2_FLOORROVER)
{
size_t floor_sectornum = (size_t)READUINT32(save_p);
size_t floor_rovernum = (size_t)READUINT32(save_p);
ffloor_t *rover = NULL;
size_t rovernum = 0;
for (rover = sectors[floor_sectornum].ffloors; rover; rover = rover->next)
{
if (rovernum == floor_rovernum)
break;
rovernum++;
}
floorrover = rover;
}
if (diff2 & MD2_CEILINGROVER)
{
size_t ceiling_sectornum = (size_t)READUINT32(save_p);
size_t ceiling_rovernum = (size_t)READUINT32(save_p);
ffloor_t *rover = NULL;
size_t rovernum = 0;
for (rover = sectors[ceiling_sectornum].ffloors; rover; rover = rover->next)
{
if (rovernum == ceiling_rovernum)
break;
rovernum++;
}
ceilingrover = rover;
}
if (diff & MD_SPAWNPOINT) if (diff & MD_SPAWNPOINT)
{ {
UINT16 spawnpointnum = READUINT16(save_p); UINT16 spawnpointnum = READUINT16(save_p);
@ -2048,6 +2438,8 @@ static void LoadMobjThinker(actionf_p1 thinker)
mobj->z = z; mobj->z = z;
mobj->floorz = floorz; mobj->floorz = floorz;
mobj->ceilingz = ceilingz; mobj->ceilingz = ceilingz;
mobj->floorrover = floorrover;
mobj->ceilingrover = ceilingrover;
if (diff & MD_TYPE) if (diff & MD_TYPE)
mobj->type = READUINT32(save_p); mobj->type = READUINT32(save_p);
@ -2258,7 +2650,10 @@ static void LoadSpecialLevelThinker(actionf_p1 thinker, UINT8 floorOrCeiling)
size_t i; size_t i;
ht->thinker.function.acp1 = thinker; ht->thinker.function.acp1 = thinker;
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)
{
ht->vars[i] = READFIXED(save_p); //var[16] ht->vars[i] = READFIXED(save_p); //var[16]
ht->var2s[i] = READFIXED(save_p); //var[16]
}
ht->sourceline = LoadLine(READUINT32(save_p)); ht->sourceline = LoadLine(READUINT32(save_p));
ht->sector = LoadSector(READUINT32(save_p)); ht->sector = LoadSector(READUINT32(save_p));
@ -2532,8 +2927,11 @@ static inline void LoadLightlevelThinker(actionf_p1 thinker)
lightlevel_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); lightlevel_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker; ht->thinker.function.acp1 = thinker;
ht->sector = LoadSector(READUINT32(save_p)); ht->sector = LoadSector(READUINT32(save_p));
ht->destlevel = READINT32(save_p); ht->sourcelevel = READINT16(save_p);
ht->speed = READINT32(save_p); ht->destlevel = READINT16(save_p);
ht->fixedcurlevel = READFIXED(save_p);
ht->fixedpertic = READFIXED(save_p);
ht->timer = READINT32(save_p);
if (ht->sector) if (ht->sector)
ht->sector->lightingdata = ht; ht->sector->lightingdata = ht;
P_AddThinker(&ht->thinker); P_AddThinker(&ht->thinker);
@ -2574,6 +2972,26 @@ static inline void LoadDisappearThinker(actionf_p1 thinker)
P_AddThinker(&ht->thinker); P_AddThinker(&ht->thinker);
} }
//
// LoadFadeColormapThinker
//
// Loads a fadecolormap_t from a save game
//
static inline void LoadFadeColormapThinker(actionf_p1 thinker)
{
fadecolormap_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker;
ht->sector = LoadSector(READUINT32(save_p));
ht->source_exc = GetNetColormapFromList(READUINT32(save_p));
ht->dest_exc = GetNetColormapFromList(READUINT32(save_p));
ht->ticbased = (boolean)READUINT8(save_p);
ht->duration = READINT32(save_p);
ht->timer = READINT32(save_p);
if (ht->sector)
ht->sector->fadecolormapdata = ht;
P_AddThinker(&ht->thinker);
}
// //
// LoadPlaneDisplaceThinker // LoadPlaneDisplaceThinker
// //
@ -2711,6 +3129,26 @@ static inline void LoadPolydisplaceThinker(actionf_p1 thinker)
ht->oldHeights = READFIXED(save_p); ht->oldHeights = READFIXED(save_p);
P_AddThinker(&ht->thinker); P_AddThinker(&ht->thinker);
} }
//
// LoadPolyfadeThinker
//
// Loads a polyfadet_t thinker
//
static void LoadPolyfadeThinker(actionf_p1 thinker)
{
polyfade_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker;
ht->polyObjNum = READINT32(save_p);
ht->sourcevalue = READINT32(save_p);
ht->destvalue = READINT32(save_p);
ht->docollision = (boolean)READUINT8(save_p);
ht->doghostfade = (boolean)READUINT8(save_p);
ht->ticbased = (boolean)READUINT8(save_p);
ht->duration = READINT32(save_p);
ht->timer = READINT32(save_p);
P_AddThinker(&ht->thinker);
}
#endif #endif
/* /*
@ -2760,7 +3198,7 @@ static void P_NetUnArchiveThinkers(void)
// clear sector thinker pointers so they don't point to non-existant thinkers for all of eternity // clear sector thinker pointers so they don't point to non-existant thinkers for all of eternity
for (i = 0; i < numsectors; i++) for (i = 0; i < numsectors; i++)
{ {
sectors[i].floordata = sectors[i].ceilingdata = sectors[i].lightingdata = NULL; sectors[i].floordata = sectors[i].ceilingdata = sectors[i].lightingdata = sectors[i].fadecolormapdata = NULL;
} }
// read in saved thinkers // read in saved thinkers
@ -2848,6 +3286,10 @@ static void P_NetUnArchiveThinkers(void)
LoadSpecialLevelThinker((actionf_p1)T_MarioBlock, 3); LoadSpecialLevelThinker((actionf_p1)T_MarioBlock, 3);
break; break;
case tc_marioblockchecker:
LoadSpecialLevelThinker((actionf_p1)T_MarioBlockChecker, 0);
break;
case tc_spikesector: case tc_spikesector:
LoadSpecialLevelThinker((actionf_p1)T_SpikeSector, 0); LoadSpecialLevelThinker((actionf_p1)T_SpikeSector, 0);
break; break;
@ -2877,6 +3319,10 @@ static void P_NetUnArchiveThinkers(void)
LoadDisappearThinker((actionf_p1)T_Disappear); LoadDisappearThinker((actionf_p1)T_Disappear);
break; break;
case tc_fadecolormap:
LoadFadeColormapThinker((actionf_p1)T_FadeColormap);
break;
case tc_planedisplace: case tc_planedisplace:
LoadPlaneDisplaceThinker((actionf_p1)T_PlaneDisplace); LoadPlaneDisplaceThinker((actionf_p1)T_PlaneDisplace);
break; break;
@ -2908,6 +3354,10 @@ static void P_NetUnArchiveThinkers(void)
case tc_polydisplace: case tc_polydisplace:
LoadPolydisplaceThinker((actionf_p1)T_PolyObjDisplace); LoadPolydisplaceThinker((actionf_p1)T_PolyObjDisplace);
break; break;
case tc_polyfade:
LoadPolyfadeThinker((actionf_p1)T_PolyObjFade);
break;
#endif #endif
case tc_scroll: case tc_scroll:
LoadScrollThinker((actionf_p1)T_Scroll); LoadScrollThinker((actionf_p1)T_Scroll);
@ -3460,6 +3910,7 @@ void P_SaveNetGame(void)
#endif #endif
P_NetArchiveThinkers(); P_NetArchiveThinkers();
P_NetArchiveSpecials(); P_NetArchiveSpecials();
P_NetArchiveColormaps();
} }
#ifdef HAVE_BLUA #ifdef HAVE_BLUA
LUA_Archive(); LUA_Archive();
@ -3502,6 +3953,7 @@ boolean P_LoadNetGame(void)
#endif #endif
P_NetUnArchiveThinkers(); P_NetUnArchiveThinkers();
P_NetUnArchiveSpecials(); P_NetUnArchiveSpecials();
P_NetUnArchiveColormaps();
P_RelinkPointers(); P_RelinkPointers();
P_FinishMobjs(); P_FinishMobjs();
} }

View file

@ -718,13 +718,12 @@ static void P_LoadRawSectors(UINT8 *data, size_t i)
ss->moved = true; ss->moved = true;
ss->extra_colormap = NULL; ss->extra_colormap = NULL;
ss->spawn_extra_colormap = NULL;
ss->floor_xoffs = ss->ceiling_xoffs = ss->floor_yoffs = ss->ceiling_yoffs = 0; ss->floor_xoffs = ss->ceiling_xoffs = ss->floor_yoffs = ss->ceiling_yoffs = 0;
ss->spawn_flr_xoffs = ss->spawn_ceil_xoffs = ss->spawn_flr_yoffs = ss->spawn_ceil_yoffs = 0; ss->spawn_flr_xoffs = ss->spawn_ceil_xoffs = ss->spawn_flr_yoffs = ss->spawn_ceil_yoffs = 0;
ss->floorpic_angle = ss->ceilingpic_angle = 0; ss->floorpic_angle = ss->ceilingpic_angle = 0;
ss->spawn_flrpic_angle = ss->spawn_ceilpic_angle = 0; ss->spawn_flrpic_angle = ss->spawn_ceilpic_angle = 0;
ss->bottommap = ss->midmap = ss->topmap = -1;
ss->spawn_bottommap = ss->spawn_midmap = ss->spawn_topmap = -1;
ss->gravity = NULL; ss->gravity = NULL;
ss->cullheight = NULL; ss->cullheight = NULL;
ss->verticalflip = false; ss->verticalflip = false;
@ -1337,7 +1336,8 @@ static void P_LoadLineDefs2(void)
ld->backsector = ld->sidenum[1] != 0xffff ? sides[ld->sidenum[1]].sector : 0; ld->backsector = ld->sidenum[1] != 0xffff ? sides[ld->sidenum[1]].sector : 0;
// Repeat count for midtexture // Repeat count for midtexture
if ((ld->flags & ML_EFFECT5) && (ld->sidenum[1] != 0xffff)) if ((ld->flags & ML_EFFECT5) && (ld->sidenum[1] != 0xffff)
&& !(ld->special >= 300 && ld->special < 500)) // exempt linedef exec specials
{ {
sides[ld->sidenum[0]].repeatcnt = (INT16)(((unsigned)sides[ld->sidenum[0]].textureoffset >> FRACBITS) >> 12); sides[ld->sidenum[0]].repeatcnt = (INT16)(((unsigned)sides[ld->sidenum[0]].textureoffset >> FRACBITS) >> 12);
sides[ld->sidenum[0]].textureoffset = (((unsigned)sides[ld->sidenum[0]].textureoffset >> FRACBITS) & 2047) << FRACBITS; sides[ld->sidenum[0]].textureoffset = (((unsigned)sides[ld->sidenum[0]].textureoffset >> FRACBITS) & 2047) << FRACBITS;
@ -1444,7 +1444,6 @@ static inline void P_LoadSideDefs(lumpnum_t lumpnum)
static void P_LoadRawSideDefs2(void *data) static void P_LoadRawSideDefs2(void *data)
{ {
UINT16 i; UINT16 i;
INT32 num;
for (i = 0; i < numsides; i++) for (i = 0; i < numsides; i++)
{ {
@ -1466,118 +1465,23 @@ static void P_LoadRawSideDefs2(void *data)
sd->sector = sec = &sectors[sector_num]; sd->sector = sec = &sectors[sector_num];
} }
// refined to allow colormaps to work as wall textures if invalid as colormaps
// but valid as textures.
sd->sector = sec = &sectors[SHORT(msd->sector)]; sd->sector = sec = &sectors[SHORT(msd->sector)];
sd->colormap_data = NULL;
// Colormaps! // Colormaps!
switch (sd->special) switch (sd->special)
{ {
case 63: // variable colormap via 242 linedef case 63: // variable colormap via 242 linedef
case 606: //SoM: 4/4/2000: Just colormap transfer case 606: //SoM: 4/4/2000: Just colormap transfer
case 447: // Change colormap of tagged sectors! -- Monster Iestyn 14/06/18 case 447: // Change colormap of tagged sectors! -- Monster Iestyn 14/06/18
case 455: // Fade colormaps! mazmazz 9/12/2018 (:flag_us:)
// SoM: R_CreateColormap will only create a colormap in software mode... // SoM: R_CreateColormap will only create a colormap in software mode...
// Perhaps we should just call it instead of doing the calculations here. // Perhaps we should just call it instead of doing the calculations here.
if (rendermode == render_soft || rendermode == render_none) sd->colormap_data = R_CreateColormap(msd->toptexture, msd->midtexture,
{ msd->bottomtexture);
if (msd->toptexture[0] == '#' || msd->bottomtexture[0] == '#') sd->toptexture = sd->midtexture = sd->bottomtexture = 0;
{ break;
sec->midmap = sec->spawn_midmap = R_CreateColormap(msd->toptexture, msd->midtexture,
msd->bottomtexture);
sd->toptexture = sd->bottomtexture = 0;
}
else
{
if ((num = R_CheckTextureNumForName(msd->toptexture)) == -1)
sd->toptexture = 0;
else
sd->toptexture = num;
if ((num = R_CheckTextureNumForName(msd->midtexture)) == -1)
sd->midtexture = 0;
else
sd->midtexture = num;
if ((num = R_CheckTextureNumForName(msd->bottomtexture)) == -1)
sd->bottomtexture = 0;
else
sd->bottomtexture = num;
}
break;
}
#ifdef HWRENDER
else
{
// for now, full support of toptexture only
if ((msd->toptexture[0] == '#' && msd->toptexture[1] && msd->toptexture[2] && msd->toptexture[3] && msd->toptexture[4] && msd->toptexture[5] && msd->toptexture[6])
|| (msd->bottomtexture[0] == '#' && msd->bottomtexture[1] && msd->bottomtexture[2] && msd->bottomtexture[3] && msd->bottomtexture[4] && msd->bottomtexture[5] && msd->bottomtexture[6]))
{
char *col;
sec->midmap = sec->spawn_midmap = R_CreateColormap(msd->toptexture, msd->midtexture,
msd->bottomtexture);
sd->toptexture = sd->bottomtexture = 0;
#define HEX2INT(x) (x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0)
#define ALPHA2INT(x) (x >= 'a' && x <= 'z' ? x - 'a' : x >= 'A' && x <= 'Z' ? x - 'A' : x >= '0' && x <= '9' ? 25 : 0)
sec->extra_colormap = &extra_colormaps[sec->midmap];
if (msd->toptexture[0] == '#' && msd->toptexture[1] && msd->toptexture[2] && msd->toptexture[3] && msd->toptexture[4] && msd->toptexture[5] && msd->toptexture[6])
{
col = msd->toptexture;
sec->extra_colormap->rgba =
(HEX2INT(col[1]) << 4) + (HEX2INT(col[2]) << 0) +
(HEX2INT(col[3]) << 12) + (HEX2INT(col[4]) << 8) +
(HEX2INT(col[5]) << 20) + (HEX2INT(col[6]) << 16);
// alpha
if (msd->toptexture[7])
sec->extra_colormap->rgba += (ALPHA2INT(col[7]) << 24);
else
sec->extra_colormap->rgba += (25 << 24);
}
else
sec->extra_colormap->rgba = 0;
if (msd->bottomtexture[0] == '#' && msd->bottomtexture[1] && msd->bottomtexture[2] && msd->bottomtexture[3] && msd->bottomtexture[4] && msd->bottomtexture[5] && msd->bottomtexture[6])
{
col = msd->bottomtexture;
sec->extra_colormap->fadergba =
(HEX2INT(col[1]) << 4) + (HEX2INT(col[2]) << 0) +
(HEX2INT(col[3]) << 12) + (HEX2INT(col[4]) << 8) +
(HEX2INT(col[5]) << 20) + (HEX2INT(col[6]) << 16);
// alpha
if (msd->bottomtexture[7])
sec->extra_colormap->fadergba += (ALPHA2INT(col[7]) << 24);
else
sec->extra_colormap->fadergba += (25 << 24);
}
else
sec->extra_colormap->fadergba = 0x19000000; // default alpha, (25 << 24)
#undef ALPHA2INT
#undef HEX2INT
}
else
{
if ((num = R_CheckTextureNumForName(msd->toptexture)) == -1)
sd->toptexture = 0;
else
sd->toptexture = num;
if ((num = R_CheckTextureNumForName(msd->midtexture)) == -1)
sd->midtexture = 0;
else
sd->midtexture = num;
if ((num = R_CheckTextureNumForName(msd->bottomtexture)) == -1)
sd->bottomtexture = 0;
else
sd->bottomtexture = num;
}
break;
}
#endif
case 413: // Change music case 413: // Change music
{ {

View file

@ -103,6 +103,9 @@ static void P_SpawnFriction(void);
static void P_SpawnPushers(void); static void P_SpawnPushers(void);
static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, mobj_t *source, INT32 affectee, INT32 referrer, INT32 exclusive, INT32 slider); //SoM: 3/9/2000 static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, mobj_t *source, INT32 affectee, INT32 referrer, INT32 exclusive, INT32 slider); //SoM: 3/9/2000
static void Add_MasterDisappearer(tic_t appeartime, tic_t disappeartime, tic_t offset, INT32 line, INT32 sourceline); static void Add_MasterDisappearer(tic_t appeartime, tic_t disappeartime, tic_t offset, INT32 line, INT32 sourceline);
static void P_ResetColormapFader(sector_t *sector);
static void Add_ColormapFader(sector_t *sector, extracolormap_t *source_exc, extracolormap_t *dest_exc,
boolean ticbased, INT32 duration);
static void P_AddBlockThinker(sector_t *sec, line_t *sourceline); static void P_AddBlockThinker(sector_t *sec, line_t *sourceline);
static void P_AddFloatThinker(sector_t *sec, INT32 tag, line_t *sourceline); static void P_AddFloatThinker(sector_t *sec, INT32 tag, line_t *sourceline);
//static void P_AddBridgeThinker(line_t *sourceline, sector_t *sec); //static void P_AddBridgeThinker(line_t *sourceline, sector_t *sec);
@ -1218,7 +1221,7 @@ static void PolyVisible(line_t *line)
po->flags |= POF_SOLID; po->flags |= POF_SOLID;
po->flags &= ~POF_NOSPECIALS; po->flags &= ~POF_NOSPECIALS;
po->flags |= POF_RENDERALL; po->flags |= (po->spawnflags & POF_RENDERALL);
} }
// //
@ -1242,7 +1245,94 @@ static void PolyTranslucency(line_t *line)
if (po->isBad) if (po->isBad)
return; return;
po->translucency = (line->frontsector->floorheight >> FRACBITS) / 100; // if DONTPEGBOTTOM, specify raw translucency value in Front X Offset
// else, take it out of 1000. If Front X Offset is specified, use that. Else, use floorheight.
if (line->flags & ML_EFFECT3) // relative calc
po->translucency = max(min(po->translucency + ((line->flags & ML_DONTPEGBOTTOM) ?
(sides[line->sidenum[0]].textureoffset ?
max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, NUMTRANSMAPS), -NUMTRANSMAPS)
: max(min(line->frontsector->floorheight>>FRACBITS, NUMTRANSMAPS), -NUMTRANSMAPS))
: (sides[line->sidenum[0]].textureoffset ?
max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, 1000), -1000) / 100
: max(min(line->frontsector->floorheight>>FRACBITS, 1000), -1000) / 100)),
NUMTRANSMAPS), 0);
else
po->translucency = (line->flags & ML_DONTPEGBOTTOM) ?
(sides[line->sidenum[0]].textureoffset ?
max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, NUMTRANSMAPS), 0)
: max(min(line->frontsector->floorheight>>FRACBITS, NUMTRANSMAPS), 0))
: (sides[line->sidenum[0]].textureoffset ?
max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, 1000), 0) / 100
: max(min(line->frontsector->floorheight>>FRACBITS, 1000), 0) / 100);
}
//
// PolyFade
//
// Makes a polyobject translucency fade and applies tangibility
//
static boolean PolyFade(line_t *line)
{
INT32 polyObjNum = line->tag;
polyobj_t *po;
polyfadedata_t pfd;
if (!(po = Polyobj_GetForNum(polyObjNum)))
{
CONS_Debug(DBG_POLYOBJ, "PolyFade: bad polyobj %d\n", polyObjNum);
return 0;
}
// don't allow line actions to affect bad polyobjects
if (po->isBad)
return 0;
// Prevent continuous execs from interfering on an existing fade
if (!(line->flags & ML_EFFECT5)
&& po->thinker
&& po->thinker->function.acp1 == (actionf_p1)T_PolyObjFade)
{
CONS_Debug(DBG_POLYOBJ, "Line type 492 Executor: Fade PolyObject thinker already exists\n");
return 0;
}
pfd.polyObjNum = polyObjNum;
// if DONTPEGBOTTOM, specify raw translucency value in Front X Offset
// else, take it out of 1000. If Front X Offset is specified, use that. Else, use floorheight.
if (line->flags & ML_EFFECT3) // relative calc
pfd.destvalue = max(min(po->translucency + ((line->flags & ML_DONTPEGBOTTOM) ?
(sides[line->sidenum[0]].textureoffset ?
max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, NUMTRANSMAPS), -NUMTRANSMAPS)
: max(min(line->frontsector->floorheight>>FRACBITS, NUMTRANSMAPS), -NUMTRANSMAPS))
: (sides[line->sidenum[0]].textureoffset ?
max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, 1000), -1000) / 100
: max(min(line->frontsector->floorheight>>FRACBITS, 1000), -1000) / 100)),
NUMTRANSMAPS), 0);
else
pfd.destvalue = (line->flags & ML_DONTPEGBOTTOM) ?
(sides[line->sidenum[0]].textureoffset ?
max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, NUMTRANSMAPS), 0)
: max(min(line->frontsector->floorheight>>FRACBITS, NUMTRANSMAPS), 0))
: (sides[line->sidenum[0]].textureoffset ?
max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, 1000), 0) / 100
: max(min(line->frontsector->floorheight>>FRACBITS, 1000), 0) / 100);
// already equal, nothing to do
if (po->translucency == pfd.destvalue)
return 1;
pfd.docollision = !(line->flags & ML_BOUNCY); // do not handle collision flags
pfd.doghostfade = (line->flags & ML_EFFECT1); // do ghost fade (no collision flags during fade)
pfd.ticbased = (line->flags & ML_EFFECT4); // Speed = Tic Duration
// allow Back Y Offset to be consistent with other fade specials
pfd.speed = (line->sidenum[1] != 0xFFFF && !sides[line->sidenum[0]].rowoffset) ?
abs(sides[line->sidenum[1]].rowoffset>>FRACBITS)
: abs(sides[line->sidenum[0]].rowoffset>>FRACBITS);
return EV_DoPolyObjFade(&pfd);
} }
// //
@ -2780,7 +2870,17 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
break; break;
case 420: // Fade light levels in tagged sectors to new value case 420: // Fade light levels in tagged sectors to new value
P_FadeLight(line->tag, line->frontsector->lightlevel, P_AproxDistance(line->dx, line->dy)>>FRACBITS); P_FadeLight(line->tag,
(line->flags & ML_DONTPEGBOTTOM) ? max(sides[line->sidenum[0]].textureoffset>>FRACBITS, 0) : line->frontsector->lightlevel,
// failsafe: if user specifies Back Y Offset and NOT Front Y Offset, use the Back Offset
// to be consistent with other light and fade specials
(line->flags & ML_DONTPEGBOTTOM) ?
((line->sidenum[1] != 0xFFFF && !(sides[line->sidenum[0]].rowoffset>>FRACBITS)) ?
max(min(sides[line->sidenum[1]].rowoffset>>FRACBITS, 255), 0)
: max(min(sides[line->sidenum[0]].rowoffset>>FRACBITS, 255), 0))
: abs(P_AproxDistance(line->dx, line->dy))>>FRACBITS,
(line->flags & ML_EFFECT4),
(line->flags & ML_EFFECT5));
break; break;
case 421: // Stop lighting effect in tagged sectors case 421: // Stop lighting effect in tagged sectors
@ -3258,7 +3358,58 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
// This could even override existing colormaps I believe // This could even override existing colormaps I believe
// -- Monster Iestyn 14/06/18 // -- Monster Iestyn 14/06/18
for (secnum = -1; (secnum = P_FindSectorFromLineTag(line, secnum)) >= 0 ;) for (secnum = -1; (secnum = P_FindSectorFromLineTag(line, secnum)) >= 0 ;)
sectors[secnum].midmap = line->frontsector->midmap; {
P_ResetColormapFader(&sectors[secnum]);
if (line->flags & ML_EFFECT3) // relative calc
{
extracolormap_t *exc = R_AddColormaps(
(line->flags & ML_TFERLINE) && line->sidenum[1] != 0xFFFF ?
sides[line->sidenum[1]].colormap_data : sectors[secnum].extra_colormap, // use back colormap instead of target sector
sides[line->sidenum[0]].colormap_data,
line->flags & ML_EFFECT1, // subtract R
line->flags & ML_NOCLIMB, // subtract G
line->flags & ML_EFFECT2, // subtract B
false, // subtract A (no flag for this, just pass negative alpha)
line->flags & ML_EFFECT1, // subtract FadeR
line->flags & ML_NOCLIMB, // subtract FadeG
line->flags & ML_EFFECT2, // subtract FadeB
false, // subtract FadeA (no flag for this, just pass negative alpha)
false, // subtract FadeStart (we ran out of flags)
false, // subtract FadeEnd (we ran out of flags)
false, // ignore Fog (we ran out of flags)
line->flags & ML_DONTPEGBOTTOM,
(line->flags & ML_DONTPEGBOTTOM) ? (sides[line->sidenum[0]].textureoffset >> FRACBITS) : 0,
(line->flags & ML_DONTPEGBOTTOM) ? (sides[line->sidenum[0]].rowoffset >> FRACBITS) : 0,
false);
if (!(sectors[secnum].extra_colormap = R_GetColormapFromList(exc)))
{
exc->colormap = R_CreateLightTable(exc);
R_AddColormapToList(exc);
sectors[secnum].extra_colormap = exc;
}
else
Z_Free(exc);
}
else if (line->flags & ML_DONTPEGBOTTOM) // alternate alpha (by texture offsets)
{
extracolormap_t *exc = R_CopyColormap(sides[line->sidenum[0]].colormap_data, false);
exc->rgba = R_GetRgbaRGB(exc->rgba) + R_PutRgbaA(max(min(sides[line->sidenum[0]].textureoffset >> FRACBITS, 25), 0));
exc->fadergba = R_GetRgbaRGB(exc->fadergba) + R_PutRgbaA(max(min(sides[line->sidenum[0]].rowoffset >> FRACBITS, 25), 0));
if (!(sectors[secnum].extra_colormap = R_GetColormapFromList(exc)))
{
exc->colormap = R_CreateLightTable(exc);
R_AddColormapToList(exc);
sectors[secnum].extra_colormap = exc;
}
else
Z_Free(exc);
}
else
sectors[secnum].extra_colormap = sides[line->sidenum[0]].colormap_data;
}
break; break;
case 448: // Change skybox viewpoint/centerpoint case 448: // Change skybox viewpoint/centerpoint
@ -3321,6 +3472,100 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
break; break;
} }
case 455: // Fade colormap
for (secnum = -1; (secnum = P_FindSectorFromLineTag(line, secnum)) >= 0 ;)
{
extracolormap_t *source_exc, *dest_exc, *exc;
INT32 speed = (INT32)((line->flags & ML_DONTPEGBOTTOM) || !sides[line->sidenum[0]].rowoffset) && line->sidenum[1] != 0xFFFF ?
abs(sides[line->sidenum[1]].rowoffset >> FRACBITS)
: abs(sides[line->sidenum[0]].rowoffset >> FRACBITS);
// Prevent continuous execs from interfering on an existing fade
if (!(line->flags & ML_EFFECT5)
&& sectors[secnum].fadecolormapdata)
//&& ((fadecolormap_t*)sectors[secnum].fadecolormapdata)->timer > (ticbased ? 2 : speed*2))
{
CONS_Debug(DBG_GAMELOGIC, "Line type 455 Executor: Fade color thinker already exists, timer: %d\n", ((fadecolormap_t*)sectors[secnum].fadecolormapdata)->timer);
continue;
}
if (line->flags & ML_TFERLINE) // use back colormap instead of target sector
sectors[secnum].extra_colormap = (line->sidenum[1] != 0xFFFF) ?
sides[line->sidenum[1]].colormap_data : NULL;
exc = sectors[secnum].extra_colormap;
if (!(line->flags & ML_BOUNCY) // BOUNCY: Do not override fade from default rgba
&& !R_CheckDefaultColormap(sides[line->sidenum[0]].colormap_data, true, false, false)
&& R_CheckDefaultColormap(exc, true, false, false))
{
exc = R_CopyColormap(exc, false);
exc->rgba = R_GetRgbaRGB(sides[line->sidenum[0]].colormap_data->rgba) + R_PutRgbaA(R_GetRgbaA(exc->rgba));
//exc->fadergba = R_GetRgbaRGB(sides[line->sidenum[0]].colormap_data->rgba) + R_PutRgbaA(R_GetRgbaA(exc->fadergba));
if (!(source_exc = R_GetColormapFromList(exc)))
{
exc->colormap = R_CreateLightTable(exc);
R_AddColormapToList(exc);
source_exc = exc;
}
else
Z_Free(exc);
sectors[secnum].extra_colormap = source_exc;
}
else
source_exc = exc ? exc : R_GetDefaultColormap();
if (line->flags & ML_EFFECT3) // relative calc
{
exc = R_AddColormaps(
source_exc,
sides[line->sidenum[0]].colormap_data,
line->flags & ML_EFFECT1, // subtract R
line->flags & ML_NOCLIMB, // subtract G
line->flags & ML_EFFECT2, // subtract B
false, // subtract A (no flag for this, just pass negative alpha)
line->flags & ML_EFFECT1, // subtract FadeR
line->flags & ML_NOCLIMB, // subtract FadeG
line->flags & ML_EFFECT2, // subtract FadeB
false, // subtract FadeA (no flag for this, just pass negative alpha)
false, // subtract FadeStart (we ran out of flags)
false, // subtract FadeEnd (we ran out of flags)
false, // ignore Fog (we ran out of flags)
line->flags & ML_DONTPEGBOTTOM,
(line->flags & ML_DONTPEGBOTTOM) ? (sides[line->sidenum[0]].textureoffset >> FRACBITS) : 0,
(line->flags & ML_DONTPEGBOTTOM) ? (sides[line->sidenum[0]].rowoffset >> FRACBITS) : 0,
false);
}
else if (line->flags & ML_DONTPEGBOTTOM) // alternate alpha (by texture offsets)
{
exc = R_CopyColormap(sides[line->sidenum[0]].colormap_data, false);
exc->rgba = R_GetRgbaRGB(exc->rgba) + R_PutRgbaA(max(min(sides[line->sidenum[0]].textureoffset >> FRACBITS, 25), 0));
exc->fadergba = R_GetRgbaRGB(exc->fadergba) + R_PutRgbaA(max(min(sides[line->sidenum[0]].rowoffset >> FRACBITS, 25), 0));
}
else
exc = R_CopyColormap(sides[line->sidenum[0]].colormap_data, false);
if (!(dest_exc = R_GetColormapFromList(exc)))
{
exc->colormap = R_CreateLightTable(exc);
R_AddColormapToList(exc);
dest_exc = exc;
}
else
Z_Free(exc);
Add_ColormapFader(&sectors[secnum], source_exc, dest_exc, (line->flags & ML_EFFECT4), // tic-based timing
speed);
}
break;
case 456: // Stop fade colormap
for (secnum = -1; (secnum = P_FindSectorFromLineTag(line, secnum)) >= 0 ;)
P_ResetColormapFader(&sectors[secnum]);
break;
#ifdef POLYOBJECTS #ifdef POLYOBJECTS
case 480: // Polyobj_DoorSlide case 480: // Polyobj_DoorSlide
case 481: // Polyobj_DoorSwing case 481: // Polyobj_DoorSwing
@ -3348,6 +3593,9 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
case 491: case 491:
PolyTranslucency(line); PolyTranslucency(line);
break; break;
case 492:
PolyFade(line);
break;
#endif #endif
default: default:
@ -6771,7 +7019,7 @@ void P_SpawnSpecials(INT32 fromnetsave)
case 606: // HACK! Copy colormaps. Just plain colormaps. case 606: // HACK! Copy colormaps. Just plain colormaps.
for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
sectors[s].midmap = sectors[s].spawn_midmap = lines[i].frontsector->midmap; sectors[s].extra_colormap = sectors[s].spawn_extra_colormap = sides[lines[i].sidenum[0]].colormap_data;
break; break;
#ifdef ESLOPE // Slope copy specials. Handled here for sanity. #ifdef ESLOPE // Slope copy specials. Handled here for sanity.
@ -7333,6 +7581,139 @@ void T_Disappear(disappear_t *d)
} }
} }
static void P_ResetColormapFader(sector_t *sector)
{
if (sector->fadecolormapdata)
{
// The thinker is the first member in all the action structs,
// so just let the thinker get freed, and that will free the whole
// structure.
P_RemoveThinker(&((elevator_t *)sector->fadecolormapdata)->thinker);
sector->fadecolormapdata = NULL;
}
}
static void Add_ColormapFader(sector_t *sector, extracolormap_t *source_exc, extracolormap_t *dest_exc,
boolean ticbased, INT32 duration)
{
fadecolormap_t *d;
P_ResetColormapFader(sector);
// nothing to do, set immediately
if (!duration || R_CheckEqualColormaps(source_exc, dest_exc, true, true, true))
{
sector->extra_colormap = dest_exc;
return;
}
d = Z_Malloc(sizeof *d, PU_LEVSPEC, NULL);
d->thinker.function.acp1 = (actionf_p1)T_FadeColormap;
d->sector = sector;
d->source_exc = source_exc;
d->dest_exc = dest_exc;
if (ticbased)
{
d->ticbased = true;
d->duration = d->timer = duration;
}
else
{
d->ticbased = false;
d->timer = 256;
d->duration = duration; // use as speed
}
sector->fadecolormapdata = d;
P_AddThinker(&d->thinker); // add thinker
}
void T_FadeColormap(fadecolormap_t *d)
{
if ((d->ticbased && --d->timer <= 0)
|| (!d->ticbased && (d->timer -= d->duration) <= 0)) // d->duration used as speed decrement
{
d->sector->extra_colormap = d->dest_exc;
P_ResetColormapFader(d->sector);
}
else
{
extracolormap_t *exc;
INT32 duration = d->ticbased ? d->duration : 256;
fixed_t factor = min(FixedDiv(duration - d->timer, duration), 1*FRACUNIT);
INT16 cr, cg, cb, ca, fadestart, fadeend, fog;
INT32 rgba, fadergba;
// NULL failsafes (or intentionally set to signify default)
if (!d->sector->extra_colormap)
d->sector->extra_colormap = R_GetDefaultColormap();
if (!d->source_exc)
d->source_exc = R_GetDefaultColormap();
if (!d->dest_exc)
d->dest_exc = R_GetDefaultColormap();
// For each var (rgba + fadergba + params = 11 vars), we apply
// percentage fading: currentval = sourceval + (delta * percent of duration elapsed)
// delta is negative when fading out (destval is lower)
// max/min are used to ensure progressive calcs don't go backwards and to cap values to dest.
#define APPLYFADE(dest, src, cur) (\
(dest-src < 0) ? \
max(\
min(cur,\
src + (INT16)FixedMul(dest-src, factor)),\
dest)\
: (dest-src > 0) ? \
min(\
max(cur,\
src + (INT16)FixedMul(dest-src, factor)),\
dest)\
: \
dest\
)
cr = APPLYFADE(R_GetRgbaR(d->dest_exc->rgba), R_GetRgbaR(d->source_exc->rgba), R_GetRgbaR(d->sector->extra_colormap->rgba));
cg = APPLYFADE(R_GetRgbaG(d->dest_exc->rgba), R_GetRgbaG(d->source_exc->rgba), R_GetRgbaG(d->sector->extra_colormap->rgba));
cb = APPLYFADE(R_GetRgbaB(d->dest_exc->rgba), R_GetRgbaB(d->source_exc->rgba), R_GetRgbaB(d->sector->extra_colormap->rgba));
ca = APPLYFADE(R_GetRgbaA(d->dest_exc->rgba), R_GetRgbaA(d->source_exc->rgba), R_GetRgbaA(d->sector->extra_colormap->rgba));
rgba = R_PutRgbaRGBA(cr, cg, cb, ca);
cr = APPLYFADE(R_GetRgbaR(d->dest_exc->fadergba), R_GetRgbaR(d->source_exc->fadergba), R_GetRgbaR(d->sector->extra_colormap->fadergba));
cg = APPLYFADE(R_GetRgbaG(d->dest_exc->fadergba), R_GetRgbaG(d->source_exc->fadergba), R_GetRgbaG(d->sector->extra_colormap->fadergba));
cb = APPLYFADE(R_GetRgbaB(d->dest_exc->fadergba), R_GetRgbaB(d->source_exc->fadergba), R_GetRgbaB(d->sector->extra_colormap->fadergba));
ca = APPLYFADE(R_GetRgbaA(d->dest_exc->fadergba), R_GetRgbaA(d->source_exc->fadergba), R_GetRgbaA(d->sector->extra_colormap->fadergba));
fadergba = R_PutRgbaRGBA(cr, cg, cb, ca);
fadestart = APPLYFADE(d->dest_exc->fadestart, d->source_exc->fadestart, d->sector->extra_colormap->fadestart);
fadeend = APPLYFADE(d->dest_exc->fadeend, d->source_exc->fadeend, d->sector->extra_colormap->fadeend);
fog = abs(factor) > FRACUNIT/2 ? d->dest_exc->fog : d->source_exc->fog; // set new fog flag halfway through fade
#undef APPLYFADE
//////////////////
// setup new colormap
//////////////////
if (!(d->sector->extra_colormap = R_GetColormapFromListByValues(rgba, fadergba, fadestart, fadeend, fog)))
{
exc = R_CreateDefaultColormap(false);
exc->fadestart = fadestart;
exc->fadeend = fadeend;
exc->fog = (boolean)fog;
exc->rgba = rgba;
exc->fadergba = fadergba;
exc->colormap = R_CreateLightTable(exc);
R_AddColormapToList(exc);
d->sector->extra_colormap = exc;
}
}
}
/* /*
SoM: 3/8/2000: Friction functions start. SoM: 3/8/2000: Friction functions start.
Add_Friction, Add_Friction,

View file

@ -134,10 +134,15 @@ typedef struct
*/ */
typedef struct typedef struct
{ {
thinker_t thinker; ///< Thinker in use for the effect. thinker_t thinker; ///< Thinker in use for the effect.
sector_t *sector; ///< Sector where action is taking place. sector_t *sector; ///< Sector where action is taking place.
INT32 destlevel; ///< Light level we're fading to. INT16 sourcelevel; ///< Light level we're fading from.
INT32 speed; ///< Speed at which to change light level. INT16 destlevel; ///< Light level we're fading to.
fixed_t fixedcurlevel; ///< Fixed point for current light level.
fixed_t fixedpertic; ///< Fixed point for increment per tic.
// The reason for those two above to be fixed point is to deal with decimal values that would otherwise get trimmed away.
INT32 timer; ///< Internal timer.
} lightlevel_t; } lightlevel_t;
#define GLOWSPEED 8 #define GLOWSPEED 8
@ -156,7 +161,8 @@ strobe_t * P_SpawnAdjustableStrobeFlash(sector_t *minsector, sector_t *maxsector
void T_Glow(glow_t *g); void T_Glow(glow_t *g);
glow_t *P_SpawnAdjustableGlowingLight(sector_t *minsector, sector_t *maxsector, INT32 length); glow_t *P_SpawnAdjustableGlowingLight(sector_t *minsector, sector_t *maxsector, INT32 length);
void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed); void P_FadeLightBySector(sector_t *sector, INT32 destvalue, INT32 speed, boolean ticbased);
void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased, boolean force);
void T_LightFade(lightlevel_t *ll); void T_LightFade(lightlevel_t *ll);
typedef enum typedef enum
@ -453,6 +459,21 @@ typedef struct
void T_Disappear(disappear_t *d); void T_Disappear(disappear_t *d);
// Model for fading colormaps
typedef struct
{
thinker_t thinker; ///< Thinker structure for effect.
sector_t *sector; ///< Sector where action is taking place.
extracolormap_t *source_exc;
extracolormap_t *dest_exc;
boolean ticbased; ///< Tic-based timing
INT32 duration; ///< Total duration for tic-based logic (OR: speed increment)
INT32 timer; ///< Timer for tic-based logic (OR: internal speed counter)
} fadecolormap_t;
void T_FadeColormap(fadecolormap_t *d);
// Prototype functions for pushers // Prototype functions for pushers
void T_Pusher(pusher_t *p); void T_Pusher(pusher_t *p);
mobj_t *P_GetPushThing(UINT32 s); mobj_t *P_GetPushThing(UINT32 s);

View file

@ -234,8 +234,6 @@ static INT32 R_DoorClosed(void)
sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel, sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel,
INT32 *ceilinglightlevel, boolean back) INT32 *ceilinglightlevel, boolean back)
{ {
INT32 mapnum = -1;
if (floorlightlevel) if (floorlightlevel)
*floorlightlevel = sec->floorlightsec == -1 ? *floorlightlevel = sec->floorlightsec == -1 ?
sec->lightlevel : sectors[sec->floorlightsec].lightlevel; sec->lightlevel : sectors[sec->floorlightsec].lightlevel;
@ -244,10 +242,10 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel,
*ceilinglightlevel = sec->ceilinglightsec == -1 ? *ceilinglightlevel = sec->ceilinglightsec == -1 ?
sec->lightlevel : sectors[sec->ceilinglightsec].lightlevel; sec->lightlevel : sectors[sec->ceilinglightsec].lightlevel;
// If the sector has a midmap, it's probably from 280 type // if (sec->midmap != -1)
if (sec->midmap != -1) // mapnum = sec->midmap;
mapnum = sec->midmap; // In original colormap code, this block did not run if sec->midmap was set
else if (sec->heightsec != -1) if (!sec->extra_colormap && sec->heightsec != -1)
{ {
const sector_t *s = &sectors[sec->heightsec]; const sector_t *s = &sectors[sec->heightsec];
mobj_t *viewmobj = viewplayer->mo; mobj_t *viewmobj = viewplayer->mo;
@ -271,8 +269,6 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel,
tempsec->floorheight = s->floorheight; tempsec->floorheight = s->floorheight;
tempsec->ceilingheight = s->ceilingheight; tempsec->ceilingheight = s->ceilingheight;
mapnum = s->midmap;
if ((underwater && (tempsec-> floorheight = sec->floorheight, if ((underwater && (tempsec-> floorheight = sec->floorheight,
tempsec->ceilingheight = s->floorheight - 1, !back)) || viewz <= s->floorheight) tempsec->ceilingheight = s->floorheight - 1, !back)) || viewz <= s->floorheight)
{ // head-below-floor hack { // head-below-floor hack
@ -298,7 +294,6 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel,
tempsec->ceiling_yoffs = s->ceiling_yoffs; tempsec->ceiling_yoffs = s->ceiling_yoffs;
tempsec->ceilingpic_angle = s->ceilingpic_angle; tempsec->ceilingpic_angle = s->ceilingpic_angle;
} }
mapnum = s->bottommap;
} }
tempsec->lightlevel = s->lightlevel; tempsec->lightlevel = s->lightlevel;
@ -322,8 +317,6 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel,
tempsec->floor_yoffs = tempsec->ceiling_yoffs = s->ceiling_yoffs; tempsec->floor_yoffs = tempsec->ceiling_yoffs = s->ceiling_yoffs;
tempsec->floorpic_angle = tempsec->ceilingpic_angle = s->ceilingpic_angle; tempsec->floorpic_angle = tempsec->ceilingpic_angle = s->ceilingpic_angle;
mapnum = s->topmap;
if (s->floorpic == skyflatnum) // SKYFIX? if (s->floorpic == skyflatnum) // SKYFIX?
{ {
tempsec->ceilingheight = tempsec->floorheight-1; tempsec->ceilingheight = tempsec->floorheight-1;
@ -354,11 +347,6 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel,
sec = tempsec; sec = tempsec;
} }
if (mapnum >= 0 && (size_t)mapnum < num_extra_colormaps)
sec->extra_colormap = &extra_colormaps[mapnum];
else
sec->extra_colormap = NULL;
return sec; return sec;
} }
@ -937,11 +925,11 @@ static void R_Subsector(size_t num)
light = R_GetPlaneLight(frontsector, floorcenterz, false); light = R_GetPlaneLight(frontsector, floorcenterz, false);
if (frontsector->floorlightsec == -1) if (frontsector->floorlightsec == -1)
floorlightlevel = *frontsector->lightlist[light].lightlevel; floorlightlevel = *frontsector->lightlist[light].lightlevel;
floorcolormap = frontsector->lightlist[light].extra_colormap; floorcolormap = *frontsector->lightlist[light].extra_colormap;
light = R_GetPlaneLight(frontsector, ceilingcenterz, false); light = R_GetPlaneLight(frontsector, ceilingcenterz, false);
if (frontsector->ceilinglightsec == -1) if (frontsector->ceilinglightsec == -1)
ceilinglightlevel = *frontsector->lightlist[light].lightlevel; ceilinglightlevel = *frontsector->lightlist[light].lightlevel;
ceilingcolormap = frontsector->lightlist[light].extra_colormap; ceilingcolormap = *frontsector->lightlist[light].extra_colormap;
} }
sub->sector->extra_colormap = frontsector->extra_colormap; sub->sector->extra_colormap = frontsector->extra_colormap;
@ -1038,7 +1026,7 @@ static void R_Subsector(size_t num)
ffloor[numffloors].plane = R_FindPlane(*rover->bottomheight, *rover->bottompic, ffloor[numffloors].plane = R_FindPlane(*rover->bottomheight, *rover->bottompic,
*frontsector->lightlist[light].lightlevel, *rover->bottomxoffs, *frontsector->lightlist[light].lightlevel, *rover->bottomxoffs,
*rover->bottomyoffs, *rover->bottomangle, frontsector->lightlist[light].extra_colormap, rover *rover->bottomyoffs, *rover->bottomangle, *frontsector->lightlist[light].extra_colormap, rover
#ifdef POLYOBJECTS_PLANES #ifdef POLYOBJECTS_PLANES
, NULL , NULL
#endif #endif
@ -1084,7 +1072,7 @@ static void R_Subsector(size_t num)
ffloor[numffloors].plane = R_FindPlane(*rover->topheight, *rover->toppic, ffloor[numffloors].plane = R_FindPlane(*rover->topheight, *rover->toppic,
*frontsector->lightlist[light].lightlevel, *rover->topxoffs, *rover->topyoffs, *rover->topangle, *frontsector->lightlist[light].lightlevel, *rover->topxoffs, *rover->topyoffs, *rover->topangle,
frontsector->lightlist[light].extra_colormap, rover *frontsector->lightlist[light].extra_colormap, rover
#ifdef POLYOBJECTS_PLANES #ifdef POLYOBJECTS_PLANES
, NULL , NULL
#endif #endif
@ -1237,7 +1225,7 @@ void R_Prep3DFloors(sector_t *sector)
ffloor_t *rover; ffloor_t *rover;
ffloor_t *best; ffloor_t *best;
fixed_t bestheight, maxheight; fixed_t bestheight, maxheight;
INT32 count, i, mapnum; INT32 count, i;
sector_t *sec; sector_t *sec;
#ifdef ESLOPE #ifdef ESLOPE
pslope_t *bestslope = NULL; pslope_t *bestslope = NULL;
@ -1276,7 +1264,7 @@ void R_Prep3DFloors(sector_t *sector)
#endif #endif
sector->lightlist[0].lightlevel = &sector->lightlevel; sector->lightlist[0].lightlevel = &sector->lightlevel;
sector->lightlist[0].caster = NULL; sector->lightlist[0].caster = NULL;
sector->lightlist[0].extra_colormap = sector->extra_colormap; sector->lightlist[0].extra_colormap = &sector->extra_colormap;
sector->lightlist[0].flags = 0; sector->lightlist[0].flags = 0;
maxheight = INT32_MAX; maxheight = INT32_MAX;
@ -1342,11 +1330,6 @@ void R_Prep3DFloors(sector_t *sector)
sector->lightlist[i].slope = bestslope; sector->lightlist[i].slope = bestslope;
#endif #endif
sec = &sectors[best->secnum]; sec = &sectors[best->secnum];
mapnum = sec->midmap;
if (mapnum >= 0 && (size_t)mapnum < num_extra_colormaps)
sec->extra_colormap = &extra_colormaps[mapnum];
else
sec->extra_colormap = NULL;
if (best->flags & FF_NOSHADE) if (best->flags & FF_NOSHADE)
{ {
@ -1356,12 +1339,12 @@ void R_Prep3DFloors(sector_t *sector)
else if (best->flags & FF_COLORMAPONLY) else if (best->flags & FF_COLORMAPONLY)
{ {
sector->lightlist[i].lightlevel = sector->lightlist[i-1].lightlevel; sector->lightlist[i].lightlevel = sector->lightlist[i-1].lightlevel;
sector->lightlist[i].extra_colormap = sec->extra_colormap; sector->lightlist[i].extra_colormap = &sec->extra_colormap;
} }
else else
{ {
sector->lightlist[i].lightlevel = best->toplightlevel; sector->lightlist[i].lightlevel = best->toplightlevel;
sector->lightlist[i].extra_colormap = sec->extra_colormap; sector->lightlist[i].extra_colormap = &sec->extra_colormap;
} }
if (best->flags & FF_DOUBLESHADOW) if (best->flags & FF_DOUBLESHADOW)

View file

@ -1144,6 +1144,10 @@ void R_ParseTEXTURESLump(UINT16 wadNum, UINT16 lumpNum, INT32 *texindex)
Z_Free((void *)texturesText); Z_Free((void *)texturesText);
} }
#ifdef EXTRACOLORMAPLUMPS
static lumplist_t *colormaplumps = NULL; ///\todo free leak
static size_t numcolormaplumps = 0;
static inline lumpnum_t R_CheckNumForNameList(const char *name, lumplist_t *list, size_t listsize) static inline lumpnum_t R_CheckNumForNameList(const char *name, lumplist_t *list, size_t listsize)
{ {
size_t i; size_t i;
@ -1160,9 +1164,6 @@ static inline lumpnum_t R_CheckNumForNameList(const char *name, lumplist_t *list
return LUMPERROR; return LUMPERROR;
} }
static lumplist_t *colormaplumps = NULL; ///\todo free leak
static size_t numcolormaplumps = 0;
static void R_InitExtraColormaps(void) static void R_InitExtraColormaps(void)
{ {
lumpnum_t startnum, endnum; lumpnum_t startnum, endnum;
@ -1195,6 +1196,7 @@ static void R_InitExtraColormaps(void)
} }
CONS_Printf(M_GetText("Number of Extra Colormaps: %s\n"), sizeu1(numcolormaplumps)); CONS_Printf(M_GetText("Number of Extra Colormaps: %s\n"), sizeu1(numcolormaplumps));
} }
#endif
// Search for flat name through all // Search for flat name through all
lumpnum_t R_GetFlatNumForName(const char *name) lumpnum_t R_GetFlatNumForName(const char *name)
@ -1291,7 +1293,9 @@ static void R_InitColormaps(void)
// Init Boom colormaps. // Init Boom colormaps.
R_ClearColormaps(); R_ClearColormaps();
#ifdef EXTRACOLORMAPLUMPS
R_InitExtraColormaps(); R_InitExtraColormaps();
#endif
} }
void R_ReInitColormaps(UINT16 num) void R_ReInitColormaps(UINT16 num)
@ -1311,8 +1315,6 @@ void R_ReInitColormaps(UINT16 num)
R_ClearColormaps(); R_ClearColormaps();
} }
static lumpnum_t foundcolormaps[MAXCOLORMAPS];
// //
// R_ClearColormaps // R_ClearColormaps
// //
@ -1320,49 +1322,264 @@ static lumpnum_t foundcolormaps[MAXCOLORMAPS];
// //
void R_ClearColormaps(void) void R_ClearColormaps(void)
{ {
size_t i; // Purged by PU_LEVEL, just overwrite the pointer
extra_colormaps = R_CreateDefaultColormap(true);
num_extra_colormaps = 0;
for (i = 0; i < MAXCOLORMAPS; i++)
foundcolormaps[i] = LUMPERROR;
memset(extra_colormaps, 0, sizeof (extra_colormaps));
} }
INT32 R_ColormapNumForName(char *name) //
// R_CreateDefaultColormap()
// NOTE: The result colormap is not added to the extra_colormaps chain. You must do that yourself!
//
extracolormap_t *R_CreateDefaultColormap(boolean lighttable)
{ {
lumpnum_t lump, i; extracolormap_t *exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL);
exc->fadestart = 0;
exc->fadeend = 31;
exc->fog = 0;
exc->rgba = 0;
exc->fadergba = 0x19000000;
exc->colormap = lighttable ? R_CreateLightTable(exc) : NULL;
#ifdef EXTRACOLORMAPLUMPS
exc->lump = LUMPERROR;
exc->lumpname[0] = 0;
#endif
exc->next = exc->prev = NULL;
return exc;
}
if (num_extra_colormaps == MAXCOLORMAPS) //
I_Error("R_ColormapNumForName: Too many colormaps! the limit is %d\n", MAXCOLORMAPS); // R_GetDefaultColormap()
//
extracolormap_t *R_GetDefaultColormap(void)
{
#ifdef COLORMAPREVERSELIST
extracolormap_t *exc;
#endif
if (!extra_colormaps)
return (extra_colormaps = R_CreateDefaultColormap(true));
#ifdef COLORMAPREVERSELIST
for (exc = extra_colormaps; exc->next; exc = exc->next);
return exc;
#else
return extra_colormaps;
#endif
}
//
// R_CopyColormap()
// NOTE: The result colormap is not added to the extra_colormaps chain. You must do that yourself!
//
extracolormap_t *R_CopyColormap(extracolormap_t *extra_colormap, boolean lighttable)
{
extracolormap_t *exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL);
if (!extra_colormap)
extra_colormap = R_GetDefaultColormap();
*exc = *extra_colormap;
exc->next = exc->prev = NULL;
#ifdef EXTRACOLORMAPLUMPS
strncpy(exc->lumpname, extra_colormap->lumpname, 9);
if (exc->lump != LUMPERROR && lighttable)
{
// aligned on 8 bit for asm code
exc->colormap = Z_MallocAlign(W_LumpLength(lump), PU_LEVEL, NULL, 16);
W_ReadLump(lump, exc->colormap);
}
else
#endif
if (lighttable)
exc->colormap = R_CreateLightTable(exc);
else
exc->colormap = NULL;
return exc;
}
//
// R_AddColormapToList
//
// Sets prev/next chain for extra_colormaps var
// Copypasta from P_AddFFloorToList
//
void R_AddColormapToList(extracolormap_t *extra_colormap)
{
#ifndef COLORMAPREVERSELIST
extracolormap_t *exc;
#endif
if (!extra_colormaps)
{
extra_colormaps = extra_colormap;
extra_colormap->next = 0;
extra_colormap->prev = 0;
return;
}
#ifdef COLORMAPREVERSELIST
extra_colormaps->prev = extra_colormap;
extra_colormap->next = extra_colormaps;
extra_colormaps = extra_colormap;
extra_colormap->prev = 0;
#else
for (exc = extra_colormaps; exc->next; exc = exc->next);
exc->next = extra_colormap;
extra_colormap->prev = exc;
extra_colormap->next = 0;
#endif
}
//
// R_CheckDefaultColormapByValues()
//
#ifdef EXTRACOLORMAPLUMPS
boolean R_CheckDefaultColormapByValues(boolean checkrgba, boolean checkfadergba, boolean checkparams,
INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 fog, lumpnum_t lump)
#else
boolean R_CheckDefaultColormapByValues(boolean checkrgba, boolean checkfadergba, boolean checkparams,
INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 fog)
#endif
{
return (
(!checkparams ? true :
(fadestart == 0
&& fadeend == 31
&& !fog)
)
&& (!checkrgba ? true : rgba == 0)
&& (!checkfadergba ? true : fadergba == 0x19000000)
#ifdef EXTRACOLORMAPLUMPS
&& lump == LUMPERROR
&& extra_colormap->lumpname[0] == 0
#endif
);
}
boolean R_CheckDefaultColormap(extracolormap_t *extra_colormap, boolean checkrgba, boolean checkfadergba, boolean checkparams)
{
if (!extra_colormap)
return true;
#ifdef EXTRACOLORMAPLUMPS
return R_CheckDefaultColormapByValues(checkrgba, checkfadergba, checkparams, extra_colormap->rgba, extra_colormap->fadergba, extra_colormap->fadestart, extra_colormap->fadeend, extra_colormap->fog, extra_colormap->lump);
#else
return R_CheckDefaultColormapByValues(checkrgba, checkfadergba, checkparams, extra_colormap->rgba, extra_colormap->fadergba, extra_colormap->fadestart, extra_colormap->fadeend, extra_colormap->fog);
#endif
}
boolean R_CheckEqualColormaps(extracolormap_t *exc_a, extracolormap_t *exc_b, boolean checkrgba, boolean checkfadergba, boolean checkparams)
{
// Treat NULL as default colormap
// We need this because what if one exc is a default colormap, and the other is NULL? They're really both equal.
if (!exc_a)
exc_a = R_GetDefaultColormap();
if (!exc_b)
exc_b = R_GetDefaultColormap();
if (exc_a == exc_b)
return true;
return (
(!checkparams ? true :
(exc_a->fadestart == exc_b->fadestart
&& exc_a->fadeend == exc_b->fadeend
&& exc_a->fog == exc_b->fog)
)
&& (!checkrgba ? true : exc_a->rgba == exc_b->rgba)
&& (!checkfadergba ? true : exc_a->fadergba == exc_b->fadergba)
#ifdef EXTRACOLORMAPLUMPS
&& exc_a->lump == exc_b->lump
&& !strncmp(exc_a->lumpname, exc_b->lumpname, 9)
#endif
);
}
//
// R_GetColormapFromListByValues()
// NOTE: Returns NULL if no match is found
//
#ifdef EXTRACOLORMAPLUMPS
extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 fog, lumpnum_t lump)
#else
extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 fog)
#endif
{
extracolormap_t *exc;
UINT32 dbg_i = 0;
for (exc = extra_colormaps; exc; exc = exc->next)
{
if (rgba == exc->rgba
&& fadergba == exc->fadergba
&& fadestart == exc->fadestart
&& fadeend == exc->fadeend
&& fog == exc->fog
#ifdef EXTRACOLORMAPLUMPS
&& (lump != LUMPERROR && lump == exc->lump)
#endif
)
{
CONS_Debug(DBG_RENDER, "Found Colormap %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n",
dbg_i, R_GetRgbaR(rgba), R_GetRgbaG(rgba), R_GetRgbaB(rgba), R_GetRgbaA(rgba),
R_GetRgbaR(fadergba), R_GetRgbaG(fadergba), R_GetRgbaB(fadergba), R_GetRgbaA(fadergba));
return exc;
}
dbg_i++;
}
return NULL;
}
extracolormap_t *R_GetColormapFromList(extracolormap_t *extra_colormap)
{
#ifdef EXTRACOLORMAPLUMPS
return R_GetColormapFromListByValues(extra_colormap->rgba, extra_colormap->fadergba, extra_colormap->fadestart, extra_colormap->fadeend, extra_colormap->fog, extra_colormap->lump);
#else
return R_GetColormapFromListByValues(extra_colormap->rgba, extra_colormap->fadergba, extra_colormap->fadestart, extra_colormap->fadeend, extra_colormap->fog);
#endif
}
#ifdef EXTRACOLORMAPLUMPS
extracolormap_t *R_ColormapForName(char *name)
{
lumpnum_t lump;
extracolormap_t *exc;
lump = R_CheckNumForNameList(name, colormaplumps, numcolormaplumps); lump = R_CheckNumForNameList(name, colormaplumps, numcolormaplumps);
if (lump == LUMPERROR) if (lump == LUMPERROR)
I_Error("R_ColormapNumForName: Cannot find colormap lump %.8s\n", name); I_Error("R_ColormapForName: Cannot find colormap lump %.8s\n", name);
for (i = 0; i < num_extra_colormaps; i++) exc = R_GetColormapFromListByValues(0, 0x19000000, 0, 31, 0, lump);
if (lump == foundcolormaps[i]) if (exc)
return i; return exc;
foundcolormaps[num_extra_colormaps] = lump; exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL);
exc->lump = lump;
strncpy(exc->lumpname, name, 9);
exc->lumpname[8] = 0;
// aligned on 8 bit for asm code // aligned on 8 bit for asm code
extra_colormaps[num_extra_colormaps].colormap = Z_MallocAlign(W_LumpLength(lump), PU_LEVEL, NULL, 16); exc->colormap = Z_MallocAlign(W_LumpLength(lump), PU_LEVEL, NULL, 16);
W_ReadLump(lump, extra_colormaps[num_extra_colormaps].colormap); W_ReadLump(lump, exc->colormap);
// We set all params of the colormap to normal because there // We set all params of the colormap to normal because there
// is no real way to tell how GL should handle a colormap lump anyway.. // is no real way to tell how GL should handle a colormap lump anyway..
extra_colormaps[num_extra_colormaps].maskcolor = 0xffff; exc->fadestart = 0;
extra_colormaps[num_extra_colormaps].fadecolor = 0x0; exc->fadeend = 31;
extra_colormaps[num_extra_colormaps].maskamt = 0x0; exc->fog = 0;
extra_colormaps[num_extra_colormaps].fadestart = 0; exc->rgba = 0;
extra_colormaps[num_extra_colormaps].fadeend = 31; exc->fadergba = 0x19000000;
extra_colormaps[num_extra_colormaps].fog = 0;
num_extra_colormaps++; R_AddColormapToList(exc);
return (INT32)num_extra_colormaps - 1;
return exc;
} }
#endif
// //
// R_CreateColormap // R_CreateColormap
@ -1377,107 +1594,60 @@ static double deltas[256][3], map[256][3];
static UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b); static UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b);
static int RoundUp(double number); static int RoundUp(double number);
INT32 R_CreateColormap(char *p1, char *p2, char *p3) lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap)
{ {
double cmaskr, cmaskg, cmaskb, cdestr, cdestg, cdestb; double cmaskr, cmaskg, cmaskb, cdestr, cdestg, cdestb;
double maskamt = 0, othermask = 0; double maskamt = 0, othermask = 0;
int mask, fog = 0;
size_t mapnum = num_extra_colormaps; UINT8 cr = R_GetRgbaR(extra_colormap->rgba),
cg = R_GetRgbaG(extra_colormap->rgba),
cb = R_GetRgbaB(extra_colormap->rgba),
ca = R_GetRgbaA(extra_colormap->rgba),
cfr = R_GetRgbaR(extra_colormap->fadergba),
cfg = R_GetRgbaG(extra_colormap->fadergba),
cfb = R_GetRgbaB(extra_colormap->fadergba);
// cfa = R_GetRgbaA(extra_colormap->fadergba); // unused in software
UINT8 fadestart = extra_colormap->fadestart,
fadedist = extra_colormap->fadeend - extra_colormap->fadestart;
lighttable_t *lighttable = NULL;
size_t i; size_t i;
UINT32 cr, cg, cb, maskcolor, fadecolor;
UINT32 fadestart = 0, fadeend = 31, fadedist = 31;
#define HEX2INT(x) (UINT32)(x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0) /////////////////////
if (p1[0] == '#') // Calc the RGBA mask
{ /////////////////////
cr = ((HEX2INT(p1[1]) * 16) + HEX2INT(p1[2])); cmaskr = cr;
cmaskr = cr; cmaskg = cg;
cg = ((HEX2INT(p1[3]) * 16) + HEX2INT(p1[4])); cmaskb = cb;
cmaskg = cg;
cb = ((HEX2INT(p1[5]) * 16) + HEX2INT(p1[6]));
cmaskb = cb;
// Create a rough approximation of the color (a 16 bit color)
maskcolor = ((cb) >> 3) + (((cg) >> 2) << 5) + (((cr) >> 3) << 11);
if (p1[7] >= 'a' && p1[7] <= 'z')
mask = (p1[7] - 'a');
else if (p1[7] >= 'A' && p1[7] <= 'Z')
mask = (p1[7] - 'A');
else
mask = 24;
maskamt = (double)(mask/24.0l); maskamt = (double)(ca/24.0l);
othermask = 1 - maskamt;
maskamt /= 0xff;
othermask = 1 - maskamt; cmaskr *= maskamt;
maskamt /= 0xff; cmaskg *= maskamt;
cmaskr *= maskamt; cmaskb *= maskamt;
cmaskg *= maskamt;
cmaskb *= maskamt;
}
else
{
cmaskr = cmaskg = cmaskb = 0xff;
maskamt = 0;
maskcolor = ((0xff) >> 3) + (((0xff) >> 2) << 5) + (((0xff) >> 3) << 11);
}
#define NUMFROMCHAR(c) (c >= '0' && c <= '9' ? c - '0' : 0) /////////////////////
if (p2[0] == '#') // Calc the RGBA fade mask
{ /////////////////////
// Get parameters like fadestart, fadeend, and the fogflag cdestr = cfr;
fadestart = NUMFROMCHAR(p2[3]) + (NUMFROMCHAR(p2[2]) * 10); cdestg = cfg;
fadeend = NUMFROMCHAR(p2[5]) + (NUMFROMCHAR(p2[4]) * 10); cdestb = cfb;
if (fadestart > 30)
fadestart = 0;
if (fadeend > 31 || fadeend < 1)
fadeend = 31;
fadedist = fadeend - fadestart;
fog = NUMFROMCHAR(p2[1]);
}
#undef NUMFROMCHAR
if (p3[0] == '#') // fade alpha unused in software
{ // maskamt = (double)(cfa/24.0l);
cdestr = cr = ((HEX2INT(p3[1]) * 16) + HEX2INT(p3[2])); // othermask = 1 - maskamt;
cdestg = cg = ((HEX2INT(p3[3]) * 16) + HEX2INT(p3[4])); // maskamt /= 0xff;
cdestb = cb = ((HEX2INT(p3[5]) * 16) + HEX2INT(p3[6]));
fadecolor = (((cb) >> 3) + (((cg) >> 2) << 5) + (((cr) >> 3) << 11));
}
else
cdestr = cdestg = cdestb = fadecolor = 0;
#undef HEX2INT
for (i = 0; i < num_extra_colormaps; i++) // cdestr *= maskamt;
{ // cdestg *= maskamt;
if (foundcolormaps[i] != LUMPERROR) // cdestb *= maskamt;
continue;
if (maskcolor == extra_colormaps[i].maskcolor
&& fadecolor == extra_colormaps[i].fadecolor
&& (float)maskamt == (float)extra_colormaps[i].maskamt
&& fadestart == extra_colormaps[i].fadestart
&& fadeend == extra_colormaps[i].fadeend
&& fog == extra_colormaps[i].fog)
{
return (INT32)i;
}
}
if (num_extra_colormaps == MAXCOLORMAPS)
I_Error("R_CreateColormap: Too many colormaps! the limit is %d\n", MAXCOLORMAPS);
num_extra_colormaps++;
foundcolormaps[mapnum] = LUMPERROR;
// aligned on 8 bit for asm code
extra_colormaps[mapnum].colormap = NULL;
extra_colormaps[mapnum].maskcolor = (UINT16)maskcolor;
extra_colormaps[mapnum].fadecolor = (UINT16)fadecolor;
extra_colormaps[mapnum].maskamt = maskamt;
extra_colormaps[mapnum].fadestart = (UINT16)fadestart;
extra_colormaps[mapnum].fadeend = (UINT16)fadeend;
extra_colormaps[mapnum].fog = fog;
/////////////////////
// This code creates the colormap array used by software renderer // This code creates the colormap array used by software renderer
/////////////////////
if (rendermode == render_soft) if (rendermode == render_soft)
{ {
double r, g, b, cbrightness; double r, g, b, cbrightness;
@ -1513,8 +1683,9 @@ INT32 R_CreateColormap(char *p1, char *p2, char *p3)
} }
// Now allocate memory for the actual colormap array itself! // Now allocate memory for the actual colormap array itself!
// aligned on 8 bit for asm code
colormap_p = Z_MallocAlign((256 * 34) + 10, PU_LEVEL, NULL, 8); colormap_p = Z_MallocAlign((256 * 34) + 10, PU_LEVEL, NULL, 8);
extra_colormaps[mapnum].colormap = (UINT8 *)colormap_p; lighttable = (UINT8 *)colormap_p;
// Calculate the palette index for each palette index, for each light level // Calculate the palette index for each palette index, for each light level
// (as well as the two unused colormap lines we inherited from Doom) // (as well as the two unused colormap lines we inherited from Doom)
@ -1549,7 +1720,285 @@ INT32 R_CreateColormap(char *p1, char *p2, char *p3)
} }
} }
return (INT32)mapnum; return lighttable;
}
extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3)
{
extracolormap_t *extra_colormap, *exc;
// default values
UINT8 cr = 0, cg = 0, cb = 0, ca = 0, cfr = 0, cfg = 0, cfb = 0, cfa = 25;
UINT32 fadestart = 0, fadeend = 31;
UINT8 fog = 0;
INT32 rgba = 0, fadergba = 0x19000000;
#define HEX2INT(x) (UINT32)(x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0)
#define ALPHA2INT(x) (x >= 'a' && x <= 'z' ? x - 'a' : x >= 'A' && x <= 'Z' ? x - 'A' : x >= '0' && x <= '9' ? 25 : 0)
// Get base colormap value
// First alpha-only, then full value
if (p1[0] >= 'a' && p1[0] <= 'z' && !p1[1])
ca = (p1[0] - 'a');
else if (p1[0] == '#' && p1[1] >= 'a' && p1[1] <= 'z' && !p1[2])
ca = (p1[1] - 'a');
else if (p1[0] >= 'A' && p1[0] <= 'Z' && !p1[1])
ca = (p1[0] - 'A');
else if (p1[0] == '#' && p1[1] >= 'A' && p1[1] <= 'Z' && !p1[2])
ca = (p1[1] - 'A');
else if (p1[0] == '#')
{
// For each subsequent value, the value before it must exist
// If we don't get every value, then set alpha to max
if (p1[1] && p1[2])
{
cr = ((HEX2INT(p1[1]) * 16) + HEX2INT(p1[2]));
if (p1[3] && p1[4])
{
cg = ((HEX2INT(p1[3]) * 16) + HEX2INT(p1[4]));
if (p1[5] && p1[6])
{
cb = ((HEX2INT(p1[5]) * 16) + HEX2INT(p1[6]));
if (p1[7] >= 'a' && p1[7] <= 'z')
ca = (p1[7] - 'a');
else if (p1[7] >= 'A' && p1[7] <= 'Z')
ca = (p1[7] - 'A');
else
ca = 25;
}
else
ca = 25;
}
else
ca = 25;
}
else
ca = 25;
}
#define NUMFROMCHAR(c) (c >= '0' && c <= '9' ? c - '0' : 0)
// Get parameters like fadestart, fadeend, and the fogflag
if (p2[0] == '#')
{
if (p2[1])
{
fog = NUMFROMCHAR(p2[1]);
if (p2[2] && p2[3])
{
fadestart = NUMFROMCHAR(p2[3]) + (NUMFROMCHAR(p2[2]) * 10);
if (p2[4] && p2[5])
fadeend = NUMFROMCHAR(p2[5]) + (NUMFROMCHAR(p2[4]) * 10);
}
}
if (fadestart > 30)
fadestart = 0;
if (fadeend > 31 || fadeend < 1)
fadeend = 31;
}
#undef NUMFROMCHAR
// Get fade (dark) colormap value
// First alpha-only, then full value
if (p3[0] >= 'a' && p3[0] <= 'z' && !p3[1])
cfa = (p3[0] - 'a');
else if (p3[0] == '#' && p3[1] >= 'a' && p3[1] <= 'z' && !p3[2])
cfa = (p3[1] - 'a');
else if (p3[0] >= 'A' && p3[0] <= 'Z' && !p3[1])
cfa = (p3[0] - 'A');
else if (p3[0] == '#' && p3[1] >= 'A' && p3[1] <= 'Z' && !p3[2])
cfa = (p3[1] - 'A');
else if (p3[0] == '#')
{
// For each subsequent value, the value before it must exist
// If we don't get every value, then set alpha to max
if (p3[1] && p3[2])
{
cfr = ((HEX2INT(p3[1]) * 16) + HEX2INT(p3[2]));
if (p3[3] && p3[4])
{
cfg = ((HEX2INT(p3[3]) * 16) + HEX2INT(p3[4]));
if (p3[5] && p3[6])
{
cfb = ((HEX2INT(p3[5]) * 16) + HEX2INT(p3[6]));
if (p3[7] >= 'a' && p3[7] <= 'z')
cfa = (p3[7] - 'a');
else if (p3[7] >= 'A' && p3[7] <= 'Z')
cfa = (p3[7] - 'A');
else
cfa = 25;
}
else
cfa = 25;
}
else
cfa = 25;
}
else
cfa = 25;
}
#undef ALPHA2INT
#undef HEX2INT
// Pack rgba values into combined var
// OpenGL also uses this instead of lighttables for rendering
rgba = R_PutRgbaRGBA(cr, cg, cb, ca);
fadergba = R_PutRgbaRGBA(cfr, cfg, cfb, cfa);
// Did we just make a default colormap?
#ifdef EXTRACOLORMAPLUMPS
if (R_CheckDefaultColormapByValues(true, true, true, rgba, fadergba, fadestart, fadeend, fog, LUMPERROR))
return NULL;
#else
if (R_CheckDefaultColormapByValues(true, true, true, rgba, fadergba, fadestart, fadeend, fog))
return NULL;
#endif
// Look for existing colormaps
#ifdef EXTRACOLORMAPLUMPS
exc = R_GetColormapFromListByValues(rgba, fadergba, fadestart, fadeend, fog, LUMPERROR);
#else
exc = R_GetColormapFromListByValues(rgba, fadergba, fadestart, fadeend, fog);
#endif
if (exc)
return exc;
CONS_Debug(DBG_RENDER, "Creating Colormap: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n",
cr, cg, cb, ca, cfr, cfg, cfb, cfa);
extra_colormap = Z_Calloc(sizeof (*extra_colormap), PU_LEVEL, NULL);
extra_colormap->fadestart = (UINT16)fadestart;
extra_colormap->fadeend = (UINT16)fadeend;
extra_colormap->fog = fog;
extra_colormap->rgba = rgba;
extra_colormap->fadergba = fadergba;
#ifdef EXTRACOLORMAPLUMPS
extra_colormap->lump = LUMPERROR;
extra_colormap->lumpname[0] = 0;
#endif
// Having lighttables for alpha-only entries is kind of pointless,
// but if there happens to be a matching rgba entry that is NOT alpha-only (but has same rgb values),
// then it needs this lighttable because we share matching entries.
extra_colormap->colormap = R_CreateLightTable(extra_colormap);
R_AddColormapToList(extra_colormap);
return extra_colormap;
}
//
// R_AddColormaps()
// NOTE: The result colormap is not added to the extra_colormaps chain. You must do that yourself!
//
extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *exc_addend,
boolean subR, boolean subG, boolean subB, boolean subA,
boolean subFadeR, boolean subFadeG, boolean subFadeB, boolean subFadeA,
boolean subFadeStart, boolean subFadeEnd, boolean ignoreFog,
boolean useAltAlpha, INT16 altAlpha, INT16 altFadeAlpha,
boolean lighttable)
{
INT16 red, green, blue, alpha;
// exc_augend is added (or subtracted) onto by exc_addend
// In Rennaisance times, the first number was considered the augend, the second number the addend
// But since the commutative property was discovered, today they're both called addends!
// So let's be Olde English for a hot second.
exc_augend = R_CopyColormap(exc_augend, false);
if(!exc_addend)
exc_addend = R_GetDefaultColormap();
///////////////////
// base rgba
///////////////////
red = max(min(
R_GetRgbaR(exc_augend->rgba)
+ (subR ? -1 : 1) // subtract R
* R_GetRgbaR(exc_addend->rgba)
, 255), 0);
green = max(min(
R_GetRgbaG(exc_augend->rgba)
+ (subG ? -1 : 1) // subtract G
* R_GetRgbaG(exc_addend->rgba)
, 255), 0);
blue = max(min(
R_GetRgbaB(exc_augend->rgba)
+ (subB ? -1 : 1) // subtract B
* R_GetRgbaB(exc_addend->rgba)
, 255), 0);
alpha = useAltAlpha ? altAlpha : R_GetRgbaA(exc_addend->rgba);
alpha = max(min(R_GetRgbaA(exc_augend->rgba) + (subA ? -1 : 1) * alpha, 25), 0);
exc_augend->rgba = R_PutRgbaRGBA(red, green, blue, alpha);
///////////////////
// fade/dark rgba
///////////////////
red = max(min(
R_GetRgbaR(exc_augend->fadergba)
+ (subFadeR ? -1 : 1) // subtract R
* R_GetRgbaR(exc_addend->fadergba)
, 255), 0);
green = max(min(
R_GetRgbaG(exc_augend->fadergba)
+ (subFadeG ? -1 : 1) // subtract G
* R_GetRgbaG(exc_addend->fadergba)
, 255), 0);
blue = max(min(
R_GetRgbaB(exc_augend->fadergba)
+ (subFadeB ? -1 : 1) // subtract B
* R_GetRgbaB(exc_addend->fadergba)
, 255), 0);
alpha = useAltAlpha ? altFadeAlpha : R_GetRgbaA(exc_addend->fadergba);
if (alpha == 25 && !useAltAlpha && !R_GetRgbaRGB(exc_addend->fadergba))
alpha = 0; // HACK: fadergba A defaults at 25, so don't add anything in this case
alpha = max(min(R_GetRgbaA(exc_augend->fadergba) + (subFadeA ? -1 : 1) * alpha, 25), 0);
exc_augend->fadergba = R_PutRgbaRGBA(red, green, blue, alpha);
///////////////////
// parameters
///////////////////
exc_augend->fadestart = max(min(
exc_augend->fadestart
+ (subFadeStart ? -1 : 1) // subtract fadestart
* exc_addend->fadestart
, 31), 0);
exc_augend->fadeend = max(min(
exc_augend->fadeend
+ (subFadeEnd ? -1 : 1) // subtract fadeend
* (exc_addend->fadeend == 31 && !exc_addend->fadestart ? 0 : exc_addend->fadeend)
// HACK: fadeend defaults to 31, so don't add anything in this case
, 31), 0);
if (!ignoreFog) // overwrite fog with new value
exc_augend->fog = exc_addend->fog;
///////////////////
// put it together
///////////////////
exc_augend->colormap = lighttable ? R_CreateLightTable(exc_augend) : NULL;
exc_augend->next = exc_augend->prev = NULL;
return exc_augend;
} }
// Thanks to quake2 source! // Thanks to quake2 source!
@ -1592,20 +2041,18 @@ static int RoundUp(double number)
return (int)number; return (int)number;
} }
const char *R_ColormapNameForNum(INT32 num) #ifdef EXTRACOLORMAPLUMPS
const char *R_NameForColormap(extracolormap_t *extra_colormap)
{ {
if (num == -1) if (!extra_colormap)
return "NONE"; return "NONE";
if (num < 0 || num > MAXCOLORMAPS) if (extra_colormap->lump == LUMPERROR)
I_Error("R_ColormapNameForNum: num %d is invalid!\n", num);
if (foundcolormaps[num] == LUMPERROR)
return "INLEVEL"; return "INLEVEL";
return W_CheckNameForNum(foundcolormaps[num]); return extra_colormap->lumpname;
} }
#endif
// //
// build a table for quick conversion from 8bpp to 15bpp // build a table for quick conversion from 8bpp to 15bpp

View file

@ -96,11 +96,57 @@ void R_ClearTextureNumCache(boolean btell);
INT32 R_TextureNumForName(const char *name); INT32 R_TextureNumForName(const char *name);
INT32 R_CheckTextureNumForName(const char *name); INT32 R_CheckTextureNumForName(const char *name);
// Extra Colormap lumps (C_START/C_END) are not used anywhere
// Uncomment to enable
//#define EXTRACOLORMAPLUMPS
// Uncomment to make extra_colormaps order Newest -> Oldest
//#define COLORMAPREVERSELIST
void R_ReInitColormaps(UINT16 num); void R_ReInitColormaps(UINT16 num);
void R_ClearColormaps(void); void R_ClearColormaps(void);
INT32 R_ColormapNumForName(char *name); extracolormap_t *R_CreateDefaultColormap(boolean lighttable);
INT32 R_CreateColormap(char *p1, char *p2, char *p3); extracolormap_t *R_GetDefaultColormap(void);
const char *R_ColormapNameForNum(INT32 num); extracolormap_t *R_CopyColormap(extracolormap_t *extra_colormap, boolean lighttable);
void R_AddColormapToList(extracolormap_t *extra_colormap);
#ifdef EXTRACOLORMAPLUMPS
boolean R_CheckDefaultColormapByValues(boolean checkrgba, boolean checkfadergba, boolean checkparams,
INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 fog, lumpnum_t lump);
extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 fog, lumpnum_t lump);
#else
boolean R_CheckDefaultColormapByValues(boolean checkrgba, boolean checkfadergba, boolean checkparams,
INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 fog);
extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 fog);
#endif
boolean R_CheckDefaultColormap(extracolormap_t *extra_colormap, boolean checkrgba, boolean checkfadergba, boolean checkparams);
boolean R_CheckEqualColormaps(extracolormap_t *exc_a, extracolormap_t *exc_b, boolean checkrgba, boolean checkfadergba, boolean checkparams);
extracolormap_t *R_GetColormapFromList(extracolormap_t *extra_colormap);
lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap);
extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3);
extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *exc_addend,
boolean subR, boolean subG, boolean subB, boolean subA,
boolean subFadeR, boolean subFadeG, boolean subFadeB, boolean subFadeA,
boolean subFadeStart, boolean subFadeEnd, boolean ignoreFog,
boolean useAltAlpha, INT16 altAlpha, INT16 altFadeAlpha,
boolean lighttable);
#ifdef EXTRACOLORMAPLUMPS
extracolormap_t *R_ColormapForName(char *name);
const char *R_NameForColormap(extracolormap_t *extra_colormap);
#endif
#define R_GetRgbaR(rgba) (rgba & 0xFF)
#define R_GetRgbaG(rgba) ((rgba >> 8) & 0xFF)
#define R_GetRgbaB(rgba) ((rgba >> 16) & 0xFF)
#define R_GetRgbaA(rgba) ((rgba >> 24) & 0xFF)
#define R_GetRgbaRGB(rgba) (rgba & 0xFFFFFF)
#define R_PutRgbaR(r) (r)
#define R_PutRgbaG(g) (g << 8)
#define R_PutRgbaB(b) (b << 16)
#define R_PutRgbaA(a) (a << 24)
#define R_PutRgbaRGB(r, g, b) (R_PutRgbaR(r) + R_PutRgbaG(g) + R_PutRgbaB(b))
#define R_PutRgbaRGBA(r, g, b, a) (R_PutRgbaRGB(r, g, b) + R_PutRgbaA(a))
extern INT32 numtextures; extern INT32 numtextures;

View file

@ -50,18 +50,25 @@ typedef struct
typedef UINT8 lighttable_t; typedef UINT8 lighttable_t;
// ExtraColormap type. Use for extra_colormaps from now on. // ExtraColormap type. Use for extra_colormaps from now on.
typedef struct typedef struct extracolormap_s
{ {
UINT16 maskcolor, fadecolor; UINT8 fadestart, fadeend;
double maskamt; UINT8 fog; // categorical value, not boolean
UINT16 fadestart, fadeend;
INT32 fog;
// rgba is used in hw mode for colored sector lighting // store rgba values in combined bitwise
// also used in OpenGL instead lighttables
INT32 rgba; // similar to maskcolor in sw mode INT32 rgba; // similar to maskcolor in sw mode
INT32 fadergba; // The colour the colourmaps fade to INT32 fadergba; // The colour the colourmaps fade to
lighttable_t *colormap; lighttable_t *colormap;
#ifdef EXTRACOLORMAPLUMPS
lumpnum_t lump; // for colormap lump matching, init to LUMPERROR
char lumpname[9]; // for netsyncing
#endif
struct extracolormap_s *next;
struct extracolormap_s *prev;
} extracolormap_t; } extracolormap_t;
// //
@ -187,7 +194,7 @@ typedef struct lightlist_s
{ {
fixed_t height; fixed_t height;
INT16 *lightlevel; INT16 *lightlevel;
extracolormap_t *extra_colormap; extracolormap_t **extra_colormap; // pointer-to-a-pointer, so we can react to colormap changes
INT32 flags; INT32 flags;
ffloor_t *caster; ffloor_t *caster;
#ifdef ESLOPE #ifdef ESLOPE
@ -308,6 +315,7 @@ typedef struct sector_s
void *floordata; // floor move thinker void *floordata; // floor move thinker
void *ceilingdata; // ceiling move thinker void *ceilingdata; // ceiling move thinker
void *lightingdata; // lighting change thinker void *lightingdata; // lighting change thinker
void *fadecolormapdata; // fade colormap thinker
// floor and ceiling texture offsets // floor and ceiling texture offsets
fixed_t floor_xoffs, floor_yoffs; fixed_t floor_xoffs, floor_yoffs;
@ -323,8 +331,6 @@ typedef struct sector_s
INT32 floorlightsec, ceilinglightsec; INT32 floorlightsec, ceilinglightsec;
INT32 crumblestate; // used for crumbling and bobbing INT32 crumblestate; // used for crumbling and bobbing
INT32 bottommap, midmap, topmap; // dynamic colormaps
// list of mobjs that are at least partially in the sector // list of mobjs that are at least partially in the sector
// thinglist is a subset of touching_thinglist // thinglist is a subset of touching_thinglist
struct msecnode_s *touching_thinglist; struct msecnode_s *touching_thinglist;
@ -385,7 +391,6 @@ typedef struct sector_s
// these are saved for netgames, so do not let Lua touch these! // these are saved for netgames, so do not let Lua touch these!
INT32 spawn_nexttag, spawn_firsttag; // the actual nexttag/firsttag values may differ if the sector's tag was changed INT32 spawn_nexttag, spawn_firsttag; // the actual nexttag/firsttag values may differ if the sector's tag was changed
INT32 spawn_bottommap, spawn_midmap, spawn_topmap;
// offsets sector spawned with (via linedef type 7) // offsets sector spawned with (via linedef type 7)
fixed_t spawn_flr_xoffs, spawn_flr_yoffs; fixed_t spawn_flr_xoffs, spawn_flr_yoffs;
@ -394,6 +399,9 @@ typedef struct sector_s
// flag angles sector spawned with (via linedef type 7) // flag angles sector spawned with (via linedef type 7)
angle_t spawn_flrpic_angle; angle_t spawn_flrpic_angle;
angle_t spawn_ceilpic_angle; angle_t spawn_ceilpic_angle;
// colormap structure
extracolormap_t *spawn_extra_colormap;
} sector_t; } sector_t;
// //
@ -469,6 +477,8 @@ typedef struct
INT16 repeatcnt; // # of times to repeat midtexture INT16 repeatcnt; // # of times to repeat midtexture
char *text; // a concatination of all top, bottom, and mid texture names, for linedef specials that require a string. char *text; // a concatination of all top, bottom, and mid texture names, for linedef specials that require a string.
extracolormap_t *colormap_data; // storage for colormaps; not applied to sectors.
} side_t; } side_t;
// //

View file

@ -118,8 +118,7 @@ lighttable_t *scalelightfixed[MAXLIGHTSCALE];
lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ]; lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ];
// Hack to support extra boom colormaps. // Hack to support extra boom colormaps.
size_t num_extra_colormaps; extracolormap_t *extra_colormaps = NULL;
extracolormap_t extra_colormaps[MAXCOLORMAPS];
static CV_PossibleValue_t drawdist_cons_t[] = { static CV_PossibleValue_t drawdist_cons_t[] = {
{256, "256"}, {512, "512"}, {768, "768"}, {256, "256"}, {512, "512"}, {768, "768"},

View file

@ -413,7 +413,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
#endif #endif
rlight->startheight = rlight->height; // keep starting value here to reset for each repeat rlight->startheight = rlight->height; // keep starting value here to reset for each repeat
rlight->lightlevel = *light->lightlevel; rlight->lightlevel = *light->lightlevel;
rlight->extra_colormap = light->extra_colormap; rlight->extra_colormap = *light->extra_colormap;
rlight->flags = light->flags; rlight->flags = light->flags;
if (rlight->flags & FF_FOG || (rlight->extra_colormap && rlight->extra_colormap->fog)) if (rlight->flags & FF_FOG || (rlight->extra_colormap && rlight->extra_colormap->fog))
@ -944,7 +944,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
} }
rlight->lightlevel = *light->lightlevel; rlight->lightlevel = *light->lightlevel;
rlight->extra_colormap = light->extra_colormap; rlight->extra_colormap = *light->extra_colormap;
// Check if the current light effects the colormap/lightlevel // Check if the current light effects the colormap/lightlevel
if (pfloor->flags & FF_FOG) if (pfloor->flags & FF_FOG)
@ -2808,7 +2808,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
} }
rlight->lightlevel = *light->lightlevel; rlight->lightlevel = *light->lightlevel;
rlight->extra_colormap = light->extra_colormap; rlight->extra_colormap = *light->extra_colormap;
p++; p++;
} }

View file

@ -40,11 +40,7 @@ extern sprcache_t *spritecachedinfo;
extern lighttable_t *colormaps; extern lighttable_t *colormaps;
// Boom colormaps. // Boom colormaps.
// Had to put a limit on colormaps :( extern extracolormap_t *extra_colormaps;
#define MAXCOLORMAPS 60
extern size_t num_extra_colormaps;
extern extracolormap_t extra_colormaps[MAXCOLORMAPS];
// for global animation // for global animation
extern INT32 *texturetranslation; extern INT32 *texturetranslation;

View file

@ -981,7 +981,7 @@ static void R_SplitSprite(vissprite_t *sprite)
else else
spritelights = scalelight[lightnum]; spritelights = scalelight[lightnum];
newsprite->extra_colormap = sector->lightlist[i].extra_colormap; newsprite->extra_colormap = *sector->lightlist[i].extra_colormap;
if (!((newsprite->cut & SC_FULLBRIGHT) if (!((newsprite->cut & SC_FULLBRIGHT)
&& (!newsprite->extra_colormap || !(newsprite->extra_colormap->fog & 1)))) && (!newsprite->extra_colormap || !(newsprite->extra_colormap->fog & 1))))
@ -1360,7 +1360,7 @@ static void R_ProjectSprite(mobj_t *thing)
vis->sz = (INT16)((centeryfrac - FixedMul(vis->gz - viewz, sortscale))>>FRACBITS); vis->sz = (INT16)((centeryfrac - FixedMul(vis->gz - viewz, sortscale))>>FRACBITS);
vis->cut = cut; vis->cut = cut;
if (thing->subsector->sector->numlights) if (thing->subsector->sector->numlights)
vis->extra_colormap = thing->subsector->sector->lightlist[light].extra_colormap; vis->extra_colormap = *thing->subsector->sector->lightlist[light].extra_colormap;
else else
vis->extra_colormap = thing->subsector->sector->extra_colormap; vis->extra_colormap = thing->subsector->sector->extra_colormap;

View file

@ -38,7 +38,7 @@ extern INT32 msg_id;
#include "p_local.h" // camera info #include "p_local.h" // camera info
#include "fastcmp.h" #include "fastcmp.h"
#ifdef HAVE_BLUA #if defined(HAVE_BLUA) && defined(HAVE_LUA_MUSICPLUS)
#include "lua_hook.h" // MusicChange hook #include "lua_hook.h" // MusicChange hook
#endif #endif
@ -1592,14 +1592,17 @@ void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32
S_StopMusic(); S_StopMusic();
if (!S_LoadMusic(newmusic)) if (!S_LoadMusic(newmusic))
{
CONS_Alert(CONS_ERROR, "Music %.6s could not be loaded!\n", newmusic);
return; return;
}
music_flags = mflags; music_flags = mflags;
music_looping = looping; music_looping = looping;
if (!S_PlayMusic(looping, fadeinms)) if (!S_PlayMusic(looping, fadeinms))
{ {
CONS_Alert(CONS_ERROR, "Music cannot be played!\n"); CONS_Alert(CONS_ERROR, "Music %.6s could not be played!\n", newmusic);
return; return;
} }

View file

@ -1144,6 +1144,8 @@ boolean I_PlaySong(boolean looping)
void I_StopSong(void) void I_StopSong(void)
{ {
I_StopFadingSong();
#ifdef HAVE_LIBGME #ifdef HAVE_LIBGME
if (gme) if (gme)
{ {
@ -1153,12 +1155,12 @@ void I_StopSong(void)
#endif #endif
if (music) if (music)
{ {
var_cleanup();
I_StopFadingSong();
Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes); Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes);
Mix_HookMusicFinished(NULL); Mix_HookMusicFinished(NULL);
Mix_HaltMusic(); Mix_HaltMusic();
} }
var_cleanup();
} }
void I_PauseSong() void I_PauseSong()

View file

@ -1480,7 +1480,7 @@ void I_StopFadingSong(void)
{ {
} }
boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void)); boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void))
{ {
(void)target_volume; (void)target_volume;
(void)source_volume; (void)source_volume;
@ -1488,7 +1488,7 @@ boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms
return false; return false;
} }
boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void)); boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void))
{ {
(void)target_volume; (void)target_volume;
(void)ms; (void)ms;

View file

@ -812,10 +812,10 @@ void I_SetMusicVolume(UINT8 volume)
UINT32 I_GetSongLength() UINT32 I_GetSongLength()
{ {
if (midimode) if (I_SongType() == MU_MID)
return 0; return 0;
UINT32 length; UINT32 length;
e = FMOD_Sound_GetLength(music_stream, length, FMOD_TIMEUNIT_MS); FMR_MUSIC(FMOD_Sound_GetLength(music_stream, &length, FMOD_TIMEUNIT_MS));
return length; return length;
} }
@ -832,7 +832,7 @@ UINT32 I_GetSongLoopPoint(void)
boolean I_SetSongPosition(UINT32 position) boolean I_SetSongPosition(UINT32 position)
{ {
if(midimode) if(I_SongType() == MU_MID)
// Dummy out; this works for some MIDI, but not others. // Dummy out; this works for some MIDI, but not others.
// SDL does not support this for any MIDI. // SDL does not support this for any MIDI.
return false; return false;
@ -852,7 +852,7 @@ boolean I_SetSongPosition(UINT32 position)
UINT32 I_GetSongPosition(void) UINT32 I_GetSongPosition(void)
{ {
if(midimode) if(I_SongType() == MU_MID)
// Dummy out because unsupported, even though FMOD does this correctly. // Dummy out because unsupported, even though FMOD does this correctly.
return 0; return 0;
FMOD_RESULT e; FMOD_RESULT e;
@ -922,7 +922,7 @@ void I_StopFadingSong(void)
{ {
} }
boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void)); boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void))
{ {
(void)target_volume; (void)target_volume;
(void)source_volume; (void)source_volume;
@ -930,7 +930,7 @@ boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms
return false; return false;
} }
boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void)); boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void))
{ {
(void)target_volume; (void)target_volume;
(void)ms; (void)ms;