212 lines
4.1 KiB
C#
212 lines
4.1 KiB
C#
using Godot;
|
|
using Rokojori;
|
|
using System.Collections.Generic;
|
|
using System.Threading.Tasks;
|
|
|
|
[Tool, GlobalClass]
|
|
public partial class Eye : Node
|
|
{
|
|
[Export]
|
|
public Node3D transform;
|
|
|
|
[Export]
|
|
public Node3D beamScale;
|
|
|
|
[Export]
|
|
public Action onHasCollider;
|
|
|
|
[Export]
|
|
public Action onNoCollider;
|
|
|
|
[Export]
|
|
public PlayerSight playerSight;
|
|
|
|
[Export]
|
|
public Smoothing toPlayerRotationSmoothing;
|
|
|
|
[Export]
|
|
public float maxLength = 10;
|
|
|
|
[Export]
|
|
public float rootScale = 20;
|
|
|
|
[Export]
|
|
public MultiRayCaster multiRayCaster;
|
|
|
|
[Export]
|
|
public Health health;
|
|
|
|
[Export]
|
|
public Smoothing lengthSmoothing;
|
|
|
|
float _nextLength = 10;
|
|
|
|
[Export]
|
|
public Collider collider;
|
|
|
|
[ExportGroup( "Debugging")]
|
|
|
|
|
|
[Export]
|
|
public bool forceDebugLength = false;
|
|
|
|
[Export]
|
|
public float debugLength = 5;
|
|
|
|
[Export]
|
|
public float wobbleRaycast = 1;
|
|
|
|
|
|
|
|
|
|
|
|
public override void _Process( double delta )
|
|
{
|
|
var currentNumColliders = _colliders.Count;
|
|
|
|
var pos = multiRayCaster.Position;
|
|
var random = GodotRandom.Get().InsideCircle( wobbleRaycast );
|
|
|
|
|
|
multiRayCaster.Position = new Vector3( random.X, random.Y, pos.Z );
|
|
|
|
ResolveCollisions();
|
|
|
|
if ( currentNumColliders != _colliders.Count )
|
|
{
|
|
var hasColliders = _colliders.Count > 0;
|
|
Action.Trigger( hasColliders ? onNoCollider : onHasCollider );
|
|
}
|
|
|
|
if ( forceDebugLength )
|
|
{
|
|
_nextLength = debugLength;
|
|
}
|
|
|
|
var length = Smoothing.Apply( lengthSmoothing, _nextLength, (float) delta );
|
|
|
|
beamScale.SetScaleZ( length / maxLength );
|
|
|
|
UpdateRotation( (float) delta );
|
|
|
|
}
|
|
|
|
void UpdateRotation( float delta )
|
|
{
|
|
if ( playerSight == null )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( playerSight.visible )
|
|
{
|
|
var player = Unique<Player>.Get();
|
|
var playerDirection = transform.DirectionTowards( player.transform.GlobalPosition );
|
|
var toPlayerRotation = Math3D.LookRotation( playerDirection );
|
|
|
|
var smoothedRotation = Smoothing.Apply( toPlayerRotationSmoothing, toPlayerRotation, delta );
|
|
transform.SetGlobalQuaternion( smoothedRotation );
|
|
|
|
|
|
// this.LogInfo( playerDirection, toPlayerRotation, smoothedRotation );
|
|
}
|
|
else
|
|
{
|
|
if ( toPlayerRotationSmoothing != null )
|
|
{
|
|
toPlayerRotationSmoothing.SetCurrent( transform.GlobalQuaternion() );
|
|
}
|
|
}
|
|
}
|
|
|
|
List<Node> _colliders = new List<Node>();
|
|
|
|
void ResolveCollisions()
|
|
{
|
|
var invalid = _colliders.Has( c => ! IsInstanceValid( c ) );
|
|
|
|
if ( invalid )
|
|
{
|
|
_colliders = _colliders.Filter( c=> IsInstanceValid( c ) );
|
|
}
|
|
|
|
var numColliders = multiRayCaster.NumColliders();
|
|
|
|
if ( health.isDead )
|
|
{
|
|
numColliders = 0;
|
|
}
|
|
|
|
var same = _colliders.Count == numColliders;
|
|
|
|
var minDistance = maxLength;
|
|
|
|
for ( int i = 0; i < numColliders; i++ )
|
|
{
|
|
|
|
|
|
if ( same && _colliders[ i ] != multiRayCaster.GetCollider( i ) )
|
|
{
|
|
same = false;
|
|
}
|
|
|
|
var distance = transform.DistanceTo( multiRayCaster.GetCollisionPosition( i ) ) / rootScale;
|
|
|
|
minDistance = Mathf.Min( distance, minDistance );
|
|
}
|
|
|
|
_nextLength = minDistance;
|
|
|
|
|
|
if ( same )
|
|
{
|
|
|
|
return;
|
|
}
|
|
|
|
var newColliders = new List<Node>();
|
|
|
|
var enteredColliders = new List<Node>();
|
|
|
|
for ( int i = 0; i < numColliders; i++ )
|
|
{
|
|
var collider = multiRayCaster.GetCollider( i );
|
|
|
|
if ( collider == null )
|
|
{
|
|
// this.LogInfo( "Collider is null!", i, multiRayCaster.NumColliders() );
|
|
continue;
|
|
}
|
|
newColliders.Add( collider );
|
|
|
|
if ( ! _colliders.Contains( collider ) )
|
|
{
|
|
enteredColliders.Add( collider );
|
|
}
|
|
}
|
|
|
|
var exitedColliders = _colliders.Filter( c => ! newColliders.Contains( c ) );
|
|
|
|
exitedColliders.ForEach(
|
|
( c )=>
|
|
{
|
|
// this.LogInfo( "Collider exited:", HierarchyName.Of( c ) );
|
|
collider.TriggerOnExited( c as Node3D );
|
|
}
|
|
);
|
|
|
|
|
|
enteredColliders.ForEach(
|
|
( c )=>
|
|
{
|
|
// this.LogInfo( "Collider entered:", HierarchyName.Of( c ) );
|
|
collider.TriggerOnEnter( c as Node3D );
|
|
}
|
|
);
|
|
|
|
_colliders = newColliders;
|
|
|
|
|
|
}
|
|
|
|
} |