forge friendlier health and damage management
Removed knockback though
This commit is contained in:
@@ -5,13 +5,10 @@ using Chickensoft.Introspection;
|
||||
using Gamesmiths.Forge.Abilities;
|
||||
using Gamesmiths.Forge.Attributes;
|
||||
using Gamesmiths.Forge.Core;
|
||||
using Gamesmiths.Forge.Cues;
|
||||
using Gamesmiths.Forge.Effects;
|
||||
using Gamesmiths.Forge.Effects.Calculator;
|
||||
using Gamesmiths.Forge.Effects.Components;
|
||||
using Gamesmiths.Forge.Effects.Duration;
|
||||
using Gamesmiths.Forge.Effects.Magnitudes;
|
||||
using Gamesmiths.Forge.Effects.Modifiers;
|
||||
using Gamesmiths.Forge.Effects.Periodic;
|
||||
using Gamesmiths.Forge.Events;
|
||||
using Gamesmiths.Forge.Godot.Core;
|
||||
using Gamesmiths.Forge.Godot.Nodes;
|
||||
@@ -27,11 +24,7 @@ using Movementtests.addons.godot_state_charts.csharp;
|
||||
using Movementtests.interfaces;
|
||||
using Movementtests.systems;
|
||||
using Movementtests.player_controller.Scripts;
|
||||
using Movementtests.scenes.player_controller.scripts;
|
||||
using Movementtests.tools;
|
||||
using Movementtests.forge.abilities;
|
||||
using Movementtests.managers;
|
||||
using Movementtests.tools.calculators;
|
||||
using RustyOptions;
|
||||
using Node = Godot.Node;
|
||||
|
||||
@@ -39,12 +32,7 @@ public record struct EmpoweredActionPayload;
|
||||
|
||||
|
||||
[GlobalClass, Icon("res://assets/ui/IconGodotNode/node_3D/icon_character.png"), Meta(typeof(IAutoNode))]
|
||||
public partial class PlayerController : CharacterBody3D,
|
||||
IDamageable,
|
||||
IDamageDealer,
|
||||
IHealthable,
|
||||
IKnockbackable,
|
||||
IForgeEntity
|
||||
public partial class PlayerController : CharacterBody3D, IForgeEntity, ICueHandler
|
||||
{
|
||||
public override void _Notification(int what) => this.Notify(what);
|
||||
|
||||
@@ -53,7 +41,7 @@ public partial class PlayerController : CharacterBody3D,
|
||||
public InventoryManager InventoryManager => this.DependOn<InventoryManager>();
|
||||
#endregion
|
||||
|
||||
#region Enums
|
||||
#region Utils
|
||||
|
||||
public enum BufferedActions
|
||||
{
|
||||
@@ -66,6 +54,14 @@ public partial class PlayerController : CharacterBody3D,
|
||||
|
||||
#endregion
|
||||
|
||||
#region Forge
|
||||
|
||||
private AbilityHandle? _empoweredActionHandle;
|
||||
public required EntityAttribute HealthAttribute { get; set; }
|
||||
public required EntityAttribute ManaAttribute { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Signals
|
||||
|
||||
[Signal]
|
||||
@@ -79,27 +75,25 @@ public partial class PlayerController : CharacterBody3D,
|
||||
|
||||
#region Publics
|
||||
|
||||
public HeadSystem HeadSystem = null!;
|
||||
public StairsSystem StairsSystem = null!;
|
||||
public MantleSystem MantleSystem = null!;
|
||||
public DashSystem DashSystem = null!;
|
||||
public CollisionShape3D StandingCollider = null!;
|
||||
public CollisionShape3D SlideCollider = null!;
|
||||
public WeaponSystem WeaponSystem = null!;
|
||||
public WallHugSystem WallHugSystem = null!;
|
||||
public PlayerUi PlayerUi = null!;
|
||||
public Node3D DashIndicatorNode = null!;
|
||||
public MeshInstance3D DashIndicatorMesh = null!;
|
||||
public CylinderMesh DashIndicatorMeshCylinder = null!;
|
||||
public RayCast3D WallRunSnapper = null!;
|
||||
public ShapeCast3D GroundDetector = null!;
|
||||
public ShapeCast3D CeilingDetector = null!;
|
||||
public RayCast3D DirectGroundDetector = null!;
|
||||
public Area3D WeaponHitbox = null!;
|
||||
public AudioStreamPlayer3D SfxPlayer = null!;
|
||||
|
||||
public ShapeCast3D DashDamageDetector = null!;
|
||||
public Area3D SlidingEnemyDetector = null!;
|
||||
[Node("HeadSystem")] public required HeadSystem HeadSystem { get; set; }
|
||||
[Node("StairsSystem")] public required StairsSystem StairsSystem { get; set; }
|
||||
[Node("HeadSystem/MantleSystem")] public required MantleSystem MantleSystem { get; set; }
|
||||
[Node("DashSystem")] public required DashSystem DashSystem { get; set; }
|
||||
[Node("StandingCollider")] public required CollisionShape3D StandingCollider { get; set; }
|
||||
[Node("SlideCollider")] public required CollisionShape3D SlideCollider { get; set; }
|
||||
[Node("WeaponSystem")] public required WeaponSystem WeaponSystem { get; set; }
|
||||
[Node("WallHugSystem")] public required WallHugSystem WallHugSystem { get; set; }
|
||||
[Node("UI")] public required PlayerUi PlayerUi { get; set; }
|
||||
[Node("GroundDetector")] public required ShapeCast3D GroundDetector { get; set; }
|
||||
[Node("CeilingDetector")] public required ShapeCast3D CeilingDetector { get; set; }
|
||||
[Node("DirectGroundDetector")] public required RayCast3D DirectGroundDetector { get; set; }
|
||||
[Node("%WeaponHitbox")] public required Area3D WeaponHitbox { get; set; }
|
||||
[Node("SFXPlayer")] public required AudioStreamPlayer3D SfxPlayer { get; set; }
|
||||
[Node("DashDamage")] public required ShapeCast3D DashDamageDetector { get; set; }
|
||||
[Node("SlidingEnemyDetector")] public required Area3D SlidingEnemyDetector { get; set; }
|
||||
[Node("%CloseEnemyDetector")] public required ShapeCast3D CloseEnemyDetector { get; set; }
|
||||
[Node("AimAssistRayCast")] public required RayCast3D AimAssistRayCast { get; set; }
|
||||
[Node("HeadSystem/CameraSmooth/Camera3D")] public required Camera3D Camera { get; set; }
|
||||
|
||||
public EntityAttributes Attributes { get; set; } = null!;
|
||||
public EntityTags Tags { get; set; } = null!;
|
||||
@@ -117,17 +111,14 @@ public partial class PlayerController : CharacterBody3D,
|
||||
// Forge stuff
|
||||
[ExportCategory("Forge")]
|
||||
[ExportGroup("General")]
|
||||
[Export]
|
||||
public ForgeTagContainer BaseTags { get; set; }
|
||||
[Export] public ForgeTag EmpoweredActionUsed;
|
||||
[Export] public required ForgeTagContainer BaseTags { get; set; }
|
||||
[Export] public required ForgeTag EmpoweredActionUsed { get; set; }
|
||||
[Export] public required ForgeTag InvincibleTag { get; set; }
|
||||
|
||||
[ExportGroup("Abilities")]
|
||||
[ExportSubgroup("Common and defaults")]
|
||||
[Export] public ForgeAbilityData EmpoweredActionAbility = null!;
|
||||
[Export] public ForgeAbilityData[] DefaultPermanentAbilities = [];
|
||||
|
||||
[ExportSubgroup("WeaponThrow")] [Export]
|
||||
public ForgeAbilityBehavior WeaponExplosionBehavior;
|
||||
[Export] public ForgeAbilityData? EmpoweredActionAbility;
|
||||
[Export] public ForgeAbilityData[] DefaultGrantedAbilities = [];
|
||||
|
||||
[ExportGroup("Effects")]
|
||||
[ExportSubgroup("Common and defaults")]
|
||||
@@ -147,7 +138,6 @@ public partial class PlayerController : CharacterBody3D,
|
||||
|
||||
[ExportGroup("Damage")] [Export] public RDamage RDamage { get; set; } = null!;
|
||||
[Export] public RKnockback? RKnockback { get; set; } = null!;
|
||||
[Export] public RHealth? RHealth { get; set; } = null!;
|
||||
|
||||
[ExportGroup("Targeting")]
|
||||
[Export(PropertyHint.Range, "0,20,0.1,or_greater")]
|
||||
@@ -409,29 +399,48 @@ public partial class PlayerController : CharacterBody3D,
|
||||
private Transition _onGroundSlideJump = null!;
|
||||
private Transition _onAirGlideDoubleJump = null!;
|
||||
|
||||
// Damage
|
||||
public CDamageable? CDamageable { get; set; }
|
||||
public CHealth? CHealth { get; set; }
|
||||
public CKnockback? CKnockback { get; set; }
|
||||
public float CurrentHealth { get; set; }
|
||||
#endregion
|
||||
|
||||
private bool _isInvincible;
|
||||
public bool IsInvincibleOverride { get; set; }
|
||||
#region DamageManagement
|
||||
|
||||
// Invincibility
|
||||
private ActiveEffectHandle? _invincibleEffect;
|
||||
public bool IsInvincible
|
||||
{
|
||||
get => _isInvincible || IsInvincibleOverride;
|
||||
set => _isInvincible = value;
|
||||
get => Tags.CombinedTags.HasTag(InvincibleTag.GetTag());
|
||||
set => SetInvincible(value);
|
||||
}
|
||||
|
||||
public void SetInvincible(bool invincible)
|
||||
{
|
||||
if (invincible && !IsInvincible)
|
||||
{
|
||||
var invincibility = new EffectData(
|
||||
"Invincibility",
|
||||
new DurationData(DurationType.Infinite),
|
||||
effectComponents:
|
||||
[
|
||||
new ModifierTagsEffectComponent(
|
||||
InvincibleTag.GetTag().GetSingleTagContainer()!
|
||||
)
|
||||
]);
|
||||
GD.Print("Applying invincibility");
|
||||
_invincibleEffect = EffectsManager.ApplyEffect(new Effect(invincibility,
|
||||
new EffectOwnership(this, this)));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (_invincibleEffect == null) return;
|
||||
EffectsManager.RemoveEffect(_invincibleEffect);
|
||||
GD.Print("Removing effect");
|
||||
_invincibleEffect = null;
|
||||
}
|
||||
|
||||
// Damage dealing
|
||||
private readonly List<IDamageable> _hitEnemies = new List<IDamageable>();
|
||||
|
||||
private ShapeCast3D _closeEnemyDetector = null!;
|
||||
private RayCast3D _aimAssisRayCast = null!;
|
||||
private Camera3D _camera = null!;
|
||||
|
||||
private AbilityHandle? _empoweredActionHandle;
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
public void OnReady()
|
||||
{
|
||||
@@ -439,16 +448,15 @@ public partial class PlayerController : CharacterBody3D,
|
||||
|
||||
// General use stuff
|
||||
PlayerUi = GetNode<PlayerUi>("UI");
|
||||
_closeEnemyDetector = GetNode<ShapeCast3D>("%CloseEnemyDetector");
|
||||
_closeEnemyDetector.TargetPosition = _closeEnemyDetector.TargetPosition.Normalized() * TargetingDistance;
|
||||
_aimAssisRayCast = GetNode<RayCast3D>("AimAssistRayCast");
|
||||
_aimAssisRayCast.TargetPosition = _aimAssisRayCast.TargetPosition.Normalized() * (TargetingDistance*1.5f);
|
||||
CloseEnemyDetector = GetNode<ShapeCast3D>("%CloseEnemyDetector");
|
||||
CloseEnemyDetector.TargetPosition = CloseEnemyDetector.TargetPosition.Normalized() * TargetingDistance;
|
||||
AimAssistRayCast = GetNode<RayCast3D>("AimAssistRayCast");
|
||||
AimAssistRayCast.TargetPosition = AimAssistRayCast.TargetPosition.Normalized() * (TargetingDistance*1.5f);
|
||||
|
||||
#region Forge
|
||||
|
||||
|
||||
var tagsManager = ForgeManagers.Instance.TagsManager;
|
||||
var cuesManager = ForgeManagers.Instance.CuesManager;
|
||||
|
||||
List<AttributeSet> attributeSetList = [];
|
||||
foreach (Node node in GetChildren())
|
||||
{
|
||||
@@ -468,15 +476,24 @@ public partial class PlayerController : CharacterBody3D,
|
||||
Abilities = new(this);
|
||||
Events = new();
|
||||
|
||||
_empoweredActionHandle = Abilities.GrantAbilityPermanently(
|
||||
EmpoweredActionAbility.GetAbilityData(),
|
||||
abilityLevel: 1,
|
||||
levelOverridePolicy: LevelComparison.None,
|
||||
sourceEntity: this);
|
||||
foreach (var ability in DefaultPermanentAbilities)
|
||||
HealthAttribute = Attributes["PlayerAttributeSet.Health"];
|
||||
ManaAttribute = Attributes["PlayerAttributeSet.Mana"];
|
||||
|
||||
cuesManager.RegisterCue(Tag.RequestTag(tagsManager, "cues.resources.health"), this);
|
||||
|
||||
if (EmpoweredActionAbility != null)
|
||||
{
|
||||
_empoweredActionHandle = Abilities.GrantAbilityPermanently(
|
||||
EmpoweredActionAbility.GetAbilityData(),
|
||||
abilityLevel: 1,
|
||||
levelOverridePolicy: LevelComparison.None,
|
||||
sourceEntity: this);
|
||||
}
|
||||
|
||||
foreach (var defaultGrantedAbility in DefaultGrantedAbilities)
|
||||
{
|
||||
Abilities.GrantAbilityPermanently(
|
||||
ability.GetAbilityData(),
|
||||
defaultGrantedAbility.GetAbilityData(),
|
||||
abilityLevel: 1,
|
||||
levelOverridePolicy: LevelComparison.None,
|
||||
sourceEntity: this);
|
||||
@@ -496,37 +513,23 @@ public partial class PlayerController : CharacterBody3D,
|
||||
EffectsManager.ApplyEffect(new Effect(effect.GetEffectData(), new EffectOwnership(this, this)));
|
||||
});
|
||||
}
|
||||
|
||||
Events.Subscribe(Tag.RequestTag(ForgeManagers.Instance.TagsManager, "events.combat.damage"), OnDamageReceived);
|
||||
Events.Subscribe(Tag.RequestTag(ForgeManagers.Instance.TagsManager, "events.combat.death"), OnDeath);
|
||||
|
||||
PlayerUi.Initialize(HealthAttribute, ManaAttribute);
|
||||
#endregion
|
||||
|
||||
// DashIndicator = GetNode<TextureRect>("%DashIndicator");
|
||||
TargetSpeed = WalkSpeed;
|
||||
DashIndicatorNode = GetNode<Node3D>("DashIndicator");
|
||||
DashIndicatorMesh = GetNode<MeshInstance3D>("DashIndicator/DashIndicatorMesh");
|
||||
DashIndicatorMeshCylinder = (DashIndicatorMesh.Mesh as CylinderMesh)!;
|
||||
DashIndicatorMesh.Visible = false;
|
||||
|
||||
SfxPlayer = GetNode<AudioStreamPlayer3D>("SFXPlayer");
|
||||
_audioStream = (SfxPlayer.GetStreamPlayback() as AudioStreamPlaybackInteractive)!;
|
||||
|
||||
// Camera stuff
|
||||
HeadSystem = GetNode<HeadSystem>("HeadSystem");
|
||||
_camera = GetNode<Camera3D>("HeadSystem/CameraSmooth/Camera3D");
|
||||
Node3D cameraSmooth = GetNode<Node3D>("HeadSystem/CameraSmooth");
|
||||
|
||||
// Movement stuff
|
||||
WeaponSystem = GetNode<WeaponSystem>("WeaponSystem");
|
||||
MantleSystem = GetNode<MantleSystem>("HeadSystem/MantleSystem");
|
||||
StandingCollider = GetNode<CollisionShape3D>("StandingCollider");
|
||||
SlideCollider = GetNode<CollisionShape3D>("SlideCollider");
|
||||
DashSystem = GetNode<DashSystem>("DashSystem");
|
||||
StairsSystem = GetNode<StairsSystem>("StairsSystem");
|
||||
WallHugSystem = GetNode<WallHugSystem>("WallHugSystem");
|
||||
WallRunSnapper = GetNode<RayCast3D>("%WallRunSnapper");
|
||||
GroundDetector = GetNode<ShapeCast3D>("GroundDetector");
|
||||
CeilingDetector = GetNode<ShapeCast3D>("CeilingDetector");
|
||||
DirectGroundDetector = GetNode<RayCast3D>("DirectGroundDetector");
|
||||
DashDamageDetector = GetNode<ShapeCast3D>("DashDamage");
|
||||
SlidingEnemyDetector = GetNode<Area3D>("SlidingEnemyDetector");
|
||||
RayCast3D stairsBelowRayCast3D = GetNode<RayCast3D>("StairsBelowRayCast3D");
|
||||
RayCast3D stairsAheadRayCast3D = GetNode<RayCast3D>("StairsAheadRayCast3D");
|
||||
_headCollisionDetectors = new RayCast3D[NumOfHeadCollisionDetectors];
|
||||
@@ -545,26 +548,18 @@ public partial class PlayerController : CharacterBody3D,
|
||||
WeaponHitbox.Monitoring = false;
|
||||
WeaponHitbox.BodyEntered += RegisterHitEnnemy;
|
||||
|
||||
CHealth = GetNode<Node>("CHealth") as CHealth;
|
||||
CKnockback = GetNode<Node>("CKnockback") as CKnockback;
|
||||
CDamageable = GetNode<Node>("CDamageable") as CDamageable;
|
||||
if (CHealth == null) throw new Exception("CHealth not found!");
|
||||
if (CKnockback == null) throw new Exception("CKnockback not found!");
|
||||
if (CDamageable == null) throw new Exception("CDamageable not found!");
|
||||
// if (RHealth != null)
|
||||
// {
|
||||
// CHealth.RHealth = RHealth;
|
||||
// CHealth.CurrentHealth = RHealth.StartingHealth;
|
||||
// }
|
||||
// if (RKnockback != null) CKnockback!.RKnockback = RKnockback;
|
||||
//
|
||||
// CDamageable.DamageTaken += (damageable, record) => ReduceHealth(damageable, record);
|
||||
// CDamageable.DamageTaken += (_, record) => RegisterKnockback(new KnockbackRecord(record));
|
||||
// CHealth.HealthChanged += PlayerUi.OnHealthChanged;
|
||||
// CHealth.HealthDepleted += (_) => Kill();
|
||||
|
||||
if (RHealth != null)
|
||||
{
|
||||
CHealth.RHealth = RHealth;
|
||||
CHealth.CurrentHealth = RHealth.StartingHealth;
|
||||
}
|
||||
if (RKnockback != null) CKnockback!.RKnockback = RKnockback;
|
||||
|
||||
PlayerUi.Initialize(CHealth.CurrentHealth, Attributes["PlayerAttributeSet.Mana"].BaseValue);
|
||||
CDamageable.DamageTaken += (damageable, record) => ReduceHealth(damageable, record);
|
||||
CDamageable.DamageTaken += (_, record) => RegisterKnockback(new KnockbackRecord(record));
|
||||
CHealth.HealthChanged += PlayerUi.OnHealthChanged;
|
||||
CHealth.HealthDepleted += (_) => Kill();
|
||||
|
||||
#region StateManagement
|
||||
|
||||
_playerState = StateChart.Of(GetNode("StateChart"));
|
||||
@@ -633,7 +628,7 @@ public partial class PlayerController : CharacterBody3D,
|
||||
Gravity = (float)ProjectSettings.GetSetting("physics/3d/default_gravity");
|
||||
MantleSystem.Init();
|
||||
StairsSystem.Init(stairsBelowRayCast3D, stairsAheadRayCast3D, cameraSmooth);
|
||||
DashSystem.Init(HeadSystem, _camera);
|
||||
DashSystem.Init(HeadSystem, Camera);
|
||||
WeaponSystem.Init();
|
||||
WallHugSystem.Init();
|
||||
|
||||
@@ -728,6 +723,8 @@ public partial class PlayerController : CharacterBody3D,
|
||||
var weaponLeftToken = WeaponSystem.Events.Subscribe(WeaponSystem.WeaponStartedFlyingEventTag, OnWeaponLeft);
|
||||
var weaponLandedToken = WeaponSystem.Events.Subscribe(WeaponSystem.WeaponStoppedFlyingEventTag, OnWeaponLanded);
|
||||
}
|
||||
|
||||
#region LifecycleManagement
|
||||
|
||||
public void OnResolved()
|
||||
{
|
||||
@@ -737,8 +734,7 @@ public partial class PlayerController : CharacterBody3D,
|
||||
{
|
||||
foreach (var ability in abilities)
|
||||
{
|
||||
if (ability is not ForgeAbilityBehavior abilityBehavior) continue;
|
||||
WeaponSystem.GrantNewAbilityForEvent(weaponEvent, abilityBehavior);
|
||||
WeaponSystem.GrantNewAbilityForEvent(weaponEvent, ability);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -753,6 +749,10 @@ public partial class PlayerController : CharacterBody3D,
|
||||
InventoryManager.WeaponEventAbilityRemoved -= OnWeaponEventAbilityRemoved;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region WeaponEvents
|
||||
|
||||
public void OnWeaponLeft(EventData data)
|
||||
{
|
||||
var target = data.Target;
|
||||
@@ -789,10 +789,11 @@ public partial class PlayerController : CharacterBody3D,
|
||||
{
|
||||
WeaponSystem.RemoveAbilityForEvent(data.ForEvent, data.Ability);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
///////////////////////////
|
||||
// Settings & tutorial //
|
||||
///////////////////////////
|
||||
#region Settings
|
||||
|
||||
public void LoadSettings()
|
||||
{
|
||||
var config = new ConfigFile();
|
||||
@@ -812,25 +813,26 @@ public partial class PlayerController : CharacterBody3D,
|
||||
_fovChangeMultiplier = (float) config.GetValue("InputSettings", "FovChangeWithSpeed", 1.0f);
|
||||
_aimAssistMultiplier = (float) config.GetValue("InputSettings", "AimAssist", 1.0f);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
///////////////////////////
|
||||
// Toolbox Utils //
|
||||
///////////////////////////
|
||||
#region Toolbox
|
||||
|
||||
public void SetPlayerHealthOverride(float newHealthValue)
|
||||
{
|
||||
RHealth.StartingHealth = newHealthValue;
|
||||
CHealth!.CurrentHealth = newHealthValue;
|
||||
PlayerUi.Initialize(CHealth.CurrentHealth, Attributes["PlayerAttributeSet.Mana"].BaseValue);
|
||||
// RHealth.StartingHealth = newHealthValue;
|
||||
// CHealth!.CurrentHealth = newHealthValue;
|
||||
// PlayerUi.Initialize(CHealth.CurrentHealth, Attributes["PlayerAttributeSet.Mana"].BaseValue);
|
||||
}
|
||||
public void SetPlayerDamageOverride(float newDamageValue)
|
||||
{
|
||||
RDamage.DamageDealt = newDamageValue;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
///////////////////////////
|
||||
// Grounded management //
|
||||
///////////////////////////
|
||||
|
||||
#region GroundManagement
|
||||
|
||||
public void OnGrounded()
|
||||
{
|
||||
_isWallJumpAvailable = true;
|
||||
@@ -882,10 +884,7 @@ public partial class PlayerController : CharacterBody3D,
|
||||
_audioStream.SwitchToClipByName("land");
|
||||
}
|
||||
|
||||
public bool IsGroundLike()
|
||||
{
|
||||
return GroundDetector.GetCollisionResult().Count > 0;
|
||||
}
|
||||
public bool IsGroundLike() => GroundDetector.GetCollisionResult().Count > 0;
|
||||
|
||||
public void HandleGrounded(float delta)
|
||||
{
|
||||
@@ -972,11 +971,10 @@ public partial class PlayerController : CharacterBody3D,
|
||||
{
|
||||
return IsOnFloor() || StairsSystem.WasSnappedToStairsLastFrame();
|
||||
}
|
||||
|
||||
///////////////////////////
|
||||
// Airborne management //
|
||||
///////////////////////////
|
||||
|
||||
#endregion
|
||||
|
||||
#region AirborneManagement
|
||||
public void OnAirborne()
|
||||
{
|
||||
if (_aiming.Active)
|
||||
@@ -1026,6 +1024,8 @@ public partial class PlayerController : CharacterBody3D,
|
||||
var verticalVelocity = ComputeVerticalSpeedGravity((float) delta);
|
||||
Velocity = new Vector3(horizontalVelocity.X, verticalVelocity, horizontalVelocity.Z);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
///////////////////////////
|
||||
// Movement input //
|
||||
@@ -1091,17 +1091,17 @@ public partial class PlayerController : CharacterBody3D,
|
||||
// Camera stuff
|
||||
private Vector2 ComputeAimAssist()
|
||||
{
|
||||
_aimAssisRayCast.SetRotation(HeadSystem.GetGlobalLookRotation());
|
||||
if (!_aimAssisRayCast.IsColliding()) return Vector2.Zero;
|
||||
AimAssistRayCast.SetRotation(HeadSystem.GetGlobalLookRotation());
|
||||
if (!AimAssistRayCast.IsColliding()) return Vector2.Zero;
|
||||
|
||||
// Hard dependency on the aim assist to be an Area3D and having a parent
|
||||
var collidedObject = _aimAssisRayCast.GetCollider() as Area3D;
|
||||
var collidedObject = AimAssistRayCast.GetCollider() as Area3D;
|
||||
if (collidedObject is null) return Vector2.Zero;
|
||||
if (collidedObject.GetParent() is not ITargetable targetable) return Vector2.Zero;
|
||||
|
||||
var targetPosition = targetable.GetTargetGlobalPosition();
|
||||
var targetPositionOnCamera = _camera.UnprojectPosition(targetPosition);
|
||||
var centerOfScreen = _camera.GetViewport().GetVisibleRect().Size / 2f;
|
||||
var targetPositionOnCamera = Camera.UnprojectPosition(targetPosition);
|
||||
var centerOfScreen = Camera.GetViewport().GetVisibleRect().Size / 2f;
|
||||
var aimAssistDirection = centerOfScreen - targetPositionOnCamera;
|
||||
var aimAssist = aimAssistDirection * AimAssistStrength / 1000f;
|
||||
|
||||
@@ -2061,7 +2061,7 @@ public partial class PlayerController : CharacterBody3D,
|
||||
if (!isOnFloorCustom())
|
||||
ReduceTimeScaleWhileAiming();
|
||||
|
||||
_aimAssisRayCast.TargetPosition = _aimAssisRayCast.TargetPosition.Normalized() *
|
||||
AimAssistRayCast.TargetPosition = AimAssistRayCast.TargetPosition.Normalized() *
|
||||
(DashSystem.DashCast3D.TargetPosition.Length() + DashSystem.DashCastRadius);
|
||||
}
|
||||
public void HandleAiming(float delta)
|
||||
@@ -2076,7 +2076,7 @@ public partial class PlayerController : CharacterBody3D,
|
||||
{
|
||||
DashSystem.StopPreparingDash();
|
||||
|
||||
_aimAssisRayCast.TargetPosition = _aimAssisRayCast.TargetPosition.Normalized() * (TargetingDistance*1.5f);
|
||||
AimAssistRayCast.TargetPosition = AimAssistRayCast.TargetPosition.Normalized() * (TargetingDistance*1.5f);
|
||||
|
||||
// DashIndicatorMesh.Visible = false;
|
||||
}
|
||||
@@ -2337,6 +2337,11 @@ public partial class PlayerController : CharacterBody3D,
|
||||
// private float _oldMana = 100;
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
if (Engine.GetProcessFrames() % 60 == 0)
|
||||
{
|
||||
GD.Print(_invincibleEffect);
|
||||
GD.Print(Tags.CombinedTags.Count);
|
||||
}
|
||||
EffectsManager.UpdateEffects(delta);
|
||||
}
|
||||
|
||||
@@ -2351,7 +2356,7 @@ public partial class PlayerController : CharacterBody3D,
|
||||
public void HandleEnemyTargeting()
|
||||
{
|
||||
_isEnemyInDashAttackRange = false;
|
||||
_closeEnemyDetector.SetRotation(HeadSystem.GetGlobalLookRotation());
|
||||
CloseEnemyDetector.SetRotation(HeadSystem.GetGlobalLookRotation());
|
||||
var enemyTargetState = PlayerUi.TargetState.NoTarget;
|
||||
var positionOnScreen = Vector2.Zero;
|
||||
|
||||
@@ -2359,20 +2364,20 @@ public partial class PlayerController : CharacterBody3D,
|
||||
{
|
||||
enemyTargetState = PlayerUi.TargetState.TargetWouldKill;
|
||||
_targetLocation = dashTarget.GetTargetGlobalPosition();
|
||||
positionOnScreen = _camera.UnprojectPosition(_targetLocation);
|
||||
positionOnScreen = Camera.UnprojectPosition(_targetLocation);
|
||||
PlayerUi.SetEnemyTargetProperties(new PlayerUi.TargetProperties(enemyTargetState, positionOnScreen));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!_closeEnemyDetector.IsColliding())
|
||||
if (!CloseEnemyDetector.IsColliding())
|
||||
{
|
||||
PlayerUi.SetEnemyTargetProperties(new PlayerUi.TargetProperties(enemyTargetState, positionOnScreen));
|
||||
return;
|
||||
}
|
||||
|
||||
_targetHitLocation = _closeEnemyDetector.GetCollisionPoint(0);
|
||||
_targetObject = _closeEnemyDetector.GetCollider(0);
|
||||
_targetHitLocation = CloseEnemyDetector.GetCollisionPoint(0);
|
||||
_targetObject = CloseEnemyDetector.GetCollider(0);
|
||||
if (_targetObject is not ITargetable target)
|
||||
{
|
||||
PlayerUi.SetEnemyTargetProperties(new PlayerUi.TargetProperties(enemyTargetState, positionOnScreen));
|
||||
@@ -2381,7 +2386,7 @@ public partial class PlayerController : CharacterBody3D,
|
||||
|
||||
_targetLocation = target.GetTargetGlobalPosition();
|
||||
// var targetDistance = _targetLocation.DistanceTo(GlobalPosition);
|
||||
positionOnScreen = _camera.UnprojectPosition(_targetLocation);
|
||||
positionOnScreen = Camera.UnprojectPosition(_targetLocation);
|
||||
|
||||
var wouldKill = false;
|
||||
if (_targetObject is IHealthable h and IDamageable d)
|
||||
@@ -2399,20 +2404,21 @@ public partial class PlayerController : CharacterBody3D,
|
||||
if (IsInvincible)
|
||||
return damageRecord with { Damage = new RDamage(0, damageRecord.Damage.DamageType) };
|
||||
|
||||
var finalDamage = CDamageable!.TakeDamage(damageRecord);
|
||||
DamageTaken?.Invoke(this, finalDamage);
|
||||
// var finalDamage = CDamageable!.TakeDamage(damageRecord);
|
||||
// DamageTaken?.Invoke(this, finalDamage);
|
||||
|
||||
HeadSystem.OnGetHit();
|
||||
_audioStream.SwitchToClipByName("damage_taken");
|
||||
TriggerHitstop();
|
||||
OnHitInvincibility();
|
||||
|
||||
return finalDamage;
|
||||
return damageRecord;
|
||||
}
|
||||
|
||||
public DamageRecord ComputeDamage(DamageRecord damageRecord)
|
||||
{
|
||||
return CDamageable!.ComputeDamage(damageRecord);
|
||||
// return CDamageable!.ComputeDamage(damageRecord);
|
||||
return damageRecord;
|
||||
}
|
||||
|
||||
public void OnHitInvincibility()
|
||||
@@ -2590,19 +2596,25 @@ public partial class PlayerController : CharacterBody3D,
|
||||
}
|
||||
public HealthChangedRecord ReduceHealth(IDamageable source, DamageRecord damageRecord)
|
||||
{
|
||||
var record = CHealth!.ReduceHealth(source, damageRecord);
|
||||
HealthChanged?.Invoke(this, record);
|
||||
return record;
|
||||
// var record = CHealth!.ReduceHealth(source, damageRecord);
|
||||
// HealthChanged?.Invoke(this, record);
|
||||
return new HealthChangedRecord(100, 0, 100);
|
||||
}
|
||||
public void RegisterKnockback(KnockbackRecord knockbackRecord)
|
||||
{
|
||||
CKnockback!.RegisterKnockback(knockbackRecord);
|
||||
// CKnockback!.RegisterKnockback(knockbackRecord);
|
||||
}
|
||||
|
||||
public Vector3 ComputeKnockback()
|
||||
{
|
||||
var kb = CKnockback!.ComputeKnockback();
|
||||
return kb;
|
||||
// var kb = CKnockback!.ComputeKnockback();
|
||||
// return kb;
|
||||
return Vector3.Zero;
|
||||
}
|
||||
|
||||
public void OnDeath(EventData data)
|
||||
{
|
||||
Kill();
|
||||
}
|
||||
|
||||
public void Kill()
|
||||
@@ -2625,4 +2637,43 @@ public partial class PlayerController : CharacterBody3D,
|
||||
{
|
||||
_audioStream.SwitchToClipByName("footsteps");
|
||||
}
|
||||
|
||||
// Forge Damage handling
|
||||
public void OnDamageReceived(EventData data)
|
||||
{
|
||||
var newHealth = HealthAttribute.CurrentValue + data.EventMagnitude;
|
||||
if (newHealth > HealthAttribute.Min) return;
|
||||
|
||||
var tagsManager = ForgeManagers.Instance.TagsManager;
|
||||
Events.Raise(new EventData
|
||||
{
|
||||
EventTags = Tag.RequestTag(tagsManager, "events.combat.death").GetSingleTagContainer()!,
|
||||
Source = data.Source,
|
||||
Target = data.Target
|
||||
});
|
||||
}
|
||||
|
||||
public void OnExecute(IForgeEntity? target, CueParameters? parameters)
|
||||
{
|
||||
if (target == null || !parameters.HasValue) return;
|
||||
|
||||
float magnitude = parameters.Value.Magnitude;
|
||||
if (magnitude >= 0) return;
|
||||
|
||||
HeadSystem.OnGetHit();
|
||||
_audioStream.SwitchToClipByName("damage_taken");
|
||||
TriggerHitstop();
|
||||
}
|
||||
|
||||
public void OnApply(IForgeEntity? target, CueParameters? parameters)
|
||||
{
|
||||
}
|
||||
|
||||
public void OnRemove(IForgeEntity? target, bool interrupted)
|
||||
{
|
||||
}
|
||||
|
||||
public void OnUpdate(IForgeEntity? target, CueParameters? parameters)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user