Files
MovementTests/systems/weapon/WeaponSystem.cs
Minimata fd16342aca
All checks were successful
Create tag and build when new code gets to main / BumpTag (push) Successful in 16s
Create tag and build when new code gets to main / Export (push) Successful in 4m47s
getting the weapon tutorial
2025-10-31 16:18:59 +01:00

161 lines
4.9 KiB
C#

using System;
using Godot;
using GodotStateCharts;
namespace Movementtests.systems;
public partial class WeaponSystem : RigidBody3D
{
[Signal]
public delegate void WeaponThrownEventHandler();
[Signal]
public delegate void WeaponRetrievedEventHandler();
[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 MeshInstance3D WeaponLocationIndicator { get; set; }
public StandardMaterial3D WeaponLocationIndicatorMaterial { get; set; }
public MeshInstance3D WeaponMesh { get; set; }
public StandardMaterial3D WeaponMaterial { 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"));
WeaponLocationIndicator = GetNode<MeshInstance3D>("WeaponLocationIndicator");
WeaponLocationIndicator.Visible = false;
WeaponLocationIndicatorMaterial = WeaponLocationIndicator.GetActiveMaterial(0) as StandardMaterial3D;
WeaponMesh = GetNode<MeshInstance3D>("Weapon");
WeaponMaterial = WeaponMesh.GetActiveMaterial(0) as StandardMaterial3D;
_tweenQueueSystem = GetNode<TweenQueueSystem>("TweenQueueSystem");
_tweenQueueSystem.Init(this);
_startTransform = Transform;
Freeze = true;
BodyEntered += OnThrownWeaponReachesGround;
InHandState.StateExited += WeaponLeft;
InHandState.StateEntered += WeaponBack;
}
public void WeaponLeft()
{
WeaponLocationIndicator.Visible = true;
WeaponMaterial!.UseFovOverride = false;
EmitSignalWeaponThrown();
}
public void WeaponBack()
{
WeaponLocationIndicator.Visible = false;
WeaponMaterial!.UseFovOverride = true;
EmitSignalWeaponRetrieved();
}
public void PlaceWeaponForTutorial(Vector3 location)
{
_weaponState.SendEvent("plant");
Freeze = true;
GlobalPosition = location;
PlantLocation = location;
Visible = false;
}
public void ThrowWeapon(Vector3 end, bool hasHit, Vector3 collisionLocation, Vector3 collisionNormal)
{
_weaponState.SendEvent("throw");
WeaponLocationIndicatorMaterial.StencilColor = new Color(1f, 1f, 1f);
_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");
WeaponLocationIndicatorMaterial.StencilColor = new Color(1f, 0.2f, 0.2f);
Freeze = true;
GlobalPosition = PlantLocation;
LookAt(GlobalTransform.Origin + PlantNormal, Vector3.Up, true);
}
public void OnThrownWeaponReachesGround(Node other)
{
PlantWeaponInWall();
}
public void ResetWeapon()
{
_weaponState.SendEvent("recover");
Transform = _startTransform;
Freeze = true;
Visible = 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;
}
}