From 12619671e6846fa7831e1814ff75c69421062512 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 27 Dec 2021 15:33:10 +0100 Subject: [PATCH] - 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. --- source/core/intvec.h | 1 + source/games/duke/src/inlines.h | 1 - source/games/duke/src/player.cpp | 24 ++++++++++++++++++++---- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/source/core/intvec.h b/source/core/intvec.h index 11c6f76e6..8e9e45edc 100644 --- a/source/core/intvec.h +++ b/source/core/intvec.h @@ -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 }; } }; diff --git a/source/games/duke/src/inlines.h b/source/games/duke/src/inlines.h index e547214f2..91fc329c0 100644 --- a/source/games/duke/src/inlines.h +++ b/source/games/duke/src/inlines.h @@ -112,7 +112,6 @@ inline bool isIn(int value, const std::initializer_list& 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) { diff --git a/source/games/duke/src/player.cpp b/source/games/duke/src/player.cpp index d7219fa28..59739145c 100644 --- a/source/games/duke/src/player.cpp +++ b/source/games/duke/src/player.cpp @@ -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) {