Split hitlag into its own file

This commit is contained in:
Sally Coolatta 2023-05-02 17:33:07 -04:00 committed by James R
parent 98841e5c15
commit 5067bb854a
14 changed files with 338 additions and 173 deletions

View file

@ -147,6 +147,7 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32
k_zvote.c
k_mapuser.c
k_powerup.cpp
k_hitlag.c
)
if(SRB2_CONFIG_ENABLE_WEBM_MOVIES)

View file

@ -44,7 +44,7 @@
#include "hw_md2.h"
// SRB2Kart
#include "../k_kart.h" // HITLAGJITTERS
#include "../k_hitlag.h" // HITLAGJITTERS
#include "../r_fps.h"
#include "../r_plane.h" // R_FlatDimensionsFromLumpSize

View file

@ -46,7 +46,7 @@
// SRB2Kart
#include "../k_color.h"
#include "../k_kart.h" // HITLAGJITTERS
#include "../k_hitlag.h" // HITLAGJITTERS
#include "../r_fps.h"
#ifdef HAVE_PNG

View file

@ -17,6 +17,7 @@
#include "k_roulette.h"
#include "k_podium.h"
#include "k_powerup.h"
#include "k_hitlag.h"
angle_t K_GetCollideAngle(mobj_t *t1, mobj_t *t2)
{
@ -423,7 +424,7 @@ boolean K_LandMineCollide(mobj_t *t1, mobj_t *t2)
{
// Melt item
S_StartSound(t2, sfx_s3k43);
K_SetHitLagForObjects(t2, t1, 3, false);
K_SetHitLagForObjects(t2, t1, t1->target, 3, false);
}
else
{

249
src/k_hitlag.c Normal file
View file

@ -0,0 +1,249 @@
// DR. ROBOTNIK'S RING RACERS
//-----------------------------------------------------------------------------
// Copyright (C) by Sally "TehRealSalt" Cochenour
// Copyright (C) by Kart Krew
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file k_hitlag.c
/// \brief Hitlag functions
#include "k_hitlag.h"
#include "doomdef.h"
#include "doomstat.h"
#include "k_kart.h"
#include "m_random.h"
#include "p_local.h"
#include "r_main.h"
/*--------------------------------------------------
void K_AddHitLag(mobj_t *mo, INT32 tics, boolean fromDamage)
See header file for description.
--------------------------------------------------*/
void K_AddHitLag(mobj_t *mo, INT32 tics, boolean fromDamage)
{
if (mo == NULL || P_MobjWasRemoved(mo) || (mo->flags & MF_NOHITLAGFORME && mo->type != MT_PLAYER))
{
return;
}
mo->hitlag += tics;
mo->hitlag = min(mo->hitlag, MAXHITLAGTICS);
if (mo->player != NULL)
{
// Reset each time. We want to explicitly set this for bananas afterwards,
// so make sure an old value doesn't possibly linger.
mo->player->flipDI = false;
}
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;
}
}
/*--------------------------------------------------
static void K_SpawnSingleHitLagSpark(
mobj_t *parent,
vector3_t *offset, fixed_t scale,
UINT8 tics, UINT8 pause,
skincolornum_t color)
Spawns a set of damage hitlag spark papersprites.
Input Arguments:-
parent - Object that the hitlag was added to.
offset - Offset from the parent to spawn the spark.
scale - The scale of the spark.
tics - Which hitlag state to use.
pause - How long to wait before it displays.
color - The color of the damage source.
Return:-
N/A
--------------------------------------------------*/
static void K_SpawnSingleHitLagSpark(
mobj_t *parent,
vector3_t *offset, fixed_t scale,
UINT8 tics, UINT8 pause,
skincolornum_t color)
{
INT32 i;
if (tics == 0)
{
return;
}
for (i = 0; i < 2; i++)
{
mobj_t *spark = P_SpawnMobj(
parent->x + offset->x,
parent->y + offset->y,
parent->z + offset->z,
MT_HITLAG
);
P_SetMobjState(spark, spark->info->spawnstate + (tics - 1));
P_SetTarget(&spark->target, parent);
spark->destscale = scale;
P_SetScale(spark, scale);
if (parent->eflags & MFE_VERTICALFLIP)
{
spark->eflags |= MFE_VERTICALFLIP;
spark->flags2 |= MF2_OBJECTFLIP;
spark->z = parent->z + parent->height - offset->z;
}
spark->angle = R_PointToAngle2(
parent->x, parent->y,
spark->x, spark->y
);
if (i & 1)
{
spark->angle += ANGLE_90;
}
spark->hitlag = pause;
if (color != SKINCOLOR_NONE)
{
spark->color = color;
spark->colorized = true;
}
}
}
/*--------------------------------------------------
static void K_SpawnHitLagEFX(mobj_t *victim, mobj_t *inflictor, mobj_t *source, UINT8 tics)
Spawns several hitlag sparks for damage.
Input Arguments:-
victim - Object getting touched.
inflictor - Object touching the victim. May be NULL.
source - Object that inflictor came from. May be NULL or same as inflictor.
tics - How long the hitlag was.
Return:-
N/A
--------------------------------------------------*/
static void K_SpawnHitLagEFX(mobj_t *victim, mobj_t *inflictor, mobj_t *source, UINT8 tics)
{
vector3_t offset = { 0, 0, 0 };
fixed_t newScale = FRACUNIT;
UINT8 startTics = 0, endTics = 0;
skincolornum_t color = SKINCOLOR_NONE;
I_Assert(P_MobjWasRemoved(victim) == false);
P_StartQuakeFromMobj(tics, tics * 2 * mapobjectscale, 512 * mapobjectscale, victim);
if (P_MobjWasRemoved(inflictor) == false)
{
offset.x = (inflictor->x - victim->x) / 2;
offset.y = (inflictor->y - victim->y) / 2;
offset.z = (P_GetMobjHead(inflictor) - P_GetMobjHead(victim)) / 2;
newScale = (3 * (victim->destscale + inflictor->destscale) / 2);
}
else
{
offset.z = victim->height;
newScale = 3 * victim->destscale;
}
if (P_MobjWasRemoved(source) == false)
{
color = (source->player != NULL) ? source->player->skincolor : source->color;
}
while (endTics < tics)
{
UINT8 particle = max(1, FixedMul((tics * FRACUNIT) + (FRACUNIT/2), FRACUNIT*2/3) / FRACUNIT);
if (particle > NUM_HITLAG_STATES)
{
particle = NUM_HITLAG_STATES;
}
UINT8 ticsLeft = endTics - tics;
if (particle > ticsLeft)
{
particle = ticsLeft;
}
K_SpawnSingleHitLagSpark(victim, &offset, newScale, particle, startTics, color);
startTics += max(1, FixedMul((particle * FRACUNIT) + (FRACUNIT/2), FRACUNIT/3) / FRACUNIT);
endTics += particle;
offset.x += P_RandomRange(PR_DECORATION, -75, 75) * newScale;
offset.y += P_RandomRange(PR_DECORATION, -75, 75) * newScale;
offset.z += P_RandomRange(PR_DECORATION, -75, 75) * newScale;
newScale = (newScale * 2) / 3;
}
}
/*--------------------------------------------------
void K_SetHitLagForObjects(mobj_t *victim, mobj_t *inflictor, mobj_t *source, INT32 tics, boolean fromDamage)
See header file for description.
--------------------------------------------------*/
void K_SetHitLagForObjects(mobj_t *victim, mobj_t *inflictor, mobj_t *source, INT32 tics, boolean fromDamage)
{
INT32 finalTics = tics;
if (tics <= 0)
{
return;
}
if (P_MobjWasRemoved(victim) == false && P_MobjWasRemoved(inflictor) == false)
{
const fixed_t speedTicFactor = (mapobjectscale * 8);
const INT32 angleTicFactor = ANGLE_22h;
const fixed_t victimSpeed = FixedHypot(FixedHypot(victim->momx, victim->momy), victim->momz);
const fixed_t inflictorSpeed = FixedHypot(FixedHypot(inflictor->momx, inflictor->momy), inflictor->momz);
const fixed_t speedDiff = abs(inflictorSpeed - victimSpeed);
const fixed_t scaleDiff = abs(inflictor->scale - victim->scale);
angle_t victimAngle = K_MomentumAngle(victim);
angle_t inflictorAngle = K_MomentumAngle(inflictor);
INT32 angleDiff = 0;
if (victimSpeed > 0 && inflictorSpeed > 0)
{
// If either object is completely not moving, their speed doesn't matter.
angleDiff = AngleDelta(victimAngle, inflictorAngle);
}
// Add extra "damage" based on what was happening to the objects on impact.
finalTics += (FixedMul(speedDiff, FRACUNIT + scaleDiff) / speedTicFactor) + (angleDiff / angleTicFactor);
// This shouldn't happen anymore, but just in case something funky happens.
if (finalTics < tics)
{
finalTics = tics;
}
}
K_AddHitLag(victim, finalTics, fromDamage);
K_AddHitLag(inflictor, finalTics, false); // Don't use the damage property.
if (P_MobjWasRemoved(victim) == false && fromDamage == true)
{
K_SpawnHitLagEFX(victim, inflictor, source, finalTics);
}
}

68
src/k_hitlag.h Normal file
View file

@ -0,0 +1,68 @@
// DR. ROBOTNIK'S RING RACERS
//-----------------------------------------------------------------------------
// Copyright (C) by Sally "TehRealSalt" Cochenour
// Copyright (C) by Kart Krew
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file k_hitlag.h
/// \brief Race Mode specific code.
#ifndef __K_HITLAG__
#define __K_HITLAG__
#include "doomtype.h"
#include "doomstat.h"
#ifdef __cplusplus
extern "C" {
#endif
#define MAXHITLAGTICS (20)
#define HITLAGJITTERS (FRACUNIT / 20)
#define NUM_HITLAG_STATES (4)
/*--------------------------------------------------
void K_AddHitLag(mobj_t *mo, INT32 tics, boolean fromDamage);
Adds hitlag to an object.
Input Arguments:-
mo - Object to add hitlag to.
tics - How much hitlag to add.
fromDamage - Whenever or not this was a damage interaction.
Return:-
N/A
--------------------------------------------------*/
void K_AddHitLag(mobj_t *mo, INT32 tics, boolean fromDamage);
/*--------------------------------------------------
void K_SetHitLagForObjects(mobj_t *victim, mobj_t *inflictor, mobj_t *source, INT32 tics, boolean fromDamage);
Sets the hitlag for two objects, victim and inflictor,
in a touch-related interaction (typically damage).
Input Arguments:-
victim - Object getting touched.
inflictor - Object touching the victim. May be NULL.
source - Object that inflictor came from. May be NULL or same as inflictor.
tics - Minimum time for the hitlag to be. Can be increased if it is a damage interaction.
fromDamage - Whenever or not this was a damage interaction.
Return:-
N/A
--------------------------------------------------*/
void K_SetHitLagForObjects(mobj_t *victim, mobj_t *inflictor, mobj_t *source, INT32 tics, boolean fromDamage);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // __K_HITLAG__

View file

@ -42,6 +42,7 @@
#include "k_bot.h"
#include "k_rank.h"
#include "g_party.h"
#include "k_hitlag.h"
//{ Patch Definitions
static patch_t *kp_nodraw;

View file

@ -46,6 +46,7 @@
#include "k_roulette.h"
#include "k_podium.h"
#include "k_powerup.h"
#include "k_hitlag.h"
// SOME IMPORTANT VARIABLES DEFINED IN DOOMDEF.H:
// gamespeed is cc (0 for easy, 1 for normal, 2 for hard)
@ -3625,156 +3626,6 @@ angle_t K_MomentumAngleReal(const mobj_t *mo)
}
}
void K_AddHitLag(mobj_t *mo, INT32 tics, boolean fromDamage)
{
if (mo == NULL || P_MobjWasRemoved(mo) || (mo->flags & MF_NOHITLAGFORME && mo->type != MT_PLAYER))
{
return;
}
mo->hitlag += tics;
mo->hitlag = min(mo->hitlag, MAXHITLAGTICS);
if (mo->player != NULL)
{
// Reset each time. We want to explicitly set this for bananas afterwards,
// so make sure an old value doesn't possibly linger.
mo->player->flipDI = false;
}
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;
}
}
#define NUM_HITLAG_STATES (4)
static void K_SpawnSingleHitLagSpark(mobj_t *mo1, mobj_t *mo2, vector3_t *offset, fixed_t newScale, UINT8 tics)
{
INT32 i;
if (tics == 0)
{
return;
}
if (tics > NUM_HITLAG_STATES)
{
tics = NUM_HITLAG_STATES;
}
for (i = 0; i < 2; i++)
{
mobj_t *spark = P_SpawnMobj(
mo1->x + offset->x,
mo1->y + offset->y,
mo1->z + offset->z,
MT_HITLAG
);
P_SetMobjState(spark, spark->info->spawnstate + (tics - 1));
P_SetTarget(&spark->target, mo1);
spark->destscale = newScale;
P_SetScale(spark, newScale);
if (mo1->eflags & MFE_VERTICALFLIP)
{
spark->eflags |= MFE_VERTICALFLIP;
spark->flags2 |= MF2_OBJECTFLIP;
spark->z = mo1->z + mo1->height - offset->z;
}
spark->angle = R_PointToAngle2(
mo1->x, mo1->y,
spark->x, spark->y
);
if (i & 1)
{
spark->angle += ANGLE_90;
}
}
}
static void K_SpawnHitLagEFX(mobj_t *mo1, mobj_t *mo2, UINT8 tics)
{
vector3_t offset = { 0, 0, 0 };
fixed_t newScale = FRACUNIT;
I_Assert(P_MobjWasRemoved(mo1) == false);
P_StartQuakeFromMobj(tics, tics * 2 * mapobjectscale, 512 * mapobjectscale, mo1);
if (P_MobjWasRemoved(mo2) == false)
{
offset.x = (mo2->x - mo1->x) / 2;
offset.y = (mo2->y - mo1->y) / 2;
offset.z = (P_GetMobjHead(mo2) - P_GetMobjHead(mo1)) / 2;
newScale = (3 * (mo1->destscale + mo2->destscale) / 2);
}
else
{
offset.z = mo1->height;
newScale = 3 * mo1->destscale;
}
// temp
K_SpawnSingleHitLagSpark(mo1, mo2, &offset, newScale, tics);
}
void K_SetHitLagForObjects(mobj_t *mo1, mobj_t *mo2, INT32 tics, boolean fromDamage)
{
INT32 finalTics = tics;
if (tics <= 0)
{
return;
}
if ((mo1 && !P_MobjWasRemoved(mo1)) == true && (mo2 && !P_MobjWasRemoved(mo2)) == true)
{
const fixed_t speedTicFactor = (mapobjectscale * 8);
const INT32 angleTicFactor = ANGLE_22h;
const fixed_t mo1speed = FixedHypot(FixedHypot(mo1->momx, mo1->momy), mo1->momz);
const fixed_t mo2speed = FixedHypot(FixedHypot(mo2->momx, mo2->momy), mo2->momz);
const fixed_t speedDiff = abs(mo2speed - mo1speed);
const fixed_t scaleDiff = abs(mo2->scale - mo1->scale);
angle_t mo1angle = K_MomentumAngleReal(mo1);
angle_t mo2angle = K_MomentumAngleReal(mo2);
INT32 angleDiff = 0;
if (mo1speed > 0 && mo2speed > 0)
{
// If either object is completely not moving, their speed doesn't matter.
angleDiff = AngleDelta(mo1angle, mo2angle);
}
// Add extra "damage" based on what was happening to the objects on impact.
finalTics += (FixedMul(speedDiff, FRACUNIT + scaleDiff) / speedTicFactor) + (angleDiff / angleTicFactor);
// This shouldn't happen anymore, but just in case something funky happens.
if (finalTics < tics)
{
finalTics = tics;
}
}
K_AddHitLag(mo1, finalTics, fromDamage);
K_AddHitLag(mo2, finalTics, false); // mo2 is the inflictor, so don't use the damage property.
if (P_MobjWasRemoved(mo1) == false && fromDamage == true)
{
K_SpawnHitLagEFX(mo1, mo2, finalTics);
}
}
void K_AwardPlayerRings(player_t *player, INT32 rings, boolean overload)
{
UINT16 superring;
@ -6023,7 +5874,7 @@ void K_PuntMine(mobj_t *origMine, mobj_t *punter)
mine->momy = punter->momy + FixedMul(FINESINE(fa >> ANGLETOFINESHIFT), spd);
P_SetObjectMomZ(mine, z, false);
//K_SetHitLagForObjects(punter, mine, 5);
//K_SetHitLagForObjects(punter, mine, mine->target, 5);
mine->flags &= ~(MF_NOCLIP|MF_NOCLIPTHING);
}

View file

@ -23,9 +23,6 @@ Make sure this matches the actual number of states
*/
#define KART_NUMINVSPARKLESANIM 12
#define MAXHITLAGTICS (20)
#define HITLAGJITTERS (FRACUNIT / 20)
#define GROW_SCALE (2*FRACUNIT)
#define SHRINK_SCALE (FRACUNIT/2)
@ -92,8 +89,6 @@ void K_KartPlayerAfterThink(player_t *player);
angle_t K_MomentumAngleEx(const mobj_t *mo, const fixed_t threshold);
angle_t K_MomentumAngleReal(const mobj_t *mo);
#define K_MomentumAngle(mo) K_MomentumAngleEx(mo, 6 * mo->scale)
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_AwardPlayerRings(player_t *player, INT32 rings, boolean overload);
void K_DoInstashield(player_t *player);
void K_DoPowerClash(mobj_t *t1, mobj_t *t2);

View file

@ -37,6 +37,7 @@
#include "i_system.h" // I_GetPreciseTime, I_GetPrecisePrecision
#include "hu_stuff.h" // for the cecho
#include "k_powerup.h"
#include "k_hitlag.h"
#include "lua_script.h"
#include "lua_libs.h"

View file

@ -21,6 +21,7 @@
#include "../r_main.h"
#include "../s_sound.h"
#include "../g_game.h"
#include "../k_hitlag.h"
enum {
HYU_PATROL,

View file

@ -24,6 +24,7 @@
#include "../k_waypoint.h"
#include "../k_specialstage.h"
#include "../r_skins.h"
#include "../k_hitlag.h"
#include "../acs/interface.h"
#define UFO_BASE_SPEED (42 * FRACUNIT) // UFO's slowest speed.
@ -744,8 +745,6 @@ boolean Obj_SpecialUFODamage(mobj_t *ufo, mobj_t *inflictor, mobj_t *source, UIN
const fixed_t addSpeed = FixedMul(UFO_DAMAGED_SPEED, K_GetKartGameSpeedScalar(gamespeed));
UINT8 damage = 1;
(void)source;
if (UFOEmeraldChase(ufo) == true)
{
// Damaged fully already, no need for any more.
@ -768,13 +767,12 @@ boolean Obj_SpecialUFODamage(mobj_t *ufo, mobj_t *inflictor, mobj_t *source, UIN
SetRandomFakePlayerSkin(source->player, true);
}
// Speed up on damage!
ufo_speed(ufo) += addSpeed;
ufo->health = max(1, ufo->health - damage);
K_SetHitLagForObjects(ufo, inflictor, (damage / 3) + 2, true);
K_SetHitLagForObjects(ufo, inflictor, source, (damage / 3) + 2, true);
UFOCopyHitlagToPieces(ufo);
if (ufo->health == 1)

View file

@ -40,6 +40,7 @@
#include "k_objects.h"
#include "k_roulette.h"
#include "k_boss.h"
#include "k_hitlag.h"
#include "acs/interface.h"
#include "k_powerup.h"
@ -523,7 +524,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
firework->color = toucher->color;
}*/
K_SetHitLagForObjects(special, toucher, 2, true);
K_SetHitLagForObjects(special, toucher, toucher, 2, true);
break;
@ -1130,7 +1131,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
P_ActivateThingSpecial(target, source);
//K_SetHitLagForObjects(target, inflictor, MAXHITLAGTICS, true);
//K_SetHitLagForObjects(target, inflictor, source, MAXHITLAGTICS, true);
// SRB2kart
// I wish I knew a better way to do this
@ -1962,8 +1963,6 @@ static boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj_t *sou
static boolean P_KillPlayer(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8 type)
{
(void)source;
if (player->respawn.state != RESPAWNST_NONE)
{
K_DoInstashield(player);
@ -2036,7 +2035,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, true);
K_SetHitLagForObjects(player->mo, inflictor, source, MAXHITLAGTICS, true);
player->carry = CR_NONE;
@ -2330,7 +2329,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
}
laglength = max(laglength / 2, 1);
K_SetHitLagForObjects(target, inflictor, laglength, false);
K_SetHitLagForObjects(target, inflictor, source, laglength, false);
AddNullHitlag(player, oldHitlag);
AddNullHitlag(playerInflictor, oldHitlagInflictor);
@ -2394,7 +2393,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
}
else if (target->flags2 & MF2_ALREADYHIT) // do not deal extra damage in the same tic
{
K_SetHitLagForObjects(target, inflictor, laglength, true);
K_SetHitLagForObjects(target, inflictor, source, laglength, true);
return false;
}
}
@ -2586,7 +2585,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, true);
K_SetHitLagForObjects(target, inflictor, source, laglength, true);
target->flags2 |= MF2_ALREADYHIT;
@ -2596,7 +2595,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
return true;
}
//K_SetHitLagForObjects(target, inflictor, laglength, true);
//K_SetHitLagForObjects(target, inflictor, source, laglength, true);
if (!player)
{

View file

@ -46,7 +46,7 @@
// SRB2kart
#include "k_color.h"
#include "k_kart.h" // HITLAGJITTERS
#include "k_hitlag.h" // HITLAGJITTERS
#include "r_fps.h"
#define MINZ (FRACUNIT*4)