|
|
@@ -16,6 +16,15 @@ public class PuckController : MonoBehaviour
|
|
|
[SerializeField] private Material normalMaterial;
|
|
|
[SerializeField] private Material possessedMaterial;
|
|
|
|
|
|
+ [Header("Interception Settings")]
|
|
|
+ [SerializeField] private bool canBeIntercepted = true;
|
|
|
+ [SerializeField] private float interceptionCheckRadius = 0.5f;
|
|
|
+ [SerializeField] private LayerMask playerLayer;
|
|
|
+
|
|
|
+ private bool isPassActive = false;
|
|
|
+ private float passStartTime = 0f;
|
|
|
+ private float passProtectionTime = 0.1f; // Short window where pass can't be intercepted
|
|
|
+
|
|
|
private Rigidbody rb;
|
|
|
private MeshRenderer meshRenderer;
|
|
|
private PlayerController currentCarrier;
|
|
|
@@ -45,21 +54,29 @@ public class PuckController : MonoBehaviour
|
|
|
rb.collisionDetectionMode = CollisionDetectionMode.Continuous;
|
|
|
rb.interpolation = RigidbodyInterpolation.Interpolate;
|
|
|
|
|
|
+ // IMPORTANT: Make sure puck is NOT kinematic at start
|
|
|
+ rb.isKinematic = false;
|
|
|
+
|
|
|
+ // Freeze rotation on X and Z to keep puck flat
|
|
|
+ rb.constraints = RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationZ;
|
|
|
+
|
|
|
// Set up collider if not present
|
|
|
SphereCollider collider = GetComponent<SphereCollider>();
|
|
|
if (collider == null)
|
|
|
{
|
|
|
collider = gameObject.AddComponent<SphereCollider>();
|
|
|
- collider.radius = 0.038f; // ~76mm diameter regulation puck
|
|
|
}
|
|
|
|
|
|
+ collider.radius = 0.038f; // ~76mm diameter regulation puck
|
|
|
+ collider.isTrigger = false; // MUST be false for physics collisions
|
|
|
+
|
|
|
// Create physics material for ice-like behavior
|
|
|
PhysicsMaterial puckPhysicsMaterial = new PhysicsMaterial("PuckPhysics");
|
|
|
puckPhysicsMaterial.dynamicFriction = friction;
|
|
|
puckPhysicsMaterial.staticFriction = friction;
|
|
|
- puckPhysicsMaterial.bounciness = 0.2f;
|
|
|
+ puckPhysicsMaterial.bounciness = 0.1f; // Reduced bounce
|
|
|
puckPhysicsMaterial.frictionCombine = PhysicsMaterialCombine.Minimum;
|
|
|
- puckPhysicsMaterial.bounceCombine = PhysicsMaterialCombine.Average;
|
|
|
+ puckPhysicsMaterial.bounceCombine = PhysicsMaterialCombine.Minimum; // Changed to Minimum
|
|
|
collider.material = puckPhysicsMaterial;
|
|
|
}
|
|
|
|
|
|
@@ -89,10 +106,8 @@ public class PuckController : MonoBehaviour
|
|
|
targetCarryPosition = currentCarrier.transform.position + carrierForward * carrierOffset;
|
|
|
targetCarryPosition.y = 0.025f;
|
|
|
|
|
|
- // Instant positioning while carried (no lerp to prevent lag)
|
|
|
transform.position = targetCarryPosition;
|
|
|
|
|
|
- // Make absolutely sure no velocity while carried
|
|
|
if (rb != null)
|
|
|
{
|
|
|
rb.linearVelocity = Vector3.zero;
|
|
|
@@ -101,6 +116,12 @@ public class PuckController : MonoBehaviour
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
+ // Check for interceptions during passes
|
|
|
+ if (isPassActive && canBeIntercepted)
|
|
|
+ {
|
|
|
+ CheckForInterception();
|
|
|
+ }
|
|
|
+
|
|
|
// Keep puck at proper height on ice when loose
|
|
|
if (transform.position.y < 0.025f)
|
|
|
{
|
|
|
@@ -108,7 +129,6 @@ public class PuckController : MonoBehaviour
|
|
|
pos.y = 0.025f;
|
|
|
transform.position = pos;
|
|
|
|
|
|
- // Dampen vertical velocity
|
|
|
if (rb != null)
|
|
|
{
|
|
|
Vector3 vel = rb.linearVelocity;
|
|
|
@@ -118,16 +138,61 @@ public class PuckController : MonoBehaviour
|
|
|
rb.linearVelocity = vel;
|
|
|
}
|
|
|
|
|
|
- // Dampen excessive spinning
|
|
|
if (rb.angularVelocity.magnitude > 10f)
|
|
|
{
|
|
|
rb.angularVelocity *= 0.9f;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ // End pass if puck has slowed down
|
|
|
+ if (isPassActive && rb != null && rb.linearVelocity.magnitude < 1f)
|
|
|
+ {
|
|
|
+ isPassActive = false;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
+ private void CheckForInterception()
|
|
|
+ {
|
|
|
+ // Skip interception check during protection window
|
|
|
+ if (Time.time - passStartTime < passProtectionTime)
|
|
|
+ return;
|
|
|
|
|
|
+ // Find nearby players
|
|
|
+ Collider[] nearbyColliders = Physics.OverlapSphere(transform.position, interceptionCheckRadius, playerLayer);
|
|
|
+
|
|
|
+ foreach (var col in nearbyColliders)
|
|
|
+ {
|
|
|
+ PlayerController player = col.GetComponent<PlayerController>();
|
|
|
+ if (player != null && player.CanPickupPuck())
|
|
|
+ {
|
|
|
+ // Calculate interception chance based on player stats and positioning
|
|
|
+ float interceptChance = CalculateInterceptionChance(player);
|
|
|
+
|
|
|
+ if (Random.value < interceptChance)
|
|
|
+ {
|
|
|
+ Debug.Log($"{player.stats.playerName} intercepts the pass!");
|
|
|
+ AssignToPlayer(player);
|
|
|
+ isPassActive = false;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ private float CalculateInterceptionChance(PlayerController player)
|
|
|
+ {
|
|
|
+ // Base chance very low (5%)
|
|
|
+ float baseChance = 0.05f;
|
|
|
+
|
|
|
+ // Increase based on awareness and stick handling
|
|
|
+ float statBonus = (player.stats.awareness + player.stats.stickHandling) / 200f * 0.1f;
|
|
|
+
|
|
|
+ // Increase if player is facing the puck
|
|
|
+ Vector3 toPuck = (transform.position - player.transform.position).normalized;
|
|
|
+ float facingBonus = Vector3.Dot(player.transform.forward, toPuck) * 0.05f;
|
|
|
+
|
|
|
+ return Mathf.Clamp01(baseChance + statBonus + facingBonus);
|
|
|
+ }
|
|
|
public void AssignToPlayer(PlayerController player)
|
|
|
{
|
|
|
if (currentCarrier != null)
|
|
|
@@ -180,8 +245,12 @@ public class PuckController : MonoBehaviour
|
|
|
|
|
|
public void ApplyForce(Vector3 force, ForceMode mode = ForceMode.Impulse)
|
|
|
{
|
|
|
- Release(); // Free the puck first
|
|
|
+ Release();
|
|
|
rb.AddForce(force, mode);
|
|
|
+
|
|
|
+ // Mark as active pass
|
|
|
+ isPassActive = true;
|
|
|
+ passStartTime = Time.time;
|
|
|
}
|
|
|
|
|
|
public void SetVelocity(Vector3 velocity)
|
|
|
@@ -213,8 +282,8 @@ public class PuckController : MonoBehaviour
|
|
|
// Physics collision - check if any player can pick up the puck
|
|
|
void OnTriggerStay(Collider other)
|
|
|
{
|
|
|
- // Only auto-pickup if puck is moving slowly (not during passes)
|
|
|
- if (IsLoose && rb != null && rb.linearVelocity.magnitude < 2f)
|
|
|
+ // Only auto-pickup if puck is NOT in active pass and moving slowly
|
|
|
+ if (IsLoose && !isPassActive && rb != null && rb.linearVelocity.magnitude < 2f)
|
|
|
{
|
|
|
PlayerController player = other.GetComponent<PlayerController>();
|
|
|
if (player != null && player.CanPickupPuck())
|