package org.project; import org.project.combat.*; import org.project.entity.enemies.*; import org.project.entity.players.*; import org.project.location.Location; import org.project.managers.*; import java.util.*; public class GameLoop { private final Scanner scanner = new Scanner(System.in); private final ActionDecisionManager actionManager = new ActionDecisionManager(); private final StatusEffectManager statusManager = new StatusEffectManager(); private final SpecialAbilityManager abilityManager = new SpecialAbilityManager(); private final ManaCostManager manaManager = new ManaCostManager(); private final TotalAttackCalculator attackCalculator = new TotalAttackCalculator(statusManager, abilityManager, manaManager); private Player player; private Enemy currentEnemy; private boolean gameRunning = true; private boolean hasGoblinKey; private boolean hasSkeletonKey; private boolean hasVampireKey; private Location currentLocation; private final List locations = new ArrayList<>(); public GameLoop() { initializeLocations(); } private void initializeLocations() { Location valhalla = new Location("Valhalla"); Location elysium = new Location("Elysium"); Location niflheim = new Location("Niflheim"); Location castle = new Location("Castle"); valhalla.connect(elysium); valhalla.connect(niflheim); elysium.connect(niflheim); niflheim.connect(castle); locations.add(valhalla); locations.add(elysium); locations.add(niflheim); locations.add(castle); currentLocation = valhalla; } public void start() { System.out.println("====== JAVA KNIGHT ======"); chooseClass(); spawnEnemy(); while (gameRunning) { showMenu(); } System.out.println("Game Ended."); } private void chooseClass() { System.out.println(""" Choose class: 1. Knight (HP:150 MP:80 DMG:12) 2. Wizard (HP:80 MP:200 DMG:10) 3. Assassin (HP:90 MP:120 DMG:15) """); int choice = scanner.nextInt(); switch (choice) { case 2 -> player = new Wizard("Merlin"); case 3 -> player = new Assassin("Shadow"); default -> player = new Knight("Sir Duncan"); } } private void showMenu() { System.out.println("====" + Colors.YELLOW + " GAME MENU " + Colors.RESET + "===="); System.out.println("Location: " + currentLocation.getName()); if (currentEnemy != null) System.out.println("Enemy: " + currentEnemy); System.out.println(""" \n1. Fight 2. Inventory 3. Move 0. Exit """); if (hasAllKeys()) System.out.println("4. Fight Dragon"); int choice = scanner.nextInt(); switch (choice) { case 1 -> startCombat(); case 2 -> new InventoryManager().displayInventory(player); case 3 -> move(); case 4 -> { if (hasAllKeys()) fightDragon(); } case 0 -> gameRunning = false; } } private void move() { List connected = currentLocation.getConnectedLocations(); if (connected.isEmpty()) { System.out.println("No paths from here."); return; } System.out.println("Choose destination:"); for (int i = 0; i < connected.size(); i++) System.out.println((i + 1) + ". " + connected.get(i).getName()); int choice = scanner.nextInt(); if (choice < 1 || choice > connected.size()) return; currentLocation = connected.get(choice - 1); spawnEnemy(); } private void spawnEnemy() { Enemy[] enemies = { new Goblin(), new Skeleton(), new Vampire() }; currentEnemy = enemies[(int) (Math.random() * enemies.length)]; } private void startCombat() { if (currentEnemy == null) { System.out.println("No enemy here."); return; } System.out.println(Colors.RED_BRIGHT + "⚔ COMBAT STARTED! ⚔" + Colors.RESET); while (player.isLive() && currentEnemy.isLive()) { statusManager.tick(player); statusManager.tick(currentEnemy); abilityManager.tick(currentEnemy, player); abilityManager.tick(player, currentEnemy); if (!player.isLive() || !currentEnemy.isLive()) break; playerTurn(); currentEnemy.resetTurnState(); if (currentEnemy.isLive()) enemyTurn(); player.resetTurnState(); } if (player.isLive()) victory(); else gameRunning = false; } private void playerTurn() { System.out.println("====" + Colors.YELLOW + " YOUR TURN " + Colors.RESET + "===="); System.out.println(player.getName() + "-> HP: " + player.getHp() + " | MP: " + player.getMp() + " | level: " + player.getLevel() + " | XP: " + player.getXp()); System.out.println(currentEnemy.getName() + "-> HP: " + currentEnemy.getHp() + " | MP: " + currentEnemy.getMp()); System.out.println("\n"); var action = actionManager.userChooseAction(); AttackResult result = attackCalculator.calculate(player, currentEnemy, action); int totalDamage = result.getDamageToTarget(); int healAmount = result.getHealSelf(); boolean isDefend = result.isDefended(); if (totalDamage > 0) { System.out.println(currentEnemy.getName() + " got " + totalDamage + " damage"); currentEnemy.takeDamage(totalDamage); } if (healAmount > 0) { player.heal(healAmount); if (player.getHp() < player.getMaxHP()) System.out.println(player.getName() + "healed " + healAmount + " HP"); } if (isDefend) { player.defend(); System.out.println(player.getName() + " will defend (50% damage)"); } System.out.println("\n"); } private void enemyTurn() { System.out.println("====" + Colors.YELLOW + " ENEMY TURN " + Colors.RESET + "====\n"); var action = actionManager.botChooseAction(); System.out.println("enemy random choose action: " + Colors.RED + action + Colors.RESET); AttackResult result = attackCalculator.calculate(currentEnemy, player, action); int totalDamage = result.getDamageToTarget(); int healAmount = result.getHealSelf(); boolean isDefend = result.isDefended(); if (totalDamage > 0) { System.out.println(player.getName() + " got " + totalDamage + " damage"); player.takeDamage(totalDamage); } if (healAmount > 0) { currentEnemy.heal(healAmount); if (currentEnemy.getHp() < currentEnemy.getMaxHP()) System.out.println(currentEnemy.getName() + " healed " + healAmount + " HP"); } if (isDefend) { currentEnemy.defend(); System.out.println(currentEnemy.getName() + " will defend (50% damage)"); } System.out.println("\n"); } private void victory() { System.out.println(Colors.GREEN + "Victory!" + Colors.RESET); currentEnemy.rewardXp(player); checkKeyDrop(); player.restore(); currentEnemy = null; } private void checkKeyDrop() { if (Math.random() * 100 > 20) return; if (currentEnemy instanceof Goblin && !hasGoblinKey) { hasGoblinKey = true; System.out.println("Goblin Key obtained!"); } else if (currentEnemy instanceof Skeleton && ! hasSkeletonKey) { hasSkeletonKey = true; System.out.println("Skeleton Key obtained!"); } else if (currentEnemy instanceof Vampire && !hasVampireKey) { hasVampireKey = true; System.out.println("Vampire Key obtained!"); } } private boolean hasAllKeys() { return hasGoblinKey && hasSkeletonKey && hasVampireKey; } private void fightDragon() { currentEnemy = new Dragon(); System.out.println("The Dragon Appears!"); startCombat(); if (player.isLive()) System.out.println("YOU SAVED JAVANEST!"); else System.out.println("The Dragon has defeated you..."); } }