Pārlūkot izejas kodu

Get Enemies attacking.

CartBlanche 2 nedēļas atpakaļ
vecāks
revīzija
37d6724bc1

+ 58 - 20
Shooter/Gameplay/Components/EnemyAI.cs

@@ -162,12 +162,11 @@ public class EnemyAI : EntityComponent
             _health.OnDeath += OnDeath;
             _health.OnDeath += OnDeath;
         }
         }
 
 
+        // Reduced logging - only show critical warnings
         if (_enemyController == null)
         if (_enemyController == null)
         {
         {
-            Console.WriteLine($"[EnemyAI] WARNING: {Owner?.Name} has no EnemyController - ranged attacks disabled");
+            Console.WriteLine($"[EnemyAI] WARNING: {Owner?.Name} has no EnemyController");
         }
         }
-
-        Console.WriteLine($"[EnemyAI] {Owner?.Name} initialized in {_currentState} state (Range: {_detectionRange}, Attack: {_attackRange})");
     }
     }
 
 
     /// <summary>
     /// <summary>
@@ -176,10 +175,28 @@ public class EnemyAI : EntityComponent
     public override void Update(GameTime gameTime)
     public override void Update(GameTime gameTime)
     {
     {
         base.Update(gameTime);
         base.Update(gameTime);
-        
+
+        // Lazy-load target transform if we have a target but no transform cached
+        if (_target != null && _targetTransform == null)
+        {
+            _targetTransform = _target.GetComponent<Transform3D>();
+            if (_targetTransform != null)
+            {
+                Console.WriteLine($"[EnemyAI] {Owner?.Name} successfully loaded target transform");
+            }
+        }
+
         if (_transform == null || _target == null || _targetTransform == null)
         if (_transform == null || _target == null || _targetTransform == null)
+        {
+            // DEBUG: Log why update is skipped (only once per second to avoid spam)
+            if (_stateTimer == 0f || _stateTimer > 1f)
+            {
+                Console.WriteLine($"[EnemyAI] {Owner?.Name} Update skipped - Transform:{_transform != null}, Target:{_target != null}, TargetTransform:{_targetTransform != null}");
+                _stateTimer = 0.01f; // Reset to avoid immediate re-log
+            }
             return;
             return;
-        
+        }
+
         float deltaTime = (float)gameTime.ElapsedGameTime.TotalSeconds;
         float deltaTime = (float)gameTime.ElapsedGameTime.TotalSeconds;
         _stateTimer += deltaTime;
         _stateTimer += deltaTime;
         
         
@@ -216,9 +233,16 @@ public class EnemyAI : EntityComponent
     {
     {
         if (_targetTransform == null || _transform == null)
         if (_targetTransform == null || _transform == null)
             return;
             return;
-        
+
         float distanceToTarget = Vector3.Distance(_transform.Position, _targetTransform.Position);
         float distanceToTarget = Vector3.Distance(_transform.Position, _targetTransform.Position);
-        
+
+        // DEBUG: Log detection checks every 2 seconds
+        if (_stateTimer > 2f)
+        {
+            Console.WriteLine($"[EnemyAI] {Owner?.Name} Idle - Distance:{distanceToTarget:F1}, LOS:{_hasLineOfSight}, Range:{_detectionRange}");
+            _stateTimer = 0f;
+        }
+
         // If player is in range and visible, start chasing
         // If player is in range and visible, start chasing
         if (distanceToTarget <= _detectionRange && _hasLineOfSight)
         if (distanceToTarget <= _detectionRange && _hasLineOfSight)
         {
         {
@@ -316,28 +340,42 @@ public class EnemyAI : EntityComponent
     {
     {
         if (_transform == null || _targetTransform == null)
         if (_transform == null || _targetTransform == null)
             return false;
             return false;
-        
+
         var physicsProvider = ServiceLocator.Get<Core.Plugins.Physics.IPhysicsProvider>();
         var physicsProvider = ServiceLocator.Get<Core.Plugins.Physics.IPhysicsProvider>();
         if (physicsProvider == null)
         if (physicsProvider == null)
             return false;
             return false;
-        
-        Vector3 origin = _transform.Position;
-        Vector3 targetPos = _targetTransform.Position;
-        Vector3 direction = Vector3.Normalize(targetPos - origin);
-        float distance = Vector3.Distance(origin, targetPos);
-        
+
+        // Calculate direction to target
+        Vector3 targetPos = _targetTransform.Position + new Vector3(0, 0.5f, 0);
+        Vector3 toTarget = targetPos - _transform.Position;
+        Vector3 direction = Vector3.Normalize(toTarget);
+        float distance = toTarget.Length();
+
+        // Start raycast from slightly in front of enemy to avoid hitting self
+        // Offset by 1.5 units forward to clear the enemy's collider
+        Vector3 origin = _transform.Position + new Vector3(0, 0.5f, 0) + (direction * 1.5f);
+
+        // Reduce distance by the offset amount
+        float adjustedDistance = distance - 1.5f;
+        if (adjustedDistance <= 0f)
+        {
+            // Target is too close to raycast offset, assume we can see them
+            return true;
+        }
+
         // Raycast toward target
         // Raycast toward target
-        if (physicsProvider.Raycast(origin, direction, distance, out var hit))
+        if (physicsProvider.Raycast(origin, direction, adjustedDistance, out var hit))
         {
         {
-            // Check if we hit the target or something else
+            // We hit something - check if it's the target or an obstacle
             if (hit.Body?.UserData is Entity hitEntity)
             if (hit.Body?.UserData is Entity hitEntity)
             {
             {
                 return hitEntity == _target;
                 return hitEntity == _target;
             }
             }
+            // Hit something that's not an entity (terrain, etc)
             return false;
             return false;
         }
         }
-        
-        // No obstacle in the way
+
+        // No obstacle in the way - clear line of sight
         return true;
         return true;
     }
     }
 
 
@@ -407,7 +445,8 @@ public class EnemyAI : EntityComponent
     /// </summary>
     /// </summary>
     private void OnStateEnter(AIState state)
     private void OnStateEnter(AIState state)
     {
     {
-        Console.WriteLine($"[EnemyAI] {Owner?.Name} entered {state} state");
+        // DEBUG: Track AI state changes
+        Console.WriteLine($"[EnemyAI] {Owner?.Name} -> {state}");
     }
     }
 
 
     /// <summary>
     /// <summary>
@@ -424,7 +463,6 @@ public class EnemyAI : EntityComponent
     private void OnDeath(DamageInfo killingBlow)
     private void OnDeath(DamageInfo killingBlow)
     {
     {
         CurrentState = AIState.Dead;
         CurrentState = AIState.Dead;
-        Console.WriteLine($"[EnemyAI] {Owner?.Name} AI disabled (dead)");
     }
     }
 
 
     /// <summary>
     /// <summary>

+ 5 - 3
Shooter/Gameplay/Components/EnemyController.cs

@@ -41,7 +41,6 @@ public class EnemyController : EntityComponent
     public void SetWeapon(Weapon weapon)
     public void SetWeapon(Weapon weapon)
     {
     {
         _weapon = weapon;
         _weapon = weapon;
-        Console.WriteLine($"[EnemyController] {Owner?.Name} equipped with {weapon?.Name}");
     }
     }
 
 
     /// <summary>
     /// <summary>
@@ -75,8 +74,11 @@ public class EnemyController : EntityComponent
         OrientTowards(targetPosition);
         OrientTowards(targetPosition);
 
 
         // Calculate firing direction
         // Calculate firing direction
-        Vector3 origin = _transform.Position + new Vector3(0, 0.5f, 0); // Offset for weapon height
-        Vector3 direction = Vector3.Normalize(targetPosition - origin);
+        Vector3 direction = Vector3.Normalize(targetPosition - _transform.Position);
+
+        // Offset origin up for weapon height and forward to avoid hitting self
+        // Same offset as line-of-sight check (1.5 units forward)
+        Vector3 origin = _transform.Position + new Vector3(0, 0.5f, 0) + (direction * 1.5f);
 
 
         // Attempt to fire
         // Attempt to fire
         bool didFire = _weapon.TryFire(origin, direction);
         bool didFire = _weapon.TryFire(origin, direction);

+ 5 - 34
Shooter/Platforms/Desktop/Game.cs

@@ -112,14 +112,6 @@ public class ShooterGame : Game
         // _sceneManager.RegisterComponentType<PlayerController>("PlayerController");
         // _sceneManager.RegisterComponentType<PlayerController>("PlayerController");
         
         
         base.Initialize();
         base.Initialize();
-        
-        Console.WriteLine("MonoGame FPS initialized!");
-        Console.WriteLine("Phase 1 services registered:");
-        Console.WriteLine("  - InputService (keyboard, mouse, gamepad)");
-        Console.WriteLine("  - TimeService (delta time, time scaling)");
-        Console.WriteLine("  - AudioService (placeholder for Phase 4)");
-        Console.WriteLine("  - BepuPhysicsProvider (multi-threaded physics)");
-        Console.WriteLine("  - ForwardGraphicsProvider (BasicEffect rendering)");
     }
     }
     
     
     /// <summary>
     /// <summary>
@@ -184,9 +176,7 @@ public class ShooterGame : Game
         // Store player entity reference for later (for weapon firing events)
         // Store player entity reference for later (for weapon firing events)
         _playerEntity = playerEntity;
         _playerEntity = playerEntity;
 
 
-        Console.WriteLine("[Phase 2 Test Scene] Player created with FirstPersonController");
-        Console.WriteLine("  Controls: WASD = Move, Mouse = Look, Space = Jump, Shift = Sprint, Escape = Release Mouse");
-        Console.WriteLine("  Weapons: 1 = Pistol, 2 = Assault Rifle, LMB = Fire, R = Reload");
+        // Player setup complete
         
         
         // Create Ground Plane (large flat box)
         // Create Ground Plane (large flat box)
         var groundEntity = new Core.Entities.Entity("Ground");
         var groundEntity = new Core.Entities.Entity("Ground");
@@ -195,7 +185,6 @@ public class ShooterGame : Game
         groundTransform.LocalScale = new System.Numerics.Vector3(20, 0.5f, 20); // Wide and flat
         groundTransform.LocalScale = new System.Numerics.Vector3(20, 0.5f, 20); // Wide and flat
         var groundRenderer = groundEntity.AddComponent<Core.Components.MeshRenderer>();
         var groundRenderer = groundEntity.AddComponent<Core.Components.MeshRenderer>();
         groundRenderer.SetCube(1.0f, new System.Numerics.Vector4(0.3f, 0.5f, 0.3f, 1.0f)); // Green ground
         groundRenderer.SetCube(1.0f, new System.Numerics.Vector4(0.3f, 0.5f, 0.3f, 1.0f)); // Green ground
-        Console.WriteLine($"[DEBUG] Ground cube material color: {groundRenderer.Material.Color}");
         var groundRigid = groundEntity.AddComponent<Core.Components.Rigidbody>();
         var groundRigid = groundEntity.AddComponent<Core.Components.Rigidbody>();
         groundRigid.BodyType = Core.Plugins.Physics.BodyType.Static;
         groundRigid.BodyType = Core.Plugins.Physics.BodyType.Static;
         groundRigid.Shape = new Core.Plugins.Physics.BoxShape(20, 0.5f, 20);
         groundRigid.Shape = new Core.Plugins.Physics.BoxShape(20, 0.5f, 20);
@@ -217,24 +206,10 @@ public class ShooterGame : Game
         // Initialize the scene
         // Initialize the scene
         scene.Initialize();
         scene.Initialize();
         
         
-        Console.WriteLine($"[DEBUG] Scene has {scene.Entities.Count} entities after initialization");
-        foreach (var ent in scene.Entities)
-        {
-            Console.WriteLine($"[DEBUG]   - {ent.Name}: Active={ent.Active}, ComponentCount={ent.GetType().GetProperty("Components")?.GetValue(ent)}");
-        }
-        
         // Make it the active scene (hacky but works for testing)
         // Make it the active scene (hacky but works for testing)
         var activeSceneField = typeof(SceneManager).GetField("_activeScene", 
         var activeSceneField = typeof(SceneManager).GetField("_activeScene", 
             System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
             System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
         activeSceneField?.SetValue(_sceneManager, scene);
         activeSceneField?.SetValue(_sceneManager, scene);
-        
-        Console.WriteLine("[Phase 2 Test Scene] Created:");
-        Console.WriteLine("  - Player with FPS controller, weapons, health (100 HP), and HUD at (0, 2, 10)");
-        Console.WriteLine("  - Ground plane (20x0.5x20 static box)");
-        Console.WriteLine("  - 2 enemy entities with AI (20 HP, 10 damage melee attacks)");
-        Console.WriteLine("  - 3 pickups (2 health, 1 ammo) with auto-collect");
-        Console.WriteLine("  - Controls: WASD=Move, Mouse=Look, Space=Jump, Shift=Sprint, Esc=Pause");
-        Console.WriteLine("  - Weapons: 1=Pistol, 2=Assault Rifle, LMB=Fire, R=Reload");
     }
     }
     
     
     /// <summary>
     /// <summary>
@@ -311,7 +286,6 @@ public class ShooterGame : Game
 
 
         // Add EnemyController for weapon management
         // Add EnemyController for weapon management
         var enemyController = entity.AddComponent<Gameplay.Components.EnemyController>();
         var enemyController = entity.AddComponent<Gameplay.Components.EnemyController>();
-        enemyController.SetWeapon(eyeLazers);
 
 
         // Add EnemyAI component
         // Add EnemyAI component
         var enemyAI = entity.AddComponent<Gameplay.Components.EnemyAI>();
         var enemyAI = entity.AddComponent<Gameplay.Components.EnemyAI>();
@@ -342,10 +316,11 @@ public class ShooterGame : Game
             // Death effect: disable rigidbody collisions (corpse shouldn't block movement)
             // Death effect: disable rigidbody collisions (corpse shouldn't block movement)
             rigidbody.BodyType = Core.Plugins.Physics.BodyType.Static;
             rigidbody.BodyType = Core.Plugins.Physics.BodyType.Static;
         };
         };
-        
+
         scene.AddEntity(entity);
         scene.AddEntity(entity);
-        
-        Console.WriteLine($"[Test Scene] Created enemy '{name}' at {position} targeting player");
+
+        // Set weapon AFTER entity is added and initialized
+        enemyController.SetWeapon(eyeLazers);
     }
     }
 
 
     /// <summary>
     /// <summary>
@@ -371,7 +346,6 @@ public class ShooterGame : Game
         pickup.PickupRadius = 2.0f;
         pickup.PickupRadius = 2.0f;
 
 
         scene.AddEntity(entity);
         scene.AddEntity(entity);
-        Console.WriteLine($"[Test Scene] Created health pickup '{name}' (+{healAmount} HP) at {position}");
     }
     }
 
 
     /// <summary>
     /// <summary>
@@ -395,7 +369,6 @@ public class ShooterGame : Game
         pickup.PickupRadius = 2.0f;
         pickup.PickupRadius = 2.0f;
 
 
         scene.AddEntity(entity);
         scene.AddEntity(entity);
-        Console.WriteLine($"[Test Scene] Created ammo pickup '{name}' (+{ammoAmount} rounds) at {position}");
     }
     }
 
 
     /// <summary>
     /// <summary>
@@ -1100,8 +1073,6 @@ public class ShooterGame : Game
         
         
         ServiceLocator.Clear();
         ServiceLocator.Clear();
         
         
-        Console.WriteLine("MonoGame FPS shutdown complete");
-        
         base.UnloadContent();
         base.UnloadContent();
     }
     }
 }
 }