Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
CharacterCameraHandlerComponent.c
Go to the documentation of this file.
1[ComponentEditorProps(category: "GameScripted/Character", description: "Scripted character camera handler (new)")]
5
6class SCR_CharacterCameraHandlerComponent : CameraHandlerComponent
7{
8 [Attribute(category: "Camera Shake")]
9 protected ref SCR_RecoilCameraShakeParams m_pRecoilShakeParams;
10
12 protected ref SCR_RecoilCameraShakeProgress m_pRecoilShake = new SCR_RecoilCameraShakeProgress();
13
14 protected ref ScriptInvokerVoid m_OnThirdPersonSwitch = new ScriptInvokerVoid();
15 protected static float s_fOverlayCameraFOV;
16 protected static float s_fADSSensitivity = 1.0;
17
18 protected int m_iHipsBoneIndex = 0;
19
20 protected bool m_bCameraActive;
21
22 protected bool m_bTraceCharacters = true;
23
24 protected ref PointInfo m_pAttachmentReference;
25
26 //------------------------------------------------------------------------------------------------
27 // constructor
31 void SCR_CharacterCameraHandlerComponent(IEntityComponentSource src, IEntity ent, IEntity parent)
32 {
33 #ifdef ENABLE_DIAG
34 DiagMenu.RegisterRange(SCR_DebugMenuID.DEBUGUI_CHARACTER_DEBUG_VIEW, "", "Cycle Debug View", "Character", "0, 8, 0, 1");
35 DiagMenu.RegisterBool(SCR_DebugMenuID.DEBUGUI_DRAW_CAMERA_COLLISION_SOLVER, "", "Draw Camera Collision Solver", "Character");
36 #endif
37 }
38
39 //------------------------------------------------------------------------------------------------
40 override void Init()
41 {
42 m_OwnerCharacter = SCR_ChimeraCharacter.Cast(GetOwner());
43 m_ControllerComponent = SCR_CharacterControllerComponent.Cast(m_OwnerCharacter.FindComponent(SCR_CharacterControllerComponent));
44 m_AnimationComponent = CharacterAnimationComponent.Cast(m_OwnerCharacter.FindComponent(CharacterAnimationComponent));
45 m_LoadoutStorage = EquipedLoadoutStorageComponent.Cast(m_OwnerCharacter.FindComponent(EquipedLoadoutStorageComponent));
46 m_InputManager = GetGame().GetInputManager();
47 m_IdentityComponent = CharacterIdentityComponent.Cast(m_OwnerCharacter.FindComponent(CharacterIdentityComponent));
48 m_CmdHandler = CharacterCommandHandlerComponent.Cast(m_OwnerCharacter.FindComponent(CharacterCommandHandlerComponent));
49
50 m_iHeadBoneIndex = m_OwnerCharacter.GetAnimation().GetBoneIndex("Head");
51 m_iHipsBoneIndex = m_OwnerCharacter.GetAnimation().GetBoneIndex("Hips");
52 }
53
54 //------------------------------------------------------------------------------------------------
55 override void OnCameraActivate()
56 {
58 m_bCameraActive = true;
59
60 if (m_OwnerCharacter && m_AnimationComponent)
61 {
62 OnThirdPersonSwitch(IsInThirdPerson());
63 }
64
66 if (playerController)
67 {
68 if (playerController.m_bRetain3PV)
69 SetThirdPerson(true);
70 playerController.m_bRetain3PV = false;
71 }
72
73 if (!IsInThirdPerson() && m_OwnerCharacter)
74 {
75 OnAlphatestChange(m_OwnerCharacter.m_fFaceAlphaTest);
76 }
77 }
78
79 //------------------------------------------------------------------------------------------------
82 {
83 m_OwnerCharacter.m_fFaceAlphaTest = a;
84
85 if (m_IdentityComponent)
86 m_IdentityComponent.SetHeadAlpha(a);
87
88 if (m_LoadoutStorage)
89 {
90 IEntity ent = m_LoadoutStorage.GetClothFromArea(LoadoutHeadCoverArea);
91 if (ent)
92 {
94 if (cloth)
95 cloth.SetAlpha(a);
96 }
97 }
98 }
99
100 //------------------------------------------------------------------------------------------------
101 override void OnCameraDeactivate()
102 {
103 if (m_OwnerCharacter)
105
107 m_fFocusValue = 0.0;
108 SetFocusMode(m_fFocusValue);
109
110 m_bCameraActive = false;
111 }
112
113 //------------------------------------------------------------------------------------------------
116 {
117 #ifdef ENABLE_DIAG
118 return DiagMenu.GetValue(SCR_DebugMenuID.DEBUGUI_CHARACTER_DEBUG_VIEW) != CharacterCameraSet.DEBUGVIEW_NONE;
119 #else
120 return false;
121 #endif
122 }
123
124 private bool m_bWasVehicleADS;
125
126 //------------------------------------------------------------------------------------------------
129 bool CheckVehicleADS()
130 {
131 CheckIsInTurret(m_bWasVehicleADS);
132 return m_bWasVehicleADS;
133 }
134
135 //------------------------------------------------------------------------------------------------
139 bool CheckIsInTurret(out bool isInAds)
140 {
141 isInAds = false;
142 CompartmentAccessComponent compartmentAccess = m_OwnerCharacter.GetCompartmentAccessComponent();
143 // Fallback to default VehicleCamera behavior if getting out
144 if (compartmentAccess && compartmentAccess.IsInCompartment() && !compartmentAccess.IsGettingOut())
145 {
146 BaseCompartmentSlot compartment = compartmentAccess.GetCompartment();
147 if (compartment)
148 {
149 BaseControllerComponent controller = compartment.GetController();
150 if (!controller)
151 {
152 controller = compartment.GetAttachedTurret();
153 if (!controller || compartment.GetAttachedTurret().GetContextIDs() != ETurretContextID.TURRET_OPSCONTEXT || compartment.IsOccupantTurnedOut())
154 return false;
155 }
156
157 if (controller)
158 {
159 TurretControllerComponent turretController = TurretControllerComponent.Cast(controller);
160 if(turretController && turretController.GetTurretComponent())
161 {
162 isInAds = turretController.IsWeaponADS();
163
164 if (!turretController.GetUseVehicleCamera() || isInAds || IsInThirdPerson())
165 {
166 return true;
167 }
168 }
169 }
170 }
171 }
172
173 return false;
174 }
175
176 //------------------------------------------------------------------------------------------------
177 override int CameraSelector()
178 {
179 m_AnimationComponent.GetMovementState(m_CharMovementState);
180
181 #ifdef ENABLE_DIAG
182 if (IsDebugView())
183 {
184 return CharacterCameraSet.CHARACTERCAMERA_DEBUG;
185 }
186 #endif
187
188 if (!IsInThirdPerson())
189 {
190 ECharacterLifeState lifeState = m_ControllerComponent.GetLifeState();
191 if (lifeState == ECharacterLifeState.DEAD)
192 return CharacterCameraSet.CHARACTERCAMERA_1ST_BONE_TRANSFORM;
193
194 if (lifeState == ECharacterLifeState.INCAPACITATED)
195 return CharacterCameraSet.CHARACTERCAMERA_1ST_UNCONSCIOUS;
196 }
197 else
198 {
199 if (m_ControllerComponent.IsUnconscious())
200 return CharacterCameraSet.CHARACTERCAMERA_3RD_UNCONSCIOUS;
201 }
202
203 if (m_ControllerComponent.IsSwimming())
204 {
205 if (IsInThirdPerson())
206 return CharacterCameraSet.CHARACTERCAMERA_3RD_FLOAT;
207 else
208 return CharacterCameraSet.CHARACTERCAMERA_1ST_FLOAT;
209 }
210
211 if (SCR_PlayerController.s_pLocalPlayerController && SCR_PlayerController.s_pLocalPlayerController.GetIsBinocularsZoomed())
212 return CharacterCameraSet.CHARACTERCAMERA_BINOCULARS;
213
215 if (m_ControllerComponent.IsWeaponADS() || (m_ControllerComponent.GetInputContext().IsWeaponADS() && m_ControllerComponent.IsChangingStance()))
216 return CharacterCameraSet.CHARACTERCAMERA_ADS;
217
218 if (m_ControllerComponent.IsGadgetRaisedModeWanted() && !m_OwnerCharacter.IsInVehicle())
219 return CharacterCameraSet.CHARACTERCAMERA_1ST;
220
221 CompartmentAccessComponent compartmentAccess = m_OwnerCharacter.GetCompartmentAccessComponent();
222
223 if (m_ControllerComponent.GetInspect() && !m_OwnerCharacter.IsInVehicle())
224 return CharacterCameraSet.CHARACTERCAMERA_1ST;
225
226 bool isRolling = false;
227 if (m_ControllerComponent.IsRoll() && m_CmdHandler)
228 {
229 CharacterCommandMove moveCmd = m_CmdHandler.GetCommandMove();
231 if (moveCmd && !moveCmd.IsBlendingOutRoll())
232 isRolling = true;
233 }
234
235 if (IsInThirdPerson())
236 {
237 if( m_OwnerCharacter.IsInVehicle() && compartmentAccess && !compartmentAccess.IsGettingOut() )
238 {
239 bool isTurretAds = false;
240 bool inTurret = CheckIsInTurret(isTurretAds);
241 if (inTurret)
242 {
243 if (isTurretAds && !m_ControllerComponent.GetFreeLookInput())
244 return CharacterCameraSet.CHARACTERCAMERA_ADS_VEHICLE;
245
246 return CharacterCameraSet.CHARACTERCAMERA_3RD_TURRET;
247 }
248
249 if (m_ControllerComponent.GetInspect())
250 return CharacterCameraSet.CHARACTERCAMERA_1ST_VEHICLE;
251
252 return CharacterCameraSet.CHARACTERCAMERA_3RD_VEHICLE;
253 }
254
255 if (compartmentAccess && (compartmentAccess.IsGettingOut() || compartmentAccess.IsGettingIn()))
256 return CharacterCameraSet.CHARACTERCAMERA_3RD_ERC;
257
258 if( m_CharMovementState.m_CommandTypeId == ECharacterCommandIDs.CLIMB )
259 return CharacterCameraSet.CHARACTERCAMERA_3RD_CLIMB;
260
261 if (m_ControllerComponent.GetScrInputContext().m_iLoiteringType == 1)
262 {
263 SCR_CharacterCommandHandlerComponent scrCmdHandler = SCR_CharacterCommandHandlerComponent.Cast(m_CmdHandler);
264 if (scrCmdHandler && scrCmdHandler.IsLoitering())
265 return CharacterCameraSet.CHARACTERCAMERA_3RD_SITTING;
266 }
267
268 if( m_CharMovementState.m_iStanceIdx == ECharacterStance.PRONE )
269 {
270 if (ShouldForceFirstPersonInThirdPerson(m_ControllerComponent))
271 {
272 if (isRolling)
273 return CharacterCameraSet.CHARACTERCAMERA_1ST_BONE_TRANSFORM;
274
275 return CharacterCameraSet.CHARACTERCAMERA_1ST;
276 }
277
278 return CharacterCameraSet.CHARACTERCAMERA_3RD_PRO;
279 }
280 else if( m_CharMovementState.m_iStanceIdx == ECharacterStance.CROUCH )
281 {
282 if (ShouldForceFirstPersonInThirdPerson(m_ControllerComponent))
283 return CharacterCameraSet.CHARACTERCAMERA_1ST;
284
285 return CharacterCameraSet.CHARACTERCAMERA_3RD_CRO;
286 }
287
288 if (ShouldForceFirstPersonInThirdPerson(m_ControllerComponent))
289 return CharacterCameraSet.CHARACTERCAMERA_1ST;
290
291 return CharacterCameraSet.CHARACTERCAMERA_3RD_ERC;
292 }
293 else if (compartmentAccess && (compartmentAccess.IsGettingIn() || compartmentAccess.IsGettingOut()))
294 {
295 if (compartmentAccess.GetCompartment() && TurretControllerComponent.Cast(compartmentAccess.GetCompartment().GetController())) // is leaving turret
296 return CharacterCameraSet.CHARACTERCAMERA_1ST_TURRET_TRANSITION;
297 return CharacterCameraSet.CHARACTERCAMERA_1ST_VEHICLE_TRANSITION;
298 }
299 else if( m_OwnerCharacter.IsInVehicle() )
300 {
301 bool isTurretAds = false;
302 bool inTurret = CheckIsInTurret(isTurretAds);
303 if (inTurret)
304 {
305 if (isTurretAds && !m_ControllerComponent.GetFreeLookInput())
306 return CharacterCameraSet.CHARACTERCAMERA_ADS_VEHICLE;
307
308 BaseCompartmentSlot compartment = compartmentAccess.GetCompartment();
309 if (compartment && compartment.GetAttachedTurret())
310 {
311 return CharacterCameraSet.CHARACTERCAMERA_1ST_VEHICLE;
312 }
313
314 return CharacterCameraSet.CHARACTERCAMERA_1ST_TURRET;
315 }
316 else if( CheckVehicleADS() )
317 {
318 return CharacterCameraSet.CHARACTERCAMERA_ADS_VEHICLE;
319 }
320
321 return CharacterCameraSet.CHARACTERCAMERA_1ST_VEHICLE;
322 }
325 else if (isRolling)
326 {
327 return CharacterCameraSet.CHARACTERCAMERA_1ST_BONE_TRANSFORM;
328 }
329
330 return CharacterCameraSet.CHARACTERCAMERA_1ST;
331 }
332
333 //------------------------------------------------------------------------------------------------
334 protected bool ShouldForceFirstPersonInThirdPerson(CharacterControllerComponent controller)
335 {
336 if (!m_ControllerComponent.GetWeaponADSInput())
337 return false;
338
339 if (m_ControllerComponent.IsSprinting() || m_ControllerComponent.IsSwimming())
340 return false;
341
342 return true;
343 }
344
345 protected float m_fADSProgress;
346 protected float m_fADSTime;
347
348 //------------------------------------------------------------------------------------------------
349 override float GetCameraTransitionTime(int pFrom, int pTo)
350 {
351 float transTime = 0.4;
352
353 if (pFrom == CharacterCameraSet.CHARACTERCAMERA_3RD_ERC && pTo == CharacterCameraSet.CHARACTERCAMERA_3RD_PRO
354 || pFrom == CharacterCameraSet.CHARACTERCAMERA_3RD_PRO && pTo == CharacterCameraSet.CHARACTERCAMERA_3RD_ERC)
355 transTime = 1.4;
356 else if (pFrom == CharacterCameraSet.CHARACTERCAMERA_3RD_CRO && pTo == CharacterCameraSet.CHARACTERCAMERA_3RD_PRO
357 || pFrom == CharacterCameraSet.CHARACTERCAMERA_3RD_PRO && pTo == CharacterCameraSet.CHARACTERCAMERA_3RD_CRO)
358 transTime = 0.8;
359 else if (pTo == CharacterCameraSet.CHARACTERCAMERA_1ST_UNCONSCIOUS || pTo == CharacterCameraSet.CHARACTERCAMERA_3RD_UNCONSCIOUS)
360 transTime = 0.8;
361 else if (pFrom == CharacterCameraSet.CHARACTERCAMERA_DEBUG || pTo == CharacterCameraSet.CHARACTERCAMERA_DEBUG)
362 transTime = 0.0;
363 else if (pTo == CharacterCameraSet.CHARACTERCAMERA_ADS || pTo == CharacterCameraSet.CHARACTERCAMERA_1ST_READY)
364 {
365 if (m_ControllerComponent)
366 {
367 m_fADSTime = m_ControllerComponent.GetADSTime();
368 if (m_fADSProgress > 0)
369 transTime = m_fADSTime * (1 - m_fADSProgress);
370 else
371 transTime = m_fADSTime;
372 }
373 }
374 else if (pFrom == CharacterCameraSet.CHARACTERCAMERA_ADS)
375 {
376 transTime = m_fADSTime * m_fADSProgress;
377 }
378 else if (pTo == CharacterCameraSet.CHARACTERCAMERA_ADS_VEHICLE)
379 {
380 CompartmentAccessComponent compAcc = m_OwnerCharacter.GetCompartmentAccessComponent();
381 if (compAcc && compAcc.IsInCompartment())
382 {
383 BaseCompartmentSlot compartment = compAcc.GetCompartment();
384 if (compartment)
385 {
386 BaseControllerComponent controller = compartment.GetController();
387 if (controller)
388 {
389 TurretControllerComponent turretController = TurretControllerComponent.Cast(controller);
390 if (turretController)
391 {
392 m_fADSTime = turretController.GetADSTime();
393 if (m_fADSProgress > 0)
394 transTime = m_fADSTime * (1 - m_fADSProgress);
395 else
396 transTime = m_fADSTime;
397 }
398 }
399 }
400 }
401 }
402 else if ((pFrom == CharacterCameraSet.CHARACTERCAMERA_ADS_VEHICLE/* || pFrom == CharacterCameraSet.CHARACTERCAMERA_1ST_TURRET*/) && pTo == CharacterCameraSet.CHARACTERCAMERA_1ST_READY)
403 {
404 transTime = 0.0;
405 }
406 else if ((pFrom == CharacterCameraSet.CHARACTERCAMERA_ADS_VEHICLE/* || pFrom == CharacterCameraSet.CHARACTERCAMERA_3RD_TURRET*/) && pTo == CharacterCameraSet.CHARACTERCAMERA_3RD_ERC)
407 {
408 transTime = 0.0;
409 }
410 else if (pFrom == CharacterCameraSet.CHARACTERCAMERA_1ST_VEHICLE_TRANSITION || pTo == CharacterCameraSet.CHARACTERCAMERA_1ST_VEHICLE_TRANSITION ||
411 pFrom == CharacterCameraSet.CHARACTERCAMERA_1ST_TURRET_TRANSITION || pTo == CharacterCameraSet.CHARACTERCAMERA_1ST_TURRET_TRANSITION)
412 {
413 transTime = 0.8;
414 }
415 else
416 {
417 transTime = GetCameraSet().GetTransitionTime(pFrom, pTo);
418 }
419
420 return transTime;
421 }
422
423 //------------------------------------------------------------------------------------------------
424 override void OnThirdPersonSwitch(bool isInThirdPerson)
425 {
426 if (m_AnimationComponent)
427 {
428 if (isInThirdPerson)
429 m_AnimationComponent.SetAnimationLayerTPP();
430 else
431 m_AnimationComponent.SetAnimationLayerFPP();
432 }
433
434 m_OnThirdPersonSwitch.Invoke(isInThirdPerson);
435 }
436
437 //------------------------------------------------------------------------------------------------
440 {
441 return m_OnThirdPersonSwitch;
442 }
443
444 // Empirical multiplier for focus deceleration
445 protected const float FOCUS_DECELERATION_RATIO = 4.5;
446 protected const float FOCUS_DEFAULT_ADS_TIME = 0.35;
447 protected const float FOCUS_ADS_TIME_RATIO = 0.75;
448
449 [Attribute("0.5", UIWidgets.Slider, "Focus interpolation time", "0 10 0.05")]
450 protected float m_fFocusTime;
451
452 [Attribute("0.9", UIWidgets.Slider, "Focus interpolation deceleration", "0 1 0.05")]
453 protected float m_fFocusDeceleration;
454
455 protected bool m_bDoInterpolateFocus;
456 protected float m_fFocusTargetValue;
457 protected float m_fFocusValue;
458 protected float m_fAutoFocusProgress;
459
460 //------------------------------------------------------------------------------------------------
461 override void OnBeforeCameraUpdate(float pDt, bool pIsKeyframe)
462 {
463 m_fCameraDistanceFilter = Math.SmoothCD(m_fCameraDistanceFilter, m_fTargetDistance, m_fCameraDistanceFilterVel, 0.3, 1000, pDt);
464
465 m_fCameraSlideFilter = Math.SmoothCD(m_fCameraSlideFilter, m_fTargetSlide, m_fCameraSlideFilterVelocity, m_fSlideTime, 1000, pDt);
466 float currDiff = Math.AbsFloat(m_fTargetSlide - m_fCameraSlideFilter);
467 if (currDiff <= DISTANCE_EPSILON)
468 m_fCameraSlideFilter = m_fTargetSlide;
469
470 m_InputManager.ActivateContext("PlayerCameraContext");
471
472 bool isADSAllowed = m_CmdHandler && m_CmdHandler.IsWeaponADSAllowed(false);
473 bool isWeaponADS = isADSAllowed && m_ControllerComponent.GetWeaponADSInput() && !m_ControllerComponent.IsReloading();
474 bool resetFocus = false;
475 if (!isWeaponADS)
476 {
477 if (CheckIsInTurret(isWeaponADS) && m_ControllerComponent.GetFreeLookInput())
478 resetFocus = true;
479 }
480
482
483 if (!isWeaponADS && playerController)
484 isWeaponADS = playerController.GetGadgetFocus();
485
486 // Gadgets do not have ADS time defined
487 float adsTime = m_fADSTime;
488 if (adsTime <= 0)
489 adsTime = FOCUS_DEFAULT_ADS_TIME;
490
491 float adsChange = pDt / adsTime;
492 float autoFocusChange = adsChange / FOCUS_ADS_TIME_RATIO;
493
494 if (isWeaponADS)
495 {
496 if (m_fADSProgress < 1)
497 m_fADSProgress = Math.Min(1, m_fADSProgress + adsChange);
498
499 if (m_fAutoFocusProgress < 1)
500 m_fAutoFocusProgress = Math.Min(1, m_fAutoFocusProgress + autoFocusChange);
501 }
502 else
503 {
504 if (m_fADSProgress > 0)
505 m_fADSProgress = Math.Max(0, m_fADSProgress - adsChange);
506
507 if (m_fAutoFocusProgress > 0)
508 m_fAutoFocusProgress = Math.Max(0, m_fAutoFocusProgress - autoFocusChange);
509 }
510
511 float cameraFocus;
512 if (playerController && !m_ControllerComponent.GetDisableViewControls())
513 cameraFocus = playerController.GetFocusValue(m_fAutoFocusProgress, pDt);
514
515 if (!float.AlmostEqual(m_fFocusTargetValue, cameraFocus))
516 {
517 m_fFocusTargetValue = cameraFocus;
519 }
520
521 if (pIsKeyframe)
522 UpdateViewBob(pDt);
523
524 // When ADS in third person, the fpv view is not necesarilly toggled, but oddly enforced,
525 // so the camera never activates/deactivates, thus bleeding values in
526 if (IsInThirdPerson() && m_ControllerComponent && m_ControllerComponent.GetInputContext().GetDie())
528
529 if (resetFocus)
530 {
531 m_fFocusValue = 0;
532 SetFocusMode(m_fFocusValue);
533 return;
534 }
535
537 return;
538
539 float absDelta = 0;
540
541 // Only care about transition if it takes time
542 if (m_fFocusTime > 0)
543 {
544 absDelta = Math.AbsFloat(m_fFocusTargetValue - m_fFocusValue);
545
546 // Scale the focusChange by absDelta to smooth out the transition
547 float focusDeceleration = FOCUS_DECELERATION_RATIO * absDelta * m_fFocusDeceleration;
548
549 // Linear component needs to be squared so that focus is 99% correct after m_fFocusTime
550 float focusSpeed = (1 - m_fFocusDeceleration) * (1 - m_fFocusDeceleration) + focusDeceleration;
551 float focusChange = pDt * focusSpeed / m_fFocusTime;
552
554 m_fFocusValue += focusChange;
555 else
556 m_fFocusValue -= focusChange;
557
558 m_fFocusValue = Math.Clamp(m_fFocusValue, 0, 1);
559 }
560
561 if (float.AlmostEqual(absDelta, 0))
562 {
564 m_bDoInterpolateFocus = false;
565 }
566
567 SetFocusMode(m_fFocusValue);
568 }
569
570 //------------------------------------------------------------------------------------------------
571 override void OnAfterCameraUpdate(float pDt, bool pIsKeyframe, inout vector transformMS[4], inout vector transformWS[4])
572 {
573 UpdateHeadVisibility(transformWS[3]);
574
575 if (m_ControllerComponent.IsDead())
576 return;
577
578 if (GetCurrentCamera())
579 GetCurrentCamera().OnAfterCameraUpdate(pDt, pIsKeyframe, transformMS);
580
582 UpdateShake(pDt);
583 }
584
585 //------------------------------------------------------------------------------------------------
586 void UpdateHeadVisibility(vector cameraPositionWS)
587 {
588 vector headBoneMat[4];
589 m_OwnerCharacter.GetAnimation().GetBoneMatrix(m_iHeadBoneIndex, headBoneMat);
590
591 vector charMat[4];
592 m_OwnerCharacter.GetWorldTransform(charMat);
593 Math3D.MatrixMultiply4(charMat, headBoneMat, headBoneMat);
594
595 // Set alpha based on distance from camera
596 OnAlphatestChange(255 - Math.Clamp((vector.Distance(cameraPositionWS, headBoneMat[3]) - 0.3) / 0.15, 0.0, 1.0)*255);
597 }
598
599 //------------------------------------------------------------------------------------------------
600 protected void UpdateShake(float pDt)
601 {
602 // Update and apply recoil based camera shake
603 if (m_pRecoilShake && !m_pRecoilShake.IsFinished())
604 m_pRecoilShake.Update(m_OwnerCharacter, pDt);
605 }
606
607 //------------------------------------------------------------------------------------------------
611 void AddShakeToToTransform(inout vector transform[4], inout float fieldOfView)
612 {
613 bool applyRecoilShake = true;
614 #ifdef ENABLE_DIAG
615 applyRecoilShake = !DiagMenu.GetBool(SCR_DebugMenuID.DEBUGUI_CHARACTER_RECOIL_CAMERASHAKE_DISABLE);
616 #endif
617
618 // Apply recoil shake
619 if (applyRecoilShake && m_pRecoilShake)
620 m_pRecoilShake.Apply(transform, fieldOfView);
621
622 // Apply generic shakes from shake manager to out transform
623 SCR_CameraShakeManagerComponent.ApplyCameraShake(transform, fieldOfView);
624 }
625
626 //------------------------------------------------------------------------------------------------
628 {
629 bool current = IsInThirdPerson();
630 SetThirdPerson(!current);
631 }
632
633 //------------------------------------------------------------------------------------------------
634 override void CollisionSolver(float pDt, inout ScriptedCameraItemResult pOutResult, inout vector resCamTM[4], bool isKeyframe)
635 {
636 // In case of changes, test:
637 // Freelook vs. collisions, heading vs. collisions
638 // Turrets - transitions between FPV, 3PV, ADS; collisions in ADS
639 // Jumping and collisions
640 // Collisions when close to a wall under a sharp angle, collisions when between two vehicles (<1m gap)
641 // Smoothness of transitions and slide/distance smoothing
642
643 if (pOutResult.m_fDistance <= MIN_TRACE_DISTANCE)
644 {
645 m_fCameraDistanceFilter = 0.0;
646 ResetSlide();
647 }
648
649 IEntity owner = pOutResult.m_pOwner;
650 vector ownerTransformWS[4];
651 if (owner)
652 owner.GetWorldTransform(ownerTransformWS);
653 else
654 Math3D.MatrixIdentity4(ownerTransformWS);
655
656 vector resultWorldTransform[4]; // If pOutResult.m_CameraTM is in someone's model space, this transforms it back to world space.
657 m_pAttachmentReference = pOutResult.m_pWSAttachmentReference;
658 if (pOutResult.m_pWSAttachmentReference && pOutResult.m_pWSAttachmentReference.GetOwner())
659 pOutResult.m_pWSAttachmentReference.GetWorldTransform(resultWorldTransform);
660 else if (owner)
661 owner.GetWorldTransform(resultWorldTransform);
662 else
663 Math3D.MatrixIdentity4(resultWorldTransform);
664
665 if (pOutResult.m_bNoParent)
666 {
667 vector ypr = {Math3D.MatrixToAngles(resultWorldTransform)[0], 0.0, 0.0};
668 Math3D.AnglesToMatrix(ypr, resultWorldTransform);
669 }
670
671 vector hipBoneWS[4];
672 m_OwnerCharacter.GetAnimation().GetBoneMatrix(m_iHipsBoneIndex, hipBoneWS);
673 if (pOutResult.m_bNoParent)
674 Math3D.MatrixMultiply4(ownerTransformWS, hipBoneWS, hipBoneWS);
675 else
676 Math3D.MatrixMultiply4(resultWorldTransform, hipBoneWS, hipBoneWS);
677
678 #ifdef ENABLE_DIAG // These things are only useful for showing the debug spheres.
679 vector camPos = pOutResult.m_CameraTM[3];
680 vector inputCameraPosWS = camPos.Multiply4(resultWorldTransform);
681 #endif
682
683 vector camTransformLS[4];
684 Math3D.MatrixCopy(pOutResult.m_CameraTM, camTransformLS);
685
686 vector basePos = camTransformLS[3]; // Camera position without heading applied.
687
688 vector charRot[4]; // Matrix to transform from model space to heading space.
689 Math3D.MatrixIdentity4(charRot);
690
691 if (pOutResult.m_fPositionModelSpace == 2.0) // 2.0 is world space.
692 {
693 camTransformLS[3] = camTransformLS[3] - resultWorldTransform[3];
694 }
695 else
696 {
697 if (pOutResult.m_fUseHeading > 0.0)
698 {
699 vector headingMat[4];
700 Math3D.AnglesToMatrix(Vector( Math.RAD2DEG * -pOutResult.m_fHeading, 0.0, 0.0), headingMat);
701
702 if (pOutResult.m_pOwner)
703 pOutResult.m_pOwner.GetLocalTransform(charRot);
704
705 charRot[3] = vector.Zero;
706
707 Math3D.MatrixInvMultiply4(charRot, headingMat, charRot);
708 float charRotQ[4];
709 Math3D.MatrixToQuat(charRot, charRotQ);
710 float quatF[4] = {0.0, 0.0, 0.0, 1.0};
711 Math3D.QuatLerp(charRotQ, quatF, charRotQ, pOutResult.m_fUseHeading);
712 vector charRotQAngles = Math3D.QuatToAngles(charRotQ);
713 Math3D.AnglesToMatrix(charRotQAngles, charRot);
714
715 Math3D.MatrixMultiply4(charRot, camTransformLS, camTransformLS);
716
717 if (pOutResult.m_fDistance <= MIN_TRACE_DISTANCE)
718 camTransformLS[3] = basePos;
719 }
720
721 if (pOutResult.m_fPositionModelSpace > 0.0)
722 {
723 // We are blending between heading (0.0) and local space (1.0) - for instance between turret ADS and 3PV.
724 vector msPos = camTransformLS[3];
725 vector lsPos = basePos;
726 camTransformLS[3] = vector.Lerp(lsPos, msPos, pOutResult.m_fPositionModelSpace);
727 }
728 }
729
730 // Space and heading transformations are done. We transform them into WS to use with collision tracing.
731 vector camTransformWS[4];
732 if (pOutResult.m_fPositionModelSpace == 2.0)
733 Math3D.MatrixCopy(camTransformLS, camTransformWS);
734 else
735 Math3D.MatrixMultiply4(resultWorldTransform, camTransformLS, camTransformWS);
736
737 if (pOutResult.m_bAllowCollisionSolver && !isKeyframe && pOutResult.m_fDistance > MIN_TRACE_DISTANCE)
738 {
739 // We always make the traces a bit longer than they need to be and "anticipate" if it is going to collide.
740 // This way we can make the camera movement a bit smoother. This number says by how much they will be longer.
741 const float SIDE_TRACE_MARGIN_MULTIPLIER = 2.0; // TODO: check for good const usage
742 const float BACK_TRACE_MARGIN_MULTIPLIER = 1.25; // TODO: check for good const usage
743
744 // Exclude all character-related entities from any tracing.
745 array<IEntity> excludeArray = {m_OwnerCharacter};
746 IEntity parent = m_OwnerCharacter.GetParent();
747 IEntity sibling = m_OwnerCharacter.GetSibling();
748 while (parent != null)
749 {
750 excludeArray.Insert(parent);
751 while (sibling != null)
752 {
753 excludeArray.Insert(sibling);
754 sibling = sibling.GetSibling();
755 }
756 sibling = parent.GetSibling();
757 parent = parent.GetParent();
758 }
759
760 const float TRACE_RADIUS = 0.06;
761
762 BaseWorld world = m_OwnerCharacter.GetWorld();
763 TraceSphere param = new TraceSphere();
764 param.Radius = TRACE_RADIUS;
765 param.ExcludeArray = excludeArray;
766 param.Flags = TraceFlags.WORLD | TraceFlags.ENTS;
767 param.LayerMask = TRACE_LAYER_CAMERA;
768
769 // 1. Sideways collision (translating the camera to left/right from character).
770 vector sideVector;
771 if (m_ControllerComponent.IsFreeLookEnabled())
772 sideVector = resultWorldTransform[0];
773 else
774 sideVector = camTransformWS[0];
775
776 vector sideTraceStart = camTransformWS[3] - sideVector * pOutResult.m_fShoulderDist; // start trace at head position on the camera plane
777 vector sideTraceEnd = camTransformWS[3];
778
779 vector sideTraceDiff = sideTraceEnd - sideTraceStart;
780
781 // Set up the side trace
782 param.Start = sideTraceStart;
783 param.End = sideTraceStart + SIDE_TRACE_MARGIN_MULTIPLIER * sideTraceDiff;
784
785 float rightTrace;
786 if (!m_bTraceCharacters)
787 rightTrace = ChimeraCharacter.TraceMoveWithoutCharacters(world, param);
788 else
789 rightTrace = world.TraceMove(param, null);
790
791 // The slide we apply is not divided by the margin multiplier, since we want slide to move
792 // in anticipation of hitting something. We still pass the multiplier here though,
793 // so that we can change the speed of the smoothing based on how close the tracing hit.
794 ApplySmoothedSlide(pDt, rightTrace, sideTraceStart, sideTraceDiff, SIDE_TRACE_MARGIN_MULTIPLIER, pOutResult.m_fShoulderDist, camTransformWS);
795 #ifdef ENABLE_DIAG
796 sideTraceEnd = vector.Lerp(param.Start, param.End, rightTrace);
797 #endif
798
799 // Slide is applied to the camera matrix, but distance is not.
800 // So we apply it to the camTransformLS which we will be returning at the end.
801 Math3D.MatrixInvMultiply4(resultWorldTransform, camTransformWS, camTransformLS);
802
803 // 2. Backwards collision. Vars are defined outside the scope because of the debug spheres.
804 vector backtraceDir = pOutResult.m_vBacktraceDir.Multiply3(charRot).Multiply3(resultWorldTransform);
805 backtraceDir = vector.Lerp(camTransformWS[2], backtraceDir, pOutResult.m_fUseBacktraceDir);
806
807 float backTrace = 1;
808 vector backTraceStart = camTransformWS[3];
809 vector backTraceEnd = camTransformWS[3] - BACK_TRACE_MARGIN_MULTIPLIER * pOutResult.m_fDistance * backtraceDir;
810 // Trace N rays at a thickness of TRACE_RADIUS around the direction backTraceEnd - backTraceStart, approximating a sphere trace.
811 const int N = 4;
812 vector traceMat[N];
813 float rayBackTrace[N];
814 SCR_Math3D.LookAt(backTraceStart, backTraceEnd, { 0, 1, 0 }, traceMat); // Get a transform with Z axis facing the ray direction.
815 vector traceOffsets[N] = {
816 TRACE_RADIUS * traceMat[0],
817 TRACE_RADIUS * traceMat[1],
818 TRACE_RADIUS * -traceMat[0],
819 TRACE_RADIUS * -traceMat[1]
820 };
821
822 if (pOutResult.m_fPositionModelSpace <= 2.0 && pOutResult.m_fDistance > MIN_TRACE_DISTANCE)
823 {
824 TraceParam rayParam = new TraceParam();
825 if (m_CharMovementState.m_iStanceIdx != ECharacterStance.PRONE || m_OwnerCharacter.IsInVehicle() || !m_ControllerComponent.IsFreeLookEnabled())
826 rayParam.ExcludeArray = excludeArray;
827 rayParam.Flags = TraceFlags.WORLD | TraceFlags.ENTS;
828 rayParam.LayerMask = TRACE_LAYER_CAMERA;
829
830 backTrace = 1;
831 for (int i = 0; i < N; ++i)
832 {
833 rayParam.Start = backTraceStart + traceOffsets[i];
834 rayParam.End = backTraceEnd + traceOffsets[i];
835
836 if (!m_bTraceCharacters)
837 rayBackTrace[i] = ChimeraCharacter.TraceMoveWithoutCharacters(world, rayParam);
838 else
839 rayBackTrace[i] = world.TraceMove(rayParam, null);
840 backTrace = Math.Min(backTrace, rayBackTrace[i]);
841 }
842
843 if (backTrace < 1)
844 backTrace = Math.Max(0, backTrace - TRACE_RADIUS); // Push the point inwards by TRACE_RADIUS amount, approximating a sphere trace.
845
846 // Unlike with slide, distance will not move "in anticipation", so we can directly multiply this value and compare it to 1.
847 // We still want to have it a bit longer though, to cover the param.Radius margin.
848 backTrace = BACK_TRACE_MARGIN_MULTIPLIER * backTrace;
849
850 float newDistance = pOutResult.m_fDistance * Math.Min(1.0, backTrace);
851
852 if (newDistance < DISTANCE_EPSILON)
853 newDistance = 0.0;
854
855 if (Math.AbsFloat(m_fCameraDistanceFilter - newDistance) < DISTANCE_EPSILON && m_fCameraDistanceFilterVel != 0.0)
856 m_fCameraDistanceFilterVel = 0.0;
857
858 // Set distance smoothing.
859 m_fTargetDistance = newDistance;
860 if(IsCameraBlending() || newDistance < m_fCameraDistanceFilter)
861 m_fCameraDistanceFilter = newDistance;
862
863 pOutResult.m_fDistance = m_fCameraDistanceFilter;
864 }
865
866 #ifdef ENABLE_DIAG
867 if (DiagMenu.GetValue(SCR_DebugMenuID.DEBUGUI_DRAW_CAMERA_COLLISION_SOLVER))
868 {
869 int baseColor = ARGB(255, 0, 110, 255);
870 ShapeFlags shFlags = ShapeFlags.WIREFRAME|ShapeFlags.ONCE;
871
872 Shape.CreateSphere(ARGB(255, 255, 255, 255), shFlags, inputCameraPosWS, param.Radius); // WHITE
873
874 Shape.CreateSphere(ARGB(255, 0, 255, 0), shFlags, sideTraceStart, param.Radius); // GREEN
875 Shape.CreateSphere(ARGB(255, 255, 255 * rightTrace, 0), shFlags, sideTraceEnd, param.Radius); // YELLOW - RED
876
877 for (int i = 0; i < N; ++i)
878 {
879 vector rayStart = backTraceStart + traceOffsets[i];
880 vector rayEnd = backTraceEnd + traceOffsets[i];
881
882 Shape.CreateSphere(ARGB(255, 150, 0, 255), shFlags, rayStart, param.Radius * 0.2); // PURPLE
883 Shape.CreateSphere(ARGB(255, 0, 255, 255), shFlags, vector.Lerp(rayStart, rayEnd, Math.Lerp(0.05, 0.4, backTrace) * rayBackTrace[i]), param.Radius * 0.1);
884 // ^ TEAL
885 }
886
887 if (backTrace < 1)
888 Shape.CreateSphere(ARGB(255, 255, 255 * backTrace, 0), shFlags, backTraceStart + (backTraceEnd - backTraceStart).Normalized() * (m_fCameraDistanceFilter - param.Radius), param.Radius * (1 - backTrace));
889 }
890 #endif
891 }
892
893 // Return the camera position in local space with applied slide, distance is applied only if camera is in world space.
894 Math3D.MatrixCopy(camTransformLS, resCamTM);
895
896 if (pOutResult.m_fPositionModelSpace < 2.0 && pOutResult.m_fDistance > MIN_TRACE_DISTANCE)
897 {
898 vector camBoomDir = pOutResult.m_vBacktraceDir.Multiply3(charRot);
899 camBoomDir = vector.Lerp(resCamTM[2], camBoomDir, pOutResult.m_fUseBacktraceDir);
900
901 resCamTM[3] = resCamTM[3] - pOutResult.m_fDistance * camBoomDir;
902 }
903 }
904
905 //------------------------------------------------------------------------------------------------
906 private void UpdateViewBob(float pDt)
907 {
908 int stance = m_ControllerComponent.GetStance();
909
910 // Adjust bob from freelook
911 float freeLookOffsetScale = 0;
912 if (m_ControllerComponent.IsFreeLookEnabled() || m_ControllerComponent.IsTrackIREnabled())
913 freeLookOffsetScale = 1;
914
915 m_fBobFreelokFilter = Math.SmoothCD(m_fBobFreelokFilter, 1 - Math.Pow(1 - freeLookOffsetScale, 3), m_fBobFreelokFilterVel, 0.3, 1000, pDt);
916 freeLookOffsetScale = m_fBobFreelokFilter;
917
918 // Add bobbing based on speed
919 m_fBob_ScaleFast = Math.Clamp(m_ControllerComponent.GetVelocity().Length() / Math.Max(m_AnimationComponent.GetTopSpeed(-1, false), 0.1), 0, 1);
920 m_fBob_ScaleSlow += (m_fBob_ScaleFast - m_fBob_ScaleSlow) * (pDt * 4);
921
922 m_fBob_ScaleFast = Math.Pow(m_fBob_ScaleSlow, 3);
923 m_fBob_ScaleFast = Math.Clamp(m_fBob_ScaleFast + freeLookOffsetScale * m_fBob_ScaleFast, 0, 1);
924 if (m_fBob_ScaleFast < 0.01)
925 {
926 m_fBob_Up *= 1 - pDt;
927 m_fBob_Right *= 1 - pDt;
928 }
929 else
930 {
931 float stanceBobScale = 0.5;
932 if (stance == ECharacterStance.PRONE)
933 stanceBobScale = 0.25;
934 else if (stance == ECharacterStance.CROUCH)
935 stanceBobScale = 0.55;
936
937 m_fBob_Up += Math.Clamp(pDt * 2 * stanceBobScale * m_fBob_ScaleFast, 0, 1);
938 if (m_fBob_Up >= 1)
939 m_fBob_Up -= 1;
940
941 m_fBob_Right += Math.Clamp(pDt * 2.5 * stanceBobScale * m_fBob_ScaleFast, 0, 1);
942 if (m_fBob_Right >= 1)
943 m_fBob_Right -= 1;
944 }
945 }
946
947 //------------------------------------------------------------------------------------------------
953 float AddViewBobToTransform(inout vector pOutTransform[4], float pBobScale, bool pAllowTranslation)
954 {
955 // Add bob
956 float bobMoveScale = (m_fBob_ScaleFast * 0.8 + 0.2) * pBobScale;
957 if( pAllowTranslation )
958 {
959 float freeLookOffsetScale = m_fBobFreelokFilter;
960 float bobFw = m_fBob_ScaleSlow * -0.5 * m_fBob_ScaleFast * (1 - freeLookOffsetScale);
961 float bobUp = Math.Sin(m_fBob_Up * 360 * Math.DEG2RAD) * 0.02 * bobMoveScale;
962 float bobRt = Math.Sin(m_fBob_Right * 360 * Math.DEG2RAD) * 0.015 * bobMoveScale;
963 bobRt += m_fBob_ScaleSlow * -0.2 * m_fBob_ScaleFast;
964 vector bobTranslation = pOutTransform[0] * bobRt + pOutTransform[3];
965 bobTranslation = pOutTransform[1] * bobUp + bobTranslation;
966 pOutTransform[3] = pOutTransform[2] * bobFw + bobTranslation;
967 }
968
969 vector angBob = vector.Zero;
970 angBob[0] = Math.Sin(m_fBob_Up * 360 * Math.DEG2RAD) * 0.3 * bobMoveScale; // YAW < >
971 angBob[1] = Math.Sin(m_fBob_Right * 360 * Math.DEG2RAD) * 0.3 * bobMoveScale; // PITCH ^ v
972 // ROLL REMOVED, AS ITS ONLY PERCEIVABLE EFFECT WAS THAT IT CAUSES STRONG HEAD BOB WHEN LOOKING DIRECTLY AT GROUND
973 vector angBobMat[3], endBobmat[3];
974 Math3D.AnglesToMatrix(angBob * pBobScale, angBobMat);
975 Math3D.MatrixMultiply3(angBobMat, pOutTransform, endBobmat);
976 pOutTransform[0] = endBobmat[0];
977 pOutTransform[1] = endBobmat[1];
978 pOutTransform[2] = endBobmat[2];
979
980 return m_fBob_ScaleFast;
981 }
982
983 //------------------------------------------------------------------------------------------------
985 bool Is3rdPersonView()
986 {
987 return !IsDebugView() && IsInThirdPerson() && !(m_ControllerComponent && m_ControllerComponent.IsWeaponADS());
988 }
989
990 private SCR_ChimeraCharacter m_OwnerCharacter;
991 private SCR_CharacterControllerComponent m_ControllerComponent;
992 private CharacterAnimationComponent m_AnimationComponent;
993 private InputManager m_InputManager;
994 private EquipedLoadoutStorageComponent m_LoadoutStorage;
995 private CharacterIdentityComponent m_IdentityComponent;
996 private CharacterCommandHandlerComponent m_CmdHandler;
997
998 private bool m_bApplySmoothedSlideThisFrame = true;
999 private float m_fTargetSlide = 1;
1000 private float m_fSlideTime = 0.4;
1001 private float m_fCameraSlideFilter = 0;
1002 private float m_fCameraSlideFilterVelocity = 0;
1003 private float m_fChangedTimer = 0;
1004 private float m_fSlideTimeout = 0.4;
1005 private float m_fBob_Up = 0;
1006 private float m_fBob_Right = 0;
1007 private float m_fBob_ScaleSlow = 0;
1008 private float m_fBob_ScaleFast = 0;
1009 private int m_iHeadBoneIndex = -1;
1010 private float m_fTargetDistance = 0.0;
1011 private float m_fCameraDistanceFilter;
1012 private float m_fCameraDistanceFilterVel;
1013 private float m_fBobFreelokFilter;
1014 private float m_fBobFreelokFilterVel;
1015 private bool m_bPrevSlideDirectionInside = false;
1016 private bool m_b3rdCollision_UseLeftShoulder = false;
1017
1018 private ref CharacterMovementState m_CharMovementState = new CharacterMovementState();
1019
1020 private static const float DISTANCE_EPSILON = 0.0001;
1021 private static const float MIN_TRACE_DISTANCE = 0.001;
1022
1023 //------------------------------------------------------------------------------------------------
1024 private void ResetSlide()
1025 {
1026 m_fCameraSlideFilter = 1;
1027 m_fTargetSlide = 1;
1028 m_fCameraSlideFilterVelocity = 0;
1029 m_fChangedTimer = 0;
1030 }
1031
1032 //------------------------------------------------------------------------------------------------
1033 private bool ApplySmoothedSlide(float pDt, float slide, vector sideTraceStart, vector sideTraceDiff, float sideTraceMarginMultiplier, float shoulderDist, inout vector inoutMat[4])
1034 {
1035 // Slide will only be enabled in one branch.
1036 m_bApplySmoothedSlideThisFrame = false;
1037
1038 bool slideInside = Math.AbsFloat(slide) < Math.AbsFloat(m_fCameraSlideFilter);
1039 // Apply timer only when direction of slide is changed
1040 if (m_bPrevSlideDirectionInside && !slideInside)
1041 m_fChangedTimer = m_fSlideTimeout;
1042
1043 m_bPrevSlideDirectionInside = slideInside;
1044
1045 if (m_fChangedTimer > 0)
1046 {
1047 m_fChangedTimer = m_fChangedTimer - pDt;
1048 }
1049
1050 // No smoothing while we are switching shoulders.
1051 if (Math.AbsFloat(shoulderDist) < 0.98 && m_fCameraSlideFilter > slide)
1052 {
1053 m_fCameraSlideFilter = slide;
1054 m_fCameraSlideFilterVelocity = 0;
1055 inoutMat[3] = sideTraceStart + sideTraceDiff * m_fCameraSlideFilter;
1056 return slideInside;
1057 }
1058
1059 // Hard limit for the maximum slide to the side is the trace distance.
1060 if (slideInside && m_fCameraSlideFilter > slide * sideTraceMarginMultiplier)
1061 {
1062 m_fCameraSlideFilter = slide;
1063 m_fCameraSlideFilterVelocity = m_fSlideTimeout * (slide - m_fCameraSlideFilterVelocity);
1064 }
1065 else
1066 {
1067 if (IsCameraBlending())
1068 m_fChangedTimer = 0;
1069
1070 if (m_fChangedTimer <= 0 && m_fCameraSlideFilter != slide)
1071 {
1072 float slideTime = m_fSlideTimeout;
1073
1074 // The aim of this is to increase the speed of adjusting to the target if current slide puts
1075 // the camera too close to the wall (so that we don't reach the above hard limit as easily).
1076 if (slideInside)
1077 {
1078 float slideT = sideTraceMarginMultiplier * ((m_fCameraSlideFilter)/Math.Max(0.01, slide * sideTraceMarginMultiplier) - (1/sideTraceMarginMultiplier));
1079 slideTime = Math.Lerp(0.1, m_fSlideTimeout, Math.Clamp(slideT, 0, 1));
1080 }
1081
1082 // Set up data for slide smoothing for next frame.
1083 m_bApplySmoothedSlideThisFrame = true;
1084 m_fTargetSlide = slide;
1085 m_fSlideTime = slideTime;
1086 }
1087 }
1088
1089 inoutMat[3] = sideTraceStart + sideTraceDiff * m_fCameraSlideFilter;
1090 return slideInside;
1091 }
1092
1093 //------------------------------------------------------------------------------------------------
1094 protected bool CanUseOverlayCameraFOV()
1095 {
1096 if (!m_ControllerComponent)
1097 return false;
1098
1099 if (m_ControllerComponent.IsFreeLookEnabled())
1100 return false;
1101
1102 if (m_ControllerComponent.GetWeaponObstructedState() >= EWeaponObstructedState.SIGNIFICANTLY_OBSTRUCTED)
1103 return false;
1104
1105 return true;
1106 }
1107
1108 //------------------------------------------------------------------------------------------------
1110 {
1112 }
1113
1114 //------------------------------------------------------------------------------------------------
1117 {
1118 return m_pRecoilShakeParams;
1119 }
1120
1121 //------------------------------------------------------------------------------------------------
1123 static void SetOverlayCameraFOV(float fov)
1124 {
1125 s_fOverlayCameraFOV = fov;
1126 }
1127
1128 //------------------------------------------------------------------------------------------------
1130 static void SetADSSensitivity(float sensitivity)
1131 {
1132 s_fADSSensitivity = sensitivity;
1133 }
1134
1135 //------------------------------------------------------------------------------------------------
1136 protected override event float CalculateFovScalar(notnull CameraBase mainCamera, CameraBase overlayCamera)
1137 {
1138 float fov = mainCamera.GetVerticalFOV();
1139 if (overlayCamera && s_fOverlayCameraFOV > 0 && CanUseOverlayCameraFOV())
1140 fov = Math.Lerp(fov, s_fOverlayCameraFOV, GetOverlayCameraFOVScalarWeight());
1141
1142 // Account for player ADS sensitivity
1143 float sensitivity = 1.0;
1144 if (m_fADSProgress > 0)
1145 sensitivity = Math.Lerp(1.0, s_fADSSensitivity, m_fADSProgress);
1146
1147 float referenceFOV = 28;
1148 PlayerCamera playerCamera = PlayerCamera.Cast(mainCamera);
1149 if (playerCamera)
1150 referenceFOV = playerCamera.GetFocusFOV();
1151
1152 return sensitivity * fov / referenceFOV;
1153 }
1154
1155 //------------------------------------------------------------------------------------------------
1158 {
1159 return m_bCameraActive;
1160 }
1161
1162 //------------------------------------------------------------------------------------------------
1164 void SetTraceCharacters(bool bTraceCharacters)
1165 {
1166 m_bTraceCharacters = bTraceCharacters;
1167 }
1168
1169}
void OnAlphatestChange(int a)
void UpdateShake(float pDt)
void OnCameraSwitchPressed()
void SetTraceCharacters(bool bTraceCharacters)
const float FOCUS_DEFAULT_ADS_TIME
ScriptInvokerVoid GetThirdPersonSwitchInvoker()
void UpdateHeadVisibility(vector cameraPositionWS)
bool ShouldForceFirstPersonInThirdPerson(CharacterControllerComponent controller)
const float FOCUS_ADS_TIME_RATIO
const float FOCUS_DECELERATION_RATIO
bool CanUseOverlayCameraFOV()
SCR_RecoilCameraShakeParams GetRecoilShakeParams()
void AddShakeToToTransform(inout vector transform[4], inout float fieldOfView)
ECharacterCommandIDs
SCR_DebugMenuID
This enum contains all IDs for DiagMenu entries added in script.
Definition DebugMenuID.c:4
const int TRACE_LAYER_CAMERA
Definition Constants.c:14
ArmaReforgerScripted GetGame()
Definition game.c:1398
enum EAIGroupCombatMode ComponentEditorProps(category:"GameScripted/AI", description:"Component for utility AI system for groups")
InputManager m_InputManager
CharacterAnimationComponent m_AnimationComponent
ScriptInvokerBase< ScriptInvokerVoidMethod > ScriptInvokerVoid
event void CollisionSolver(float pDt, inout ScriptedCameraItemResult pOutResult, inout vector resCamTM[4], bool isKeyframe)
collision solver
event void OnBeforeCameraUpdate(float pDt, bool pIsKeyframe)
before camera update
event int CameraSelector()
selects next camera
event float GetCameraTransitionTime(int pFrom, int pTo)
get how long should transition between given cameras be
event void OnCameraDeactivate()
deactivation
float CalculateFovScalar(notnull CameraBase mainCamera, CameraBase overlayCamera)
event float GetOverlayCameraFOVScalarWeight()
event void OnCameraActivate()
activation
event void OnThirdPersonSwitch(bool isInThirdPerson)
when we switch between FPP and TPP
event void Init()
initialization
event void OnAfterCameraUpdate(float pDt, bool pIsKeyframe, inout vector transformMS[4], inout vector transformWS[4])
after camera update
Diagnostic and developer menu system.
Definition DiagMenu.c:18
proto external Managed FindComponent(typename typeName)
proto external void GetWorldTransform(out vector mat[])
See IEntity::GetTransform.
proto external IEntity GetParent()
proto external IEntity GetSibling()
Definition Math.c:13
PointInfo - allows to define position.
Definition PointInfo.c:9
SCR_ScriptedCharacterInputContext GetScrInputContext()
Contains various scripted 3D math functions.
Definition SCR_Math3D.c:3
proto external GenericEntity GetOwner()
Get owner entity.
Instance of created debug visualizer.
Definition Shape.c:14
EWeaponObstructedState
ECharacterStance
ECharacterLifeState
ShapeFlags
Definition ShapeFlags.c:13
SCR_FieldOfViewSettings Attribute
proto external PlayerController GetPlayerController()
ETurretContextID
proto native vector Vector(float x, float y, float z)
TraceFlags
Definition TraceFlags.c:13
proto int ARGB(int a, int r, int g, int b)