# combat_system.py import random import pygame from settings import * from items import WEAPON_STATS class CombatSystem: def __init__(self, weapon_manager=None): self.weapon_manager = weapon_manager # ========================================================== # SAFE VECTOR HANDLING # ========================================================== def _safe_vec(self, obj): """Ensure we always get a usable Vector2""" try: if isinstance(obj, pygame.Vector2): return obj if hasattr(obj, "x") and hasattr(obj, "y"): return pygame.Vector2(obj.x, obj.y) if isinstance(obj, (list, tuple)) and len(obj) >= 2: return pygame.Vector2(obj[0], obj[1]) except: pass return pygame.Vector2(0, 0) # ========================================================== # PLAYER ATTACK # ========================================================== def player_attack(self, player, enemies): try: if not player or not enemies: return # Get weapon safely weapon_id = None if self.weapon_manager and hasattr(self.weapon_manager, "get_current_weapon"): weapon_id = self.weapon_manager.get_current_weapon() # Default weapon if none weapon_data = WEAPON_STATS.get(weapon_id, {}) damage = weapon_data.get("damage", 5) attack_range = weapon_data.get("range", 60) player_pos = self._safe_vec(getattr(player, "pos", (0, 0))) for enemy in enemies: if not enemy: continue if hasattr(enemy, "alive") and not enemy.alive: continue enemy_pos = self._safe_vec(getattr(enemy, "pos", (0, 0))) distance = (enemy_pos - player_pos).length() if distance <= attack_range: direction = 1 if enemy_pos.x > player_pos.x else -1 # Use proper damage method if exists if hasattr(enemy, "take_damage"): enemy.take_damage(damage, direction) else: # Fallback if hasattr(enemy, "health"): enemy.health -= damage if enemy.health <= 0 and hasattr(enemy, "alive"): enemy.alive = False except Exception as e: print("CombatSystem.player_attack ERROR:", e) # ========================================================== # ENEMY ATTACK # ========================================================== def enemy_attack(self, enemy, player): try: if not enemy or not player: return if hasattr(enemy, "alive") and not enemy.alive: return enemy_pos = self._safe_vec(getattr(enemy, "pos", (0, 0))) player_pos = self._safe_vec(getattr(player, "pos", (0, 0))) attack_range = getattr(enemy, "attack_range", 50) attack_damage = getattr(enemy, "attack_damage", ENEMY_ATTACK_DAMAGE) distance = (enemy_pos - player_pos).length() if distance <= attack_range: direction = 1 if player_pos.x > enemy_pos.x else -1 if hasattr(player, "take_damage"): player.take_damage(attack_damage, direction) else: if hasattr(player, "health"): player.health -= attack_damage except Exception as e: print("CombatSystem.enemy_attack ERROR:", e) # ========================================================== # UPDATE # ========================================================== def update(self, dt): # Keep safe even if dt is weird try: dt = float(dt) except: dt = 0 player.health -= attack_damage print(f"DEBUG: Player took {attack_damage} damage! (HP left: {player.health})") def update(self, dt): """ Updates combat-related state per frame. Currently placeholder for cooldowns or status effects. """ pass