Skip to content

Commit e55a85f

Browse files
sodat1dev2v3v4
andcommitted
Add ability to enable NPCs look at actor
An optional feature to enable NPCs head turning towards actor in a certain radius Co-authored-by: v2v3v4 <v2v3v4@users.noreply.github.com>
1 parent 9e37740 commit e55a85f

File tree

5 files changed

+101
-3
lines changed

5 files changed

+101
-3
lines changed

gamedata/configs/engine_external.ltx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ DeadBodyRagdoll = false
1212
EnableThirst = false
1313
EnableSleepiness = false
1414
EnableAiDieInAnomaly = false
15+
EnableNPCLookAtActor = false
1516

1617
[render]
1718
LoadScreenTips = true

src/xrEngine/EngineExternal.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ enum class EEngineExternalGame
1515
{
1616
EnableThirst,
1717
EnableSleepiness,
18-
EnableAiDieInAnomaly
18+
EnableAiDieInAnomaly,
19+
EnableNPCLookAtActor
1920
};
2021

2122
enum class EEngineExternalRender {

src/xrGame/Actor.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,8 @@ struct SDefNewsMsg{
446446
float MaxWalkWeight () const;
447447
float get_additional_weight() const;
448448

449+
int m_head;
450+
449451
protected:
450452
CFireDispertionController m_fdisp_controller;
451453
//если актер целится в прицел
@@ -471,7 +473,6 @@ struct SDefNewsMsg{
471473
int m_r_hand;
472474
int m_l_finger1;
473475
int m_r_finger2;
474-
int m_head;
475476
int m_eye_left;
476477
int m_eye_right;
477478

src/xrGame/ai/stalker/ai_stalker.cpp

Lines changed: 90 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "../../../Include/xrRender/Kinematics.h"
2828
#include "../../../xrServerEntities/character_info.h"
2929
#include "../../actor.h"
30+
#include "../xrEngine/CameraBase.h"
3031
#include "../../relation_registry.h"
3132
#include "../../stalker_animation_manager.h"
3233
#include "../../stalker_planner.h"
@@ -91,6 +92,10 @@ CAI_Stalker::CAI_Stalker () :
9192
m_dbg_hud_draw = false;
9293
#endif // DEBUG
9394
m_registered_in_combat_on_migration = false;
95+
96+
savedOrientation = { 0.f, 0.f, 0.f };
97+
dTimeFSeen = Device.dwTimeGlobal + 1000;
98+
dTimeNfSeen = Device.dwTimeGlobal + 1000;
9499
}
95100

96101
CAI_Stalker::~CAI_Stalker ()
@@ -502,6 +507,84 @@ void CAI_Stalker::Load (LPCSTR section)
502507
m_can_select_items = !!pSettings->r_bool(section,"can_select_items");
503508
}
504509

510+
void CAI_Stalker::BoneCallback(CBoneInstance* B) {
511+
CAI_Stalker* this_class = static_cast<CAI_Stalker*>(B->callback_param());
512+
513+
this_class->LookAtActor(B);
514+
R_ASSERT2(_valid(B->mTransform), "CAI_Stalker::BoneCallback");
515+
}
516+
517+
void CAI_Stalker::LookAtActor(CBoneInstance* headBone) {
518+
if (!g_Alive())
519+
return;
520+
521+
if (!Actor())
522+
return;
523+
524+
if (wounded())
525+
return;
526+
527+
auto adjustHeadOrientation = [&](float targetPitch, float targetYaw, float targetRoll) {
528+
savedOrientation.x = angle_inertion(savedOrientation.x, targetPitch, angle_difference(savedOrientation.x, targetPitch), PI_MUL_2, Device.fTimeDelta);
529+
savedOrientation.y = angle_inertion(savedOrientation.y, targetYaw, angle_difference(savedOrientation.y, targetYaw), PI_MUL_2, Device.fTimeDelta);
530+
savedOrientation.z = angle_inertion(savedOrientation.z, targetRoll, angle_difference(savedOrientation.z, targetRoll), PI_MUL_2, Device.fTimeDelta);
531+
};
532+
533+
if (Actor()->Position().distance_to(Position()) > 4.f) {
534+
adjustHeadOrientation(0.f, 0.f, 0.f);
535+
Fmatrix M;
536+
M.setHPB(VPUSH(savedOrientation));
537+
headBone->mTransform.mulB_43(M);
538+
return;
539+
}
540+
541+
if (memory().visual().visible_right_now(Actor())) {
542+
Fmatrix actorHead;
543+
smart_cast<IKinematics*>(Actor()->Visual())->Bone_GetAnimPos(actorHead, u16(Actor()->m_head), u8(-1), false);
544+
actorHead.mulA_43(Actor()->XFORM());
545+
546+
Fmatrix myHead = headBone->mTransform;
547+
myHead.mulA_43(XFORM());
548+
myHead.c.mad(myHead.i, .15f);
549+
550+
Fvector dir, cam_pos = Actor()->HUDview() ? Actor()->cam_FirstEye()->Position() : actorHead.c;
551+
dir.sub(cam_pos, myHead.c).normalize();
552+
553+
Fmatrix target_matrix;
554+
target_matrix.identity();
555+
target_matrix.k.set(dir);
556+
Fvector::generate_orthonormal_basis_normalized(target_matrix.k, target_matrix.i, target_matrix.j);
557+
target_matrix.j.invert();
558+
target_matrix.mulA_43(Fmatrix(headBone->mTransform).mulA_43(XFORM()).invert());
559+
560+
float yaw, pitch, roll;
561+
target_matrix.getHPB(pitch, yaw, roll);
562+
563+
clamp(pitch, -0.75f, 0.7f);
564+
clamp(yaw, -1.0f, 1.0f);
565+
clamp(roll, -0.4f, 0.4f);
566+
567+
bool inRange = (pitch > -0.7f && pitch < 0.65f) && (yaw > -0.9f && yaw < 0.9f) && (roll > -0.35f && roll < 0.35f);
568+
if (inRange && dTimeNfSeen < Device.dwTimeGlobal) {
569+
dTimeFSeen = Device.dwTimeGlobal + 1000;
570+
adjustHeadOrientation(pitch, yaw, roll);
571+
}
572+
573+
bool outOfRange = !(pitch > -0.75f && pitch < 0.7f) && !(yaw > -1.2f && yaw < 1.2f) && !(roll > -0.5f && roll < 0.5f);
574+
if (outOfRange && dTimeFSeen < Device.dwTimeGlobal) {
575+
dTimeNfSeen = Device.dwTimeGlobal + 1000;
576+
adjustHeadOrientation(0.f, 0.f, 0.f);
577+
}
578+
}
579+
else {
580+
adjustHeadOrientation(0.f, 0.f, 0.f); // Reset if actor not visible
581+
}
582+
583+
Fmatrix M;
584+
M.setHPB(VPUSH(savedOrientation));
585+
headBone->mTransform.mulB_43(M);
586+
}
587+
505588
BOOL CAI_Stalker::net_Spawn (CSE_Abstract* DC)
506589
{
507590
CSE_Abstract *e = (CSE_Abstract*)(DC);
@@ -609,7 +692,13 @@ BOOL CAI_Stalker::net_Spawn (CSE_Abstract* DC)
609692

610693
sight().update ();
611694
Exec_Look (.001f);
612-
695+
696+
if (EngineExternal()[EEngineExternalGame::EnableNPCLookAtActor]) {
697+
CBoneInstance* bone_head = &smart_cast<IKinematics*>(Visual())->LL_GetBoneInstance(
698+
smart_cast<IKinematics*>(Visual())->LL_BoneID("bip01_head"));
699+
bone_head->set_callback(bctCustom, BoneCallback, this);
700+
}
701+
613702
m_pPhysics_support->in_NetSpawn (e);
614703

615704
return (TRUE);

src/xrGame/ai/stalker/ai_stalker.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,9 @@ class CAI_Stalker :
123123
private:
124124
float m_power_fx_factor;
125125

126+
Fvector savedOrientation;
127+
u32 dTimeFSeen;
128+
u32 dTimeNfSeen;
126129
private:
127130
float m_fRankDisperison;
128131
float m_fRankVisibility;
@@ -180,6 +183,9 @@ class CAI_Stalker :
180183
virtual void reload (LPCSTR section );
181184
virtual void LoadSounds (LPCSTR section );
182185

186+
static void BoneCallback(CBoneInstance* B);
187+
void LookAtActor(CBoneInstance* headBone);
188+
183189
virtual BOOL net_Spawn (CSE_Abstract* DC);
184190
virtual void net_Export (NET_Packet& P);
185191
virtual void net_Import (NET_Packet& P);

0 commit comments

Comments
 (0)