mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2025-03-20 01:43:50 +00:00
With permission from Kart Krew (Sal and Sryder specifically - they don't know WHY vanilla's using it):
* Port across the additional colour translation maps, including mobj-level support for "colorized" objects. * Make Fangboss and both Metal Sonic objects greyscale if, on spawn, there is a player in the game who is not a spectator whose skin is that character. * Allow bosses with MF_GRENADEBOUNCE to opt out of the MF2_FRET colour-flashing tomfoolery, and give this flag to Fang.
This commit is contained in:
parent
96d6cea569
commit
1d65caa250
12 changed files with 286 additions and 57 deletions
|
@ -28,6 +28,7 @@
|
|||
#include "p_local.h" // for var1 and var2, and some constants
|
||||
#include "p_setup.h"
|
||||
#include "r_data.h"
|
||||
#include "r_draw.h"
|
||||
#include "r_sky.h"
|
||||
#include "fastcmp.h"
|
||||
#include "lua_script.h"
|
||||
|
@ -8728,6 +8729,14 @@ struct {
|
|||
{"KR_TIMEOUT",KR_TIMEOUT},
|
||||
{"KR_BAN",KR_BAN},
|
||||
{"KR_LEAVE",KR_LEAVE},
|
||||
|
||||
// translation colormaps
|
||||
{"TC_DEFAULT",TC_DEFAULT},
|
||||
{"TC_BOSS",TC_BOSS},
|
||||
{"TC_METALSONIC",TC_METALSONIC},
|
||||
{"TC_ALLWHITE",TC_ALLWHITE},
|
||||
{"TC_RAINBOW",TC_RAINBOW},
|
||||
{"TC_BLINK",TC_BLINK},
|
||||
#endif
|
||||
|
||||
{NULL,0}
|
||||
|
|
|
@ -5660,7 +5660,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
|
|||
vis->z2 = z2;
|
||||
|
||||
//Hurdler: 25/04/2000: now support colormap in hardware mode
|
||||
if ((vis->mobj->flags & MF_BOSS) && (vis->mobj->flags2 & MF2_FRET) && (leveltime & 1)) // Bosses "flash"
|
||||
if ((vis->mobj->flags & MF_BOSS) && (vis->mobj->flags2 & MF2_FRET) && !(vis->mobj->flags & MF_GRENADEBOUNCE) && (leveltime & 1)) // Bosses "flash"
|
||||
{
|
||||
if (vis->mobj->type == MT_CYBRAKDEMON)
|
||||
vis->colormap = R_GetTranslationColormap(TC_ALLWHITE, 0, GTC_CACHE);
|
||||
|
@ -5672,7 +5672,9 @@ static void HWR_ProjectSprite(mobj_t *thing)
|
|||
else if (thing->color)
|
||||
{
|
||||
// New colormap stuff for skins Tails 06-07-2002
|
||||
if (thing->skin && thing->sprite == SPR_PLAY) // This thing is a player!
|
||||
if (thing->colorized)
|
||||
vis->colormap = R_GetTranslationColormap(TC_RAINBOW, thing->color, GTC_CACHE);
|
||||
else if (thing->skin && thing->sprite == SPR_PLAY) // This thing is a player!
|
||||
{
|
||||
size_t skinnum = (skin_t*)thing->skin-skins;
|
||||
vis->colormap = R_GetTranslationColormap((INT32)skinnum, thing->color, GTC_CACHE);
|
||||
|
|
|
@ -40,6 +40,8 @@
|
|||
#include "../w_wad.h"
|
||||
#include "../z_zone.h"
|
||||
#include "../r_things.h"
|
||||
#include "../r_draw.h"
|
||||
#include "../p_tick.h"
|
||||
|
||||
#include "hw_main.h"
|
||||
#include "../v_video.h"
|
||||
|
@ -978,8 +980,18 @@ spritemd2found:
|
|||
fclose(f);
|
||||
}
|
||||
|
||||
static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, GLMipmap_t *grmip, skincolors_t color)
|
||||
// Define for getting accurate color brightness readings according to how the human eye sees them.
|
||||
// https://en.wikipedia.org/wiki/Relative_luminance
|
||||
// 0.2126 to red
|
||||
// 0.7152 to green
|
||||
// 0.0722 to blue
|
||||
// (See this same define in k_kart.c!)
|
||||
#define SETBRIGHTNESS(brightness,r,g,b) \
|
||||
brightness = (UINT8)(((1063*((UINT16)r)/5000) + (3576*((UINT16)g)/5000) + (361*((UINT16)b)/5000)) / 3)
|
||||
|
||||
static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, GLMipmap_t *grmip, INT32 skinnum, skincolors_t color)
|
||||
{
|
||||
UINT8 i;
|
||||
UINT16 w = gpatch->width, h = gpatch->height;
|
||||
UINT32 size = w*h;
|
||||
RGBA_t *image, *blendimage, *cur, blendcolor;
|
||||
|
@ -1005,50 +1017,112 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch,
|
|||
image = gpatch->mipmap.grInfo.data;
|
||||
blendimage = blendgpatch->mipmap.grInfo.data;
|
||||
|
||||
// Average all of the translation's colors
|
||||
if (color == SKINCOLOR_NONE || color >= MAXTRANSLATIONS)
|
||||
blendcolor = V_GetColor(0xff);
|
||||
else
|
||||
blendcolor = V_GetColor(Color_Index[color-1][4]);
|
||||
|
||||
while (size--)
|
||||
{
|
||||
if (blendimage->s.alpha == 0)
|
||||
{
|
||||
// Don't bother with blending the pixel if the alpha of the blend pixel is 0
|
||||
cur->rgba = image->rgba;
|
||||
}
|
||||
else
|
||||
{
|
||||
INT32 tempcolor;
|
||||
INT16 tempmult, tempalpha;
|
||||
tempalpha = -(abs(blendimage->s.red-127)-127)*2;
|
||||
if (tempalpha > 255)
|
||||
tempalpha = 255;
|
||||
else if (tempalpha < 0)
|
||||
tempalpha = 0;
|
||||
const UINT8 div = 6;
|
||||
const UINT8 start = 4;
|
||||
UINT32 r, g, b;
|
||||
|
||||
tempmult = (blendimage->s.red-127)*2;
|
||||
if (tempmult > 255)
|
||||
tempmult = 255;
|
||||
else if (tempmult < 0)
|
||||
tempmult = 0;
|
||||
blendcolor = V_GetColor(Color_Index[color-1][start]);
|
||||
r = (UINT32)(blendcolor.s.red*blendcolor.s.red);
|
||||
g = (UINT32)(blendcolor.s.green*blendcolor.s.green);
|
||||
b = (UINT32)(blendcolor.s.blue*blendcolor.s.blue);
|
||||
|
||||
tempcolor = (image->s.red*(255-blendimage->s.alpha))/255 + ((tempmult + ((tempalpha*blendcolor.s.red)/255)) * blendimage->s.alpha)/255;
|
||||
cur->s.red = (UINT8)tempcolor;
|
||||
tempcolor = (image->s.green*(255-blendimage->s.alpha))/255 + ((tempmult + ((tempalpha*blendcolor.s.green)/255)) * blendimage->s.alpha)/255;
|
||||
cur->s.green = (UINT8)tempcolor;
|
||||
tempcolor = (image->s.blue*(255-blendimage->s.alpha))/255 + ((tempmult + ((tempalpha*blendcolor.s.blue)/255)) * blendimage->s.alpha)/255;
|
||||
cur->s.blue = (UINT8)tempcolor;
|
||||
cur->s.alpha = image->s.alpha;
|
||||
for (i = 1; i < div; i++)
|
||||
{
|
||||
RGBA_t nextcolor = V_GetColor(Color_Index[color-1][start+i]);
|
||||
r += (UINT32)(nextcolor.s.red*nextcolor.s.red);
|
||||
g += (UINT32)(nextcolor.s.green*nextcolor.s.green);
|
||||
b += (UINT32)(nextcolor.s.blue*nextcolor.s.blue);
|
||||
}
|
||||
|
||||
cur++; image++; blendimage++;
|
||||
blendcolor.s.red = (UINT8)(FixedSqrt((r/div)<<FRACBITS)>>FRACBITS);
|
||||
blendcolor.s.green = (UINT8)(FixedSqrt((g/div)<<FRACBITS)>>FRACBITS);
|
||||
blendcolor.s.blue = (UINT8)(FixedSqrt((b/div)<<FRACBITS)>>FRACBITS);
|
||||
}
|
||||
|
||||
// rainbow support, could theoretically support boss ones too
|
||||
if (skinnum == TC_RAINBOW)
|
||||
{
|
||||
while (size--)
|
||||
{
|
||||
if (image->s.alpha == 0 && blendimage->s.alpha == 0)
|
||||
{
|
||||
// Don't bother with blending the pixel if the alpha of the blend pixel is 0
|
||||
cur->rgba = image->rgba;
|
||||
}
|
||||
else
|
||||
{
|
||||
UINT32 tempcolor;
|
||||
UINT16 imagebright, blendbright, finalbright, colorbright;
|
||||
SETBRIGHTNESS(imagebright,image->s.red,image->s.green,image->s.blue);
|
||||
SETBRIGHTNESS(blendbright,blendimage->s.red,blendimage->s.green,blendimage->s.blue);
|
||||
// slightly dumb average between the blend image color and base image colour, usually one or the other will be fully opaque anyway
|
||||
finalbright = (imagebright*(255-blendimage->s.alpha))/255 + (blendbright*blendimage->s.alpha)/255;
|
||||
SETBRIGHTNESS(colorbright,blendcolor.s.red,blendcolor.s.green,blendcolor.s.blue);
|
||||
|
||||
tempcolor = (finalbright*blendcolor.s.red)/colorbright;
|
||||
tempcolor = min(255, tempcolor);
|
||||
cur->s.red = (UINT8)tempcolor;
|
||||
tempcolor = (finalbright*blendcolor.s.green)/colorbright;
|
||||
tempcolor = min(255, tempcolor);
|
||||
cur->s.green = (UINT8)tempcolor;
|
||||
tempcolor = (finalbright*blendcolor.s.blue)/colorbright;
|
||||
tempcolor = min(255, tempcolor);
|
||||
cur->s.blue = (UINT8)tempcolor;
|
||||
cur->s.alpha = image->s.alpha;
|
||||
}
|
||||
|
||||
cur++; image++; blendimage++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (size--)
|
||||
{
|
||||
if (blendimage->s.alpha == 0)
|
||||
{
|
||||
// Don't bother with blending the pixel if the alpha of the blend pixel is 0
|
||||
cur->rgba = image->rgba;
|
||||
}
|
||||
else
|
||||
{
|
||||
INT32 tempcolor;
|
||||
INT16 tempmult, tempalpha;
|
||||
tempalpha = -(abs(blendimage->s.red-127)-127)*2;
|
||||
if (tempalpha > 255)
|
||||
tempalpha = 255;
|
||||
else if (tempalpha < 0)
|
||||
tempalpha = 0;
|
||||
|
||||
tempmult = (blendimage->s.red-127)*2;
|
||||
if (tempmult > 255)
|
||||
tempmult = 255;
|
||||
else if (tempmult < 0)
|
||||
tempmult = 0;
|
||||
|
||||
tempcolor = (image->s.red*(255-blendimage->s.alpha))/255 + ((tempmult + ((tempalpha*blendcolor.s.red)/255)) * blendimage->s.alpha)/255;
|
||||
cur->s.red = (UINT8)tempcolor;
|
||||
tempcolor = (image->s.green*(255-blendimage->s.alpha))/255 + ((tempmult + ((tempalpha*blendcolor.s.green)/255)) * blendimage->s.alpha)/255;
|
||||
cur->s.green = (UINT8)tempcolor;
|
||||
tempcolor = (image->s.blue*(255-blendimage->s.alpha))/255 + ((tempmult + ((tempalpha*blendcolor.s.blue)/255)) * blendimage->s.alpha)/255;
|
||||
cur->s.blue = (UINT8)tempcolor;
|
||||
cur->s.alpha = image->s.alpha;
|
||||
}
|
||||
|
||||
cur++; image++; blendimage++;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, const UINT8 *colormap, skincolors_t color)
|
||||
#undef SETBRIGHTNESS
|
||||
|
||||
static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, INT32 skinnum, const UINT8 *colormap, skincolors_t color)
|
||||
{
|
||||
// mostly copied from HWR_GetMappedPatch, hence the similarities and comment
|
||||
GLMipmap_t *grmip, *newmip;
|
||||
|
@ -1089,13 +1163,14 @@ static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, con
|
|||
grmip->nextcolormap = newmip;
|
||||
newmip->colormap = colormap;
|
||||
|
||||
HWR_CreateBlendedTexture(gpatch, blendgpatch, newmip, color);
|
||||
HWR_CreateBlendedTexture(gpatch, blendgpatch, newmip, skinnum, color);
|
||||
|
||||
HWD.pfnSetTexture(newmip);
|
||||
Z_ChangeTag(newmip->grInfo.data, PU_HWRCACHE_UNLOCKED);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// -----------------+
|
||||
// HWR_DrawMD2 : Draw MD2
|
||||
// : (monsters, bonuses, weapons, lights, ...)
|
||||
|
@ -1285,7 +1360,30 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
|
|||
md2->blendgrpatch && ((GLPatch_t *)md2->blendgrpatch)->mipmap.grInfo.format
|
||||
&& gpatch->width == ((GLPatch_t *)md2->blendgrpatch)->width && gpatch->height == ((GLPatch_t *)md2->blendgrpatch)->height)
|
||||
{
|
||||
HWR_GetBlendedTexture(gpatch, (GLPatch_t *)md2->blendgrpatch, spr->colormap, (skincolors_t)spr->mobj->color);
|
||||
INT32 skinnum = TC_DEFAULT;
|
||||
if ((spr->mobj->flags & (MF_ENEMY|MF_BOSS)) && (spr->mobj->flags2 & MF2_FRET) && !(spr->mobj->flags & MF_GRENADEBOUNCE) && (leveltime & 1)) // Bosses "flash"
|
||||
{
|
||||
if (spr->mobj->type == MT_CYBRAKDEMON)
|
||||
skinnum = TC_ALLWHITE;
|
||||
else if (spr->mobj->type == MT_METALSONIC_BATTLE)
|
||||
skinnum = TC_METALSONIC;
|
||||
else
|
||||
skinnum = TC_BOSS;
|
||||
}
|
||||
else if (spr->mobj->color)
|
||||
{
|
||||
if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY)
|
||||
{
|
||||
if (spr->mobj->colorized)
|
||||
skinnum = TC_RAINBOW;
|
||||
else
|
||||
{
|
||||
skinnum = (INT32)((skin_t*)spr->mobj->skin-skins);
|
||||
}
|
||||
}
|
||||
else skinnum = TC_DEFAULT;
|
||||
}
|
||||
HWR_GetBlendedTexture(gpatch, (GLPatch_t *)md2->blendgrpatch, skinnum, spr->colormap, (skincolors_t)spr->mobj->color);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -5397,7 +5397,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
0, // mass
|
||||
3, // damage
|
||||
sfx_boingf, // activesound
|
||||
MF_SPECIAL|MF_BOSS|MF_SHOOTABLE, // flags
|
||||
MF_SPECIAL|MF_BOSS|MF_SHOOTABLE|MF_GRENADEBOUNCE, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
|
|
@ -670,8 +670,8 @@ static int libd_getColormap(lua_State *L)
|
|||
else if (lua_type(L, 1) == LUA_TNUMBER) // skin number
|
||||
{
|
||||
skinnum = (INT32)luaL_checkinteger(L, 1);
|
||||
if (skinnum < TC_ALLWHITE || skinnum >= MAXSKINS)
|
||||
return luaL_error(L, "skin number %d is out of range (%d - %d)", skinnum, TC_ALLWHITE, MAXSKINS-1);
|
||||
if (skinnum < TC_BLINK || skinnum >= MAXSKINS)
|
||||
return luaL_error(L, "skin number %d is out of range (%d - %d)", skinnum, TC_BLINK, MAXSKINS-1);
|
||||
}
|
||||
else // skin name
|
||||
{
|
||||
|
|
|
@ -83,12 +83,11 @@ enum mobj_e {
|
|||
mobj_extravalue1,
|
||||
mobj_extravalue2,
|
||||
mobj_cusval,
|
||||
#ifdef ESLOPE
|
||||
mobj_cvmem,
|
||||
mobj_standingslope
|
||||
#else
|
||||
mobj_cvmem
|
||||
#ifdef ESLOPE
|
||||
mobj_standingslope,
|
||||
#endif
|
||||
mobj_colorized
|
||||
};
|
||||
|
||||
static const char *const mobj_opt[] = {
|
||||
|
@ -154,6 +153,7 @@ static const char *const mobj_opt[] = {
|
|||
#ifdef ESLOPE
|
||||
"standingslope",
|
||||
#endif
|
||||
"colorized",
|
||||
NULL};
|
||||
|
||||
#define UNIMPLEMENTED luaL_error(L, LUA_QL("mobj_t") " field " LUA_QS " is not implemented for Lua and cannot be accessed.", mobj_opt[field])
|
||||
|
@ -371,6 +371,9 @@ static int mobj_get(lua_State *L)
|
|||
LUA_PushUserdata(L, mo->standingslope, META_SLOPE);
|
||||
break;
|
||||
#endif
|
||||
case mobj_colorized:
|
||||
lua_pushboolean(L, mo->colorized);
|
||||
break;
|
||||
default: // extra custom variables in Lua memory
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS);
|
||||
I_Assert(lua_istable(L, -1));
|
||||
|
@ -692,6 +695,9 @@ static int mobj_set(lua_State *L)
|
|||
case mobj_standingslope:
|
||||
return NOSET;
|
||||
#endif
|
||||
case mobj_colorized:
|
||||
mo->colorized = luaL_checkboolean(L, 3);
|
||||
break;
|
||||
default:
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS);
|
||||
I_Assert(lua_istable(L, -1));
|
||||
|
|
27
src/p_mobj.c
27
src/p_mobj.c
|
@ -8894,6 +8894,7 @@ void P_SceneryThinker(mobj_t *mobj)
|
|||
mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
|
||||
{
|
||||
const mobjinfo_t *info = &mobjinfo[type];
|
||||
UINT8 sc = -1;
|
||||
state_t *st;
|
||||
mobj_t *mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL);
|
||||
|
||||
|
@ -9150,6 +9151,13 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
|
|||
if (nummaprings >= 0)
|
||||
nummaprings++;
|
||||
break;
|
||||
case MT_METALSONIC_BATTLE:
|
||||
case MT_METALSONIC_RACE:
|
||||
sc = 3;
|
||||
break;
|
||||
case MT_FANG:
|
||||
sc = 4;
|
||||
break;
|
||||
case MT_FBOMB:
|
||||
mobj->flags2 |= MF2_EXPLOSION;
|
||||
break;
|
||||
|
@ -9157,6 +9165,23 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
|
|||
break;
|
||||
}
|
||||
|
||||
if (sc != -1)
|
||||
{
|
||||
UINT8 i;
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i] || players[i].spectator)
|
||||
continue;
|
||||
|
||||
if (players[i].skin == sc)
|
||||
{
|
||||
mobj->color = SKINCOLOR_SILVER;
|
||||
mobj->colorized = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!(mobj->flags & MF_NOTHINK))
|
||||
P_AddThinker(&mobj->thinker);
|
||||
|
||||
|
@ -9427,7 +9452,7 @@ consvar_t cv_flagtime = {"flagtime", "30", CV_NETVAR|CV_CHEAT, flagtime_cons_t,
|
|||
|
||||
void P_SpawnPrecipitation(void)
|
||||
{
|
||||
INT32 i, j, mrand;
|
||||
INT32 i, /*j,*/ mrand;
|
||||
fixed_t basex, basey, x, y, height;
|
||||
subsector_t *precipsector = NULL;
|
||||
precipmobj_t *rainmo = NULL;
|
||||
|
|
|
@ -371,6 +371,8 @@ typedef struct mobj_s
|
|||
struct pslope_s *standingslope; // The slope that the object is standing on (shouldn't need synced in savegames, right?)
|
||||
#endif
|
||||
|
||||
boolean colorized; // Whether the mobj uses the rainbow colormap
|
||||
|
||||
// WARNING: New fields must be added separately to savegame and Lua.
|
||||
} mobj_t;
|
||||
|
||||
|
|
|
@ -1262,12 +1262,11 @@ typedef enum
|
|||
MD2_HNEXT = 1<<7,
|
||||
MD2_HPREV = 1<<8,
|
||||
MD2_FLOORROVER = 1<<9,
|
||||
#ifdef ESLOPE
|
||||
MD2_CEILINGROVER = 1<<10,
|
||||
MD2_SLOPE = 1<<11
|
||||
#else
|
||||
MD2_CEILINGROVER = 1<<10
|
||||
#ifdef ESLOPE
|
||||
MD2_SLOPE = 1<<11,
|
||||
#endif
|
||||
MD2_COLORIZED = 1<<12,
|
||||
} mobj_diff2_t;
|
||||
|
||||
typedef enum
|
||||
|
@ -1473,6 +1472,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
|
|||
if (mobj->standingslope)
|
||||
diff2 |= MD2_SLOPE;
|
||||
#endif
|
||||
if (mobj->colorized)
|
||||
diff2 |= MD2_COLORIZED;
|
||||
if (diff2 != 0)
|
||||
diff |= MD_MORE;
|
||||
|
||||
|
@ -1635,6 +1636,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
|
|||
if (diff2 & MD2_SLOPE)
|
||||
WRITEUINT16(save_p, mobj->standingslope->id);
|
||||
#endif
|
||||
if (diff2 & MD2_COLORIZED)
|
||||
WRITEUINT8(save_p, mobj->colorized);
|
||||
|
||||
WRITEUINT32(save_p, mobj->mobjnum);
|
||||
}
|
||||
|
@ -2660,7 +2663,8 @@ static void LoadMobjThinker(actionf_p1 thinker)
|
|||
if (diff2 & MD2_SLOPE)
|
||||
mobj->standingslope = P_SlopeById(READUINT16(save_p));
|
||||
#endif
|
||||
|
||||
if (diff2 & MD2_COLORIZED)
|
||||
mobj->colorized = READUINT8(save_p);
|
||||
|
||||
if (diff & MD_REDFLAG)
|
||||
{
|
||||
|
|
87
src/r_draw.c
87
src/r_draw.c
|
@ -126,10 +126,12 @@ UINT32 nflatxshift, nflatyshift, nflatshiftup, nflatmask;
|
|||
#define BOSS_TT_CACHE_INDEX (MAXSKINS + 1)
|
||||
#define METALSONIC_TT_CACHE_INDEX (MAXSKINS + 2)
|
||||
#define ALLWHITE_TT_CACHE_INDEX (MAXSKINS + 3)
|
||||
#define RAINBOW_TT_CACHE_INDEX (MAXSKINS + 4)
|
||||
#define BLINK_TT_CACHE_INDEX (MAXSKINS + 5)
|
||||
#define DEFAULT_STARTTRANSCOLOR 96
|
||||
#define NUM_PALETTE_ENTRIES 256
|
||||
|
||||
static UINT8** translationtablecache[MAXSKINS + 4] = {NULL};
|
||||
static UINT8** translationtablecache[MAXSKINS + 6] = {NULL};
|
||||
|
||||
const UINT8 Color_Index[MAXTRANSLATIONS-1][16] = {
|
||||
// {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, // SKINCOLOR_NONE
|
||||
|
@ -457,17 +459,85 @@ void R_InitTranslationTables(void)
|
|||
|
||||
\return void
|
||||
*/
|
||||
|
||||
// Define for getting accurate color brightness readings according to how the human eye sees them.
|
||||
// https://en.wikipedia.org/wiki/Relative_luminance
|
||||
// 0.2126 to red
|
||||
// 0.7152 to green
|
||||
// 0.0722 to blue
|
||||
// (See this same define in hw_md2.c!)
|
||||
#define SETBRIGHTNESS(brightness,r,g,b) \
|
||||
brightness = (UINT8)(((1063*((UINT16)r)/5000) + (3576*((UINT16)g)/5000) + (361*((UINT16)b)/5000)) / 3)
|
||||
|
||||
/** \brief Generates the rainbow colourmaps that are used when a player has the invincibility power... stolen from kart, with permission
|
||||
|
||||
\param dest_colormap colormap to populate
|
||||
\param skincolor translation color
|
||||
*/
|
||||
static void R_RainbowColormap(UINT8 *dest_colormap, UINT8 skincolor)
|
||||
{
|
||||
INT32 i;
|
||||
RGBA_t color;
|
||||
UINT8 brightness;
|
||||
INT32 j;
|
||||
UINT8 colorbrightnesses[16];
|
||||
UINT16 brightdif;
|
||||
INT32 temp;
|
||||
|
||||
// first generate the brightness of all the colours of that skincolour
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
color = V_GetColor(Color_Index[skincolor-1][i]);
|
||||
SETBRIGHTNESS(colorbrightnesses[i], color.s.red, color.s.green, color.s.blue);
|
||||
}
|
||||
|
||||
// next, for every colour in the palette, choose the transcolor that has the closest brightness
|
||||
for (i = 0; i < NUM_PALETTE_ENTRIES; i++)
|
||||
{
|
||||
if (i == 0 || i == 31) // pure black and pure white don't change
|
||||
{
|
||||
dest_colormap[i] = (UINT8)i;
|
||||
continue;
|
||||
}
|
||||
color = V_GetColor(i);
|
||||
SETBRIGHTNESS(brightness, color.s.red, color.s.green, color.s.blue);
|
||||
brightdif = 256;
|
||||
for (j = 0; j < 16; j++)
|
||||
{
|
||||
temp = abs((INT16)brightness - (INT16)colorbrightnesses[j]);
|
||||
if (temp < brightdif)
|
||||
{
|
||||
brightdif = (UINT16)temp;
|
||||
dest_colormap[i] = Color_Index[skincolor-1][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#undef SETBRIGHTNESS
|
||||
|
||||
static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, UINT8 color)
|
||||
{
|
||||
INT32 i, starttranscolor, skinramplength;
|
||||
|
||||
// Handle a couple of simple special cases
|
||||
if (skinnum == TC_BOSS || skinnum == TC_ALLWHITE || skinnum == TC_METALSONIC || color == SKINCOLOR_NONE)
|
||||
if (skinnum == TC_BOSS
|
||||
|| skinnum == TC_ALLWHITE
|
||||
|| skinnum == TC_METALSONIC
|
||||
|| skinnum == TC_BLINK
|
||||
|| color == SKINCOLOR_NONE)
|
||||
{
|
||||
for (i = 0; i < NUM_PALETTE_ENTRIES; i++)
|
||||
if (skinnum == TC_ALLWHITE)
|
||||
memset(dest_colormap, 0, NUM_PALETTE_ENTRIES * sizeof(UINT8**));
|
||||
else if (skinnum == TC_BLINK && color != SKINCOLOR_NONE)
|
||||
{
|
||||
if (skinnum == TC_ALLWHITE) dest_colormap[i] = 0;
|
||||
else dest_colormap[i] = (UINT8)i;
|
||||
for (i = 0; i < NUM_PALETTE_ENTRIES; i++)
|
||||
dest_colormap[i] = Color_Index[color-1][3];
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < NUM_PALETTE_ENTRIES; i++)
|
||||
dest_colormap[i] = (UINT8)i;
|
||||
}
|
||||
|
||||
// White!
|
||||
|
@ -478,6 +548,11 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U
|
|||
|
||||
return;
|
||||
}
|
||||
else if (skinnum == TC_RAINBOW)
|
||||
{
|
||||
R_RainbowColormap(dest_colormap, color);
|
||||
return;
|
||||
}
|
||||
|
||||
if (color >= MAXTRANSLATIONS)
|
||||
I_Error("Invalid skin color #%hu.", (UINT16)color);
|
||||
|
@ -522,6 +597,8 @@ UINT8* R_GetTranslationColormap(INT32 skinnum, skincolors_t color, UINT8 flags)
|
|||
else if (skinnum == TC_BOSS) skintableindex = BOSS_TT_CACHE_INDEX;
|
||||
else if (skinnum == TC_METALSONIC) skintableindex = METALSONIC_TT_CACHE_INDEX;
|
||||
else if (skinnum == TC_ALLWHITE) skintableindex = ALLWHITE_TT_CACHE_INDEX;
|
||||
else if (skinnum == TC_RAINBOW) skintableindex = RAINBOW_TT_CACHE_INDEX;
|
||||
else if (skinnum == TC_BLINK) skintableindex = BLINK_TT_CACHE_INDEX;
|
||||
else skintableindex = skinnum;
|
||||
|
||||
if (flags & GTC_CACHE)
|
||||
|
|
|
@ -105,6 +105,8 @@ extern lumpnum_t viewborderlump[8];
|
|||
#define TC_BOSS -2
|
||||
#define TC_METALSONIC -3 // For Metal Sonic battle
|
||||
#define TC_ALLWHITE -4 // For Cy-Brak-demon
|
||||
#define TC_RAINBOW -5 // For single colour
|
||||
#define TC_BLINK -6 // For item blinking, according to kart
|
||||
|
||||
// Initialize color translation tables, for player rendering etc.
|
||||
void R_InitTranslationTables(void);
|
||||
|
|
|
@ -719,7 +719,7 @@ static void R_DrawVisSprite(vissprite_t *vis)
|
|||
|
||||
colfunc = basecolfunc; // hack: this isn't resetting properly somewhere.
|
||||
dc_colormap = vis->colormap;
|
||||
if (!(vis->cut & SC_PRECIP) && (vis->mobj->flags & (MF_ENEMY|MF_BOSS)) && (vis->mobj->flags2 & MF2_FRET) && (leveltime & 1)) // Bosses "flash"
|
||||
if (!(vis->cut & SC_PRECIP) && (vis->mobj->flags & (MF_ENEMY|MF_BOSS)) && (vis->mobj->flags2 & MF2_FRET) && !(vis->mobj->flags & MF_GRENADEBOUNCE) && (leveltime & 1)) // Bosses "flash"
|
||||
{
|
||||
// translate certain pixels to white
|
||||
colfunc = transcolfunc;
|
||||
|
@ -734,7 +734,9 @@ static void R_DrawVisSprite(vissprite_t *vis)
|
|||
{
|
||||
colfunc = transtransfunc;
|
||||
dc_transmap = vis->transmap;
|
||||
if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // MT_GHOST LOOKS LIKE A PLAYER SO USE THE PLAYER TRANSLATION TABLES. >_>
|
||||
if (!(vis->cut & SC_PRECIP) && vis->mobj->colorized)
|
||||
dc_translation = R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE);
|
||||
else if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // MT_GHOST LOOKS LIKE A PLAYER SO USE THE PLAYER TRANSLATION TABLES. >_>
|
||||
{
|
||||
size_t skinnum = (skin_t*)vis->mobj->skin-skins;
|
||||
dc_translation = R_GetTranslationColormap((INT32)skinnum, vis->mobj->color, GTC_CACHE);
|
||||
|
@ -753,7 +755,9 @@ static void R_DrawVisSprite(vissprite_t *vis)
|
|||
colfunc = transcolfunc;
|
||||
|
||||
// New colormap stuff for skins Tails 06-07-2002
|
||||
if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // This thing is a player!
|
||||
if (!(vis->cut & SC_PRECIP) && vis->mobj->colorized)
|
||||
dc_translation = R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE);
|
||||
else if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // This thing is a player!
|
||||
{
|
||||
size_t skinnum = (skin_t*)vis->mobj->skin-skins;
|
||||
dc_translation = R_GetTranslationColormap((INT32)skinnum, vis->mobj->color, GTC_CACHE);
|
||||
|
|
Loading…
Reference in a new issue