Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_NarrativeComponent.c
Go to the documentation of this file.
2{
3}
4
5class SCR_NarrativeComponent : ScriptComponent
6{
7 [Attribute("Initial gesture")]
8 protected int m_iCharacterID;
9
10 [Attribute("false")]
11 protected bool m_bDeathAnimation;
12
13 [Attribute("false")]
14 protected bool m_bRootMotion;
15
16 [Attribute("")]
17 protected string m_sPositionToEntity;
18
19 [Attribute("false")]
20 protected bool m_bDisablePhysics;
21
22 [Attribute("0", params: "0 6")]
23 protected int m_iDefaultEmotion;
24
25 [Attribute("true")]
26 protected bool m_bProximityLook;
27
28 [Attribute("5", params: "1 100")]
29 protected float m_fProximityLookRadius;
30
31 [Attribute("1.1", params: "0.01 3.1")]
32 protected float m_fProximityLookWidth;
33
34 [Attribute("false")]
35 protected bool m_bProximityTalk;
36
37 [Attribute("5", params: "1 100")]
38 protected float m_fProximityTalkRadius;
39
40 [Attribute("false")]
41 protected bool m_bProximityTalkOnlyOnce;
42
43 [Attribute("1", params: "0 100")]
44 protected int m_iProximityTalkDefaultStage;
45
46 [Attribute("1", params: "1 10")]
47 protected int m_iTalkVariants;
48
49 [Attribute("false")]
50 protected bool m_bRandomTalkVariant;
51
52 [Attribute("false")]
53 protected bool m_bStopTalkWhenOutOfProximity;
54
55 protected bool m_bStoppingTalk;
56 protected bool m_bProximityTalkEnabled = true;
57
58 protected int m_iPermanentNarrativeStage;
59 protected int m_iActualTalkVariant = 1;
60 protected int m_iPlayerBoneId;
61
62 protected float m_fLookAtIntensity;
63 protected float m_fDistanceToPlayer;
64
65 protected vector m_vLook[4];
66 protected vector m_vLookEnd[4];
67 protected vector m_vLookAxis;
68 protected vector m_vPlayerHead[4];
69 protected vector m_vPlayerPosition[4];
70 protected vector m_vPlayerHeadPosition;
71
72 protected IEntity m_EntityInHand;
73 protected IEntity m_Player;
74 protected IEntity entityToAttachTo;
75
76 protected EntitySlotInfo m_PointOfViewStart;
77 protected EntitySlotInfo m_PointOfViewEnd;
78
79 protected TAnimGraphVariable m_LookAtVariable;
80 protected TAnimGraphVariable m_EmotionId;
81
82 protected CharacterAnimationComponent m_CharacterAnimation;
83
84 protected SCR_CommunicationSoundComponent m_CommSoundComp;
85
86 protected SlotManagerComponent m_SlotManager;
87
89
91
92 //------------------------------------------------------------------------------------------------
93 void PlayAnimation(bool in = false, string command = "CMD_NarrativeStage", int animId = 0)
94 {
95 if (!m_CharacterAnimation)
96 return;
97
98 TAnimGraphCommand commandId = m_CharacterAnimation.BindCommand(command);
99
100 if (m_bRootMotion && m_CharController && animId > -1)
101 {
103 customAnimData.m_CustomCommand = commandId;
104
105 SCR_CharacterCommandHandlerComponent scrCmdHandler = SCR_CharacterCommandHandlerComponent.Cast(m_CharacterAnimation.GetCommandHandler());
106 scrCmdHandler.StartCommand_Move();
107
108 vector targetPosition[4] = { "1 0 0", "0 1 0", "0 0 1", "0 0 0" };
109
110 bool alignToPosition = false;
111
112 if (m_sPositionToEntity != "")
113 {
114 entityToAttachTo = GetGame().GetWorld().FindEntityByName(m_sPositionToEntity);
115 if (entityToAttachTo)
116 {
117 entityToAttachTo.GetTransform(targetPosition);
118 alignToPosition = true;
119 }
120 }
121
122 m_CharController.StartLoitering(entityToAttachTo, animId, false, true, alignToPosition, targetPosition, false, customAnimData);
123 }
124 else
125 {
126 if (in)
127 m_CharacterAnimation.CallCommand4I(commandId, 0, animId, 0, 0, 0);
128 else
129 m_CharacterAnimation.CallCommand(commandId, animId, 0);
130 }
131
132 if (m_iActualTalkVariant < m_iTalkVariants)
133 m_iActualTalkVariant++;
134 else
135 m_iActualTalkVariant = 1;
136
137 if (m_bRandomTalkVariant)
138 m_iActualTalkVariant = Math.RandomInt(1, m_iTalkVariants + 1);
139
140 TAnimGraphVariable variableId = m_CharacterAnimation.BindVariableInt("TalkVariant");
141
142 if (variableId > 0)
143 m_CharacterAnimation.SetVariableInt(variableId, m_iActualTalkVariant);
144
145 if (m_EmotionId)
146 m_CharacterAnimation.SetVariableInt(m_EmotionId, m_iDefaultEmotion);
147 }
148
149 //------------------------------------------------------------------------------------------------
151 {
152 m_iPermanentNarrativeStage = stage;
153 m_bProximityTalkEnabled = true;
154 }
155
156 //------------------------------------------------------------------------------------------------
157 override void EOnFixedFrame(IEntity owner, float timeSlice)
158 {
159 m_Player = EntityUtils.GetPlayer();
160
161 if (!m_Player)
162 return;
163
164 m_Player.GetTransform(m_vPlayerPosition);
165 m_fDistanceToPlayer = vector.Distance(m_vPlayerPosition[3], owner.GetOrigin());
166
167 if (m_fDistanceToPlayer > m_fProximityTalkRadius) // NPC is too far to speak...
168 {
169 if (m_fDistanceToPlayer < m_fProximityLookRadius) // ... but can see the player
170 LookAtPlayer(owner, timeSlice);
171 else if (m_fDistanceToPlayer < 50) // NPC is too far to speak and look
172 LookAtPlayer(owner, timeSlice, true);
173
174 if (m_bStopTalkWhenOutOfProximity && !m_bStoppingTalk && IsActualCourseFreeRoam()) //NPC need tho shut-up when player goes away ONLY IN FREE_ROAM
175 {
176 PlayAnimation(true, "CMD_NarrativeStage", -1); // Shut-up BUT only for FREE_ROAM
177 m_bStoppingTalk = true;
178 }
179
180 if (!m_bProximityTalkOnlyOnce) // When NPC too far, we enable possibility to talk again
181 m_bProximityTalkEnabled = true;
182 }
183 else if (LookAtPlayer(owner, timeSlice)) // NPC is near to speak and see the player
184 {
185 m_bStoppingTalk = false;
186
187 if (m_bProximityTalk && m_bProximityTalkEnabled) // Proximity talk is ON, NPC din“t talk yet
188 {
189 if (!m_bProximityTalkOnlyOnce) // NPC should talk whenever see player
190 {
191 PlayAnimation(true, "CMD_NarrativeStage", m_iPermanentNarrativeStage);
192 m_bProximityTalkEnabled = false;
193 }
194 else if (IsActualCourseFreeRoam()) // NPC has just specific line need to be said only once ... and just in FREE_ROAM
195 {
196 PlayAnimation(true, "CMD_NarrativeStage", m_iPermanentNarrativeStage);
197 m_bProximityTalkEnabled = false;
198 }
199 }
200 }
201 else if (m_bStopTalkWhenOutOfProximity && !m_bStoppingTalk && IsActualCourseFreeRoam()) // Player is near but at NPC's back
202 {
203 PlayAnimation(true, "CMD_NarrativeStage", -1); // Shut-up BUT only for FREE_ROAM
204 m_bStoppingTalk = true;
205 }
206 }
207
208 //------------------------------------------------------------------------------------------------
209 bool LookAtPlayer(IEntity owner, float timeSlice, bool lookAway = false)
210 {
211 m_fLookAtIntensity = Math.Clamp(m_fLookAtIntensity, 0.01, 0.99);
212
213 if (m_LookAtVariable)
214 m_CharacterAnimation.SetVariableFloat(m_LookAtVariable, 1 / (1 + Math.Pow(m_fLookAtIntensity / (1 - m_fLookAtIntensity), -2)));
215
216 if (lookAway)
217 {
218 m_fLookAtIntensity -= timeSlice * 1.3;
219 return false;
220 }
221
222 // Compute lookAt region origin
223 if (m_PointOfViewStart)
224 m_PointOfViewStart.GetWorldTransform(m_vLook);
225
226 if (m_PointOfViewEnd)
227 m_PointOfViewEnd.GetWorldTransform(m_vLookEnd);
228
229 m_vLookAxis = vector.Direction(m_vLook[3], m_vLookEnd[3]);
230 m_vLookAxis.Normalize();
231
232 if (Math3D.IntersectionSphereCone(m_vPlayerPosition[3], 1, m_vLook[3], m_vLookAxis, m_fProximityLookWidth))
233 {
234 Animation playerAnimation = m_Player.GetAnimation();
235 m_iPlayerBoneId = playerAnimation.GetBoneIndex("Head");
236 playerAnimation.GetBoneMatrix(m_iPlayerBoneId, m_vPlayerHead);
237
238 Math3D.MatrixMultiply4(m_vPlayerPosition, m_vPlayerHead, m_vPlayerHead);
239
240 m_vPlayerHeadPosition = GetOwner().CoordToLocal(m_vPlayerHead[3]);
241 m_CharacterAnimation.SetIKTarget("HeadLook", "HeadLook", m_vPlayerHeadPosition, {0, 0, 0});
242
243 m_fLookAtIntensity += timeSlice * 1.3;
244 return true;
245 }
246 else
247 {
248 m_fLookAtIntensity -= timeSlice * 1.3;
249 return false;
250 }
251
252 //DebugTextWorldSpace.Create(GetOwner().GetWorld(), "X", DebugTextFlags.ONCE, m_vPlayerHead[3][0], m_vPlayerHead[3][1], m_vPlayerHead[3][2]);
253 }
254
255 //------------------------------------------------------------------------------------------------
256 override void OnPostInit(IEntity owner)
257 {
258 if (!GetGame().InPlayMode())
259 return;
260
261 SetEventMask(owner, EntityEvent.INIT);
262 }
263
264 //------------------------------------------------------------------------------------------------
265 override void EOnInit(IEntity owner)
266 {
267 Initialize(owner);
268
269 m_iPermanentNarrativeStage = m_iProximityTalkDefaultStage;
270 }
271
272 //------------------------------------------------------------------------------------------------
273 void Initialize(IEntity owner)
274 {
275
276 if (m_bDisablePhysics)
277 SCR_PhysicsHelper.ChangeSimulationState(owner, SimulationState.NONE, false);
278
279 if (m_bProximityLook)
280 SetEventMask(owner, EntityEvent.FIXEDFRAME);
281
282 m_SlotManager = SlotManagerComponent.Cast(owner.FindComponent(SlotManagerComponent));
283
284 if (m_SlotManager)
285 {
286 m_PointOfViewStart = m_SlotManager.GetSlotByName("PointOfViewStart");
287 m_PointOfViewEnd = m_SlotManager.GetSlotByName("PointOfViewEnd");
288 }
289
291
292 if (m_CharacterAnimation)
293 {
294 m_LookAtVariable = m_CharacterAnimation.BindVariableFloat("NarrativeLookAtIntensity");
295 m_EmotionId = m_CharacterAnimation.BindVariableInt("emotion");
296 }
297
299
300 if (m_DamageManager)
301 {
302 m_DamageManager.GetOnDamage().Remove(OnDamage);
303 m_DamageManager.GetOnDamage().Insert(OnDamage);
304 }
305
307
309 {
310 m_CharController.GetOnAnimationEvent().Remove(OnAnimationEvent);
311 m_CharController.GetOnAnimationEvent().Insert(OnAnimationEvent);
312 }
313
315
316 if (m_CommSoundComp)
317 m_CommSoundComp.TerminateAll();
318
319 // Play initial animation
320 GetGame().GetCallqueue().CallLater(PlayAnimation, 1000, false, true, "CMD_Narrative", m_iCharacterID);
321 }
322
323 //------------------------------------------------------------------------------------------------
325 {
326 SCR_TutorialGamemodeComponent tutorialGamemodeComponent = SCR_TutorialGamemodeComponent.GetInstance();
327
328 if (!tutorialGamemodeComponent)
329 return true;
330
331 SCR_ETutorialCourses actualCourse = tutorialGamemodeComponent.GetActiveConfig().GetCourseType();
332
333 return actualCourse == SCR_ETutorialCourses.FREE_ROAM || actualCourse == SCR_ETutorialCourses.OUTRO || actualCourse == SCR_ETutorialCourses.INTRO;
334 }
335
336 //------------------------------------------------------------------------------------------------
337 void OnDamage()
338 {
339 array<EntitySlotInfo> npcSlotInfos = {};
340
341 if (m_SlotManager)
342 {
343 m_SlotManager.GetSlotInfos(npcSlotInfos);
344
345 foreach (EntitySlotInfo slotInfo : npcSlotInfos)
346 {
347 if (slotInfo.GetAttachedEntity())
348 slotInfo.DetachEntity(false);
349 }
350 }
351
352 if (m_bDeathAnimation)
353 {
354 PlayAnimation(true, "CMD_Narrative", -1);
355 }
356 else
357 {
358 CharacterControllerComponent controller = CharacterControllerComponent.Cast(GetOwner().FindComponent(CharacterControllerComponent));
359
360 if (controller)
361 controller.ForceDeath();
362 }
363 }
364
365 //------------------------------------------------------------------------------------------------
366 void OnAnimationEvent(AnimationEventID animEventType, AnimationEventID animUserString, int intParam, float timeFromStart, float timeToEnd)
367 {
368 string eventName = GameAnimationUtils.GetEventString(animEventType);
369
370 if (eventName == "TutorialVoice")
371 {
372 if (m_CommSoundComp)
373 m_CommSoundComp.SoundEventPriority(GameAnimationUtils.GetEventString(animUserString), intParam, true);
374 }
375 else if (eventName == "PropDetach")
376 {
378
379 if (baseSlot)
380 {
381 EntitySlotInfo slotInfo = baseSlot.GetSlotInfo();
382
383 if (slotInfo)
384 {
385 m_EntityInHand = slotInfo.GetAttachedEntity();
386 slotInfo.DetachEntity(true);
387 }
388 }
389 }
390 else if (eventName == "PropAttach")
391 {
393
394 if (baseSlot)
395 {
396 EntitySlotInfo telephoneSlot = baseSlot.GetSlotInfo();
397
398 if (telephoneSlot && m_EntityInHand)
399 telephoneSlot.AttachEntity(m_EntityInHand);
400 }
401 }
402 }
403}
int AnimationEventID
int TAnimGraphVariable
Definition ECommandIDs.c:2
int TAnimGraphCommand
Definition ECommandIDs.c:1
ArmaReforgerScripted GetGame()
Definition game.c:1398
DamageManagerComponent m_DamageManager
ChimeraCharacter m_Player
SCR_CharacterBloodHitZone OnDamage
Resilience - incapacitation or death, depending on game mode settings.
SCR_CharacterControllerComponent m_CharController
SCR_ETutorialCourses
bool LookAtPlayer(IEntity owner, float timeSlice, bool lookAway=false)
void SetPermanentNarrativeStage(int stage)
bool IsActualCourseFreeRoam()
SCR_SlotServiceComponentClass m_SlotManager
Service with basic slot handling functionalities.
Adds ability to attach an object to a slot.
proto external int SetEventMask(notnull IEntity owner, int mask)
proto external GenericComponent FindComponent(typename typeName)
proto external Managed FindComponent(typename typeName)
proto external vector GetOrigin()
proto external BaseWorld GetWorld()
proto external void GetTransform(out vector mat[])
proto external vector CoordToLocal(vector coord)
Definition Math.c:13
void StartLoitering(IEntity loiterEntity, int loiteringType, bool holsterWeapon, bool allowRootMotion, bool alignToPosition, vector targetPosition[4]={ "1 0 0", "0 1 0", "0 0 1", "0 0 0" }, bool disableInput=false, SCR_LoiterCustomAnimData customAnimData=SCR_LoiterCustomAnimData.Default)
proto external GenericEntity GetOwner()
Get owner entity.
void EOnFixedFrame(IEntity owner, float timeSlice)
void EOnInit(IEntity owner)
event void OnAnimationEvent(AnimationEventID animEventType, AnimationEventID animUserString, int intParam, float timeFromStart, float timeToEnd)
SCR_FieldOfViewSettings Attribute
EntityEvent
Various entity events.
Definition EntityEvent.c:14
SimulationState