112 lines
3.3 KiB
C#
112 lines
3.3 KiB
C#
using System;
|
|
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;
|
|
public Vector3 PlantLocation { get; set; }
|
|
public Vector3 PlantNormal { 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;
|
|
LookAt(GlobalTransform.Origin + PlantNormal, Vector3.Up, true);
|
|
GD.Print(GlobalRotation);
|
|
}
|
|
|
|
public void OnThrownWeaponReachesGround(Node other)
|
|
{
|
|
PlantWeaponInWall();
|
|
}
|
|
|
|
public void ResetWeapon()
|
|
{
|
|
_weaponState.SendEvent("recover");
|
|
Transform = _startTransform;
|
|
Freeze = true;
|
|
}
|
|
|
|
public override void _IntegrateForces(PhysicsDirectBodyState3D state)
|
|
{
|
|
base._IntegrateForces(state);
|
|
|
|
if (!Freeze && state.GetContactCount() > 0)
|
|
{
|
|
PlantLocation = state.GetContactLocalPosition(0);
|
|
PlantNormal = state.GetContactLocalNormal(0);
|
|
}
|
|
}
|
|
|
|
public bool IsPlantedUnderPlatform()
|
|
{
|
|
return PlantedState.Active && GlobalRotation.X > 1 && Math.Abs(GlobalRotation.Y) > 1;
|
|
}
|
|
|
|
public bool IsPlantedInWall()
|
|
{
|
|
return PlantedState.Active && Math.Abs(GlobalRotation.X) + Math.Abs(GlobalRotation.Z) < 0.3;
|
|
}
|
|
} |