diff --git a/src/info.h b/src/info.h index 2c6f171e..25e2dfa3 100644 --- a/src/info.h +++ b/src/info.h @@ -1524,6 +1524,8 @@ typedef struct int bloodcolor; // [FG] colored blood and gibs // DEHEXTRA mobjtype_t droppeditem; // mobj to drop after death + // [crispy] height of the spawnstate's first sprite in pixels + int actualheight; } mobjinfo_t; #define NO_ALTSPEED -1 diff --git a/src/m_menu.c b/src/m_menu.c index 0d1c8f73..7d8f37cf 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4057,6 +4057,7 @@ enum { gen3_title2, gen3_hangsolid, gen3_blockmapfix, + gen3_verticalaim, gen3_pistolstart, gen3_end2, }; @@ -4248,6 +4249,9 @@ setup_menu_t gen_settings3[] = { // General Settings screen3 {"Improved Hit Detection", S_YESNO|S_STRICT|S_CRITICAL, m_null, M_X, M_Y + gen3_blockmapfix*M_SPC, {"blockmapfix"}}, + {"Direct Vertical Aiming", S_YESNO|S_STRICT|S_CRITICAL, m_null, M_X, + M_Y + gen3_verticalaim*M_SPC, {"direct_vertical_aiming"}}, + {"Pistol Start", S_YESNO|S_STRICT|S_CRITICAL, m_null, M_X, M_Y + gen3_pistolstart*M_SPC, {"pistolstart"}}, diff --git a/src/m_misc.c b/src/m_misc.c index cdf68a83..b06a2eed 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -620,6 +620,13 @@ default_t defaults[] = { "1 to enable blockmap bug fix" }, + { + "direct_vertical_aiming", + (config_t *) &direct_vertical_aiming, NULL, + {0}, {0,1}, number, ss_gen, wad_no, + "1 to enable direct vertical aiming" + }, + { "pistolstart", (config_t *) &default_pistolstart, (config_t *) &pistolstart, diff --git a/src/p_map.c b/src/p_map.c index b03e46d0..112d54a6 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -564,9 +564,14 @@ static boolean PIT_CheckThing(mobj_t *thing) // killough 3/26/98: make static if (tmthing->flags & MF_MISSILE || (tmthing->flags & MF_BOUNCES && !(tmthing->flags & MF_SOLID))) { + // [crispy] mobj or actual sprite height + const fixed_t thingheight = (tmthing->target && tmthing->target->player && + CRITICAL(direct_vertical_aiming)) ? + thing->info->actualheight : thing->height; + // see if it went over / under - if (tmthing->z > thing->z + thing->height) + if (tmthing->z > thing->z + thingheight) return true; // overhead if (tmthing->z+tmthing->height < thing->z) @@ -1565,6 +1570,29 @@ static boolean PTR_ShootTraverse(intercept_t *in) return false; } + // [crispy] check if the pullet puff's z-coordinate is below or above + // its spawning sector's floor or ceiling, respectively, and move its + // coordinates to the point where the trajectory hits the plane + if (CRITICAL(direct_vertical_aiming) && aimslope) + { + const int lineside = P_PointOnLineSide(x, y, li); + int side; + + if ((side = li->sidenum[lineside]) != NO_INDEX) + { + const sector_t *const sector = sides[side].sector; + + if (z < sector->floorheight || + (z > sector->ceilingheight && sector->ceilingpic != skyflatnum)) + { + z = BETWEEN(sector->floorheight, sector->ceilingheight, z); + frac = FixedDiv(z - shootz, FixedMul(aimslope, attackrange)); + x = trace.x + FixedMul (trace.dx, frac); + y = trace.y + FixedMul (trace.dy, frac); + } + } + } + // Spawn bullet puffs. P_SpawnPuff (x,y,z); @@ -1586,7 +1614,12 @@ static boolean PTR_ShootTraverse(intercept_t *in) // check angles to see if the thing can be aimed at dist = FixedMul (attackrange, in->frac); - thingtopslope = FixedDiv (th->z+th->height - shootz , dist); + { + // [crispy] mobj or actual sprite height + const fixed_t thingheight = (shootthing->player && CRITICAL(direct_vertical_aiming)) ? + th->info->actualheight : th->height; + thingtopslope = FixedDiv (th->z+thingheight - shootz , dist); + } if (thingtopslope < aimslope) return true; // shot over the thing diff --git a/src/p_mobj.c b/src/p_mobj.c index be014f14..fa9c4914 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -35,9 +35,12 @@ #include "g_game.h" #include "p_inter.h" #include "v_video.h" +#include "m_swap.h" +#include "w_wad.h" // [FG] colored blood and gibs boolean colored_blood; +boolean direct_vertical_aiming; // // P_SetMobjState @@ -873,6 +876,29 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) mobj->intflags &= ~MIF_FLIP; } + // [crispy] height of the spawnstate's first sprite in pixels + if (!info->actualheight) + { + const spritedef_t *const sprdef = &sprites[mobj->sprite]; + + if (!sprdef->numframes || !(mobj->flags & (MF_SOLID|MF_SHOOTABLE))) + { + info->actualheight = info->height; + } + else + { + spriteframe_t *sprframe; + int lump; + patch_t *patch; + + sprframe = &sprdef->spriteframes[mobj->frame & FF_FRAMEMASK]; + lump = sprframe->lump[0]; + patch = W_CacheLumpNum(lump + firstspritelump, PU_CACHE); + + info->actualheight = SHORT(patch->height) << FRACBITS; + } + } + P_AddThinker(&mobj->thinker); return mobj; @@ -1448,6 +1474,11 @@ mobj_t* P_SpawnPlayerMissile(mobj_t* source,mobjtype_t type) { // killough 8/2/98: prefer autoaiming at enemies int mask = demo_version < 203 ? 0 : MF_FRIEND; + if (CRITICAL(direct_vertical_aiming)) + { + slope = PLAYER_SLOPE(source->player); + } + else do { slope = P_AimLineAttack(source, an, 16*64*FRACUNIT, mask); diff --git a/src/p_mobj.h b/src/p_mobj.h index 3e6f506d..edac0eaa 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -416,6 +416,9 @@ extern int iquetail; // [FG] colored blood and gibs extern boolean colored_blood; +#define PLAYER_SLOPE(a) ((((a)->lookdir / MLOOKUNIT) << FRACBITS) / 173) // angle to fixed approximation +extern boolean direct_vertical_aiming; + mobj_t *P_SubstNullMobj(mobj_t *mobj); void P_RespawnSpecials(void); mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type); diff --git a/src/p_pspr.c b/src/p_pspr.c index d4d98650..4a80a5bb 100644 --- a/src/p_pspr.c +++ b/src/p_pspr.c @@ -786,6 +786,11 @@ void A_FireOldBFG(player_t *player, pspdef_t *psp) // killough 8/2/98: make autoaiming prefer enemies int mask = MF_FRIEND; fixed_t slope; + if (CRITICAL(direct_vertical_aiming)) + { + slope = PLAYER_SLOPE(mo->player); + } + else do { slope = P_AimLineAttack(mo, an, 16*64*FRACUNIT, mask); @@ -851,6 +856,11 @@ static void P_BulletSlope(mobj_t *mo) // killough 8/2/98: make autoaiming prefer enemies int mask = demo_version < 203 ? 0 : MF_FRIEND; + if (CRITICAL(direct_vertical_aiming)) + { + bulletslope = PLAYER_SLOPE(mo->player); + } + else do { bulletslope = P_AimLineAttack(mo, an, 16*64*FRACUNIT, mask);