diff --git a/src/k_collide.c b/src/k_collide.c index 1921e3d38..e2fa2e9d4 100644 --- a/src/k_collide.c +++ b/src/k_collide.c @@ -48,6 +48,7 @@ boolean K_OrbinautJawzCollide(mobj_t *t1, mobj_t *t2) P_DamageMobj(t2, t1, t1->target, 1); K_KartBouncing(t2, t1, false, false); S_StartSound(t2, sfx_s3k7b); + t2->hitlag = TICRATE; } damageitem = true; @@ -99,6 +100,8 @@ boolean K_OrbinautJawzCollide(mobj_t *t1, mobj_t *t2) else t1->z += t1->height; + t1->hitlag = TICRATE; + S_StartSound(t1, t1->info->deathsound); P_KillMobj(t1, t2, t2); diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 3c85c358b..a1d7eee60 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -87,6 +87,7 @@ enum mobj_e { mobj_standingslope, #endif mobj_colorized, + mobj_hitlag, mobj_shadowscale, mobj_whiteshadow, mobj_sprxoff, @@ -156,6 +157,7 @@ static const char *const mobj_opt[] = { "standingslope", #endif "colorized", + "hitlag", "shadowscale", "whiteshadow", "sprxoff", @@ -375,6 +377,9 @@ static int mobj_get(lua_State *L) case mobj_colorized: lua_pushboolean(L, mo->colorized); break; + case mobj_hitlag: + lua_pushinteger(L, mo->hitlag); + break; case mobj_shadowscale: lua_pushfixed(L, mo->shadowscale); break; @@ -710,6 +715,9 @@ static int mobj_set(lua_State *L) case mobj_colorized: mo->colorized = luaL_checkboolean(L, 3); break; + case mobj_hitlag: + mo->hitlag = luaL_checkinteger(L, 3); + break; case mobj_shadowscale: mo->shadowscale = luaL_checkfixed(L, 3); break; diff --git a/src/p_map.c b/src/p_map.c index 4ef258ebb..69a638ce4 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2598,6 +2598,12 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) if (radius < mapobjectscale) radius = mapobjectscale; + if (thing->hitlag > 0) + { + // Do not move during hitlag + return false; + } + do { if (thing->flags & MF_NOCLIP) { tryx = x; diff --git a/src/p_mobj.c b/src/p_mobj.c index 734a6e3f3..806fccf50 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6392,6 +6392,12 @@ void P_MobjThinker(mobj_t *mobj) if (mobj->flags & MF_NOTHINK) return; + if (mobj->hitlag > 0) + { + mobj->hitlag--; + return; + } + // Remove dead target/tracer. if (mobj->target && P_MobjWasRemoved(mobj->target)) P_SetTarget(&mobj->target, NULL); @@ -10875,6 +10881,8 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) mobj->colorized = false; + mobj->hitlag = 0; + // Set shadowscale here, before spawn hook so that Lua can change it P_DefaultMobjShadowScale(mobj); diff --git a/src/p_mobj.h b/src/p_mobj.h index dbb3f4d58..75a6bf3b8 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -410,6 +410,8 @@ typedef struct mobj_s fixed_t sprxoff, spryoff, sprzoff; // Sprite offsets in real space, does NOT affect position or collision + INT32 hitlag; + // WARNING: New fields must be added separately to savegame and Lua. } mobj_t; diff --git a/src/p_saveg.c b/src/p_saveg.c index c197b5a3c..5085f2644 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1000,6 +1000,7 @@ typedef enum #endif MD2_SHADOWSCALE = 1<<14, MD2_DRAWFLAGS = 1<<15, + MD2_HITLAG = 1<<16 } mobj_diff2_t; typedef enum @@ -1196,12 +1197,14 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) if (mobj->standingslope) diff2 |= MD2_SLOPE; #endif + if (mobj->colorized) + diff2 |= MD2_COLORIZED; if (mobj->shadowscale) diff2 |= MD2_SHADOWSCALE; if (mobj->drawflags) diff2 |= MD2_DRAWFLAGS; - if (mobj->colorized) - diff2 |= MD2_COLORIZED; + if (mobj->hitlag) + diff2 |= MD2_HITLAG; if (mobj == waypointcap) diff2 |= MD2_WAYPOINTCAP; if (mobj == kitemcap) @@ -1342,6 +1345,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) WRITEUINT16(save_p, df); } + if (diff2 & MD2_HITLAG) + WRITEINT32(save_p, mobj->hitlag); WRITEUINT32(save_p, mobj->mobjnum); } @@ -2273,6 +2278,8 @@ static void LoadMobjThinker(actionf_p1 thinker) mobj->shadowscale = READFIXED(save_p); if (diff2 & MD2_DRAWFLAGS) mobj->drawflags = READUINT16(save_p); + if (diff2 & MD2_HITLAG) + mobj->hitlag = READINT32(save_p); if (diff & MD_REDFLAG) { diff --git a/src/p_user.c b/src/p_user.c index 8d6014926..3750c1378 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8677,6 +8677,11 @@ void P_PlayerThink(player_t *player) } #endif + if (player->mo->hitlag > 0) + { + return; + } + if (player->awayviewmobj && P_MobjWasRemoved(player->awayviewmobj)) { P_SetTarget(&player->awayviewmobj, NULL); // remove awayviewmobj asap if invalid diff --git a/src/r_things.c b/src/r_things.c index 05672ae4d..fb12fcb4b 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1429,9 +1429,9 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, // static void R_ProjectSprite(mobj_t *thing) { - const fixed_t thingxpos = thing->x + thing->sprxoff; - const fixed_t thingypos = thing->y + thing->spryoff; - const fixed_t thingzpos = thing->z + thing->sprzoff; + fixed_t thingxpos = thing->x + thing->sprxoff; + fixed_t thingypos = thing->y + thing->spryoff; + fixed_t thingzpos = thing->z + thing->sprzoff; fixed_t tr_x, tr_y; fixed_t gxt, gyt; @@ -1468,6 +1468,14 @@ static void R_ProjectSprite(mobj_t *thing) INT32 light = 0; fixed_t this_scale = thing->scale; + // hitlag vibrating + if (thing->hitlag > 0 && (leveltime & 1)) + { + thingxpos += thing->momx; + thingypos += thing->momy; + thingzpos += thing->momz; + } + // transform the origin point tr_x = thingxpos - viewx; tr_y = thingypos - viewy;