started building NPC combat

This commit is contained in:
2026-09-29 16:11:54 +01:00
parent be2e7a5824
commit 7486c8d310
4952 changed files with 1093899 additions and 745 deletions

View File

@@ -24,6 +24,13 @@ public class BowAimLayerController : MonoBehaviour
[Tooltip("The Transform socket where the bow rests when put away (e.g., Spine_03)")]
[SerializeField] private Transform _unequippedSocket;
[Header("Stats & Stamina")]
[SerializeField] private PlayerStats _playerStats;
[Tooltip("How much stamina per second is drained while holding the bow string back.")]
[SerializeField] private float _staminaDrainRate = 15f;
[Tooltip("How many seconds you need to hold the bow to reach maximum power and distance.")]
[SerializeField] private float _maxDrawTime = 1.5f;
[Header("Projectile Settings")]
[Tooltip("The arrow prefab to spawn. Make sure it has the Projectile.cs script!")]
[SerializeField] private Projectile _arrowPrefab;
@@ -86,6 +93,9 @@ public class BowAimLayerController : MonoBehaviour
// Are we currently holding the draw button (left click)?
private bool _isDrawing;
private Projectile _loadedArrow;
private float _drawStartTime;
private float _currentPowerMultiplier;
// The current 0-1 blend weight for the bow layer (driven by equip state)
private float _equipWeight;
@@ -208,6 +218,12 @@ public class BowAimLayerController : MonoBehaviour
{
if (_isEquipped) yield break;
if (_currentWeapon == null)
{
Debug.LogWarning("Cannot equip! No bow is assigned.");
yield break;
}
_isEquipped = true;
_animator.Play("Equip", _aimLayer, 0f);
@@ -319,8 +335,43 @@ public class BowAimLayerController : MonoBehaviour
// Start drawing: left click pressed while aiming
if (drawHeld && _isAiming && !_isDrawing)
{
_isDrawing = true;
_animator.SetBool("IsDrawing", true);
// Only allow drawing if stamina is at least 10%
if (_playerStats == null || _playerStats.HasStaminaPercentage(0.10f))
{
_isDrawing = true;
_drawStartTime = Time.time;
_animator.SetBool("IsDrawing", true);
}
}
// While drawing, drain stamina and calculate power
if (_isDrawing)
{
float drawDuration = Time.time - _drawStartTime;
// Starts at a minimum power of 20%, goes up to 100% over maxDrawTime
_currentPowerMultiplier = Mathf.Lerp(0.2f, 1.0f, Mathf.Clamp01(drawDuration / _maxDrawTime));
// Tell the animator we've reached max draw so it can play a Shake animation
bool isMaxPower = drawDuration >= _maxDrawTime;
_animator.SetBool("IsMaxDraw", isMaxPower);
if (_playerStats != null)
{
AnimatorStateInfo stateInfo = _animator.GetCurrentAnimatorStateInfo(_aimLayer);
// Only drain stamina if the string is fully pulled back (in "Drawn" or "Shake" state)
if (stateInfo.IsName("Drawn") || stateInfo.IsName("Shake"))
{
_playerStats.UseStamina(_staminaDrainRate * Time.deltaTime);
// If stamina reaches 0, force the player to release the arrow
if (_playerStats.currentStamina <= 0f)
{
drawHeld = false; // Force release
}
}
}
}
// Release while drawing = fire the arrow
@@ -328,6 +379,7 @@ public class BowAimLayerController : MonoBehaviour
{
_isDrawing = false;
_animator.SetBool("IsDrawing", false);
_animator.SetBool("IsMaxDraw", false);
_animator.SetTrigger("Fire");
}
}
@@ -380,9 +432,18 @@ public class BowAimLayerController : MonoBehaviour
if (_loadedArrow == null) return;
}
// 1. Find where the crosshair is looking
// 1. Find where the crosshair is looking (or auto-aim if locked on)
Vector3 aimPoint;
if (_camera != null)
Synty.AnimationBaseLocomotion.Samples.SamplePlayerAnimationController playerController =
GetComponent<Synty.AnimationBaseLocomotion.Samples.SamplePlayerAnimationController>();
if (playerController != null && playerController.CurrentLockOnTarget != null)
{
// Auto aim directly at the locked on target's chest!
aimPoint = playerController.CurrentLockOnTarget.transform.position + (Vector3.up * 1.2f);
}
else if (_camera != null)
{
Ray ray = _camera.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0));
@@ -412,7 +473,7 @@ public class BowAimLayerController : MonoBehaviour
// 5. Enable the script to start flying!
_loadedArrow.enabled = true;
_loadedArrow.Initialize(damage, _targetLayers);
_loadedArrow.Initialize(damage, _targetLayers, _currentPowerMultiplier);
// Clear the reference so we can load a new one
_loadedArrow = null;