Add basic damage hitlag effects

- Invert high contrast greyscale colorization effect for damage hitlag
- Jitter is now also exclusive to damage-related hitlag
- Since jitter is now just tied to a flag, removed the old trick momentum hack
This commit is contained in:
Sally Coolatta 2021-11-27 13:38:45 -05:00
parent eb9e3d3e1b
commit cb5ea8b335
17 changed files with 161 additions and 91 deletions

View file

@ -456,9 +456,6 @@ typedef struct player_s
UINT8 trickpanel; // Trick panel state
UINT8 tricktime; // Increases while you're tricking. You can't input any trick until it's reached a certain threshold
fixed_t trickmomx;
fixed_t trickmomy;
fixed_t trickmomz;
fixed_t trickboostpower; // Save the rough speed multiplier. Used for upwards tricks.
UINT8 trickboostdecay; // used to know how long you've waited
UINT8 trickboost; // Trick boost. This one is weird and has variable speed. Dear god.

View file

@ -6845,6 +6845,7 @@ struct int_const_s const INT_CONST[] = {
{"TC_RAINBOW",TC_RAINBOW},
{"TC_BLINK",TC_BLINK},
{"TC_DASHMODE",TC_DASHMODE},
{"TC_HITLAG",TC_HITLAG},
// marathonmode flags
{"MA_INIT",MA_INIT},

View file

@ -3643,7 +3643,7 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale)
pslope_t *groundslope;
// hitlag vibrating
if (thing->hitlag > 0)
if (thing->hitlag > 0 && (thing->eflags & MFE_DAMAGEHITLAG))
{
fixed_t mul = thing->hitlag * (FRACUNIT / 10);
@ -5062,7 +5062,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
return;
// hitlag vibrating
if (thing->hitlag > 0)
if (thing->hitlag > 0 && (thing->eflags & MFE_DAMAGEHITLAG))
{
fixed_t mul = thing->hitlag * (FRACUNIT / 10);
@ -5401,7 +5401,11 @@ static void HWR_ProjectSprite(mobj_t *thing)
vis->mobj = thing;
//Hurdler: 25/04/2000: now support colormap in hardware mode
if ((vis->mobj->flags & (MF_ENEMY|MF_BOSS)) && (vis->mobj->flags2 & MF2_FRET) && !(vis->mobj->flags & MF_GRENADEBOUNCE) && (leveltime & 1)) // Bosses "flash"
if (vis->mobj->hitlag > 0 && (vis->mobj->eflags & MFE_DAMAGEHITLAG))
{
vis->colormap = R_GetTranslationColormap(TC_HITLAG, 0, GTC_CACHE);
}
else if ((vis->mobj->flags & (MF_ENEMY|MF_BOSS)) && (vis->mobj->flags2 & MF2_FRET) && !(vis->mobj->flags & MF_GRENADEBOUNCE) && (leveltime & 1)) // Bosses "flash"
{
if (vis->mobj->type == MT_CYBRAKDEMON || vis->mobj->colorized)
vis->colormap = R_GetTranslationColormap(TC_ALLWHITE, 0, GTC_CACHE);

View file

@ -819,7 +819,12 @@ static void HWR_CreateBlendedTexture(patch_t *gpatch, patch_t *blendgpatch, GLMi
while (size--)
{
if (skinnum == TC_BOSS)
if (skinnum == TC_HITLAG)
{
cur->s.red = cur->s.green = cur->s.blue = K_HitlagColorValue(*image);
cur->s.alpha = image->s.alpha;
}
else if (skinnum == TC_BOSS)
{
// Turn everything below a certain threshold white
if ((image->s.red == image->s.green) && (image->s.green == image->s.blue) && image->s.blue < 127)
@ -1367,7 +1372,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
float finalscale;
// hitlag vibrating
if (spr->mobj->hitlag > 0)
if (spr->mobj->hitlag > 0 && (spr->mobj->eflags & MFE_DAMAGEHITLAG))
{
fixed_t mul = spr->mobj->hitlag * (FRACUNIT / 10);
@ -1486,7 +1491,11 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
{
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->hitlag > 0 && (spr->mobj->eflags & MFE_DAMAGEHITLAG))
{
skinnum = TC_HITLAG;
}
else 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 || spr->mobj->colorized)
skinnum = TC_ALLWHITE;

View file

@ -90,6 +90,59 @@ void K_RainbowColormap(UINT8 *dest_colormap, UINT8 skincolor)
}
}
/*--------------------------------------------------
UINT8 K_HitlagColorValue(RGBA_t color)
See header file for description.
--------------------------------------------------*/
UINT8 K_HitlagColorValue(RGBA_t color)
{
// Outputs a raw brightness value (makes OGL support easier)
INT32 output = K_ColorRelativeLuminance(color.s.red, color.s.green, color.s.blue);
// Invert the color
output = 255 - output;
// Increase the contrast
output = ((output-128) * 2) + 128;
// Make sure to cap it.
if (output > 255)
{
output = 255;
}
else if (output < 0)
{
output = 0;
}
return output;
}
/*--------------------------------------------------
void K_HitlagColormap(UINT8 *dest_colormap)
See header file for description.
--------------------------------------------------*/
void K_HitlagColormap(UINT8 *dest_colormap)
{
RGBA_t color;
UINT8 v, offset;
INT32 i;
// for every colour in the palette, invert, greyscale, and increase the contrast.
for (i = 0; i < NUM_PALETTE_ENTRIES; i++)
{
color = V_GetColor(i);
v = K_HitlagColorValue(color);
// Convert raw brightness value to an offset from the greyscale palette line
offset = (255 - v) / 8;
dest_colormap[i] = offset; // Starts from 0, add it if greyscale moves.
}
}
/*--------------------------------------------------
void K_GenerateKartColormap(UINT8 *dest_colormap, INT32 skinnum, UINT8 color)
@ -100,13 +153,18 @@ void K_GenerateKartColormap(UINT8 *dest_colormap, INT32 skinnum, UINT8 color)
INT32 i;
INT32 starttranscolor;
// Handle a couple of simple special cases
if (skinnum == TC_BOSS
if (skinnum == TC_HITLAG)
{
K_HitlagColormap(dest_colormap);
return;
}
else if (skinnum == TC_BOSS
|| skinnum == TC_ALLWHITE
|| skinnum == TC_METALSONIC
|| skinnum == TC_BLINK
|| color == SKINCOLOR_NONE)
{
// Handle a couple of simple special cases
for (i = 0; i < NUM_PALETTE_ENTRIES; i++)
{
if (skinnum == TC_ALLWHITE)

View file

@ -66,6 +66,35 @@ UINT16 K_RainbowColor(tic_t time);
void K_RainbowColormap(UINT8 *dest_colormap, UINT8 skincolor);
/*--------------------------------------------------
UINT8 K_HitlagColorValue(RGBA_t color);
Gets the new replacement brightness value for the hitlag effect.
Input Arguments:-
color - Input color we intend to replace.
Return:-
0 to 255 brightness value.
--------------------------------------------------*/
UINT8 K_HitlagColorValue(RGBA_t color);
/*--------------------------------------------------
void K_HitlagColormap(UINT8 *dest_colormap);
Generates a inverted hi-contrast greyscale colormap,
for the hitlag effect.
Input Arguments:-
dest_colormap - Colormap to populate.
Return:-
None
--------------------------------------------------*/
void K_HitlagColormap(UINT8 *dest_colormap);
/*--------------------------------------------------
void K_GenerateKartColormap(UINT8 *dest_colormap, INT32 skinnum, UINT8 color);

View file

@ -3742,7 +3742,7 @@ static void K_drawKartFirstPerson(void)
fixed_t yoffs = -P_ReturnThrustX(stplyr->mo, ang, 4*FRACUNIT);
// hitlag vibrating
if (stplyr->mo->hitlag > 0)
if (stplyr->mo->hitlag > 0 && (stplyr->mo->eflags & MFE_DAMAGEHITLAG))
{
fixed_t mul = stplyr->mo->hitlag * (FRACUNIT / 10);
if (r_splitscreen && mul > FRACUNIT)

View file

@ -3021,24 +3021,25 @@ angle_t K_MomentumAngle(mobj_t *mo)
}
}
void K_AddHitLag(mobj_t *mo, INT32 tics)
void K_AddHitLag(mobj_t *mo, INT32 tics, boolean fromDamage)
{
if (mo == NULL || P_MobjWasRemoved(mo))
{
return;
}
if (mo->player != NULL && P_IsLocalPlayer(mo->player))
{
// temporary :)
CONS_Printf("tics: %d\n", tics);
}
mo->hitlag += tics;
mo->hitlag = min(mo->hitlag, MAXHITLAGTICS);
if (fromDamage == true)
{
// Dunno if this should flat-out &~ the flag out too.
// Decided it probably just just keep it since it's "adding" hitlag.
mo->eflags |= MFE_DAMAGEHITLAG;
}
}
void K_SetHitLagForObjects(mobj_t *mo1, mobj_t *mo2, INT32 tics)
void K_SetHitLagForObjects(mobj_t *mo1, mobj_t *mo2, INT32 tics, boolean fromDamage)
{
INT32 finalTics = tics;
@ -3078,8 +3079,8 @@ void K_SetHitLagForObjects(mobj_t *mo1, mobj_t *mo2, INT32 tics)
}
}
K_AddHitLag(mo1, finalTics);
K_AddHitLag(mo2, finalTics);
K_AddHitLag(mo1, finalTics, fromDamage);
K_AddHitLag(mo2, finalTics, fromDamage);
}
void K_DoInstashield(player_t *player)
@ -5112,7 +5113,7 @@ void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, UINT8 sound)
thrust = FixedMul(thrust, 9*FRACUNIT/8);
}
mo->player->trickmomx = mo->player->trickmomy = mo->player->trickmomz = mo->player->tricktime = 0; // Reset post-hitlag momentums and timer
mo->player->tricktime = 0; // Reset post-hitlag timer
// Setup the boost for potential upwards trick, at worse, make it your regular max speed. (boost = curr speed*1.25)
mo->player->trickboostpower = max(FixedDiv(mo->player->speed, K_GetKartSpeed(mo->player, false)) - FRACUNIT, 0)*125/100;
//CONS_Printf("Got boost: %d%\n", mo->player->trickboostpower*100 / FRACUNIT);
@ -9199,29 +9200,21 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
if (cmd->turning > 0)
{
P_InstaThrust(player->mo, player->mo->angle + lr, max(basespeed, speed*5/2));
player->trickmomx = player->mo->momx;
player->trickmomy = player->mo->momy;
player->trickmomz = player->mo->momz;
P_InstaThrust(player->mo, 0, 0); // Sike, you have no speed :)
player->mo->momz = 0;
player->trickpanel = 2;
player->mo->hitlag = TRICKLAG;
player->mo->eflags &= ~MFE_DAMAGEHITLAG;
K_trickPanelTimingVisual(player, momz);
}
else if (cmd->turning < 0)
{
P_InstaThrust(player->mo, player->mo->angle - lr, max(basespeed, speed*5/2));
player->trickmomx = player->mo->momx;
player->trickmomy = player->mo->momy;
player->trickmomz = player->mo->momz;
P_InstaThrust(player->mo, 0, 0); // Sike, you have no speed :)
player->mo->momz = 0;
player->trickpanel = 3;
player->mo->hitlag = TRICKLAG;
player->mo->eflags &= ~MFE_DAMAGEHITLAG;
K_trickPanelTimingVisual(player, momz);
}
else if (player->throwdir == 1)
@ -9232,15 +9225,11 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
}
P_InstaThrust(player->mo, player->mo->angle, max(basespeed, speed*3));
player->trickmomx = player->mo->momx;
player->trickmomy = player->mo->momy;
player->trickmomz = player->mo->momz;
P_InstaThrust(player->mo, 0, 0); // Sike, you have no speed :)
player->mo->momz = 0;
player->trickpanel = 2;
player->mo->hitlag = TRICKLAG;
player->mo->eflags &= ~MFE_DAMAGEHITLAG;
K_trickPanelTimingVisual(player, momz);
}
else if (player->throwdir == -1)
@ -9262,30 +9251,15 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
//CONS_Printf("decay: %d\n", player->trickboostdecay);
P_SetObjectMomZ(player->mo, 48*FRACUNIT, relative);
player->trickmomx = player->mo->momx;
player->trickmomy = player->mo->momy;
player->trickmomz = player->mo->momz;
P_InstaThrust(player->mo, 0, 0); // Sike, you have no speed :)
player->mo->momz = 0;
player->trickpanel = 4;
player->mo->hitlag = TRICKLAG;
player->mo->eflags &= ~MFE_DAMAGEHITLAG;
K_trickPanelTimingVisual(player, momz);
}
}
}
// After hitlag, we will get here and will be able to apply the desired momentums!
else if (player->trickmomx || player->trickmomy || player->trickmomz)
{
player->mo->momx = player->trickmomx;
player->mo->momy = player->trickmomy;
player->mo->momz = player->trickmomz;
player->trickmomx = player->trickmomy = player->trickmomz = 0;
}
else if (player->trickpanel == 4 && P_IsObjectOnGround(player->mo)) // Upwards trick landed!
{
//CONS_Printf("apply boost\n");

View file

@ -56,8 +56,8 @@ void K_KartPlayerHUDUpdate(player_t *player);
void K_KartPlayerThink(player_t *player, ticcmd_t *cmd);
void K_KartPlayerAfterThink(player_t *player);
angle_t K_MomentumAngle(mobj_t *mo);
void K_AddHitLag(mobj_t *mo, INT32 tics);
void K_SetHitLagForObjects(mobj_t *mo1, mobj_t *mo2, INT32 tics);
void K_AddHitLag(mobj_t *mo, INT32 tics, boolean fromDamage);
void K_SetHitLagForObjects(mobj_t *mo1, mobj_t *mo2, INT32 tics, boolean fromDamage);
void K_DoInstashield(player_t *player);
void K_BattleAwardHit(player_t *player, player_t *victim, mobj_t *inflictor, UINT8 bumpersRemoved);
void K_SpinPlayer(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 type);

View file

@ -356,12 +356,6 @@ static int player_get(lua_State *L)
lua_pushinteger(L, plr->trickpanel);
else if (fastcmp(field,"tricktime"))
lua_pushinteger(L, plr->tricktime);
else if (fastcmp(field,"trickmomx"))
lua_pushfixed(L, plr->trickmomx);
else if (fastcmp(field,"trickmomy"))
lua_pushfixed(L, plr->trickmomy);
else if (fastcmp(field,"trickmomz"))
lua_pushfixed(L, plr->trickmomz);
else if (fastcmp(field,"trickboostpower"))
lua_pushfixed(L, plr->trickboostpower);
else if (fastcmp(field,"trickboostdecay"))
@ -707,12 +701,6 @@ static int player_set(lua_State *L)
plr->trickpanel = luaL_checkinteger(L, 3);
else if (fastcmp(field,"tricktime"))
plr->tricktime = luaL_checkinteger(L, 3);
else if (fastcmp(field,"trickmomx"))
plr->trickmomx = luaL_checkfixed(L, 3);
else if (fastcmp(field,"trickmomy"))
plr->trickmomy = luaL_checkfixed(L, 3);
else if (fastcmp(field,"trickmomz"))
plr->trickmomz = luaL_checkfixed(L, 3);
else if (fastcmp(field,"trickboostpower"))
plr->trickboostpower = luaL_checkfixed(L, 3);
else if (fastcmp(field,"trickboostdecay"))

View file

@ -960,7 +960,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
if (LUAh_MobjDeath(target, inflictor, source, damagetype) || P_MobjWasRemoved(target))
return;
//K_SetHitLagForObjects(target, inflictor, MAXHITLAGTICS);
//K_SetHitLagForObjects(target, inflictor, MAXHITLAGTICS, true);
// SRB2kart
// I wish I knew a better way to do this
@ -1247,6 +1247,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
kart->angle = target->angle;
kart->color = target->color;
kart->hitlag = target->hitlag;
kart->eflags |= MFE_DAMAGEHITLAG;
P_SetObjectMomZ(kart, 6*FRACUNIT, false);
kart->extravalue1 = target->player->kartweight;
}
@ -1737,7 +1738,7 @@ static boolean P_KillPlayer(player_t *player, mobj_t *inflictor, mobj_t *source,
}
K_DropEmeraldsFromPlayer(player, player->emeralds);
K_SetHitLagForObjects(player->mo, inflictor, MAXHITLAGTICS);
K_SetHitLagForObjects(player->mo, inflictor, MAXHITLAGTICS, true);
player->carry = CR_NONE;
@ -2050,7 +2051,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
}
player->instashield = 15;
K_SetHitLagForObjects(target, inflictor, laglength);
K_SetHitLagForObjects(target, inflictor, laglength, true);
return true;
}
}
@ -2072,7 +2073,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
if (source && source->player && target)
G_GhostAddHit((INT32) (source->player - players), target);
K_SetHitLagForObjects(target, inflictor, laglength);
K_SetHitLagForObjects(target, inflictor, laglength, true);
if (target->health <= 0)
{
@ -2080,7 +2081,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
return true;
}
//K_SetHitLagForObjects(target, inflictor, laglength);
//K_SetHitLagForObjects(target, inflictor, laglength, true);
if (player)
P_ResetPlayer(target->player);

View file

@ -8613,7 +8613,7 @@ void P_MobjThinker(mobj_t *mobj)
return;
}
mobj->eflags &= ~(MFE_PUSHED|MFE_SPRUNG|MFE_JUSTBOUNCEDWALL);
mobj->eflags &= ~(MFE_PUSHED|MFE_SPRUNG|MFE_JUSTBOUNCEDWALL|MFE_DAMAGEHITLAG);
tmfloorthing = tmhitthing = NULL;

View file

@ -247,6 +247,8 @@ typedef enum
MFE_TRACERANGLE = 1<<11,
// SRB2Kart: The mobj just hit & bounced off a wall, this is cleared on next frame
MFE_JUSTBOUNCEDWALL = 1<<12,
// SRB2Kart: In damage hitlag (displays different visual efx)
MFE_DAMAGEHITLAG = 1<<13,
// free: to and including 1<<15
} mobjeflag_t;

View file

@ -306,9 +306,6 @@ static void P_NetArchivePlayers(void)
WRITEUINT8(save_p, players[i].trickpanel);
WRITEUINT8(save_p, players[i].tricktime);
WRITEUINT32(save_p, players[i].trickmomx);
WRITEUINT32(save_p, players[i].trickmomy);
WRITEUINT32(save_p, players[i].trickmomz);
WRITEUINT32(save_p, players[i].trickboostpower);
WRITEUINT8(save_p, players[i].trickboostdecay);
WRITEUINT8(save_p, players[i].trickboost);
@ -562,9 +559,6 @@ static void P_NetUnArchivePlayers(void)
players[i].trickpanel = READUINT8(save_p);
players[i].tricktime = READUINT8(save_p);
players[i].trickmomx = READUINT32(save_p);
players[i].trickmomy = READUINT32(save_p);
players[i].trickmomz = READUINT32(save_p);
players[i].trickboostpower = READUINT32(save_p);
players[i].trickboostdecay = READUINT8(save_p);
players[i].trickboost = READUINT8(save_p);
@ -1965,7 +1959,9 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
WRITEFIXED(save_p, slope->normal.z);
}
if (diff2 & MD2_HITLAG)
{
WRITEINT32(save_p, mobj->hitlag);
}
WRITEUINT32(save_p, mobj->mobjnum);
}
@ -3057,7 +3053,9 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
slope->normal.z = READFIXED(save_p);
}
if (diff2 & MD2_HITLAG)
{
mobj->hitlag = READINT32(save_p);
}
if (diff & MD_REDFLAG)
{

View file

@ -141,7 +141,9 @@ UINT32 nflatxshift, nflatyshift, nflatshiftup, nflatmask;
#define RAINBOW_TT_CACHE_INDEX (MAXSKINS + 4)
#define BLINK_TT_CACHE_INDEX (MAXSKINS + 5)
#define DASHMODE_TT_CACHE_INDEX (MAXSKINS + 6)
#define TT_CACHE_SIZE (MAXSKINS + 7)
#define HITLAG_TT_CACHE_INDEX (MAXSKINS + 7)
#define TT_CACHE_SIZE (MAXSKINS + 8)
#define SKIN_RAMP_LENGTH 16
#define DEFAULT_STARTTRANSCOLOR 96
#define NUM_PALETTE_ENTRIES 256
@ -160,6 +162,7 @@ static INT32 SkinToCacheIndex(INT32 skinnum)
case TC_RAINBOW: return RAINBOW_TT_CACHE_INDEX;
case TC_BLINK: return BLINK_TT_CACHE_INDEX;
case TC_DASHMODE: return DASHMODE_TT_CACHE_INDEX;
case TC_HITLAG: return HITLAG_TT_CACHE_INDEX;
default: break;
}
@ -177,6 +180,7 @@ static INT32 CacheIndexToSkin(INT32 ttc)
case RAINBOW_TT_CACHE_INDEX: return TC_RAINBOW;
case BLINK_TT_CACHE_INDEX: return TC_BLINK;
case DASHMODE_TT_CACHE_INDEX: return TC_DASHMODE;
case HITLAG_TT_CACHE_INDEX: return TC_HITLAG;
default: break;
}

View file

@ -119,6 +119,7 @@ enum
TC_RAINBOW, // For single colour
TC_BLINK, // For item blinking, according to kart
TC_DASHMODE, // For Metal Sonic's dashmode
TC_HITLAG, // Damage hitlag effect
TC_DEFAULT
};

View file

@ -737,7 +737,11 @@ boolean R_SpriteIsFlashing(vissprite_t *vis)
UINT8 *R_GetSpriteTranslation(vissprite_t *vis)
{
if (R_SpriteIsFlashing(vis)) // Bosses "flash"
if (vis->mobj->hitlag > 0 && (vis->mobj->eflags & MFE_DAMAGEHITLAG))
{
return R_GetTranslationColormap(TC_HITLAG, 0, GTC_CACHE);
}
else if (R_SpriteIsFlashing(vis)) // Bosses "flash"
{
if (vis->mobj->type == MT_CYBRAKDEMON || vis->mobj->colorized)
return R_GetTranslationColormap(TC_ALLWHITE, 0, GTC_CACHE);
@ -1432,7 +1436,7 @@ static void R_ProjectSprite(mobj_t *thing)
#endif
// hitlag vibrating
if (thing->hitlag > 0)
if (thing->hitlag > 0 && (thing->eflags & MFE_DAMAGEHITLAG))
{
fixed_t mul = thing->hitlag * (FRACUNIT / 10);