# Hockey Faceoff System Documentation

## Overview
A complete faceoff and puck possession system for your hockey game with realistic physics, visual indicators, and AI-ready mechanics.

---

## 📦 Components Created

### 1. **PuckController.cs**
Controls the puck physics and possession mechanics.

**Features:**
- Realistic hockey puck physics (170g mass, low friction)
- Automatic possession detection via trigger colliders
- Visual feedback (different materials for possessed/free states)
- Smooth carrying while player has possession
- Physics-based shooting and passing

**Key Properties:**
- `possessionRadius`: Distance within which players can pick up the puck (default: 1.5m)
- `carrierOffset`: How far in front of player the puck stays when carried (default: 1.0m)

### 2. **FaceoffManager.cs**
Manages the entire faceoff sequence and outcome determination.

**Faceoff Outcomes:**
- **Home Win**: Home center wins cleanly, puck passed to teammate (usually defender)
- **Away Win**: Away center wins cleanly, puck passed to teammate (usually defender)
- **Struggle**: Close contest, puck bounces loose, scramble ensues

**How Outcomes Are Determined:**
```
Faceoff Strength = (Strength × 0.3) + (Stick Handling × 0.3) + 
                   (Awareness × 0.2) + (Agility × 0.2)
```
Plus random variation (±10 points) for unpredictability.

**Testing:**
Press **F** key during play mode to trigger a faceoff.

### 3. **PlayerController.cs** (Updated)
Enhanced with puck interaction methods.

**New Methods:**
- `GainPuck(PuckController)`: Called when player gains possession
- `ReleasePuck()`: Called when player loses possession
- `CanPickupPuck()`: Checks if player can currently pick up puck
- `SetFrozen(bool)`: Freeze/unfreeze player during faceoff
- `Shoot(direction, power)`: Fire the puck with physics
- `Pass(targetPlayer)`: Pass to specific teammate
- `Check(targetPlayer)`: Body check opponent to dislodge puck

**Visual Feedback:**
- Yellow rotating ring appears around player with possession
- Makes it instantly clear who controls the puck

---

## 🎮 Setup Instructions

### Method 1: Manual Setup

1. **Create the Puck:**
   ```
   - Create GameObject → name it "Puck"
   - Add PuckController component
   - Position at center ice (y ≈ 0.5 for ice level)
   ```

2. **Tag Your Players:**
   ```
   - Edit → Project Settings → Tags & Layers
   - Add tags: "HomeTeam" and "AwayTeam"
   - Select home team players → Inspector → Tag: "HomeTeam"
   - Select away team players → Inspector → Tag: "AwayTeam"
   ```

3. **Create Faceoff Manager:**
   ```
   - Create Empty GameObject → name it "FaceoffManager"
   - Add FaceoffManager component
   - Drag Puck into the "Puck" field in Inspector
   ```

4. **Verify Centers:**
   - Ensure one player on each team has Position = "C" (Center)
   - The FaceoffManager auto-detects centers by tag and position

### Method 2: Auto Setup (Recommended)

1. Create an empty GameObject
2. Add `FaceoffSetupGuide` component
3. Drag home team players into "Home Team Players" array
4. Drag away team players into "Away Team Players" array
5. Right-click component → "Auto-Setup Faceoff System"
6. Right-click component → "Validate Setup" to check everything

---

## 🏒 How It Works

### Possession System

**Puck States:**
- **Loose**: No one has possession, slides freely on ice
- **Carried**: Attached to a player, moves with them

**Gaining Possession:**
Player automatically picks up puck when:
1. Player is within `possessionRadius` (1.5m)
2. Puck is loose (not carried by anyone)
3. Player can pickup (not on cooldown, not frozen)
4. Puck enters player's trigger collider

**Visual Indicator:**
- Yellow ring with emission around player = has puck
- Ring rotates continuously for visibility

### Faceoff Sequence

```
1. FaceoffManager.StartFaceoff() called
   ↓
2. Puck positioned at faceoff spot
   ↓
3. All players frozen (prevent movement)
   ↓
4. Calculate outcome based on center stats
   ↓
5. Execute outcome:
   - Clean Win: Puck passed to defender
   - Struggle: Puck bounces loose
   ↓
6. Unfreeze all players
   ↓
7. Game continues
```

**Timing:**
- Wind-up: 1 second
- Faceoff duration: 2 seconds
- Struggle duration: 3 additional seconds

### Physics Details

**Puck Properties:**
- Mass: 0.17 kg (170g, regulation weight)
- Radius: 0.038m (76mm diameter)
- Friction: 0.3 (simulates ice)
- Bounciness: 0.2 (minimal bounce)

**Force Ranges:**
- Pass: 10-25 N (scales with distance)
- Shot: ~30 N × power stat
- Faceoff launch: 5-15 N

---

## 🎯 Integration Examples

### Example 1: Start Faceoff at Game Start
```csharp
public class GameManager : MonoBehaviour
{
    private FaceoffManager faceoffManager;
    
    void Start()
    {
        faceoffManager = FindObjectOfType<FaceoffManager>();
        
        // Start game with center ice faceoff
        Vector3 centerIce = new Vector3(0, 0.5f, 0);
        faceoffManager.InitiateFaceoff(centerIce);
    }
}
```

### Example 2: Player Shoots on Goal
```csharp
public class PlayerAI : MonoBehaviour
{
    private PlayerController playerController;
    private Transform goal;
    
    void ShootAtGoal()
    {
        if (playerController.HasPuck())
        {
            Vector3 shootDirection = (goal.position - transform.position).normalized;
            playerController.Shoot(shootDirection, powerMultiplier: 1.0f);
        }
    }
}
```

### Example 3: Pass to Open Teammate
```csharp
public void PassToOpenPlayer()
{
    if (!playerController.HasPuck()) return;
    
    PlayerController[] teammates = FindTeammates();
    PlayerController bestTarget = FindMostOpen(teammates);
    
    if (bestTarget != null)
    {
        playerController.Pass(bestTarget);
    }
}
```

### Example 4: Defensive Check
```csharp
void OnCollisionEnter(Collision collision)
{
    PlayerController opponent = collision.gameObject.GetComponent<PlayerController>();
    
    if (opponent != null && opponent.HasPuck() && IsOpponent(opponent))
    {
        playerController.Check(opponent);
    }
}
```

---

## 🔧 Customization

### Adjust Faceoff Difficulty
In `FaceoffManager.cs`:
```csharp
[SerializeField] private float struggleChance = 0.3f; // 30% base struggle chance
[SerializeField] private float winThreshold = 0.7f;    // Higher = more clear wins needed
```

### Change Puck Physics
In `PuckController.cs`:
```csharp
[SerializeField] private float friction = 0.3f;  // Lower = slides further
[SerializeField] private float drag = 0.5f;      // Higher = stops faster
```

### Modify Possession Range
In `PuckController.cs`:
```csharp
[SerializeField] private float possessionRadius = 1.5f; // Detection range
```

---

## 🐛 Troubleshooting

### Puck doesn't get picked up
- Check that player has trigger collider
- Verify `CanPickupPuck()` returns true
- Check pickup cooldown hasn't expired

### Faceoff doesn't start
- Verify both centers are tagged correctly
- Check console for error messages
- Run "Validate Setup" in FaceoffSetupGuide

### Players don't freeze during faceoff
- Ensure PlayerController has `SetFrozen()` method
- Check that player movement script respects frozen state

### Possession indicator doesn't show
- Verify possessionIndicator GameObject is created in PlayerController.Start()
- Check that Update() is being called

---

## 📊 Stats That Matter

### For Faceoffs:
- **Strength** (30%): Physical dominance
- **Stick Handling** (30%): Puck control
- **Awareness** (20%): Reading the drop
- **Agility** (20%): Quick reactions

### For Shooting:
- **Shot Accuracy**: Determines spread angle
- **Shot Power**: Determines puck velocity

### For Passing:
- **Pass Accuracy**: Determines pass precision

### For Checking:
- **Checking**: Success rate of dislodging puck

---

## 🎨 Visual Enhancements (Optional)

### Add Trail to Puck:
```csharp
TrailRenderer trail = puck.gameObject.AddComponent<TrailRenderer>();
trail.time = 0.5f;
trail.startWidth = 0.1f;
trail.endWidth = 0.02f;
```

### Add Particles When Puck is Hit:
```csharp
// In PuckController.OnCollisionEnter()
ParticleSystem.Emit(5); // Ice spray effect
```

### Change Possession Ring Color by Team:
```csharp
if (CompareTag("HomeTeam"))
    possessionIndicator.GetComponent<Renderer>().material.color = Color.blue;
else
    possessionIndicator.GetComponent<Renderer>().material.color = Color.red;
```

---

## 🚀 Next Steps

1. **Add Goalie**: Extend PlayerController for goalie-specific behavior
2. **Implement Offsides**: Check puck/player positions
3. **Add Icing**: Detect long-range clears
4. **Improve AI**: Use puck position in decision-making
5. **Add Penalties**: Faceoff after penalty ends
6. **Post-Goal Faceoffs**: Return to center after scoring

---

## Summary

You now have:
✅ Physics-based puck with realistic ice behavior  
✅ Clear visual indication of possession (yellow ring)  
✅ Faceoff system with 3 outcomes based on player stats  
✅ Ready-to-use shooting, passing, and checking mechanics  
✅ Easy integration with your existing player system  

**Test it:** Press **F** in play mode to see a faceoff in action!
