complete project reorganization
This commit is contained in:
196
scenes/player_controller/components/weapon/WeaponSystem.cs
Normal file
196
scenes/player_controller/components/weapon/WeaponSystem.cs
Normal file
@@ -0,0 +1,196 @@
|
||||
using System;
|
||||
using Godot;
|
||||
using GodotStateCharts;
|
||||
using Movementtests.interfaces;
|
||||
using Movementtests.systems.damage;
|
||||
|
||||
namespace Movementtests.systems;
|
||||
|
||||
[GlobalClass, Icon("res://assets/ui/IconGodotNode/node_3D/icon_sword.png")]
|
||||
public partial class WeaponSystem : RigidBody3D, IDamageDealer
|
||||
{
|
||||
[Signal]
|
||||
public delegate void WeaponThrownEventHandler();
|
||||
|
||||
[Signal]
|
||||
public delegate void WeaponRetrievedEventHandler();
|
||||
|
||||
[Export]
|
||||
public RDamage RDamage { get; set; }
|
||||
[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 ShapeCast3D _dashCast3D;
|
||||
|
||||
private Transform3D _startTransform;
|
||||
private Vector3 _startMeshRotation;
|
||||
|
||||
private Vector3 _throwDirection;
|
||||
public Vector3 PlantLocation { get; set; }
|
||||
public Vector3 PlantNormal { get; set; }
|
||||
public Node PlantObject { get; set; }
|
||||
|
||||
public MeshInstance3D WeaponLocationIndicator { get; set; }
|
||||
public StandardMaterial3D WeaponLocationIndicatorMaterial { get; set; }
|
||||
public MeshInstance3D WeaponMesh { get; set; }
|
||||
|
||||
public void Init()
|
||||
{
|
||||
_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");
|
||||
_startMeshRotation = WeaponMesh.Rotation;
|
||||
|
||||
_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, Node collidedObject)
|
||||
{
|
||||
_weaponState.SendEvent("throw");
|
||||
|
||||
// WeaponLocationIndicatorMaterial.StencilColor = new Color(1f, 1f, 1f);
|
||||
|
||||
_throwDirection = (end - GlobalPosition).Normalized();
|
||||
PlantLocation = collisionLocation;
|
||||
PlantNormal = collisionNormal;
|
||||
LookAt(end);
|
||||
|
||||
|
||||
var tween = GetTree().CreateTween();
|
||||
tween.SetParallel(true);
|
||||
tween.TweenProperty(this, "global_position", end, StraightThrowDuration);
|
||||
if (hasHit)
|
||||
{
|
||||
PlantObject = collidedObject;
|
||||
tween.Finished += PlantWeaponInWall;
|
||||
}
|
||||
else
|
||||
tween.Finished += ThrowWeaponOnCurve;
|
||||
}
|
||||
|
||||
public void PlantInEnemy(Node3D enemy)
|
||||
{
|
||||
GetTree().GetRoot().CallDeferred(Node.MethodName.RemoveChild, this);
|
||||
enemy.CallDeferred(Node.MethodName.AddChild, this);
|
||||
|
||||
if (enemy is IDamageable damageable)
|
||||
{
|
||||
damageable.TakeDamage(new DamageRecord(GlobalPosition, RDamage));
|
||||
}
|
||||
}
|
||||
|
||||
public void RethrowWeapon()
|
||||
{
|
||||
_weaponState.SendEvent("throw");
|
||||
_throwDirection = Vector3.Up;
|
||||
ThrowWeaponOnCurve();
|
||||
}
|
||||
|
||||
public void ThrowWeaponOnCurve()
|
||||
{
|
||||
Freeze = false;
|
||||
ApplyImpulse(_throwDirection * ThrowForce);
|
||||
}
|
||||
|
||||
public void PlantWeaponInWall()
|
||||
{
|
||||
_weaponState.SendEvent("plant");
|
||||
|
||||
Freeze = true;
|
||||
WeaponMesh.Rotation = _startMeshRotation;
|
||||
|
||||
// WeaponLocationIndicatorMaterial.StencilColor = new Color(1f, 0.2f, 0.2f);
|
||||
if (PlantObject is Node3D node)
|
||||
{
|
||||
PlantInEnemy(node);
|
||||
}
|
||||
CallDeferred(Node3D.MethodName.SetGlobalPosition, PlantLocation);
|
||||
CallDeferred(Node3D.MethodName.LookAt, GlobalTransform.Origin + PlantNormal, Vector3.Up, true);
|
||||
}
|
||||
|
||||
public void OnThrownWeaponReachesGround(Node other)
|
||||
{
|
||||
PlantObject = 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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user