Files
MovementTests/systems/weapon/WeaponSystem.cs

103 lines
3.1 KiB
C#

using Godot;
using GodotStateCharts;
namespace Movementtests.systems;
public partial class WeaponSystem : RigidBody3D
{
[Export(PropertyHint.Range, "0,100,1,or_greater")]
public float ThrowForce { get; set; } = 1f;
[Export(PropertyHint.Range, "0,0.2,0.01,or_greater")]
public float StraightThrowDuration { get; set; } = 0.1f;
private StateChart _weaponState;
public StateChartState InHandState;
public StateChartState FlyingState;
public StateChartState PlantedState;
private Node3D _head;
private ShapeCast3D _dashCast3D;
private Camera3D _camera;
private TweenQueueSystem _tweenQueueSystem;
private Transform3D _startTransform;
private Vector3 _throwDirection;
private Vector3 _plantLocation;
private Vector3 _plantNormal;
public Vector3 PlayerDashLocation { get; set; }
public void Init(Node3D head, Camera3D camera)
{
_head = head;
_camera = camera;
_weaponState = StateChart.Of(GetNode("StateChart"));
InHandState = StateChartState.Of(GetNode("StateChart/Root/InHand"));
FlyingState = StateChartState.Of(GetNode("StateChart/Root/Flying"));
PlantedState = StateChartState.Of(GetNode("StateChart/Root/Planted"));
_tweenQueueSystem = GetNode<TweenQueueSystem>("TweenQueueSystem");
_tweenQueueSystem.Init(this);
_startTransform = Transform;
Freeze = true;
BodyEntered += OnThrownWeaponReachesGround;
}
public void ThrowWeapon(Vector3 end, bool hasHit, Vector3 collisionLocation, Vector3 collisionNormal)
{
_weaponState.SendEvent("throw");
_throwDirection = (end - GlobalPosition).Normalized();
_plantLocation = collisionLocation;
_plantNormal = collisionNormal;
LookAt(end);
var tween = _tweenQueueSystem.TweenToLocation(new TweenQueueSystem.TweenInputs(end, StraightThrowDuration));
if (hasHit)
tween.Finished += PlantWeaponInWall;
else
tween.Finished += ThrowWeaponOnCurve;
}
public void ThrowWeaponOnCurve()
{
Freeze = false;
ApplyImpulse(_throwDirection * ThrowForce);
}
public void PlantWeaponInWall()
{
_weaponState.SendEvent("plant");
Freeze = true;
GlobalPosition = _plantLocation;
PlayerDashLocation = _plantLocation + _plantNormal * 0.1f;
LookAt(GlobalTransform.Origin + _plantNormal, Vector3.Up, true);
}
public void ResetWeapon()
{
_weaponState.SendEvent("recover");
Transform = _startTransform;
Freeze = true;
}
public override void _IntegrateForces(PhysicsDirectBodyState3D state)
{
base._IntegrateForces(state);
PlayerDashLocation = GlobalPosition;
if (!Freeze && state.GetContactCount() > 0)
{
_plantLocation = state.GetContactLocalPosition(0);
_plantNormal = state.GetContactLocalNormal(0);
PlayerDashLocation = _plantLocation + _plantNormal * 0.1f;
}
}
public void OnThrownWeaponReachesGround(Node other)
{
PlantWeaponInWall();
}
}