154 lines
4.9 KiB
C#
154 lines
4.9 KiB
C#
using Godot;
|
|
using System;
|
|
using Chickensoft.AutoInject;
|
|
using Chickensoft.Introspection;
|
|
using Gamesmiths.Forge.Abilities;
|
|
using Gamesmiths.Forge.Core;
|
|
using Gamesmiths.Forge.Cues;
|
|
using Gamesmiths.Forge.Effects;
|
|
using Gamesmiths.Forge.Events;
|
|
using Gamesmiths.Forge.Godot.Resources.Abilities;
|
|
using Gamesmiths.Forge.Statescript;
|
|
using Gamesmiths.Forge.Tags;
|
|
using Movementtests.interfaces;
|
|
using Movementtests.tools;
|
|
using Node = Godot.Node;
|
|
|
|
[GlobalClass, Icon("res://assets/ui/IconGodotNode/node_3D/icon_bullet.png"), Meta(typeof(IAutoNode))]
|
|
public partial class Projectile : RigidBody3D, IForgeEntity, ITargetable, IKillable, ISpawnable
|
|
{
|
|
public override void _Notification(int what) => this.Notify(what);
|
|
|
|
#region Dependencies
|
|
|
|
[Dependency]
|
|
public TagsManager TagsManager => this.DependOn<TagsManager>();
|
|
[Dependency]
|
|
public CuesManager CuesManager => this.DependOn<CuesManager>();
|
|
|
|
#endregion
|
|
|
|
#region IForgeEntity
|
|
|
|
// Perfectly forward the IForgeEntity interface to the ForgeEntity component
|
|
public EntityAttributes Attributes
|
|
{
|
|
get => ForgeEntity.Attributes;
|
|
set => ForgeEntity.Attributes = value;
|
|
}
|
|
public EntityTags Tags
|
|
{
|
|
get => ForgeEntity.Tags;
|
|
set => ForgeEntity.Tags = value;
|
|
}
|
|
public EffectsManager EffectsManager
|
|
{
|
|
get => ForgeEntity.EffectsManager;
|
|
set => ForgeEntity.EffectsManager = value;
|
|
}
|
|
public EntityAbilities Abilities
|
|
{
|
|
get => ForgeEntity.Abilities;
|
|
set => ForgeEntity.Abilities = value;
|
|
}
|
|
public EventManager Events
|
|
{
|
|
get => ForgeEntity.Events;
|
|
set => ForgeEntity.Events = value;
|
|
}
|
|
|
|
public Variables SharedVariables
|
|
{
|
|
get => ForgeEntity.SharedVariables;
|
|
set => ForgeEntity.SharedVariables = value;
|
|
}
|
|
|
|
#endregion
|
|
|
|
[Node("ForgeEntityNode")] public required ForgeEntityNode ForgeEntity { get; set;}
|
|
|
|
[Export] public float Damage = 10f;
|
|
[Export] public float Speed = 10f;
|
|
[Export] public float HomingFactor = 0.2f;
|
|
|
|
public Node3D? Target { get; set; }
|
|
public Vector3? ImpulseDirection { get; set; }
|
|
|
|
public void Init()
|
|
{
|
|
ApplyCentralImpulse(ComputeImpulseToTarget());
|
|
}
|
|
|
|
public Vector3 ComputeImpulseToTarget()
|
|
{
|
|
if (ImpulseDirection != null) return ImpulseDirection.Value;
|
|
if (Target == null) return Vector3.Zero;
|
|
return Vector3.Up * Speed;
|
|
|
|
var targetDir = GlobalPosition.DirectionTo(Target.GlobalPosition);
|
|
var hDir = new Vector3(targetDir.X, 0, targetDir.Z).Normalized();
|
|
var throwDir = (hDir + 3*Vector3.Up).Normalized();
|
|
var distanceTo = GlobalPosition.DistanceTo(Target.GlobalPosition);
|
|
|
|
return throwDir * distanceTo*0.8f;
|
|
}
|
|
|
|
public override void _IntegrateForces(PhysicsDirectBodyState3D state)
|
|
{
|
|
base._IntegrateForces(state);
|
|
if (Target == null) return;
|
|
var targetPos = Target is ITargetable targetable ? targetable.GetTargetGlobalPosition() : Target.GlobalPosition;
|
|
var targetVel = state.LinearVelocity + GlobalPosition.DirectionTo(targetPos) * HomingFactor;
|
|
if (targetVel.Length() > Speed) targetVel = targetVel.Normalized() * Speed;
|
|
state.LinearVelocity = targetVel;
|
|
// var targetDir = GlobalPosition.DirectionTo(targetPos);
|
|
// var hDir = new Vector3(targetDir.X, 0, targetDir.Z).Normalized();
|
|
// var currentVelocityHDir = new Vector3(state.LinearVelocity.X, 0, state.LinearVelocity.Z);
|
|
// var finalHDir = hDir*HomingFactor + currentVelocityHDir;
|
|
// var combinedVelocity = new Vector3(finalHDir.X, state.LinearVelocity.Y, finalHDir.Z);
|
|
// if (combinedVelocity.Length() > Speed) combinedVelocity = combinedVelocity.Normalized() * Speed;
|
|
// state.LinearVelocity = combinedVelocity;
|
|
// state.LinearVelocity += targetDir/5.0f;
|
|
}
|
|
|
|
public void OnResolved()
|
|
{
|
|
BodyEntered += OnProjectileHit;
|
|
|
|
// Events.Subscribe(Tag.RequestTag(TagsManager, "events.weapon.flyingtick"), data => { GD.Print("tick"); });
|
|
}
|
|
|
|
private void OnProjectileHit(Node body)
|
|
{
|
|
if (body is IForgeEntity entity)
|
|
{
|
|
Events.Raise(new EventData
|
|
{
|
|
EventTags = Tag.RequestTag(TagsManager, "events.combat.hit").GetSingleTagContainer()!,
|
|
Source = this,
|
|
Target = entity,
|
|
EventMagnitude = Damage
|
|
});
|
|
}
|
|
|
|
Events.Raise(new EventData
|
|
{
|
|
EventTags = Tag.RequestTag(TagsManager, "events.weapon.planted").GetSingleTagContainer()!,
|
|
Source = this,
|
|
EventMagnitude = Damage
|
|
});
|
|
|
|
Kill();
|
|
}
|
|
|
|
public Vector3 GetTargetGlobalPosition()
|
|
{
|
|
return GlobalPosition;
|
|
}
|
|
|
|
public void Kill()
|
|
{
|
|
QueueFree(); // If thrown offmap
|
|
}
|
|
}
|