- Duke/RR: added fudging to work around aiming randomization issues with the pistol when autoaim is off.

Solution is the same as in RedNukem/EDuke32: do one hitscan directly in aiming order and if that hits a sprite, use it as aiming target.
This commit is contained in:
Christoph Oelckers 2021-12-27 15:33:10 +01:00
parent 1f2abda23c
commit 12619671e6
3 changed files with 21 additions and 5 deletions

View file

@ -41,6 +41,7 @@ struct vec3_t
vec3_t operator-(const vec3_t& other) const { return { X - other.X, Y - other.Y, Z - other.Z }; }
vec3_t& operator+=(const vec3_t& other) { X += other.X; Y += other.Y; Z += other.Z; return *this; };
vec3_t& operator-=(const vec3_t& other) { X -= other.X; Y -= other.Y; Z += other.Z; return *this; };
vec3_t withZOffset(int ofs) { return { X, Y, Z + ofs }; }
};

View file

@ -112,7 +112,6 @@ inline bool isIn(int value, const std::initializer_list<int>& list)
return false;
}
// these are mainly here to avoid directly accessing the input data so that it can be more easily refactored later.
inline bool PlayerInput(int pl, ESyncBits bit)
{

View file

@ -230,7 +230,7 @@ DDukeActor* aim(DDukeActor* actor, int aang)
{
bool gotshrinker, gotfreezer;
int a, k, cans;
int aimstats[] = { STAT_PLAYER, STAT_DUMMYPLAYER, STAT_ACTOR, STAT_ZOMBIEACTOR };
static const int aimstats[] = { STAT_PLAYER, STAT_DUMMYPLAYER, STAT_ACTOR, STAT_ZOMBIEACTOR };
int dx1, dy1, dx2, dy2, dx3, dy3, smax, sdist;
int xv, yv;
@ -239,11 +239,27 @@ DDukeActor* aim(DDukeActor* actor, int aang)
// Autoaim from DukeGDX.
if (actor->spr.picnum == TILE_APLAYER)
{
auto* plr = &ps[actor->spr.yvel];
int autoaim = Autoaim(actor->spr.yvel);
if (!autoaim)
{
// Some fudging to avoid aim randomization when autoaim is off.
// This is a reimplementation of how it was solved in RedNukem.
if (plr->curr_weapon == PISTOL_WEAPON && !isWW2GI())
{
int zvel = -plr->horizon.sum().asq16() >> 5;
HitInfo hit{};
hitscan(plr->pos.withZOffset(1024), actor->sector(), { bcos(actor->spr.ang), bsin(actor->spr.ang), zvel }, hit, CLIPMASK1);
if (hit.actor() != nullptr)
{
if (isIn(hit.actor()->spr.statnum, { STAT_PLAYER, STAT_DUMMYPLAYER, STAT_ACTOR, STAT_ZOMBIEACTOR }))
return hit.actor();
}
}
// The chickens in RRRA are homing and must always autoaim.
if (!isRRRA() || ps[actor->spr.yvel].curr_weapon != CHICKEN_WEAPON)
if (!isRRRA() || plr->curr_weapon != CHICKEN_WEAPON)
return nullptr;
}
else if (autoaim == 2)
@ -251,11 +267,11 @@ DDukeActor* aim(DDukeActor* actor, int aang)
int weap;
if (!isWW2GI())
{
weap = ps[actor->spr.yvel].curr_weapon;
weap = plr->curr_weapon;
}
else
{
weap = aplWeaponWorksLike(ps[actor->spr.yvel].curr_weapon, actor->spr.yvel);
weap = aplWeaponWorksLike(plr->curr_weapon, actor->spr.yvel);
}
if (weap > CHAINGUN_WEAPON || weap == KNEE_WEAPON)
{