From 869d2ea540bf48c7b24111e7f59570826af24bc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filips=20Kalni=C5=86=C5=A1?= Date: Mon, 16 Mar 2026 07:44:22 +0000 Subject: [PATCH] Update combat_system.py --- combat_system.py | 514 ++++++----------------------------------------- 1 file changed, 58 insertions(+), 456 deletions(-) diff --git a/combat_system.py b/combat_system.py index 193622d..4ee3ef0 100644 --- a/combat_system.py +++ b/combat_system.py @@ -1,459 +1,61 @@ -import pygame +# combat_system.py +import random from settings import * - -from world import World -from player import Player -from camera import Camera -from inventory import Inventory -from enemy_manager import EnemyManager -from menu_system import MainMenu, PauseMenu, NewGameDialog, LoadGameDialog, SettingsMenu, DeathScreen -from save_system import SaveSystem -from weapon_system import WeaponManager -from combat_system import CombatSystem -from hotbar import Hotbar -from items import get_item - - -class Game: - def __init__(self): - pygame.init() - - # ---------------------------------- - # Display Setup - # ---------------------------------- - self.setup_display() - - self.clock = pygame.time.Clock() - self.running = True - self.paused = False - - # ---------------------------------- - # Game State Management - # ---------------------------------- - self.game_state = "menu" - self.show_inventory = False - self.world_name = "Default" - - # ---------------------------------- - # Menu Systems - # ---------------------------------- - self.main_menu = MainMenu(self) - self.new_game_dialog = None - self.load_game_dialog = None - self.pause_menu = None - self.settings_menu = None - self.death_screen = None - self.save_system = SaveSystem() - - # ---------------------------------- - # Core Systems (initialized as None) - # ---------------------------------- - self.world = None - self.player = None - self.camera = None - self.inventory = None - self.enemy_manager = None - self.weapon_manager = None - self.combat_system = None - self.hotbar = None - - # ---------------------------------- - # Debug - # ---------------------------------- - self.font = pygame.font.SysFont("consolas", 18) - - def setup_display(self): - """Setup display with current resolution and fullscreen setting""" - flags = pygame.SCALED - if FULLSCREEN: - flags |= pygame.FULLSCREEN - - self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT), flags) - pygame.display.set_caption(GAME_TITLE) - - def toggle_fullscreen(self): - """Toggle fullscreen mode""" - global FULLSCREEN - FULLSCREEN = not FULLSCREEN - self.setup_display() - - def init_game(self): - """Initialize game systems (called when starting new game or loading)""" - self.world = World() - self.weapon_manager = WeaponManager() - self.player = Player(100, 100, self.weapon_manager) - self.camera = Camera(self.player) - self.inventory = Inventory() - self.hotbar = Hotbar(self.inventory, self.weapon_manager) - self.enemy_manager = EnemyManager(self.world, self.player) - self.combat_system = CombatSystem(self.weapon_manager) - self.show_inventory = False - - # Add starting items and WEAPONS - self.inventory.add_item(ITEM_WOOD, 10) - self.inventory.add_item(ITEM_STONE, 5) - - # Add all weapons to inventory - self.inventory.add_item(ITEM_WOODEN_SWORD, 1) - self.inventory.add_item(ITEM_IRON_SWORD, 1) - self.inventory.add_item(ITEM_GOLD_SWORD, 1) - - # Add weapons to weapon manager - self.weapon_manager.add_weapon(ITEM_WOODEN_SWORD) - self.weapon_manager.add_weapon(ITEM_IRON_SWORD) - self.weapon_manager.add_weapon(ITEM_GOLD_SWORD) - - # ========================================================== - # MAIN LOOP - # ========================================================== - def run(self): - while self.running: - dt = self.clock.tick(FPS) / 1000 - - if self.game_state == "menu": - self.handle_menu_events() - self.update_menu() - self.draw_menu() - - elif self.game_state == "settings": - self.handle_settings_events() - self.settings_menu.update(dt) - self.settings_menu.draw(self.screen) - - elif self.game_state == "new_game_dialog": - self.handle_new_game_dialog_events() - self.new_game_dialog.update(dt) - self.new_game_dialog.draw(self.screen) - - elif self.game_state == "load_game_dialog": - self.handle_load_game_dialog_events() - self.load_game_dialog.update() - self.load_game_dialog.draw(self.screen) - - elif self.game_state == "playing": - self.handle_events() - if not self.paused: - self.update(dt) - self.draw() - - elif self.game_state == "paused": - self.handle_pause_events() - self.pause_menu.update(dt) - self.draw_paused() - - elif self.game_state == "dead": - self.handle_death_events() - self.death_screen.update(dt) - self.draw_dead() - - pygame.quit() - - # ========================================================== - # MAIN MENU STATE - # ========================================================== - def handle_menu_events(self): - action = self.main_menu.handle_events() - - if action == "new_game": - self.new_game_dialog = NewGameDialog(self) - self.game_state = "new_game_dialog" - - elif action == "load_game": - self.load_game_dialog = LoadGameDialog(self, self.save_system) - self.game_state = "load_game_dialog" - - elif action == "settings": - self.settings_menu = SettingsMenu(self) - self.game_state = "settings" - - elif action == "quit": - self.running = False - - def update_menu(self): - self.main_menu.update() - - def draw_menu(self): - self.main_menu.draw(self.screen) - - # ========================================================== - # SETTINGS STATE - # ========================================================== - def handle_settings_events(self): - action = self.settings_menu.handle_events() - - if action == "back": - self.game_state = "menu" - - # ========================================================== - # NEW GAME DIALOG STATE - # ========================================================== - def handle_new_game_dialog_events(self): - action = self.new_game_dialog.handle_events() - - if action and action.startswith("create:"): - world_name = action.replace("create:", "") - self.world_name = world_name - self.init_game() - self.game_state = "playing" - print(f"New game '{world_name}' started") - - elif action == "cancel": - self.game_state = "menu" - - # ========================================================== - # LOAD GAME DIALOG STATE - # ========================================================== - def handle_load_game_dialog_events(self): - action = self.load_game_dialog.handle_events() - - if action and action.startswith("load:"): - save_index = int(action.replace("load:", "")) - saves = self.save_system.get_save_files() - - if 0 <= save_index < len(saves): - save_file = saves[save_index]["name"] - self.init_game() - - if self.save_system.load_game(self, save_file): - self.game_state = "playing" - print(f"Game loaded: {save_file}") - else: - print("Failed to load game") - self.game_state = "load_game_dialog" - - elif action and action.startswith("delete:"): - save_index = int(action.replace("delete:", "")) - saves = self.save_system.get_save_files() - - if 0 <= save_index < len(saves): - save_file = saves[save_index]["name"] - self.save_system.delete_save(save_file) - self.load_game_dialog = LoadGameDialog(self, self.save_system) - - elif action == "cancel": - self.game_state = "menu" - - # ========================================================== - # PAUSE STATE - # ========================================================== - def handle_pause_events(self): - action = self.pause_menu.handle_events() - - if action == "resume": - self.paused = False - self.game_state = "playing" - - elif action == "save": - self.save_system.save_game(self, self.world_name) - self.pause_menu.show_message("Game saved!") - - elif action == "backup": - self.save_system.backup_game(self) - self.pause_menu.show_message("Backup created!") - - elif action == "quit_to_menu": - self.paused = False - self.game_state = "menu" - - def draw_paused(self): - self.screen.fill(BACKGROUND_COLOR) - self.world.draw(self.screen, self.camera) - self.enemy_manager.draw(self.screen, self.camera) - self.player.draw(self.screen, self.camera) - self.pause_menu.draw(self.screen) - - # ========================================================== - # DEATH STATE - # ========================================================== - def handle_death_events(self): - action = self.death_screen.handle_events() - - if action == "respawn": - # Reset player health and position - self.player.health = self.player.max_health - self.player.pos = pygame.Vector2(100, 100) - self.player.rect.x = 100 - self.player.rect.y = 100 - self.player.velocity = pygame.Vector2(0, 0) - self.game_state = "playing" - - elif action == "quit_to_menu": - self.game_state = "menu" - - def draw_dead(self): - self.screen.fill(BACKGROUND_COLOR) - self.world.draw(self.screen, self.camera) - self.enemy_manager.draw(self.screen, self.camera) - self.player.draw(self.screen, self.camera) - self.death_screen.draw(self.screen) - - # ========================================================== - # GAMEPLAY STATE - # ========================================================== - def handle_events(self): - for event in pygame.event.get(): - - if event.type == pygame.QUIT: - self.running = False - - if event.type == pygame.KEYDOWN: - if event.key == pygame.K_ESCAPE: - self.paused = True - self.pause_menu = PauseMenu(self) - self.game_state = "paused" - - # Toggle inventory - if event.key == pygame.K_i: - self.show_inventory = not self.show_inventory - - # Hotbar input - if self.hotbar: - self.hotbar.handle_input(event) - - # Mouse input for attacking and placing - if event.type == pygame.MOUSEBUTTONDOWN: - if self.show_inventory: - continue - - if event.button == 1: # Left click - # Get current held item - items_list = list(self.inventory.slots.items()) - current_item = None - if self.hotbar.selected_slot < len(items_list): - current_item_id, _ = items_list[self.hotbar.selected_slot] - current_item = get_item(current_item_id) - - # Check if holding a weapon - is_holding_weapon = (current_item is not None and - current_item.id in WEAPON_STATS) - - if is_holding_weapon: - # Attack with sword - print(f"DEBUG: Attempting sword attack with {current_item.name}") - self.combat_system.player_attack(self.player, self.enemy_manager.enemies) - else: - # Mine block if not holding weapon - print("DEBUG: Mining block") - self.world.break_block( - pygame.mouse.get_pos(), - self.camera, - self.inventory, - self.player.rect - ) - - if event.button == 3: # Right click - place block - # Get current held item - items_list = list(self.inventory.slots.items()) - if self.hotbar.selected_slot < len(items_list): - current_item_id, _ = items_list[self.hotbar.selected_slot] - current_item = get_item(current_item_id) - - # Only place if it's placeable - if current_item and current_item.placeable: - print(f"DEBUG: Placing {current_item.name}") - self.world.place_block( - pygame.mouse.get_pos(), - self.camera, - self.player.rect, - current_item.place_tile - ) +from items import get_item, ITEMS, WEAPON_STATS + +class CombatSystem: + def __init__(self, weapon_manager): + self.weapon_manager = weapon_manager + + def player_attack(self, player, enemies): + """ + Handles player attack on enemies using the currently equipped weapon. + """ + # Get weapon ID from weapon manager + weapon_id = self.weapon_manager.get_current_weapon() + if weapon_id is None: + print("DEBUG: No weapon equipped") + return + + # Get weapon stats + damage = WEAPON_STATS.get(weapon_id, {}).get("damage", 1) + attack_range = WEAPON_STATS.get(weapon_id, {}).get("range", 50) + + player_pos = player.pos + + # Attack enemies within range + for enemy in enemies: + if not getattr(enemy, "alive", True): + continue # Skip dead enemies + + enemy_pos = enemy.pos + distance = (enemy_pos - player_pos).length() + if distance <= attack_range: + enemy.health -= damage + print(f"DEBUG: {enemy.name if hasattr(enemy,'name') else 'Enemy'} took {damage} damage! (HP left: {enemy.health})") + if enemy.health <= 0: + enemy.alive = False + print(f"DEBUG: {enemy.name if hasattr(enemy,'name') else 'Enemy'} has been defeated!") + + def enemy_attack(self, enemy, player): + """ + Handles enemy attack on player. + """ + if not getattr(enemy, "alive", True): + return + + # Ensure enemy has attack properties + 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: + player.health -= attack_damage + print(f"DEBUG: Player took {attack_damage} damage! (HP left: {player.health})") def update(self, dt): - if self.show_inventory: - return - - self.player.update(dt, self.world) - self.camera.update() - self.enemy_manager.update(dt) - self.combat_system.update(dt) - - # Check if player is dead - if self.player.health <= 0: - self.death_screen = DeathScreen(self) - self.game_state = "dead" - return - - # Enemy AI - attack player - for enemy in self.enemy_manager.enemies: - self.combat_system.enemy_attack(enemy, self.player) - - def draw(self): - self.screen.fill(BACKGROUND_COLOR) - - # Draw world relative to camera - self.world.draw(self.screen, self.camera) - - # Draw entities - self.enemy_manager.draw(self.screen, self.camera) - self.player.draw(self.screen, self.camera) - - # UI - if self.show_inventory: - self.inventory.draw(self.screen) - - # Draw hotbar - if self.hotbar and not self.show_inventory: - self.hotbar.draw(self.screen) - - self.draw_ui() - pygame.display.flip() - - # ========================================================== - # UI / DEBUG - # ========================================================== - def draw_ui(self): - if SHOW_FPS: - fps = self.clock.get_fps() - fps_text = self.font.render(f"FPS: {int(fps)}", True, (255, 255, 255)) - self.screen.blit(fps_text, (10, 10)) - - if DEBUG_MODE: - debug_text = self.font.render( - f"Player: ({int(self.player.rect.x)}, {int(self.player.rect.y)})", - True, - (255, 255, 255) - ) - self.screen.blit(debug_text, (10, 30)) - - world_name_text = self.font.render( - f"World: {self.world_name}", - True, - (255, 255, 255) - ) - self.screen.blit(world_name_text, (10, 50)) - - weapon = self.weapon_manager.get_current_weapon() - if weapon: - weapon_text = self.font.render( - f"Weapon: {weapon.name}", - True, - (255, 255, 255) - ) - self.screen.blit(weapon_text, (10, 70)) - - # Health display - health_text = self.font.render( - f"Health: {int(self.player.health)}/{int(self.player.max_health)}", - True, - (255, 50, 50) - ) - self.screen.blit(health_text, (10, 90)) - - # Enemy count - enemy_text = self.font.render( - f"Enemies: {len(self.enemy_manager.enemies)}", - True, - (255, 100, 100) - ) - self.screen.blit(enemy_text, (10, 110)) - - # Draw currently holding item (top right) - items_list = list(self.inventory.slots.items()) - if self.hotbar and items_list: - current_item_id, current_amount = items_list[self.hotbar.selected_slot] if self.hotbar.selected_slot < len( - items_list) else (None, 0) - if current_item_id: - item = get_item(current_item_id) - if item: - holding_text = self.font.render(f"Holding: {item.name}", True, (255, 255, 255)) - self.screen.blit(holding_text, (SCREEN_WIDTH - 250, 10)) \ No newline at end of file + """ + Updates combat-related state per frame. + Currently placeholder for cooldowns or status effects. + """ + pass \ No newline at end of file