Files
MovementTests/systems/weapon/WeaponSystem.cs
Minimata 4224333963
All checks were successful
Create tag and build when new code gets to main / BumpTag (push) Successful in 20s
Create tag and build when new code gets to main / Export (push) Successful in 10m20s
improved weapon system and cleaner weapon setup
2026-01-19 17:25:12 +01:00

170 lines
5.2 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 Transform3D _startMeshTransform;
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 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");
_startMeshTransform = WeaponMesh.Transform;
_tweenQueueSystem = GetNode<TweenQueueSystem>("TweenQueueSystem");
_tweenQueueSystem.Init(this);
_startTransform = Transform;
Freeze = true;
Visible = false;
BodyEntered += OnThrownWeaponReachesGround;
InHandState.StateExited += WeaponLeft;
InHandState.StateEntered += WeaponBack;
}
public void WeaponLeft()
{
Visible = true;
// WeaponLocationIndicator.Visible = true;
EmitSignalWeaponThrown();
}
public void WeaponBack()
{
Visible = false;
// WeaponLocationIndicator.Visible = false;
EmitSignalWeaponRetrieved();
}
public void PlaceWeaponForTutorial(Vector3 location)
{
_weaponState.SendEvent("plant");
Freeze = true;
GlobalPosition = location;
PlantLocation = location;
}
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;
WeaponMesh.Transform = _startMeshTransform;
LookAt(GlobalTransform.Origin + PlantNormal, Vector3.Up, true);
}
public void OnThrownWeaponReachesGround(Node other)
{
PlantWeaponInWall();
}
public void ResetWeapon()
{
_weaponState.SendEvent("recover");
Transform = _startTransform;
Freeze = true;
Visible = false;
}
public override void _IntegrateForces(PhysicsDirectBodyState3D state)
{
base._IntegrateForces(state);
if (!Freeze && state.GetContactCount() > 0)
{
PlantLocation = state.GetContactLocalPosition(0);
PlantNormal = state.GetContactLocalNormal(0);
}
}
public override void _Process(double delta)
{
if (!FlyingState.Active) return;
WeaponMesh.Rotation = new Vector3(WeaponMesh.Rotation.X, WeaponMesh.Rotation.Y + (float) delta * 100, WeaponMesh.Rotation.Z);
//LookAt(GlobalTransform.Origin + LinearVelocity.Normalized(), Vector3.Up, false);
}
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;
}
}