2022-03-18 20:49:44 +00:00
using System ;
using GhostEnums ;
2022-04-07 08:57:51 +01:00
using QSB ;
2022-03-18 20:49:44 +00:00
using QSB.EchoesOfTheEye.Ghosts ;
2022-04-07 08:57:51 +01:00
using QSB.EchoesOfTheEye.Ghosts.Messages ;
using QSB.EchoesOfTheEye.Ghosts.WorldObjects ;
using QSB.Messaging ;
2022-03-18 20:49:44 +00:00
using QSB.Utility ;
2022-04-07 08:57:51 +01:00
using QSB.WorldSync ;
2022-03-18 20:49:44 +00:00
using UnityEngine ;
public class QSBIdentifyIntruderAction : QSBGhostAction
{
private const int AGGRO_THRESHOLD = 2 ;
private static GhostNode [ ] s_nodesToSpotlight = new GhostNode [ 8 ] ;
private int _numTimesIlluminatedByPlayer ;
private bool _allowFocusBeam ;
private bool _sawPlayerOccluded ;
private bool _movingToSearchLocation ;
private bool _arrivedAtTargetSearchPosition ;
private bool _searchNodesNearTarget ;
private bool _searchNodesComplete ;
private bool _checkingTargetLocation ;
private Vector3 _searchStartPosition ;
private Vector3 _searchPosition ;
private GhostNode _searchNode ;
private float _checkTimer ;
public override GhostAction . Name GetName ( )
{
return GhostAction . Name . IdentifyIntruder ;
}
public override float CalculateUtility ( )
{
2022-04-02 10:54:12 +01:00
if ( _data . interestedPlayer = = null )
{
return - 100f ;
}
2022-03-18 20:49:44 +00:00
if ( _data . threatAwareness > = GhostData . ThreatAwareness . IntruderConfirmed )
{
return - 100f ;
}
2022-03-19 20:09:55 +00:00
2022-04-02 10:54:12 +01:00
if ( _running | | ( _data . interestedPlayer . sensor . isPlayerHeldLanternVisible & & ( _data . threatAwareness > GhostData . ThreatAwareness . EverythingIsNormal | | _data . interestedPlayer . playerLocation . distance < 20f ) ) | | _data . interestedPlayer . sensor . isIlluminatedByPlayer )
2022-03-18 20:49:44 +00:00
{
return 80f ;
}
2022-03-19 20:09:55 +00:00
2022-03-18 20:49:44 +00:00
return - 100f ;
}
public override float GetActionDelay ( )
{
2022-04-02 10:54:12 +01:00
if ( _data . interestedPlayer . playerLocation . distance < 8f )
2022-03-18 20:49:44 +00:00
{
return 0.1f ;
}
return 0.5f ;
}
public override void OnSetAsPending ( )
{
2022-04-02 10:54:12 +01:00
if ( _data . interestedPlayer . sensor . isIlluminatedByPlayer )
2022-03-18 20:49:44 +00:00
{
_numTimesIlluminatedByPlayer + + ;
_allowFocusBeam = true ;
}
}
protected override void OnEnterAction ( )
{
_sawPlayerOccluded = false ;
_movingToSearchLocation = false ;
_arrivedAtTargetSearchPosition = false ;
_searchNodesNearTarget = false ;
_searchNodesComplete = false ;
_checkingTargetLocation = false ;
_checkTimer = 0f ;
2022-04-14 12:45:56 +01:00
_effects . PlayVoiceAudioNear ( ( _numTimesIlluminatedByPlayer < = 2 ) ? AudioType . Ghost_Identify_Curious : AudioType . Ghost_Identify_Irritated , 1f ) ;
2022-03-18 20:49:44 +00:00
}
protected override void OnExitAction ( )
{
_controller . FaceVelocity ( ) ;
_allowFocusBeam = false ;
}
public override bool Update_Action ( )
{
2022-04-07 08:57:51 +01:00
if ( _checkingTargetLocation & & ! _data . interestedPlayer . isPlayerLocationKnown & & _controller . AttachedObject . GetSpeed ( ) < 0.1f )
2022-03-18 20:49:44 +00:00
{
_checkTimer + = Time . deltaTime ;
}
else
{
_checkTimer = 0f ;
}
if ( ( _searchNodesNearTarget & & _checkTimer > 1f ) | | _checkTimer > 3f )
{
2022-03-19 20:22:08 +00:00
DebugLog . DebugWrite ( $"{_brain.AttachedObject._name} : Couldn't identify target. :(" ) ;
2022-04-14 12:45:56 +01:00
_effects . PlayVoiceAudioNear ( AudioType . Ghost_Identify_Fail , 1f ) ;
2022-03-18 20:49:44 +00:00
return false ;
}
return true ;
}
public override void FixedUpdate_Action ( )
{
_checkingTargetLocation = false ;
2022-04-02 10:54:12 +01:00
if ( ! _data . interestedPlayer . wasPlayerLocationKnown & & _data . interestedPlayer . isPlayerLocationKnown & & _data . interestedPlayer . sensor . isIlluminatedByPlayer )
2022-03-18 20:49:44 +00:00
{
_numTimesIlluminatedByPlayer + + ;
}
2022-04-02 10:54:12 +01:00
if ( ! _allowFocusBeam & & _data . interestedPlayer . sensor . isIlluminatedByPlayer )
2022-03-18 20:49:44 +00:00
{
_allowFocusBeam = true ;
}
2022-04-02 10:54:12 +01:00
var flag = ! _data . interestedPlayer . lastKnownSensor . isPlayerVisible & & _data . interestedPlayer . lastKnownSensor . isIlluminatedByPlayer & & _numTimesIlluminatedByPlayer > 2 ;
if ( _data . interestedPlayer . isPlayerLocationKnown )
2022-03-18 20:49:44 +00:00
{
_sawPlayerOccluded = false ;
_movingToSearchLocation = false ;
_arrivedAtTargetSearchPosition = false ;
_searchNodesNearTarget = false ;
_searchNodesComplete = false ;
}
2022-04-02 10:54:12 +01:00
else if ( ! _movingToSearchLocation & & ( _data . interestedPlayer . lostPlayerDueToOcclusion | | flag ) )
2022-03-18 20:49:44 +00:00
{
_movingToSearchLocation = true ;
2022-04-02 10:54:12 +01:00
_sawPlayerOccluded = _data . interestedPlayer . lostPlayerDueToOcclusion ;
2022-03-18 20:49:44 +00:00
_controller . ChangeLanternFocus ( 0f , 2f ) ;
_controller . SetLanternConcealed ( true , true ) ;
if ( _allowFocusBeam )
{
_searchNodesNearTarget = true ;
2022-04-07 08:57:51 +01:00
_searchStartPosition = _controller . AttachedObject . GetLocalFeetPosition ( ) ;
_searchNode = _controller . AttachedObject . GetNodeMap ( ) . FindClosestNode ( _data . interestedPlayer . lastKnownPlayerLocation . localPosition ) ;
2022-03-18 20:49:44 +00:00
_controller . PathfindToLocalPosition ( _searchNode . localPosition , MoveType . INVESTIGATE ) ;
}
else
{
_searchNodesNearTarget = false ;
2022-04-02 10:54:12 +01:00
_controller . PathfindToLocalPosition ( _data . interestedPlayer . lastKnownPlayerLocation . localPosition , MoveType . INVESTIGATE ) ;
2022-03-18 20:49:44 +00:00
}
_controller . FaceVelocity ( ) ;
}
if ( _movingToSearchLocation )
{
if ( _arrivedAtTargetSearchPosition )
{
if ( _searchNodesNearTarget )
{
_checkingTargetLocation = _searchNodesComplete ;
return ;
}
2022-04-07 08:57:51 +01:00
if ( _controller . AttachedObject . GetAngleToLocalPosition ( _searchPosition ) < 5f )
2022-03-18 20:49:44 +00:00
{
_controller . SetLanternConcealed ( false , true ) ;
_checkingTargetLocation = true ;
return ;
}
}
}
else
{
2022-04-02 10:54:12 +01:00
var playerLocationToCheck = _data . interestedPlayer . lastKnownPlayerLocation . localPosition + new Vector3 ( 0f , 1.8f , 0f ) ;
2022-04-07 08:57:51 +01:00
var canSeePlayerCheckLocation = _sensors . AttachedObject . CheckPositionOccluded ( _controller . AttachedObject . LocalToWorldPosition ( playerLocationToCheck ) ) ;
2022-03-21 09:56:05 +00:00
var lanternRange = _allowFocusBeam
2022-04-07 08:57:51 +01:00
? ( _controller . AttachedObject . GetFocusedLanternRange ( ) - 3f )
: ( _controller . AttachedObject . GetUnfocusedLanternRange ( ) - 1f ) ;
var isLastKnownLocationInRange = _data . interestedPlayer . lastKnownPlayerLocation . distance < _controller . AttachedObject . GetUnfocusedLanternRange ( ) ;
2022-04-02 10:54:12 +01:00
if ( _data . interestedPlayer . sensor . isPlayerIlluminatedByUs )
2022-03-18 20:49:44 +00:00
{
_allowFocusBeam = true ;
2022-04-02 10:54:12 +01:00
_controller . FaceLocalPosition ( _data . interestedPlayer . lastKnownPlayerLocation . localPosition , TurnSpeed . MEDIUM ) ;
2022-04-07 08:57:51 +01:00
if ( isLastKnownLocationInRange = = _controller . AttachedObject . IsLanternFocused ( ) )
2022-03-18 20:49:44 +00:00
{
2022-03-21 09:56:05 +00:00
_controller . ChangeLanternFocus ( isLastKnownLocationInRange ? 0f : 1f , 2f ) ;
2022-03-18 20:49:44 +00:00
return ;
}
}
2022-04-02 10:54:12 +01:00
else if ( _data . interestedPlayer . lastKnownPlayerLocation . distance < lanternRange & & ! canSeePlayerCheckLocation )
2022-03-18 20:49:44 +00:00
{
2022-04-02 10:54:12 +01:00
if ( _allowFocusBeam | | ! _data . interestedPlayer . isPlayerLocationKnown )
2022-03-18 20:49:44 +00:00
{
2022-04-14 16:33:42 +01:00
_controller . StopMoving ( ) ;
2022-03-18 20:49:44 +00:00
}
2022-04-07 08:57:51 +01:00
if ( _data . interestedPlayer . lastKnownPlayerLocation . degreesToPositionXZ < 5f & & ( isLastKnownLocationInRange | | _controller . AttachedObject . IsLanternFocused ( ) ) )
2022-03-18 20:49:44 +00:00
{
_checkingTargetLocation = true ;
}
2022-03-21 09:56:05 +00:00
if ( isLastKnownLocationInRange )
2022-03-18 20:49:44 +00:00
{
2022-04-02 10:54:12 +01:00
_controller . FaceLocalPosition ( _data . interestedPlayer . lastKnownPlayerLocation . localPosition , TurnSpeed . FASTEST ) ;
2022-03-18 20:49:44 +00:00
_controller . SetLanternConcealed ( false , true ) ;
_controller . ChangeLanternFocus ( 0f , 2f ) ;
return ;
}
2022-04-02 10:54:12 +01:00
_controller . FaceLocalPosition ( _data . interestedPlayer . lastKnownPlayerLocation . localPosition , TurnSpeed . MEDIUM ) ;
if ( _data . interestedPlayer . lastKnownPlayerLocation . degreesToPositionXZ < 5f )
2022-03-18 20:49:44 +00:00
{
_controller . ChangeLanternFocus ( 1f , 2f ) ;
return ;
}
}
else
{
_controller . ChangeLanternFocus ( 0f , 2f ) ;
_controller . SetLanternConcealed ( true , true ) ;
2022-04-07 08:57:51 +01:00
if ( ! QSBCore . IsHost )
{
return ;
}
2022-04-02 10:54:12 +01:00
_controller . PathfindToLocalPosition ( _data . interestedPlayer . lastKnownPlayerLocation . localPosition , MoveType . INVESTIGATE ) ;
_controller . FaceLocalPosition ( _data . interestedPlayer . lastKnownPlayerLocation . localPosition , TurnSpeed . MEDIUM ) ;
2022-03-18 20:49:44 +00:00
}
}
}
public override void OnArriveAtPosition ( )
{
if ( _movingToSearchLocation )
{
_arrivedAtTargetSearchPosition = true ;
if ( _searchNodesNearTarget )
{
var num = GenerateSpotlightList ( _searchNode , _searchStartPosition - _searchNode . localPosition ) ;
if ( num > 0 )
{
_controller . SetLanternConcealed ( false , true ) ;
_controller . ChangeLanternFocus ( 1f , 2f ) ;
_controller . FaceNodeList ( IdentifyIntruderAction . s_nodesToSpotlight , num , TurnSpeed . MEDIUM , 1f , false ) ;
return ;
}
}
else
{
if ( _sawPlayerOccluded )
{
2022-04-02 10:54:12 +01:00
_searchPosition = _data . interestedPlayer . lastKnownPlayerLocation . localPosition + _data . interestedPlayer . lastKnownPlayerLocation . localVelocity ;
2022-03-18 20:49:44 +00:00
_controller . FaceLocalPosition ( _searchPosition , TurnSpeed . MEDIUM ) ;
return ;
}
2022-05-06 19:40:22 +01:00
DebugLog . DebugWrite ( $"{_brain.Name} : how did i get here\nthis is not my beautiful house\nthis is not my beautiful wife" , OWML . Common . MessageType . Error ) ;
2022-03-18 20:49:44 +00:00
}
}
}
public override void OnFinishFaceNodeList ( )
{
_searchNodesComplete = true ;
}
private int GenerateSpotlightList ( GhostNode node , Vector3 ignoreDirection )
{
var num = 0 ;
var localPosition = node . localPosition ;
for ( var i = 0 ; i < node . neighbors . Count ; i + + )
{
if ( Vector3 . Angle ( node . neighbors [ i ] . localPosition - localPosition , ignoreDirection ) > = 45f )
{
IdentifyIntruderAction . s_nodesToSpotlight [ num ] = node . neighbors [ i ] ;
num + + ;
if ( num = = IdentifyIntruderAction . s_nodesToSpotlight . Length )
{
break ;
}
}
}
return num ;
}
}