diff --git a/Movement tests.sln.DotSettings.user b/Movement tests.sln.DotSettings.user index 9aadd0c2..e772076b 100644 --- a/Movement tests.sln.DotSettings.user +++ b/Movement tests.sln.DotSettings.user @@ -3,6 +3,7 @@ ForceIncluded ForceIncluded ForceIncluded + ForceIncluded ForceIncluded ForceIncluded True \ No newline at end of file diff --git a/maps/GYMs/enemies.tscn b/maps/GYMs/enemies.tscn index 2a73974b..17db11a0 100644 --- a/maps/GYMs/enemies.tscn +++ b/maps/GYMs/enemies.tscn @@ -93,6 +93,12 @@ use_collision = true size = Vector3(6.5, 4, 17) material = ExtResource("2_3uydm") +[node name="CSGBox3D10" type="CSGBox3D" parent="Greybox"] +transform = Transform3D(1, 0, 0, 0, 0.9659258, 0.25881904, 0, -0.25881904, 0.9659258, 13.653999, 0.9705714, -5.336278) +use_collision = true +size = Vector3(6.5, 4, 24.5) +material = ExtResource("2_3uydm") + [node name="CSGBox3D8" type="CSGBox3D" parent="Greybox"] transform = Transform3D(0.81915206, 0, 0.57357645, 0, 1, 0, -0.57357645, 0, 0.81915206, -7.3460007, 0, -3.9585) use_collision = true @@ -124,21 +130,21 @@ size = Vector3(6.5, 11, 5.5) material = ExtResource("2_3uydm") [node name="FixedDashthroughTarget" parent="." instance=ExtResource("15_5fa36")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 14, 3.5, 2.5) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 9, 3.5, 2.5) [node name="Enemy" parent="." node_paths=PackedStringArray("Target") instance=ExtResource("3_3uydm")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -16.83681) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 13.5, 2.5, -8.336809) Target = NodePath("../Player") RKnockback = SubResource("Resource_q21h6") RMovement = SubResource("Resource_5fa36") [node name="Enemy2" parent="." node_paths=PackedStringArray("Target") instance=ExtResource("3_3uydm")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3, 0, -16.83681) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 13, 0, -17.33681) Target = NodePath("../Player") RMovement = SubResource("Resource_5fa36") [node name="Enemy3" parent="." node_paths=PackedStringArray("Target") instance=ExtResource("3_3uydm")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 7, 0, 0.16319084) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 14, 4, -3.3368092) Target = NodePath("../Player") RMovement = SubResource("Resource_5fa36") diff --git a/player_controller/PlayerController.tscn b/player_controller/PlayerController.tscn index b4ac0571..b12d8f84 100644 --- a/player_controller/PlayerController.tscn +++ b/player_controller/PlayerController.tscn @@ -54,7 +54,7 @@ [sub_resource type="Resource" id="Resource_cb2lu"] script = ExtResource("2_x835q") -DamageDealt = 3.0 +DamageDealt = 30.0 metadata/_custom_type_script = "uid://jitubgv6judn" [sub_resource type="Resource" id="Resource_abfq8"] diff --git a/player_controller/Scripts/PlayerController.cs b/player_controller/Scripts/PlayerController.cs index 7b2b8bf2..9efc30b2 100644 --- a/player_controller/Scripts/PlayerController.cs +++ b/player_controller/Scripts/PlayerController.cs @@ -313,6 +313,7 @@ public partial class PlayerController : CharacterBody3D, private StateChartState _mantling; private StateChartState _simpleDash; private StateChartState _aimedDash; + private StateChartState _weaponDash; private StateChartState _sliding; private StateChartState _groundSliding; private StateChartState _airGliding; @@ -436,6 +437,7 @@ public partial class PlayerController : CharacterBody3D, _aiming = StateChartState.Of(GetNode("StateChart/Root/Aim/On")); _simpleDash = StateChartState.Of(GetNode("StateChart/Root/Movement/Dashing/Dash")); _aimedDash = StateChartState.Of(GetNode("StateChart/Root/Movement/Dashing/AimedDash")); + _weaponDash = StateChartState.Of(GetNode("StateChart/Root/Movement/Dashing/ToWeaponDash")); _slamming = StateChartState.Of(GetNode("StateChart/Root/Movement/Slamming")); _sliding = StateChartState.Of(GetNode("StateChart/Root/Movement/Sliding")); @@ -499,7 +501,7 @@ public partial class PlayerController : CharacterBody3D, MantleSystem.Init(); StairsSystem.Init(stairsBelowRayCast3D, stairsAheadRayCast3D, cameraSmooth); DashSystem.Init(HeadSystem, _camera); - WeaponSystem.Init(HeadSystem, _camera); + WeaponSystem.Init(); WallHugSystem.Init(); EmpoweredActionsLeft = MaxNumberOfEmpoweredActions; @@ -548,6 +550,8 @@ public partial class PlayerController : CharacterBody3D, _aimedDash.StateEntered += OnAimedDashStarted; _aimedDash.StateExited += OnAimedDashFinished; + _weaponDash.StateExited += OnWeaponDashFinished; + _sliding.StateEntered += SlideStarted; _sliding.StateExited += SlideEnded; _slideCanceled.StateEntered += OnSlideCanceled; @@ -576,7 +580,7 @@ public partial class PlayerController : CharacterBody3D, _onWallRunning.StatePhysicsProcessing += HandleWallRunning; _onWallHanging.StateExited += RecoverWeapon; - _onDashEnded.Taken += RecoverWeapon; + // _onDashEnded.Taken += RecoverWeapon; _onJumpFromWall.Taken += OnJumpFromWall; _onJumpFromWallFalling.Taken += OnJumpFromWall; @@ -975,7 +979,7 @@ public partial class PlayerController : CharacterBody3D, } public void RecoverChildNode(Node3D node) { - GetTree().GetRoot().RemoveChild(node); + node.GetParent().RemoveChild(node); AddChild(node); node.SetGlobalPosition(GlobalPosition); } @@ -1703,8 +1707,6 @@ public partial class PlayerController : CharacterBody3D, if (DashSystem.CanDashThroughTarget && DashSystem.CollidedObject is ITargetable targetable) correctedLocation = ComputePositionAfterTargetedDash(targetable.GetTargetGlobalPosition(), DashSystem.CollisionPoint); - if (DashSystem.CollidedObject is IDamageable damageable) - _hitEnemies.Add(damageable); // Start invincibility timer for the duration of the dash and a bit more afterwards OnHitInvincibility(); @@ -1726,7 +1728,8 @@ public partial class PlayerController : CharacterBody3D, } public void OnAimedDashFinished() { - TriggerDamage(); + ManageAttackedEnemyPostDash(DashSystem.CollidedObject as Node); + DashSystem.CollidedObject = null; if (_customMantle) { @@ -1751,23 +1754,27 @@ public partial class PlayerController : CharacterBody3D, weaponTargetLocation, DashSystem.HasHit, DashSystem.CollisionPoint, - DashSystem.CollisionNormal); + DashSystem.CollisionNormal, + DashSystem.CollidedObject as Node); } public void RecoverWeapon() { if (WeaponSystem.GetParent() == this) return; HeadSystem.ShowWeapon(); - RecoverChildNode(WeaponSystem); WeaponSystem.ResetWeapon(); + RecoverChildNode(WeaponSystem); } public void DashToFlyingWeapon() { _playerState.SendEvent("cancel_aim"); _playerState.SendEvent("weapon_dash"); + PerformEmpoweredAction(); _audioStream.SwitchToClipByName("dash"); + // Start invincibility timer for the duration of the dash and a bit more afterwards + OnHitInvincibility(); DashSystem.ShouldMantle = false; _dashDirection = (WeaponSystem.GlobalPosition - GlobalPosition).Normalized(); @@ -1788,8 +1795,11 @@ public partial class PlayerController : CharacterBody3D, { _playerState.SendEvent("cancel_aim"); _playerState.SendEvent("weapon_dash"); + PerformEmpoweredAction(); _audioStream.SwitchToClipByName("dash"); + // Start invincibility timer for the duration of the dash and a bit more afterwards + OnHitInvincibility(); DashSystem.ShouldMantle = false; var dashLocation = WeaponSystem.PlantLocation; @@ -1797,7 +1807,9 @@ public partial class PlayerController : CharacterBody3D, dashLocation += WeaponSystem.PlantNormal * _playerRadius; if (WeaponSystem.IsPlantedUnderPlatform()) dashLocation += Vector3.Down * _playerHeight; - + if (WeaponSystem.PlantObject is ITargetable targetable) + dashLocation = targetable.GetTargetGlobalPosition(); + _wallHugStartNormal = WeaponSystem.PlantNormal; _currentWallContactPoint = WeaponSystem.PlantLocation; _wallHugStartLocation = dashLocation; @@ -1811,11 +1823,37 @@ public partial class PlayerController : CharacterBody3D, // Store the weapon state before resetting it var isPlantedOnWall = WeaponSystem.IsPlantedInWall(); var isPlantedUnderPlatform = WeaponSystem.IsPlantedUnderPlatform(); - var shouldDashToHanging = isPlantedOnWall || isPlantedUnderPlatform; - + var isPlantedInTarget = WeaponSystem.PlantObject is ITargetable; + var shouldDashToHanging = (isPlantedOnWall || isPlantedUnderPlatform) && !isPlantedInTarget; var resultingEvent = shouldDashToHanging ? "dash_to_planted" : "dash_finished"; + + if (!shouldDashToHanging) RecoverWeapon(); // Manually recover weapon before enemy is freed in case it owns the weapon object + if (WeaponSystem.PlantObject is ITargetable targetable) + { + HeadSystem.OnMantle(); // Recycle mantle animation + SetVerticalVelocity(PostDashSpeed); + } + + ManageAttackedEnemyPostDash(WeaponSystem.PlantObject); + WeaponSystem.PlantObject = null; + _playerState.SendEvent(resultingEvent); } + + public void ManageAttackedEnemyPostDash(Node enemy) + { + if (enemy is IDamageable damageable) + { + _hitEnemies.Add(damageable); + TriggerDamage(); + } + if (enemy is IStunnable stunnable) + stunnable.Stun(); + } + + public void OnWeaponDashFinished() + { + } /////////////////////////// // Processes ////////////// diff --git a/scenes/enemies/Enemy.cs b/scenes/enemies/Enemy.cs index a69fe52a..ec78c00c 100644 --- a/scenes/enemies/Enemy.cs +++ b/scenes/enemies/Enemy.cs @@ -1,6 +1,7 @@ using System; using Godot; using Movementtests.interfaces; +using Movementtests.systems; [GlobalClass] public partial class Enemy : CharacterBody3D, @@ -22,6 +23,8 @@ public partial class Enemy : CharacterBody3D, // Public export components [Export] public Node3D Target { get; set; } + [Export] + public float EnemyHeight { get; set; } = 1f; [ExportGroup("Health")] [Export] @@ -162,11 +165,23 @@ public partial class Enemy : CharacterBody3D, public void Kill(IHealthable source) { + // Remove weapon that might be planted there + foreach (var child in GetChildren()) + { + if (child is WeaponSystem system) + { + CallDeferred(Node.MethodName.RemoveChild, system); + GetTree().GetRoot().CallDeferred(Node.MethodName.AddChild, system); + system.CallDeferred(Node3D.MethodName.SetGlobalPosition, GlobalPosition + Vector3.Up*EnemyHeight); + system.CallDeferred(WeaponSystem.MethodName.RethrowWeapon); + } + } + foreach (var killable in DeathEffects.ToIKillables()) { killable.Kill(source); } - QueueFree(); + CallDeferred(Node.MethodName.QueueFree); } public void RegisterKnockback(IDamageable source, DamageRecord damageRecord) diff --git a/scenes/enemies/flying_enemy/flying_enemy.tscn b/scenes/enemies/flying_enemy/flying_enemy.tscn index 059205ee..a8210f25 100644 --- a/scenes/enemies/flying_enemy/flying_enemy.tscn +++ b/scenes/enemies/flying_enemy/flying_enemy.tscn @@ -48,6 +48,7 @@ collision_layer = 16 collision_mask = 273 motion_mode = 1 script = ExtResource("1_q8l7o") +EnemyHeight = 0.5 RHealth = ExtResource("2_ma2bq") DeathEffects = Array[Object]([]) RDamage = ExtResource("2_on7rt") diff --git a/scenes/enemies/flying_enemy/flying_enemy_health.tres b/scenes/enemies/flying_enemy/flying_enemy_health.tres index 0610b35b..8b5983db 100644 --- a/scenes/enemies/flying_enemy/flying_enemy_health.tres +++ b/scenes/enemies/flying_enemy/flying_enemy_health.tres @@ -4,5 +4,5 @@ [resource] script = ExtResource("1_jht15") -StartingHealth = 50.0 +StartingHealth = 10.0 metadata/_custom_type_script = "uid://baiapod3csndf" diff --git a/scenes/enemies/grounded_enemy/grounded_enemy.tscn b/scenes/enemies/grounded_enemy/grounded_enemy.tscn index 34388e97..e8606e49 100644 --- a/scenes/enemies/grounded_enemy/grounded_enemy.tscn +++ b/scenes/enemies/grounded_enemy/grounded_enemy.tscn @@ -43,6 +43,7 @@ size = Vector3(1, 2, 1.5) collision_layer = 16 collision_mask = 273 script = ExtResource("1_r6506") +EnemyHeight = 2.0 RHealth = ExtResource("2_w4lm8") DeathEffects = Array[Object]([]) RDamage = ExtResource("2_bn56u") diff --git a/systems/weapon/WeaponSystem.cs b/systems/weapon/WeaponSystem.cs index 489d10c1..18750a24 100644 --- a/systems/weapon/WeaponSystem.cs +++ b/systems/weapon/WeaponSystem.cs @@ -22,27 +22,23 @@ public partial class WeaponSystem : RigidBody3D 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 _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(Node3D head, Camera3D camera) + public void Init() { - _head = head; - _camera = camera; - _weaponState = StateChart.Of(GetNode("StateChart")); InHandState = StateChartState.Of(GetNode("StateChart/Root/InHand")); FlyingState = StateChartState.Of(GetNode("StateChart/Root/Flying")); @@ -53,7 +49,7 @@ public partial class WeaponSystem : RigidBody3D WeaponLocationIndicatorMaterial = WeaponLocationIndicator.GetActiveMaterial(0) as StandardMaterial3D; WeaponMesh = GetNode("Weapon"); - _startMeshTransform = WeaponMesh.Transform; + _startMeshRotation = WeaponMesh.Rotation; _tweenQueueSystem = GetNode("TweenQueueSystem"); _tweenQueueSystem.Init(this); @@ -90,7 +86,7 @@ public partial class WeaponSystem : RigidBody3D PlantLocation = location; } - public void ThrowWeapon(Vector3 end, bool hasHit, Vector3 collisionLocation, Vector3 collisionNormal) + public void ThrowWeapon(Vector3 end, bool hasHit, Vector3 collisionLocation, Vector3 collisionNormal, Node collidedObject) { _weaponState.SendEvent("throw"); @@ -103,11 +99,21 @@ public partial class WeaponSystem : RigidBody3D var tween = _tweenQueueSystem.TweenToLocation(new TweenQueueSystem.TweenInputs(end, StraightThrowDuration)); if (hasHit) + { + PlantObject = collidedObject; tween.Finished += PlantWeaponInWall; + } else tween.Finished += ThrowWeaponOnCurve; } + public void RethrowWeapon() + { + _weaponState.SendEvent("throw"); + _throwDirection = Vector3.Up; + ThrowWeaponOnCurve(); + } + public void ThrowWeaponOnCurve() { Freeze = false; @@ -118,16 +124,22 @@ public partial class WeaponSystem : RigidBody3D { _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); + WeaponMesh.Rotation = _startMeshRotation; + + // WeaponLocationIndicatorMaterial.StencilColor = new Color(1f, 0.2f, 0.2f); + if (PlantObject is Node3D node) + { + GetTree().GetRoot().CallDeferred(Node.MethodName.RemoveChild, this); + node.CallDeferred(Node.MethodName.AddChild, this); + } + CallDeferred(Node3D.MethodName.SetGlobalPosition, PlantLocation); + CallDeferred(Node3D.MethodName.LookAt, GlobalTransform.Origin + PlantNormal, Vector3.Up, true); } public void OnThrownWeaponReachesGround(Node other) { + PlantObject = other; PlantWeaponInWall(); } diff --git a/systems/weapon/weapon.tscn b/systems/weapon/weapon.tscn index 0889a4a5..76566e39 100644 --- a/systems/weapon/weapon.tscn +++ b/systems/weapon/weapon.tscn @@ -38,7 +38,7 @@ material = SubResource("StandardMaterial3D_m0v1h") [node name="Weapon" type="RigidBody3D"] collision_layer = 65536 -collision_mask = 256 +collision_mask = 304 continuous_cd = true contact_monitor = true max_contacts_reported = 1 @@ -54,6 +54,9 @@ shape = SubResource("CylinderShape3D_avini") transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0, 0, 0.8673003) mesh = ExtResource("3_svc06") +[node name="WeaponLocationIndicator" type="MeshInstance3D" parent="."] +mesh = SubResource("SphereMesh_jpdh0") + [node name="StateChart" type="Node" parent="."] script = ExtResource("3_5owyf") metadata/_custom_type_script = "uid://couw105c3bde4" @@ -89,11 +92,14 @@ delay_in_seconds = "0.0" [node name="Planted" type="Node" parent="StateChart/Root"] script = ExtResource("5_m0v1h") +[node name="ToFlying" type="Node" parent="StateChart/Root/Planted"] +script = ExtResource("6_jpdh0") +to = NodePath("../../Flying") +event = &"throw" +delay_in_seconds = "0.0" + [node name="ToHand" type="Node" parent="StateChart/Root/Planted"] script = ExtResource("6_jpdh0") to = NodePath("../../InHand") event = &"recover" delay_in_seconds = "0.0" - -[node name="WeaponLocationIndicator" type="MeshInstance3D" parent="."] -mesh = SubResource("SphereMesh_jpdh0")