diff --git a/Assets/Prefabs/Minigames/FortFight/Projectiles/TrashPiece.prefab b/Assets/Prefabs/Minigames/FortFight/Projectiles/TrashPiece.prefab index d7f3edc2..1722222c 100644 --- a/Assets/Prefabs/Minigames/FortFight/Projectiles/TrashPiece.prefab +++ b/Assets/Prefabs/Minigames/FortFight/Projectiles/TrashPiece.prefab @@ -106,8 +106,8 @@ Rigidbody2D: m_UseFullKinematicContacts: 0 m_UseAutoMass: 0 m_Mass: 1 - m_LinearDamping: 0 - m_AngularDamping: 0.05 + m_LinearDamping: 1 + m_AngularDamping: 1 m_GravityScale: 1 m_Material: {fileID: 0} m_IncludeLayers: diff --git a/Assets/Scenes/MiniGames/FortFight.unity b/Assets/Scenes/MiniGames/FortFight.unity index ed953a92..5a5dceb7 100644 --- a/Assets/Scenes/MiniGames/FortFight.unity +++ b/Assets/Scenes/MiniGames/FortFight.unity @@ -2712,7 +2712,7 @@ GameObject: - component: {fileID: 841922114} - component: {fileID: 841922117} - component: {fileID: 841922116} - - component: {fileID: 841922115} + - component: {fileID: 841922118} m_Layer: 0 m_Name: SlingShot m_TagString: Untagged @@ -2737,21 +2737,6 @@ Transform: - {fileID: 1448546925} m_Father: {fileID: 1009687014} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &841922115 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 841922113} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: b1e26667c6d4415f8dc51e4a58ba9479, type: 3} - m_Name: - m_EditorClassIdentifier: AppleHillsScripts::Minigames.FortFight.Core.TrajectoryPreview - simulationSteps: 50 - lineColor: {r: 1, g: 0.92156863, b: 0.015686275, a: 1} - lineWidth: 0.1 --- !u!120 &841922116 LineRenderer: serializedVersion: 2 @@ -2877,8 +2862,25 @@ MonoBehaviour: maxDragDistanceOverride: 0 maxForceOverride: 0 launchAnchor: {fileID: 1668202570} + trajectoryPreview: {fileID: 841922118} showDebugLogs: 1 - trajectoryPreview: {fileID: 841922115} +--- !u!114 &841922118 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 841922113} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b86a4cd82d4a47de9d1e4d97ffd01f5e, type: 3} + m_Name: + m_EditorClassIdentifier: AppleHillsScripts::Common.Visual.TrajectoryPreview + trajectoryPoints: 50 + timeStep: 0.1 + groundLevel: -10 + lineColor: {r: 1, g: 0.92156863, b: 0.015686275, a: 1} + lineWidth: 0.1 --- !u!1 &846792101 GameObject: m_ObjectHideFlags: 0 @@ -4365,7 +4367,7 @@ GameObject: - component: {fileID: 1460473367} - component: {fileID: 1460473370} - component: {fileID: 1460473369} - - component: {fileID: 1460473368} + - component: {fileID: 1460473371} m_Layer: 0 m_Name: SlingShot m_TagString: Untagged @@ -4390,21 +4392,6 @@ Transform: - {fileID: 56461670} m_Father: {fileID: 799036564} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &1460473368 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1460473366} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: b1e26667c6d4415f8dc51e4a58ba9479, type: 3} - m_Name: - m_EditorClassIdentifier: AppleHillsScripts::Minigames.FortFight.Core.TrajectoryPreview - simulationSteps: 30 - lineColor: {r: 1, g: 0.92156863, b: 0.015686275, a: 1} - lineWidth: 0.1 --- !u!120 &1460473369 LineRenderer: serializedVersion: 2 @@ -4530,8 +4517,25 @@ MonoBehaviour: maxDragDistanceOverride: 0 maxForceOverride: 0 launchAnchor: {fileID: 497509525} + trajectoryPreview: {fileID: 1460473371} showDebugLogs: 1 - trajectoryPreview: {fileID: 1460473368} +--- !u!114 &1460473371 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1460473366} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b86a4cd82d4a47de9d1e4d97ffd01f5e, type: 3} + m_Name: + m_EditorClassIdentifier: AppleHillsScripts::Common.Visual.TrajectoryPreview + trajectoryPoints: 50 + timeStep: 0.1 + groundLevel: -10 + lineColor: {r: 1, g: 0.92156863, b: 0.015686275, a: 1} + lineWidth: 0.1 --- !u!1 &1543340062 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/Scripts/Common/Input/DragLaunchController.cs b/Assets/Scripts/Common/Input/DragLaunchController.cs index 370bb959..743769df 100644 --- a/Assets/Scripts/Common/Input/DragLaunchController.cs +++ b/Assets/Scripts/Common/Input/DragLaunchController.cs @@ -6,6 +6,21 @@ using UnityEngine; namespace Common.Input { + /// + /// Cached launch parameters calculated during drag. + /// Avoids recalculating force/direction multiple times. + /// + public struct LaunchParameters + { + public Vector2 Direction; + public float Force; + public float DragDistance; + public float DragRatio; + public float Mass; + + public bool IsValid => Force > 0f && DragDistance > 0f; + } + /// /// Base class for drag-to-launch mechanics (Angry Birds style). /// Provides core drag logic, force calculation, and input handling. @@ -81,6 +96,9 @@ namespace Common.Input [Tooltip("Launch anchor point (spawn/slingshot position)")] [SerializeField] protected Transform launchAnchor; + [Tooltip("Trajectory preview component (auto-found if not assigned)")] + [SerializeField] protected Common.Visual.TrajectoryPreview trajectoryPreview; + [Header("Debug")] [SerializeField] protected bool showDebugLogs; @@ -98,7 +116,10 @@ namespace Common.Input private bool _isDragging; private Vector2 _dragStartPosition; private bool _isEnabled = false; - private bool _isRegistered = false; + private bool _isRegisteredForInput = false; + + // Cached launch parameters - calculated once during drag, used for both preview and launch + private LaunchParameters _cachedLaunchParams; public bool IsDragging => _isDragging; public bool IsEnabled => _isEnabled; @@ -135,10 +156,10 @@ namespace Common.Input _isEnabled = true; // Register with InputManager as override consumer - if (InputManager.Instance != null && !_isRegistered) + if (InputManager.Instance != null && !_isRegisteredForInput) { InputManager.Instance.RegisterOverrideConsumer(this); - _isRegistered = true; + _isRegisteredForInput = true; if (showDebugLogs) Logging.Debug($"[{GetType().Name}] Registered with InputManager"); } @@ -157,10 +178,10 @@ namespace Common.Input _isDragging = false; // Unregister from InputManager - if (InputManager.Instance != null && _isRegistered) + if (InputManager.Instance != null && _isRegisteredForInput) { InputManager.Instance.UnregisterOverrideConsumer(this); - _isRegistered = false; + _isRegisteredForInput = false; if (showDebugLogs) Logging.Debug($"[{GetType().Name}] Unregistered from InputManager"); } @@ -220,29 +241,19 @@ namespace Common.Input /// protected virtual void UpdateDrag(Vector2 currentWorldPosition) { - // Calculate drag vector from anchor to current drag position - // Pull back (away from anchor) = launch forward (toward anchor direction) - Vector2 dragVector = _dragStartPosition - currentWorldPosition; - - // Calculate force and direction - float dragDistance = dragVector.magnitude; - float dragRatio = Mathf.Clamp01(dragDistance / MaxDragDistance); - - // Use config to calculate force with multipliers - float force = Config?.CalculateForce(dragDistance, dragRatio) ?? (dragRatio * MaxForce); - Vector2 direction = dragVector.normalized; - float mass = GetProjectileMass(); + // Calculate launch parameters once and cache + _cachedLaunchParams = CalculateLaunchParameters(currentWorldPosition); // Warn if mass is zero or invalid - if (mass <= 0f && showDebugLogs) + if (_cachedLaunchParams.Mass <= 0f && showDebugLogs) { - Logging.Warning($"[{GetType().Name}] Projectile mass is {mass}! Trajectory calculation will be inaccurate. Override GetProjectileMass()."); + Logging.Warning($"[{GetType().Name}] Projectile mass is {_cachedLaunchParams.Mass}! Trajectory calculation will be inaccurate. Override GetProjectileMass()."); } - // Update visuals with mass parameter - UpdateVisuals(currentWorldPosition, direction, force, dragDistance, mass); + // Update visuals with cached parameters + UpdateVisuals(currentWorldPosition, _cachedLaunchParams); - OnDragUpdate?.Invoke(currentWorldPosition, direction, force); + OnDragUpdate?.Invoke(currentWorldPosition, _cachedLaunchParams.Direction, _cachedLaunchParams.Force); } /// @@ -255,34 +266,48 @@ namespace Common.Input // Hide preview HidePreview(); - // Calculate final launch parameters + // Recalculate final parameters (position may have changed since last UpdateDrag) + _cachedLaunchParams = CalculateLaunchParameters(currentWorldPosition); + + OnDragEnd?.Invoke(currentWorldPosition, _cachedLaunchParams.Direction, _cachedLaunchParams.Force); + + if (showDebugLogs) + Logging.Debug($"[{GetType().Name}] Launching with force {_cachedLaunchParams.Force:F2}"); + PerformLaunch(_cachedLaunchParams.Direction, _cachedLaunchParams.Force); + OnLaunch?.Invoke(_cachedLaunchParams.Direction, _cachedLaunchParams.Force); + } + + /// + /// Calculate launch parameters from current drag position. + /// Caches results to avoid recalculating force multiple times. + /// + private LaunchParameters CalculateLaunchParameters(Vector2 currentWorldPosition) + { + // Calculate drag vector from anchor to current drag position + // Pull back (away from anchor) = launch forward (toward anchor direction) Vector2 dragVector = _dragStartPosition - currentWorldPosition; + + // Calculate distance and ratio float dragDistance = dragVector.magnitude; float dragRatio = Mathf.Clamp01(dragDistance / MaxDragDistance); - // Use config to calculate force with multipliers + // Calculate force using config float force = Config?.CalculateForce(dragDistance, dragRatio) ?? (dragRatio * MaxForce); - Vector2 direction = dragVector.normalized; - // Get minimum force from config - float minForce = Config?.GetMinForce() ?? (MaxForce * 0.1f); + // Normalize direction + Vector2 direction = dragDistance > 0.01f ? dragVector.normalized : Vector2.zero; - if (showDebugLogs) - Logging.Debug($"[{GetType().Name}] Drag ended - Force: {force:F2}, Min: {minForce:F2}, Distance: {dragDistance:F2}"); + // Get mass from projectile + float mass = GetProjectileMass(); - OnDragEnd?.Invoke(currentWorldPosition, direction, force); - - // Launch if force exceeds minimum - if (force >= minForce) + return new LaunchParameters { - if (showDebugLogs) Logging.Debug($"[{GetType().Name}] Launching with force {force:F2}"); - PerformLaunch(direction, force); - OnLaunch?.Invoke(direction, force); - } - else - { - if (showDebugLogs) Logging.Debug($"[{GetType().Name}] Drag too short - force {force:F2} < min {minForce:F2}"); - } + Direction = direction, + Force = force, + DragDistance = dragDistance, + DragRatio = dragRatio, + Mass = mass + }; } #endregion @@ -303,15 +328,23 @@ namespace Common.Input /// Default: Updates trajectory preview using prefab's physics properties. /// Override for custom visuals. /// - protected virtual void UpdateVisuals(Vector2 currentPosition, Vector2 direction, float force, float dragDistance, float mass) + /// Current drag position + /// Cached launch parameters (direction, force, etc.) + protected virtual void UpdateVisuals(Vector2 currentPosition, LaunchParameters launchParams) { - if (trajectoryPreview != null && dragDistance > 0.1f) + if (trajectoryPreview != null && launchParams.DragDistance > 0.1f) { GameObject prefab = GetProjectilePrefab(); - if (prefab != null) - { - trajectoryPreview.UpdateTrajectory(launchAnchor.position, direction, force, prefab); - } + if (prefab == null) return; + + // Get gravity from prefab's Rigidbody2D gravityScale + var rb = prefab.GetComponent(); + float gravityScale = rb != null ? rb.gravityScale : 1f; + float gravity = Physics2D.gravity.magnitude * gravityScale; + + // Use mass from settings (already in launchParams) + trajectoryPreview.UpdateTrajectory(launchAnchor.position, launchParams.Direction, + launchParams.Force, launchParams.Mass, gravity); } } @@ -337,52 +370,14 @@ namespace Common.Input #endregion - #region Virtual Methods - Optional Override + #region Abstract Methods - Physics Configuration /// /// Get projectile mass for trajectory calculation. - /// Reads from the prefab's Rigidbody2D component. - /// Subclasses can override for custom behavior (e.g., if mass changes dynamically). + /// MUST read from settings - the same source that Initialize() uses. + /// Subclasses implement to return the actual runtime mass. /// - protected virtual float GetProjectileMass() - { - GameObject prefab = GetProjectilePrefab(); - if (prefab == null) - { - if (showDebugLogs) - Logging.Warning($"[{GetType().Name}] GetProjectilePrefab() returned null!"); - return 0f; - } - - var rb = prefab.GetComponent(); - if (rb == null) - { - if (showDebugLogs) - Logging.Warning($"[{GetType().Name}] Projectile prefab '{prefab.name}' has no Rigidbody2D!"); - return 0f; - } - - return rb.mass; - } - - /// - /// Get gravity value for trajectory calculation. - /// Uses Physics2D.gravity.magnitude * prefab's Rigidbody2D gravityScale. - /// - protected virtual float GetGravity() - { - GameObject prefab = GetProjectilePrefab(); - if (prefab == null) - { - // Fallback to project gravity - return Physics2D.gravity.magnitude; - } - - var rb = prefab.GetComponent(); - float gravityScale = rb != null ? rb.gravityScale : 1f; - - return Physics2D.gravity.magnitude * gravityScale; - } + protected abstract float GetProjectileMass(); #endregion @@ -393,7 +388,7 @@ namespace Common.Input base.OnManagedDestroy(); // Ensure we unregister from InputManager - if (_isRegistered && InputManager.Instance != null) + if (_isRegisteredForInput && InputManager.Instance != null) { InputManager.Instance.UnregisterOverrideConsumer(this); } diff --git a/Assets/Scripts/Core/Settings/SettingsInterfaces.cs b/Assets/Scripts/Core/Settings/SettingsInterfaces.cs index 4b38f2da..b0857977 100644 --- a/Assets/Scripts/Core/Settings/SettingsInterfaces.cs +++ b/Assets/Scripts/Core/Settings/SettingsInterfaces.cs @@ -251,12 +251,6 @@ namespace AppleHills.Core.Settings int FortBlockLayer { get; } // Layer index for fort blocks int ProjectileLayer { get; } // Layer index for projectiles - // Slingshot Settings - float BaseLaunchForce { get; } // Base launch force multiplier - float MinForceMultiplier { get; } // Minimum force required to launch (0-1) - float MaxForceMultiplier { get; } // Maximum force cap (0-2, usually 1) - float TrajectoryLockDuration { get; } // How long to show trajectory after launch - // Projectile Abilities float VacuumSlideSpeed { get; } // Constant velocity for vacuum sliding (m/s) int VacuumDestroyBlockCount { get; } // Blocks to destroy while sliding diff --git a/Assets/Scripts/Minigames/Airplane/Core/AirplaneController.cs b/Assets/Scripts/Minigames/Airplane/Core/AirplaneController.cs index 6d04d750..ac0c412a 100644 --- a/Assets/Scripts/Minigames/Airplane/Core/AirplaneController.cs +++ b/Assets/Scripts/Minigames/Airplane/Core/AirplaneController.cs @@ -44,12 +44,6 @@ namespace Minigames.Airplane.Core [Tooltip("Gravity multiplier for arc calculation")] [SerializeField] private float gravity = 9.81f; - [Tooltip("Mass of the airplane")] - [SerializeField] private float mass = 1f; - - [Tooltip("Maximum flight time before timeout (seconds)")] - [SerializeField] private float maxFlightTime = 10f; - [Header("Visual")] [Tooltip("Should airplane rotate to face velocity direction?")] [SerializeField] private bool rotateToVelocity = true; @@ -68,6 +62,10 @@ namespace Minigames.Airplane.Core private float flightTimer = 0f; private string lastHitTarget = null; + // Runtime values loaded from settings + private float mass; + private float maxFlightTime; + public bool IsFlying => isFlying; public Vector2 CurrentVelocity => currentVelocity; public string LastHitTarget => lastHitTarget; @@ -80,6 +78,20 @@ namespace Minigames.Airplane.Core { base.OnManagedAwake(); + // Load settings + var settings = GameManager.GetSettingsObject(); + if (settings != null) + { + mass = settings.AirplaneMass; + maxFlightTime = settings.MaxFlightTime; + } + else + { + Logging.Warning("[AirplaneController] AirplaneSettings not found, using defaults!"); + mass = 1f; + maxFlightTime = 10f; + } + // Cache components rb2D = GetComponent(); airplaneCollider = GetComponent(); diff --git a/Assets/Scripts/Minigames/Airplane/Core/AirplaneLaunchController.cs b/Assets/Scripts/Minigames/Airplane/Core/AirplaneLaunchController.cs index fdc41226..0836608d 100644 --- a/Assets/Scripts/Minigames/Airplane/Core/AirplaneLaunchController.cs +++ b/Assets/Scripts/Minigames/Airplane/Core/AirplaneLaunchController.cs @@ -36,6 +36,20 @@ namespace Minigames.Airplane.Core return airplanePrefab; } + protected override float GetProjectileMass() + { + var settings = GameManager.GetSettingsObject(); + if (settings == null) + { + if (showDebugLogs) + Logging.Warning("[AirplaneLaunchController] AirplaneSettings not found!"); + return 1f; // Default fallback + } + + // Read from AirplaneSettings - same mass that AirplaneController uses + return settings.AirplaneMass; + } + #endregion #region Inspector Properties @@ -84,92 +98,8 @@ namespace Minigames.Airplane.Core #region Visual Feedback - protected override void ShowPreview() - { - // Show anchor visual - if (anchorVisual != null) - { - anchorVisual.SetActive(true); - } - - // Show trajectory line (will be updated during drag) - if (trajectoryLine != null) - { - trajectoryLine.enabled = false; // Only show during drag - } - - if (showDebugLogs) Logging.Debug("[AirplaneLaunchController] Preview shown"); - } - - protected override void HidePreview() - { - // Hide anchor visual - if (anchorVisual != null) - { - anchorVisual.SetActive(false); - } - - // Hide trajectory line - if (trajectoryLine != null) - { - trajectoryLine.enabled = false; - } - - if (showDebugLogs) Logging.Debug("[AirplaneLaunchController] Preview hidden"); - } - - protected override void UpdateVisuals(Vector2 currentPosition, Vector2 direction, float force, float dragDistance, float mass) - { - // Show trajectory line during drag - if (trajectoryLine != null && trajectoryLine.enabled == false && dragDistance > 0.1f) - { - trajectoryLine.enabled = true; - } - - // Update trajectory preview - if (trajectoryLine != null && trajectoryLine.enabled) - { - UpdateTrajectoryPreview(direction, force, mass); - } - } - - /// - /// Update the trajectory preview line - /// - private void UpdateTrajectoryPreview(Vector2 direction, float force, float mass) - { - if (trajectoryLine == null) return; - - var config = Config; - if (config == null) return; - - if (mass <= 0f) - { - if (showDebugLogs) Logging.Warning("[AirplaneLaunchController] Cannot calculate trajectory with zero mass!"); - return; - } - - Vector2 startPos = launchAnchor.position; - float initialSpeed = force / mass; - Vector2 velocity = direction * initialSpeed; - - // Get gravity from prefab's Rigidbody2D (Physics2D.gravity.magnitude * rb.gravityScale) - float gravity = GetGravity(); - - trajectoryLine.positionCount = config.trajectoryPoints; - - // Calculate trajectory points using config values - for (int i = 0; i < config.trajectoryPoints; i++) - { - float time = i * config.trajectoryTimeStep; - - // Calculate position at this time - float x = startPos.x + velocity.x * time; - float y = startPos.y + velocity.y * time - 0.5f * gravity * time * time; - - trajectoryLine.SetPosition(i, new Vector3(x, y, 0)); - } - } + // Base class handles trajectory preview via TrajectoryPreview component + // No custom visual feedback needed for airplane - using default implementation #endregion diff --git a/Assets/Scripts/Minigames/FortFight/Core/FortFightSettings.cs b/Assets/Scripts/Minigames/FortFight/Core/FortFightSettings.cs index f9eb1fb8..df9360c9 100644 --- a/Assets/Scripts/Minigames/FortFight/Core/FortFightSettings.cs +++ b/Assets/Scripts/Minigames/FortFight/Core/FortFightSettings.cs @@ -126,21 +126,6 @@ namespace Minigames.FortFight.Core [Tooltip("Downward velocity when dropping (m/s)")] [SerializeField] private float ceilingFanDropSpeed = 20f; - [Header("Slingshot Settings")] - [Tooltip("Base launch force multiplier - higher values = projectiles fly farther")] - [SerializeField] private float baseLaunchForce = 20f; - - [Tooltip("Minimum force multiplier (0-1, e.g. 0.1 = 10% of max force required to launch)")] - [Range(0f, 1f)] - [SerializeField] private float minForceMultiplier = 0.1f; - - [Tooltip("Maximum force multiplier (0-1, e.g. 1.0 = 100% at max drag distance)")] - [Range(0f, 2f)] - [SerializeField] private float maxForceMultiplier = 1f; - - [Tooltip("How long to keep trajectory visible after launching (seconds)")] - [SerializeField] private float trajectoryLockDuration = 2f; - [Header("Physics Layers")] [Tooltip("Layer for fort blocks - projectiles will collide with these (Default: Layer 8 'FortBlock')")] [AppleHills.Core.Settings.Layer] @@ -180,11 +165,6 @@ namespace Minigames.FortFight.Core public Color DamageColorTint => damageColorTint; - public float BaseLaunchForce => baseLaunchForce; - public float MinForceMultiplier => minForceMultiplier; - public float MaxForceMultiplier => maxForceMultiplier; - public float TrajectoryLockDuration => trajectoryLockDuration; - public float VacuumSlideSpeed => vacuumSlideSpeed; public int VacuumDestroyBlockCount => vacuumDestroyBlockCount; public float VacuumBlockDamage => vacuumBlockDamage; diff --git a/Assets/Scripts/Minigames/FortFight/Core/SlingshotController.cs b/Assets/Scripts/Minigames/FortFight/Core/SlingshotController.cs index c13495c1..37e4bc16 100644 --- a/Assets/Scripts/Minigames/FortFight/Core/SlingshotController.cs +++ b/Assets/Scripts/Minigames/FortFight/Core/SlingshotController.cs @@ -16,9 +16,7 @@ namespace Minigames.FortFight.Core { #region Inspector Properties - [Header("FortFight Specific")] - [Tooltip("Trajectory preview component")] - [SerializeField] private TrajectoryPreview trajectoryPreview; + // Note: trajectoryPreview is inherited from DragLaunchController base class #endregion @@ -86,28 +84,13 @@ namespace Minigames.FortFight.Core { base.OnManagedAwake(); - // Base class handles launchAnchor (previously projectileSpawnPoint) - - if (trajectoryPreview == null) - { - trajectoryPreview = GetComponent(); - } + // Base class handles launchAnchor and trajectoryPreview // Set debug logging from developer settings showDebugLogs = CachedDevSettings?.SlingshotShowDebugLogs ?? false; } - internal override void OnManagedStart() - { - base.OnManagedStart(); - - // Hide trajectory by default - if (trajectoryPreview != null) - { - trajectoryPreview.Hide(); - } - } - + #endregion #region Override Methods @@ -129,6 +112,19 @@ namespace Minigames.FortFight.Core LaunchProjectile(direction, force); } + protected override float GetProjectileMass() + { + if (_currentAmmo == null) + { + if (showDebugLogs) + Logging.Warning("[SlingshotController] No ammo selected, cannot get mass!"); + return 1f; // Default fallback + } + + // Read from ProjectileConfig settings - same source as ProjectileBase.Initialize() + return _currentAmmo.mass; + } + #endregion #region Projectile Management @@ -173,7 +169,7 @@ namespace Minigames.FortFight.Core // Lock trajectory to show the shot path if (trajectoryPreview != null) { - float lockDuration = CachedSettings?.TrajectoryLockDuration ?? 2f; + float lockDuration = Config?.trajectoryLockDuration ?? 2f; trajectoryPreview.LockTrajectory(lockDuration); } diff --git a/Assets/Scripts/Minigames/FortFight/Core/TrajectoryPreview.cs b/Assets/Scripts/Minigames/FortFight/Core/TrajectoryPreview.cs deleted file mode 100644 index 264d7690..00000000 --- a/Assets/Scripts/Minigames/FortFight/Core/TrajectoryPreview.cs +++ /dev/null @@ -1,153 +0,0 @@ -using Core; -using UnityEngine; - -namespace Minigames.FortFight.Core -{ - /// - /// Displays trajectory prediction line for projectile launches. - /// Shows dotted line preview of projectile arc. - /// - [RequireComponent(typeof(LineRenderer))] - public class TrajectoryPreview : MonoBehaviour - { - [Header("Trajectory Settings")] - [Tooltip("Number of points to simulate (physics steps)")] - [SerializeField] private int simulationSteps = 50; - - [Header("Visual")] - [Tooltip("Color of trajectory line")] - [SerializeField] private Color lineColor = Color.yellow; - - [Tooltip("Width of trajectory line")] - [SerializeField] private float lineWidth = 0.1f; - - private LineRenderer lineRenderer; - private bool isLocked = false; - private float lockTimer = 0f; - private float lockDuration = 0f; - - private void Awake() - { - lineRenderer = GetComponent(); - - // Configure line renderer - if (lineRenderer != null) - { - lineRenderer.startWidth = lineWidth; - lineRenderer.endWidth = lineWidth; - lineRenderer.startColor = lineColor; - lineRenderer.endColor = lineColor; - lineRenderer.positionCount = simulationSteps; - lineRenderer.enabled = false; - } - } - - private void Update() - { - if (isLocked) - { - lockTimer += Time.deltaTime; - if (lockTimer >= lockDuration) - { - isLocked = false; - Hide(); - } - } - } - - /// - /// Show the trajectory preview - /// - public void Show() - { - if (lineRenderer != null) - { - lineRenderer.enabled = true; - } - } - - /// - /// Hide the trajectory preview (unless locked) - /// - public void Hide() - { - // Don't hide if trajectory is locked - if (isLocked) - return; - - if (lineRenderer != null) - { - lineRenderer.enabled = false; - } - } - - /// - /// Lock the current trajectory display for a duration - /// - public void LockTrajectory(float duration) - { - isLocked = true; - lockTimer = 0f; - lockDuration = duration; - - // Ensure line is visible - if (lineRenderer != null) - { - lineRenderer.enabled = true; - } - } - - /// - /// Update the trajectory preview with new parameters. - /// Uses Physics.fixedDeltaTime for accurate simulation matching Unity's physics. - /// - /// Starting position of trajectory - /// Launch direction (normalized) - /// Launch force (impulse) - /// Projectile mass - public void UpdateTrajectory(Vector2 startPosition, Vector2 direction, float force, float mass = 1f) - { - if (lineRenderer == null) return; - - // Calculate initial velocity: impulse force F gives velocity v = F/m - Vector2 startVelocity = (direction * force) / mass; - - // Get gravity with projectile gravity scale from settings - var settings = GameManager.GetSettingsObject(); - float gravityScale = settings?.ProjectileGravityScale ?? 1f; - Vector2 gravity = new Vector2(Physics2D.gravity.x, Physics2D.gravity.y) * gravityScale; - - // Simulate trajectory using Unity's physics time step - Vector3[] points = new Vector3[simulationSteps]; - Vector2 pos = startPosition; - Vector2 vel = startVelocity; - - for (int i = 0; i < simulationSteps; i++) - { - // Set current position - points[i] = new Vector3(pos.x, pos.y, 0); - - // Update velocity (gravity applied over fixedDeltaTime) - vel = vel + gravity * Time.fixedDeltaTime; - - // Update position (velocity applied over fixedDeltaTime) - pos = pos + vel * Time.fixedDeltaTime; - - // Optional: Stop if hits ground (y < threshold) - if (pos.y < -10f) - { - // Fill remaining points at ground level - for (int j = i + 1; j < simulationSteps; j++) - { - points[j] = new Vector3(pos.x, -10f, 0); - } - break; - } - } - - lineRenderer.positionCount = simulationSteps; - lineRenderer.SetPositions(points); - } - } -} - diff --git a/Assets/Scripts/Minigames/FortFight/Core/TrajectoryPreview.cs.meta b/Assets/Scripts/Minigames/FortFight/Core/TrajectoryPreview.cs.meta deleted file mode 100644 index 453a7a47..00000000 --- a/Assets/Scripts/Minigames/FortFight/Core/TrajectoryPreview.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: b1e26667c6d4415f8dc51e4a58ba9479 -timeCreated: 1764682615 \ No newline at end of file diff --git a/Assets/Settings/FortFightSettings.asset b/Assets/Settings/FortFightSettings.asset index dd3e15f9..18ca7579 100644 --- a/Assets/Settings/FortFightSettings.asset +++ b/Assets/Settings/FortFightSettings.asset @@ -13,15 +13,13 @@ MonoBehaviour: m_Name: FortFightSettings m_EditorClassIdentifier: AppleHillsScripts::Minigames.FortFight.Core.FortFightSettings slingshotSettings: - maxDragDistance: 5 + maxDragDistance: 10 baseLaunchForce: 125 minForceMultiplier: 0.1 maxForceMultiplier: 1 trajectoryPoints: 50 trajectoryTimeStep: 0.1 trajectoryLockDuration: 2 - gravity: 9.81 - defaultProjectileMass: 1 autoRegisterInput: 0 materialConfigs: - material: 0 @@ -119,10 +117,6 @@ MonoBehaviour: ceilingFanActivationDelay: 1 ceilingFanDropDelay: 0.2 ceilingFanDropSpeed: 20 - baseLaunchForce: 150 - minForceMultiplier: 0.1 - maxForceMultiplier: 1 - trajectoryLockDuration: 2 fortBlockLayer: 16 projectileLayer: 15 damageColorTint: {r: 1, g: 0, b: 0, a: 1}