diff --git a/Java-Knight/src/main/java/org/project/Main.java b/Java-Knight/src/main/java/org/project/Main.java index 6bde20e..977d988 100644 --- a/Java-Knight/src/main/java/org/project/Main.java +++ b/Java-Knight/src/main/java/org/project/Main.java @@ -1,15 +1,338 @@ package org.project; -import org.project.location.Location; +import org.project.entity.players.*; +import org.project.entity.enemies.*; +import org.project.location.*; +import org.project.item.weapons.*; +import org.project.item.consumables.*; +import org.project.item.armors.*; import java.util.ArrayList; import java.util.List; +import java.util.Random; +import java.util.Scanner; public class Main { - public static void main(String[] args) { - // TODO: ADD LOCATIONS TO YOUR GAME - List locations = new ArrayList<>(); + private static Scanner scanner = new Scanner(System.in); + private static Random random = new Random(); - // TODO: IMPLEMENT GAMEPLAY + private static Player player; + + //Collected keys + private static boolean hasGoblinKey = false; + private static boolean hasSkeletonKey = false; + private static boolean hasVampireKey = false; + + private static boolean castleUnlocked = false; + + public static void main(String[] args) { + System.out.println("⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️"); + NarrativeConsole.printNormal(" JAVA KNIGHT - THE DRAGON'S CURSE"); + System.out.println("⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️"); + NarrativeConsole.printNormal("\nFor centuries, the land of Javanest lived in peace..."); + NarrativeConsole.printNormal("Until a magical Dragon attacked, plunging the realm into darkness!"); + NarrativeConsole.printNormal("You are the last hope. Gather the 3 keys and slay the Dragon!\n"); + + //Choosing a role + createPlayer(); + + gameLoop(); + } + + private static void createPlayer() { + System.out.println("=".repeat(20)); + System.out.println("CHOOSE YOUR HERO:"); + System.out.println("1. Knight ⚔️ - High damage, strong armor"); + System.out.println("2. Wizard 🧙‍♂️ - High HP, healing spells"); + System.out.println("3. Assassin 🗡️ - High mana, critical strikes"); + System.out.print("\nEnter choice (1-3): "); + + int choice = getIntInput(); + scanner.nextLine(); + + System.out.print("Enter your hero's name: "); + String name = scanner.nextLine(); + + switch (choice) { + case 1: + player = new Knight(name); + break; + case 2: + player = new Wizard(name); + break; + case 3: + player = new Assassin(name); + break; + default: + System.out.println("Invalid choice! Defaulting to Knight."); + player = new Knight(name); + } + + System.out.println("\n✨ " + player.getName() + " the " + + player.getClass().getSimpleName() + " has entered Javanest!"); + NarrativeConsole.printHeal("💚 HP: " + player.getHp() + "/" + player.getMaxHP()); + NarrativeConsole.printMana("💙 MP: " + player.getMp() + "/" + player.getMaxMP()); + System.out.println("\nPress Enter to begin your journey..."); + scanner.nextLine(); + } + + private static void gameLoop() { + boolean gameRunning = true; + boolean firstLocation = true; + + while (gameRunning && player.isAlive()) { + //Entering a new location + if (!firstLocation) { + System.out.println("\n" + "=".repeat(30)); + System.out.println("You move to a new location..."); + } + firstLocation = false; + + Enemy currentEnemy = spawnRandomEnemy(); + NarrativeConsole.printWarning("\n⭕⭕⭕ A " + + currentEnemy.getName(currentEnemy).toUpperCase() + " appears before you! ⭕⭕⭕"); + NarrativeConsole.printWarning("❤️ " + currentEnemy.getName(currentEnemy) + " HP: " + + currentEnemy.getHp() + "/" + currentEnemy.getMaxHP()); + + //Pre-battle menu + boolean locationExited = false; + + while (!locationExited && player.isAlive() && gameRunning) { + displayMainMenu(); + int choice = getIntInput(); + + if (choice == 1) { + //Option 1: Starting the battle + boolean victory = startBattle(currentEnemy); + + if (victory) { + handleVictory(currentEnemy); + locationExited = true; //Moving on the next location + } else { + gameRunning = false; //Player's death + } + + } else if (choice == 2) { + //Option 2: Move to another location1 + System.out.println("\n🚶 You flee to another location..."); + currentEnemy = spawnRandomEnemy(); + NarrativeConsole.printWarning("⭕ A " + currentEnemy.getName(currentEnemy) + + " appears in this new location!"); + + } else if (choice == 3 && castleUnlocked) { + //Option 3: Going to the castle and fight the dragon (only with 3 keys) + System.out.println("\n🏰🏰🏰 YOU STAND BEFORE THE DRAGON'S CASTLE! 🏰🏰🏰"); + System.out.println("The gates slowly open... A massive shadow emerges...\n"); + + boolean victory = startBattle(new Dragon()); + if (victory) { + System.out.println("\n🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉"); + NarrativeConsole.printSuccess(" THE DRAGON IS DEFEATED! YOU SAVED JAVANEST!"); + System.out.println("🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉"); + gameRunning = false; + } else { + NarrativeConsole.printError("\n💀 The Dragon's flames consume you... GAME OVER!"); + gameRunning = false; + } + break; + } + + //Checking the condition for opening the castle + if (hasAllKeys() && !castleUnlocked) { + castleUnlocked = true; + System.out.println("\n🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑"); + NarrativeConsole.printSuccess(" YOU HAVE COLLECTED ALL 3 KEYS!"); + NarrativeConsole.printSuccess("🏰 THE PATH TO THE DRAGON'S CASTLE IS NOW OPEN! 🏰"); + System.out.println("🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑"); + } + + displayKeyProgress(); + + //End game + if (!player.isAlive()) { + NarrativeConsole.printError("\n💀💀💀 GAME OVER! 💀💀💀"); + NarrativeConsole.printError("Your journey ends here. The curse of Javanest remains unbroken..."); + } + } + } + } + + private static void displayMainMenu() { + System.out.println("\n" + "-".repeat(30)); + System.out.println("WHAT WILL YOU DO?"); + System.out.println("1. ⚔️ FIGHT the enemy"); + System.out.println("2. 🚶 MOVE to another location"); + + if (castleUnlocked) { + System.out.println("3. 🏰 GO TO THE CASTLE (Fight the Dragon!)"); + } + System.out.print("\nChoose: "); + } + + private static boolean startBattle(Enemy enemy) { + System.out.println("\n" + "🔥".repeat(30)); + System.out.println(" BATTLE BEGINS!"); + System.out.println("🔥".repeat(30)); + + while (player.isAlive() && enemy.isAlive()) { + displayBattleStatus(enemy); + + playerTurn(enemy); + if (!enemy.isAlive()) { + break; + } + + enemyTurn(enemy); + } + + return player.isAlive(); + } + + private static void playerTurn(Enemy enemy) { + System.out.println("\n" + "-".repeat(30)); + System.out.println("YOUR TURN"); + System.out.println("1. ⚔️ Light Attack (0 Mana)"); + System.out.println("2. 💥 Heavy Attack (-8 Mana)"); + System.out.println("3. 🛡️ Defend (-6 Mana)"); + System.out.println("4. 💚 Heal (-12 Mana)"); + System.out.println("5. ⭐ Special Ability (-15 Mana)"); + System.out.print("Choose action: "); + + int choice = getIntInput(); + + switch (choice) { + case 1: + player.lightAttack(enemy); + break; + case 2: + player.heavyAttack(enemy); + break; + case 3: + player.defend(); + break; + case 4: + player.heal(12); + break; + case 5: + player.specialAbility(enemy); + break; + default: + NarrativeConsole.printWarning("❌ Invalid choice! You hesitate and lose your turn!"); + } + + //Checking the death of enemy + if (!enemy.isAlive()) { + NarrativeConsole.printSuccess("\n💀 " + + enemy.getName(enemy).toUpperCase() + " HAS BEEN DEFEATED! 💀"); + } + } + + private static void enemyTurn(Enemy enemy) { + System.out.println("\n" + "-".repeat(30)); + System.out.println("ENEMY TURN"); + enemy.attack(player); + } + + private static void displayBattleStatus(Enemy enemy) { + System.out.println("\n" + "═".repeat(45)); + System.out.printf("❤️ %s: %d/%d HP | 💙 Mana: %d/%d%n", + player.getName(), player.getHp(), player.getMaxHP(), + player.getMp(), player.getMaxMP()); + System.out.printf("👾 %s: %d/%d HP%n", + enemy.getName(enemy), enemy.getHp(), enemy.getMaxHP()); + System.out.println("═".repeat(45)); + } + + private static Enemy spawnRandomEnemy() { + int roll = random.nextInt(3); // 0, 1, 2 + + switch (roll) { + case 0: + return new Goblin(); + case 1: + return new Skeleton(); + default: + return new Vampire(); + } + } + + private static void handleVictory(Enemy defeatedEnemy) { + NarrativeConsole.printSuccess("\n✨✨✨ VICTORY! ✨✨✨"); + NarrativeConsole.printSuccess(defeatedEnemy.getName(defeatedEnemy).toUpperCase() + + " has been defeated!"); + + //Getting Higher Max HP and MP + player.setMaxHP(player.getMaxHP() + getXpReward(defeatedEnemy)/5); + player.setMaxMP(player.getMaxMP() + getXpReward(defeatedEnemy)/5); + + //Full HP and Mana Recovery (Post-Combat Recovery) + player.setHp(player.getMaxHP()); + player.setMp(player.getMaxMP()); + NarrativeConsole.printHeal("💚 HP and Mana fully restored in higher levels!"); + + //Key Drop (20% chance) + attemptKeyDrop(defeatedEnemy); + } + + private static int getXpReward(Enemy enemy) { + if (enemy instanceof Goblin) return 50; + if (enemy instanceof Skeleton) return 65; + if (enemy instanceof Vampire) return 85; + if (enemy instanceof Dragon) return 300; + return 40; + } + + private static void attemptKeyDrop(Enemy enemy) { + //Checking if we already have this key or not + if (enemy instanceof Goblin && hasGoblinKey) { + return; + } + if (enemy instanceof Skeleton && hasSkeletonKey) { + return; + } + if (enemy instanceof Vampire && hasVampireKey) { + return; + } + + //Dropping the key (20% Chance) + int dropChance = random.nextInt(100); + if (dropChance > 80) { + if (enemy instanceof Goblin) { + hasGoblinKey = true; + NarrativeConsole.printSuccess("\n🔑🔑🔑 YOU FOUND THE GOBLIN KEY! (1/3) 🔑🔑🔑"); + } else if (enemy instanceof Skeleton) { + hasSkeletonKey = true; + NarrativeConsole.printSuccess("\n🔑🔑🔑 YOU FOUND THE SKELETON KEY! (2/3) 🔑🔑🔑"); + } else if (enemy instanceof Vampire) { + hasVampireKey = true; + NarrativeConsole.printSuccess("\n🔑🔑🔑 YOU FOUND THE VAMPIRE KEY! (3/3) 🔑🔑🔑"); + } + } else { + System.out.println("🔑 No key dropped this time... Keep fighting!"); + } + } + + private static boolean hasAllKeys() { + return hasGoblinKey && hasSkeletonKey && hasVampireKey; + } + + private static void displayKeyProgress() { + System.out.println("\n" + "-".repeat(40)); + System.out.println("KEY PROGRESS:"); + System.out.println(" " + (hasGoblinKey ? "👹" : "⬜") + " Goblin Key " + (hasGoblinKey ? "(Obtained)" : "(Missing)")); + System.out.println(" " + (hasSkeletonKey ? "💀" : "⬜") + " Skeleton Key " + (hasSkeletonKey ? "(Obtained)" : "(Missing)")); + System.out.println(" " + (hasVampireKey ? "🦇" : "⬜") + " Vampire Key " + (hasVampireKey ? "(Obtained)" : "(Missing)")); + System.out.println("-".repeat(40)); + } + + private static int getIntInput() { + while (true) { + try { + int input = Integer.parseInt(scanner.nextLine().trim()); + return input; + } catch (NumberFormatException e) { + NarrativeConsole.printWarning("❌ Invalid input! Please enter a number: "); + } + } } } \ No newline at end of file diff --git a/Java-Knight/src/main/java/org/project/entity/Entity.java b/Java-Knight/src/main/java/org/project/entity/Entity.java index 2a060f9..218b7cb 100644 --- a/Java-Knight/src/main/java/org/project/entity/Entity.java +++ b/Java-Knight/src/main/java/org/project/entity/Entity.java @@ -1,7 +1,7 @@ + package org.project.entity; public interface Entity { - void attack(Entity target); void defend(); @@ -15,7 +15,7 @@ public interface Entity { int getMaxMP(); - /* - TODO: ADD OTHER REQUIRED AND BONUS METHODS - */ -} + int getHp(); + + int getMp(); +} \ No newline at end of file diff --git a/Java-Knight/src/main/java/org/project/entity/enemies/Dragon.java b/Java-Knight/src/main/java/org/project/entity/enemies/Dragon.java new file mode 100644 index 0000000..ea8a32c --- /dev/null +++ b/Java-Knight/src/main/java/org/project/entity/enemies/Dragon.java @@ -0,0 +1,78 @@ +package org.project.entity.enemies; + +import org.project.entity.Entity; +import org.project.entity.players.Player; +import org.project.item.weapons.BoneDagger; +import org.project.item.weapons.DragonClaw; +import org.project.location.NarrativeConsole; + +import java.util.Random; + +public class Dragon extends Enemy { + private Random random; + + public Dragon() { + super("Dragon", 150, 100, new DragonClaw()); + this.random = new Random(); + } + + @Override + public void attack(Entity target) { + int chance = random.nextInt(100); + + if (chance > 40) { //Fire breath chance 60% + //Fire breath attack + fireBreath(target); + } else { + //Normal claw attack + normalAttack(target); + } + } + + private void normalAttack(Entity target) { + int damage = 25; + + if (target instanceof Player) { + Player player = (Player) target; + if (player.isDefending()) { + NarrativeConsole.printCombat("🐉 Dragon ignores your pathetic shield!"); + //Complete damage is done + } + } + + target.takeDamage(damage); + NarrativeConsole.printCombat("🐉 Dragon strikes with its claw!"); + NarrativeConsole.printDamage("💥 " + damage + " damage dealt to " + getName(target) + "!"); + } + + private void fireBreath(Entity target) { + int damage = 45; + + NarrativeConsole.printSpecial("🐉🐉🐉 DRAGON BREATHES FIRE! 🐉🐉🐉"); + NarrativeConsole.printSpecial("🔥🔥🔥 FIERY BREATH ENGULFS EVERYTHING! 🔥🔥🔥"); + + if (target instanceof Player) { + Player player = (Player) target; + if (player.isDefending()) { + NarrativeConsole.printSpecial("🛡️ Your shield MELTS under the dragon's breath!"); + NarrativeConsole.printSpecial("🔥 Defense is USELESS against this attack!"); + player.setDefending(false); //The defense is invalid + } + } + + target.takeDamage(damage); + NarrativeConsole.printDamage("💥 " + getName(target) + " takes " + damage + " MASSIVE damage!"); + } + + @Override + public int getMaxHP() { + return 150; + } + + @Override + public int getMaxMP() { + return 100; + } + + +} \ No newline at end of file diff --git a/Java-Knight/src/main/java/org/project/entity/enemies/Enemy.java b/Java-Knight/src/main/java/org/project/entity/enemies/Enemy.java index e019acb..cbc8463 100644 --- a/Java-Knight/src/main/java/org/project/entity/enemies/Enemy.java +++ b/Java-Knight/src/main/java/org/project/entity/enemies/Enemy.java @@ -1,29 +1,100 @@ package org.project.entity.enemies; +import org.project.entity.Entity; +import org.project.item.weapons.Sword; import org.project.item.weapons.Weapon; +import org.project.location.NarrativeConsole; -// TODO: UPDATE IMPLEMENTATION -public abstract class Enemy { +public abstract class Enemy implements Entity { Weapon weapon; private int hp; private int mp; + private boolean isStunned = false; + private int stunTurns = 0; + private String name; + private final int defendCost = 6; + private boolean isDefending = false; + private final int healCost = 12; - public Enemy(int hp, int mp, Weapon weapon) { + public Enemy(String name, int hp, int mp, Weapon weapon) { + this.name = name; this.hp = hp; this.mp = mp; - this.weapon = weapon; } + public abstract void attack(Entity target); + @Override public void takeDamage(int damage) { hp -= damage; } + public void setStunned(boolean stunned) { + this.isStunned = stunned; + if (stunned) { + this.stunTurns = 1; //Stunned in one turn + } + } + + //Decreasing the stunned turns + public void decrementStun() { + if (isStunned) { + stunTurns--; + if (stunTurns <= 0) { + isStunned = false; + } + } + } + + @Override + public void fillMana(int mana) { + int oldMana = mp; + mp += mana; + + mp += mana; + if (mp > getMaxMP()) { + mp = getMaxMP(); + } + } + + @Override + public void defend() { + //checking mana + + //reducing mana + mp -= defendCost; + + //activating defense mode + isDefending = true; + } + + public boolean isStunned() { + return isStunned; + } + public int getHp() { return hp; } + @Override + public void heal(int health) { + //checking mana + if (mp < healCost) { + NarrativeConsole.printWarning("❌ Not enough mana to heal!"); + return; + } + + //reducing mana + mp -= healCost; + + //increasing health + hp += health; + if (hp > getMaxHP()) { + hp = getMaxHP(); + } + } + public int getMp() { return mp; } @@ -31,4 +102,25 @@ public abstract class Enemy { public Weapon getWeapon() { return weapon; } + + public String getName(Entity target) { + if (target instanceof Skeleton) { + return "Skeleton"; + } + else if (target instanceof Goblin) { + return "Goblin"; + } + else if (target instanceof Vampire) { + return "Vampire"; + } + return "Dragon"; + } + + public void setHp(int newHp) { + hp = newHp; + } + + public boolean isAlive() { + return (getHp() > 0); + } } diff --git a/Java-Knight/src/main/java/org/project/entity/enemies/Goblin.java b/Java-Knight/src/main/java/org/project/entity/enemies/Goblin.java new file mode 100644 index 0000000..0b4b65a --- /dev/null +++ b/Java-Knight/src/main/java/org/project/entity/enemies/Goblin.java @@ -0,0 +1,50 @@ +package org.project.entity.enemies; + +import org.project.entity.Entity; +import org.project.item.weapons.BoneDagger; +import org.project.item.weapons.ToothedHook; +import org.project.location.NarrativeConsole; + +import java.util.Random; + +public class Goblin extends Enemy { + private Random random; + + public Goblin() { + super("Goblin", 30, 20, new ToothedHook()); + this.random = new Random(); + } + + @Override + public void attack(Entity target) { + int damage = 10; + boolean isCritical = false; + + //Checking Critical Chance + int chance = random.nextInt(100); + if (chance > 30) { //Critical Chance = 70% + damage *= 2; + isCritical = true; + } + + target.takeDamage(damage); + + if (isCritical) { + NarrativeConsole.printSpecial("💣 Goblin used CRITICAL STRIKE! "); + NarrativeConsole.printDamage("💥 Goblin dealt " + damage + " damage to " + getName(target) + "!"); + } else { + NarrativeConsole.printCombat("👹 Goblin attacked " + getName(target) + "!"); + NarrativeConsole.printDamage("💥 Goblin dealt " + damage + " damage to " + getName(target) + "!"); + } + } + + @Override + public int getMaxHP() { + return 30; + } + + @Override + public int getMaxMP() { + return 20; + } +} diff --git a/Java-Knight/src/main/java/org/project/entity/enemies/Skeleton.java b/Java-Knight/src/main/java/org/project/entity/enemies/Skeleton.java index 8a6a555..148341b 100644 --- a/Java-Knight/src/main/java/org/project/entity/enemies/Skeleton.java +++ b/Java-Knight/src/main/java/org/project/entity/enemies/Skeleton.java @@ -1,6 +1,69 @@ package org.project.entity.enemies; -// TODO: UPDATE IMPLEMENTATION -public class Skeleton { - // TODO: DESIGN ENEMY AND IMPLEMENT THE CONSTRUCTOR -} +import org.project.entity.Entity; +import org.project.item.weapons.BoneDagger; +import org.project.location.NarrativeConsole; + +public class Skeleton extends Enemy { + private boolean hasResurrected = false; + + public Skeleton() { + super("Skeleton", 45, 25, new BoneDagger()); + } + + @Override + public void attack(Entity target) { + int damage = 10; + + target.takeDamage(damage); + + NarrativeConsole.printWarning("💀 Skeleton attacked " + getName(target) + "!"); + NarrativeConsole.printDamage("💥 Skeleton dealt " + damage + " damage to " + + getName(target) + "!"); + } + + @Override + public void takeDamage(int damage) { + int newHp = getHp() - damage; + + if (newHp <= 0 && !hasResurrected) { + //Resurrecting + int resurrectedHp = getMaxHP() * 50 / 100; + setHp(resurrectedHp); + hasResurrected = true; + + NarrativeConsole.printSuccess("💀 Skeleton has been defeated..."); + NarrativeConsole.printSpecial("☠️ But Skeleton rises again! Resurrected with " + + resurrectedHp + " HP!"); + return; + } + + setHp(newHp); + if (getHp() < 0) setHp(0); + + NarrativeConsole.printDamage("💥 Skeleton took " + damage + " damage! HP: " + + getHp() + "/" + getMaxHP()); + + if (getHp() <= 0) { + NarrativeConsole.printSuccess("☠️ Skeleton has been destroyed for good!"); + } + } + + @Override + public int getMaxHP() { + return 45; + } + + @Override + public int getMaxMP() { + return 25; + } + + public boolean hasResurrected() { + return hasResurrected; + } + + public void setHasResurrected(boolean hasResurrected) { + this.hasResurrected = hasResurrected; + } +} \ No newline at end of file diff --git a/Java-Knight/src/main/java/org/project/entity/enemies/Vampire.java b/Java-Knight/src/main/java/org/project/entity/enemies/Vampire.java new file mode 100644 index 0000000..59e4457 --- /dev/null +++ b/Java-Knight/src/main/java/org/project/entity/enemies/Vampire.java @@ -0,0 +1,45 @@ +package org.project.entity.enemies; + +import org.project.entity.Entity; +import org.project.item.weapons.ToothedHook; +import org.project.location.NarrativeConsole; + +public class Vampire extends Enemy { + public Vampire() { + super("Vampire", 50, 40, new ToothedHook()); + } + + @Override + public void attack(Entity target) { + int damage = 12; + + target.takeDamage(damage); + + //Adding to Vampire HP + int healAmount = damage * 30 / 100; + int newHp = getHp() + healAmount; + if (newHp > getMaxHP()) { + newHp = getMaxHP(); + } + setHp(newHp); + + NarrativeConsole.printCombat("🦇 Vampire attacks " + getName(target) + "!"); + NarrativeConsole.printDamage("💥 Dealt " + damage + " damage!"); + NarrativeConsole.printSpecial("🩸 Life steal: Vampire drains " + healAmount + " HP and regenerates!"); + NarrativeConsole.printSpecial("💚 Vampire HP: " + getHp() + "/" + getMaxHP()); + + if (getHp() == getMaxHP()) { + NarrativeConsole.printInfo("🦇 Vampire is fully satiated!"); + } + } + + @Override + public int getMaxHP() { + return 50; + } + + @Override + public int getMaxMP() { + return 40; + } +} \ No newline at end of file diff --git a/Java-Knight/src/main/java/org/project/entity/players/Assassin.java b/Java-Knight/src/main/java/org/project/entity/players/Assassin.java new file mode 100644 index 0000000..708355d --- /dev/null +++ b/Java-Knight/src/main/java/org/project/entity/players/Assassin.java @@ -0,0 +1,95 @@ +package org.project.entity.players; + +import org.project.entity.Entity; +import org.project.entity.enemies.Enemy; +import org.project.item.armors.Armor; +import org.project.item.armors.AssassinMask; +import org.project.item.weapons.Dagger; +import org.project.item.weapons.Weapon; +import org.project.location.NarrativeConsole; + +public class Assassin extends Player implements Entity, ICombatActions { + public Assassin(String name) { + super(name, 45, 60, new Dagger(), new AssassinMask()); + setHp(getMaxHP()); + setMp(getMaxMP()); + } + + @Override + public void specialAbility(Enemy target) { + //Checking if the mana is enough of not + if (getMp() < 15) { + NarrativeConsole.printWarning("❌ Not enough mana for Devastating Spell!"); + return; + } + + //Consuming mana + setMp(getMp()-15); + + setInvisible(true); + setNextAttackCritical(true); + + NarrativeConsole.printSpecial("💜 " + getName() + " turns INVISIBLE!"); + NarrativeConsole.printSpecial("⚡ Next attack will be CRITICAL (2x damage)!"); + NarrativeConsole.printSpecial("🛡️ Will dodge the next incoming attack completely!"); + NarrativeConsole.printMana("💙 Mana left: " + getMp()); + } + + public void lightAttack(Enemy target) { + int damage = 10; + + //Critical Action (if enabled) + if (isNextAttackCritical()) { + damage *= 2; + NarrativeConsole.printSpecial("⚡ CRITICAL HIT! Damage doubled to " + damage + "!"); + setNextAttackCritical(false); + } + + target.takeDamage(damage); + NarrativeConsole.printDamage("⚔️ " + getName() + " used Light Attack! Dealt " + damage + " damage."); + } + + @Override + public void heavyAttack(Enemy target) { + if (getMp() < 8) { + NarrativeConsole.printWarning("❌ Not enough mana for Heavy Attack!"); + return; + } + setMp(getMp() - 8); + int damage = 20; + + //Critical Action (if enabled) + if (isNextAttackCritical()) { + damage *= 2; + NarrativeConsole.printSpecial("⚡ CRITICAL HIT! Damage doubled to " + damage + "!"); + setNextAttackCritical(false); + } + + target.takeDamage(damage); + NarrativeConsole.printDamage("💥 " + getName() + " used Heavy Attack! Dealt " + damage + " damage."); + } + + @Override + public void defend() { + if (getMp() < 6) { + NarrativeConsole.printWarning("❌ Not enough mana to defend!"); + return; + } + setMp(getMp() - 6); + setDefending(true); + NarrativeConsole.printCombat("🛡️ " + getName() + " is defending! Next attack will be halved."); + } + + @Override + public void heal() { + if (getMp() < 12) { + NarrativeConsole.printWarning("❌ Not enough mana to heal!"); + return; + } + setMp(getMp() - 12); + int healAmount = 20; + setHp(getHp() + healAmount); + if (getHp() > getMaxHP()) setHp(getMaxHP()); + NarrativeConsole.printHeal("💚 " + getName() + " healed " + healAmount + " HP!"); + } +} \ No newline at end of file diff --git a/Java-Knight/src/main/java/org/project/entity/players/ICombatActions.java b/Java-Knight/src/main/java/org/project/entity/players/ICombatActions.java new file mode 100644 index 0000000..8d1ea8e --- /dev/null +++ b/Java-Knight/src/main/java/org/project/entity/players/ICombatActions.java @@ -0,0 +1,19 @@ +package org.project.entity.players; + +import org.project.entity.Entity; +import org.project.entity.enemies.Enemy; + +import java.util.ArrayList; + +public interface ICombatActions { + + void lightAttack(Enemy target); + + void heavyAttack(Enemy target); + + void defend(); + + void heal(); + + void specialAbility(Enemy target); +} \ No newline at end of file diff --git a/Java-Knight/src/main/java/org/project/entity/players/Knight.java b/Java-Knight/src/main/java/org/project/entity/players/Knight.java index 14d8fa2..0b78c19 100644 --- a/Java-Knight/src/main/java/org/project/entity/players/Knight.java +++ b/Java-Knight/src/main/java/org/project/entity/players/Knight.java @@ -1,6 +1,81 @@ package org.project.entity.players; -// TODO: UPDATE IMPLEMENTATION -public class Knight { - // TODO: DESIGN KNIGHT'S WEAPON AND ARMOR AND IMPLEMENT THE CONSTRUCTOR +import org.project.entity.Entity; +import org.project.entity.enemies.Enemy; +import org.project.item.armors.Armor; +import org.project.item.armors.KnightArmor; +import org.project.item.weapons.Sword; +import org.project.item.weapons.Weapon; +import org.project.location.NarrativeConsole; + +import java.util.ArrayList; + + +public class Knight extends Player implements ICombatActions { + public Knight(String name) { + super(name, 45, 45, new Sword(), new KnightArmor()); + setHp(getMaxHP()); + setMp(getMaxMP()); + } + + @Override + public void specialAbility(Enemy target) { + //Checking if the mana is enough of not + if (getMp() < 15) { + NarrativeConsole.printWarning("❌ Mana is not enough for Shield Bash!"); + return; + } + + //Consuming mana + setMp(getMp()-15); + + //Stunning the enemies + if (getWeapon() instanceof Sword) { + ((Sword) getWeapon()).uniqueAbility(target); + } + + NarrativeConsole.printSpecial("💥 Shield Bash! Enemy is stunned!"); + } + + public void lightAttack(Enemy target) { + int damage = 10; + target.takeDamage(damage); + NarrativeConsole.printCombat("⚔️ " + getName() + " used Light Attack! Dealt " + damage + " damage."); + } + + @Override + public void heavyAttack(Enemy target) { + if (getMp() < 8) { + NarrativeConsole.printWarning("❌ Mana is not enough for Heavy Attack!"); + return; + } + setMp(getMp() - 8); + int damage = 20; + target.takeDamage(damage); + NarrativeConsole.printDamage("💥 " + getName() + " used Heavy Attack! Dealt " + damage + " damage."); + } + + @Override + public void defend() { + if (getMp() < 6) { + NarrativeConsole.printWarning("❌ Not enough mana to defend!"); + return; + } + setMp(getMp() - 6); + setDefending(true); + NarrativeConsole.printCombat("🛡️ " + getName() + " is defending! Next attack will be halved."); + } + + @Override + public void heal() { + if (getMp() < 12) { + NarrativeConsole.printWarning("❌ Not enough mana to heal!"); + return; + } + setMp(getMp() - 12); + int healAmount = 20; + setHp(getHp() + healAmount); + if (getHp() > getMaxHP()) setHp(getMaxHP()); + NarrativeConsole.printHeal("💚 " + getName() + " healed " + healAmount + " HP!"); + } } diff --git a/Java-Knight/src/main/java/org/project/entity/players/Player.java b/Java-Knight/src/main/java/org/project/entity/players/Player.java index ff5385c..b3d64ef 100644 --- a/Java-Knight/src/main/java/org/project/entity/players/Player.java +++ b/Java-Knight/src/main/java/org/project/entity/players/Player.java @@ -1,11 +1,15 @@ package org.project.entity.players; import org.project.entity.Entity; +import org.project.entity.enemies.Enemy; import org.project.item.armors.Armor; import org.project.item.weapons.Weapon; +import org.project.location.NarrativeConsole; -// TODO: UPDATE IMPLEMENTATION -public abstract class Player { +import java.util.ArrayList; + + +public abstract class Player implements Entity { protected String name; Weapon weapon; Armor armor; @@ -13,34 +17,86 @@ public abstract class Player { private int maxHP; private int mp; private int maxMP; + private final int defendCost = 6; + private boolean isDefending = false; + private final int healCost = 12; + private boolean isInvisible = false; + private boolean nextAttackCritical = false; - public Player(String name, int hp, int mp, Weapon weapon, Armor armor) { + public Player(String name, int maxHP, int maxMP, Weapon weapon, Armor armor) { this.name = name; - this.hp = hp; - this.mp = mp; - + this.maxMP = maxMP; + this.maxHP = maxHP; this.weapon = weapon; this.armor = armor; } - @Override - public void attack(Entity target) { - target.takeDamage(weapon.getDamage()); - } + public abstract void specialAbility(Enemy enemy); + + public abstract void lightAttack(Enemy enemy); + + public abstract void heavyAttack(Enemy enemy); @Override public void defend() { - // TODO - } + //checking mana + if (mp < defendCost) { + NarrativeConsole.printWarning("❌ Not enough mana to defend!"); + return; + } + //reducing mana + mp -= defendCost; + + //activating defense mode + isDefending = true; + + NarrativeConsole.printCombat("🛡️ " + name + " raises shield, preparing to block next attack!"); + } @Override public void takeDamage(int damage) { - hp -= damage - armor.getDefense(); + int actualDamage = damage; + + //reducing damage if the player is in defend mode + if (isDefending()) { + actualDamage = damage / 2; + NarrativeConsole.printCombat("🛡️ Defense reduced damage from " + damage + " to " + actualDamage); + setDefending(false); + } + + if (armor != null && !armor.isBroke()) { + int defense = armor.getDefense(); + actualDamage -= defense; + if (actualDamage < 0) actualDamage = 0; + + armor.reduceDurability(1); + NarrativeConsole.printCombat("🛡️ Armor blocked " + defense + + " damage! Remaining durability: " + armor.getDurability()); + } + + setHp(getHp() - actualDamage); + NarrativeConsole.printDamage("💥 " + getName() + " took " + + actualDamage + " damage! HP: " + getHp()); + + if (getHp() < 0) { + setHp(0); + NarrativeConsole.printDamage("💀 " + getName() + " has been defeated!"); + } } @Override public void heal(int health) { + //checking mana + if (mp < healCost) { + NarrativeConsole.printWarning("❌ Not enough mana to heal!"); + return; + } + + //reducing mana + mp -= healCost; + + //increasing health hp += health; if (hp > maxHP) { hp = maxHP; @@ -49,12 +105,20 @@ public abstract class Player { @Override public void fillMana(int mana) { + int oldMana = mp; + mp += mana; + mp += mana; if (mp > maxMP) { mp = maxMP; } - } + if (mp == maxMP) { + NarrativeConsole.printMana("🩵 Mana is now full! (" + mp + "/" + maxMP + ")"); + } else { + NarrativeConsole.printMana("🩵 Mana increased from " + oldMana + " to " + mp); + } + } public String getName() { return name; @@ -86,4 +150,39 @@ public abstract class Player { return armor; } + public boolean isDefending() { + return isDefending; + } + + public boolean isInvisible() { return isInvisible; } + + public boolean isNextAttackCritical() { return nextAttackCritical; } + + public boolean isAlive() { + return (getHp() != 0); + } + + public void setInvisible(boolean invisible) { this.isInvisible = invisible; } + + public void setNextAttackCritical(boolean critical) { this.nextAttackCritical = critical; } + + public void setHp(int hp) { + this.hp = hp; + } + + public void setMp(int mp) { + this.mp = mp; + } + + public void setDefending(boolean defending) { + isDefending = defending; + } + + public void setMaxHP(int maxHP) { + this.maxHP = maxHP; + } + + public void setMaxMP(int maxMP) { + this.maxMP = maxMP; + } } diff --git a/Java-Knight/src/main/java/org/project/entity/players/Wizard.java b/Java-Knight/src/main/java/org/project/entity/players/Wizard.java new file mode 100644 index 0000000..69094d5 --- /dev/null +++ b/Java-Knight/src/main/java/org/project/entity/players/Wizard.java @@ -0,0 +1,85 @@ +package org.project.entity.players; + +import org.project.entity.Entity; +import org.project.entity.enemies.Enemy; +import org.project.item.armors.Armor; +import org.project.item.armors.AssassinMask; +import org.project.item.armors.WizardRobe; +import org.project.item.weapons.Sword; +import org.project.item.weapons.Wand; +import org.project.item.weapons.Weapon; +import org.project.location.NarrativeConsole; + +public class Wizard extends Player implements Entity,ICombatActions { + public Wizard (String name) { + super(name, 60, 45, new Wand(), new WizardRobe()); + setHp(getMaxHP()); + setMp(getMaxMP()); + } + + @Override + public void specialAbility(Enemy target) { + //Checking if the mana is enough of not + if (getMp() < 15) { + NarrativeConsole.printWarning("❌ Not enough mana for Devastating Spell!"); + return; + } + + //Consuming mana + setMp(getMp()-15); + + target.takeDamage(30); + NarrativeConsole.printSpecial("🔮 " + getName() + "used DEVASTATING SPELL Dealt" + 30 + " damage!"); + + int newHp = getHp() + 10; + if (newHp > getMaxHP()) newHp = getMaxHP(); + setHp(newHp); + + NarrativeConsole.printSpecial("💚 " + getName() + " healed " + 10 + " HP! (Now: " + + getHp() + "/" + getMaxHP() + ")"); + NarrativeConsole.printMana("💙 Mana left: " + getMp()); + } + + public void lightAttack(Enemy target) { + int damage = 10; + target.takeDamage(damage); + NarrativeConsole.printCombat("⚔️ " + getName() + " used Light Attack! Dealt " + damage + " damage."); + } + + @Override + public void heavyAttack(Enemy target) { + if (getMp() < 8) { + NarrativeConsole.printWarning("❌ Not enough mana for Heavy Attack!"); + return; + } + setMp(getMp() - 8); + int damage = 20; + target.takeDamage(damage); + NarrativeConsole.printDamage("💥 " + getName() + " used Heavy Attack! Dealt " + damage + " damage."); + } + + @Override + public void defend() { + if (getMp() < 6) { + NarrativeConsole.printWarning("❌ Not enough mana to defend!"); + return; + } + setMp(getMp() - 6); + setDefending(true); + NarrativeConsole.printCombat("🛡️ " + getName() + " is defending! Next attack will be halved."); + } + + @Override + public void heal() { + if (getMp() < 12) { + NarrativeConsole.printWarning("❌ Not enough mana to heal!"); + return; + } + setMp(getMp() - 12); + int healAmount = 20; + setHp(getHp() + healAmount); + if (getHp() > getMaxHP()) setHp(getMaxHP()); + NarrativeConsole.printHeal("💚 " + getName() + " healed " + healAmount + " HP!"); + } + +} \ No newline at end of file diff --git a/Java-Knight/src/main/java/org/project/item/Item.java b/Java-Knight/src/main/java/org/project/item/Item.java index 6d6b5ad..6f0684d 100644 --- a/Java-Knight/src/main/java/org/project/item/Item.java +++ b/Java-Knight/src/main/java/org/project/item/Item.java @@ -4,8 +4,4 @@ import org.project.entity.Entity; public interface Item { void use(Entity target); - - /* - TODO: ADD OTHER REQUIRED AND BONUS METHODS - */ -} +} \ No newline at end of file diff --git a/Java-Knight/src/main/java/org/project/item/armors/Armor.java b/Java-Knight/src/main/java/org/project/item/armors/Armor.java index 7ca8774..ad078d0 100644 --- a/Java-Knight/src/main/java/org/project/item/armors/Armor.java +++ b/Java-Knight/src/main/java/org/project/item/armors/Armor.java @@ -1,31 +1,55 @@ package org.project.item.armors; -// TODO: UPDATE IMPLEMENTATION -public abstract class Armor { +import org.project.entity.Entity; +import org.project.item.Item; + +public abstract class Armor implements Item { private int defense; private int maxDefense; private int durability; private int maxDurability; - - private boolean isBroke; + public boolean isBroke; public Armor(int defense, int durability) { this.defense = defense; this.durability = durability; + this.maxDefense = defense; + this.maxDurability = durability; + this.isBroke = false; } - public void checkBreak() { + public boolean checkBreak() { if (durability <= 0) { isBroke = true; defense = 0; + durability = 0; + System.out.println("Armor is broken!"); + } + return isBroke; + } + + public void repair() { + if (isBroke) { + isBroke = false; + defense = maxDefense; + durability = maxDurability; + System.out.println("🔧 Armor repaired! Defense: " + defense + ", Durability: " + durability); + } + else { + System.out.println("Armor is not broken. No need to repair."); } } - // TODO: (BONUS) UPDATE THE REPAIR METHOD - public void repair() { - isBroke = false; - defense = maxDefense; - durability = maxDurability; + public void reduceDurability(int amount) { + if (!isBroke) { + durability -= amount; + checkBreak(); + } + } + + @Override + public void use(Entity target) { + System.out.println("🛡️ " + getClass().getSimpleName() + " equipped. Defense: " + defense); } public int getDefense() { @@ -39,4 +63,8 @@ public abstract class Armor { public boolean isBroke() { return isBroke; } + + public void setDefense(int defense) { + this.defense = defense; + } } diff --git a/Java-Knight/src/main/java/org/project/item/armors/AssassinMask.java b/Java-Knight/src/main/java/org/project/item/armors/AssassinMask.java new file mode 100644 index 0000000..9fe7ae3 --- /dev/null +++ b/Java-Knight/src/main/java/org/project/item/armors/AssassinMask.java @@ -0,0 +1,7 @@ +package org.project.item.armors; + +public class AssassinMask extends Armor { + public AssassinMask() { + super(4, 20); + } +} \ No newline at end of file diff --git a/Java-Knight/src/main/java/org/project/item/armors/KnightArmor.java b/Java-Knight/src/main/java/org/project/item/armors/KnightArmor.java index eb59a46..77d79ef 100644 --- a/Java-Knight/src/main/java/org/project/item/armors/KnightArmor.java +++ b/Java-Knight/src/main/java/org/project/item/armors/KnightArmor.java @@ -1,6 +1,8 @@ package org.project.item.armors; -// TODO: UPDATE IMPLEMENTATION -public class KnightArmor { - // TODO: DESIGN ARMOR'S ATTRIBUTES IMPLEMENT THE CONSTRUCTOR +//The knight's armor +public class KnightArmor extends Armor { + public KnightArmor() { + super(5, 25); + } } \ No newline at end of file diff --git a/Java-Knight/src/main/java/org/project/item/armors/WizardRobe.java b/Java-Knight/src/main/java/org/project/item/armors/WizardRobe.java new file mode 100644 index 0000000..14fa971 --- /dev/null +++ b/Java-Knight/src/main/java/org/project/item/armors/WizardRobe.java @@ -0,0 +1,8 @@ +package org.project.item.armors; + +//The Wizard's armor +public class WizardRobe extends Armor { + public WizardRobe() { + super(3, 15); + } +} \ No newline at end of file diff --git a/Java-Knight/src/main/java/org/project/item/consumables/Consumable.java b/Java-Knight/src/main/java/org/project/item/consumables/Consumable.java index 028e13d..81fb69d 100644 --- a/Java-Knight/src/main/java/org/project/item/consumables/Consumable.java +++ b/Java-Knight/src/main/java/org/project/item/consumables/Consumable.java @@ -1,8 +1,28 @@ package org.project.item.consumables; -// TODO: UPDATE IMPLEMENTATION -public abstract class Consumable { - /* - TODO: ADD OTHER REQUIRED AND BONUS METHODS - */ -} +import org.project.item.Item; + +public abstract class Consumable implements Item { + protected String name; + protected int healingPercent; + + public Consumable(String name) { + this.name = name; + } + + public Consumable(String name, int healingPercent) { + this(name); + this.healingPercent = healingPercent; + } + + public String getName() { + return name; + } + + public int getHealingPercent() { + return healingPercent; + } + + @Override + public abstract void use(org.project.entity.Entity target); +} \ No newline at end of file diff --git a/Java-Knight/src/main/java/org/project/item/consumables/Flask.java b/Java-Knight/src/main/java/org/project/item/consumables/Flask.java index c0e7a6d..d5add2f 100644 --- a/Java-Knight/src/main/java/org/project/item/consumables/Flask.java +++ b/Java-Knight/src/main/java/org/project/item/consumables/Flask.java @@ -1,16 +1,38 @@ package org.project.item.consumables; import org.project.entity.Entity; +import org.project.location.NarrativeConsole; -// TODO: UPDATE IMPLEMENTATION -public class Flask { - /* - THIS IS AN EXAMPLE OF A CONSUMABLE DESIGN. - */ +public class Flask extends Consumable { + public Flask(String name, int healingPercent) { + super(name , healingPercent); + } - // TODO: UPDATE USE METHOD @Override public void use(Entity target) { - target.heal(target.getMaxHP() / 10); + //Checking if the target is alive + if (target == null || target.getHp() <= 0) { + NarrativeConsole.printWarning("❌ Target is dead already!"); + return; + } + + int healAmount = target.getMaxHP() * healingPercent / 100; + if (healAmount < 10) { + healAmount = 10; + } + + int oldHp = target.getHp(); + target.heal(healAmount); + int actualHeal = target.getHp() - oldHp; + + NarrativeConsole.printHeal("🧪🧪🧪 ============== 🧪🧪🧪"); + NarrativeConsole.printHeal("💚 " + getName() + " drinks the Healing Flask!"); + NarrativeConsole.printHeal("✨ Restored " + actualHeal + " HP!"); + NarrativeConsole.printHeal("💚 HP: " + target.getHp() + "/" + target.getMaxHP()); + + if (target.getHp() == target.getMaxHP()) { + NarrativeConsole.printHeal("💪 " + getName() + " is fully healed!"); + } + NarrativeConsole.printHeal("🧪🧪🧪 ============== 🧪🧪🧪"); } -} +} \ No newline at end of file diff --git a/Java-Knight/src/main/java/org/project/item/consumables/GreatFlask.java b/Java-Knight/src/main/java/org/project/item/consumables/GreatFlask.java new file mode 100644 index 0000000..8ac8051 --- /dev/null +++ b/Java-Knight/src/main/java/org/project/item/consumables/GreatFlask.java @@ -0,0 +1,7 @@ +package org.project.item.consumables; + +public class GreatFlask extends Flask { + public GreatFlask() { + super("Great Flask", 50); //50% healing + } +} diff --git a/Java-Knight/src/main/java/org/project/item/consumables/HealthFlask.java b/Java-Knight/src/main/java/org/project/item/consumables/HealthFlask.java new file mode 100644 index 0000000..1273ad0 --- /dev/null +++ b/Java-Knight/src/main/java/org/project/item/consumables/HealthFlask.java @@ -0,0 +1,7 @@ +package org.project.item.consumables; + +public class HealthFlask extends Flask { + public HealthFlask() { + super("Health Flask",25); //25% healing + } +} \ No newline at end of file diff --git a/Java-Knight/src/main/java/org/project/item/consumables/ManaFlask.java b/Java-Knight/src/main/java/org/project/item/consumables/ManaFlask.java new file mode 100644 index 0000000..0041f3f --- /dev/null +++ b/Java-Knight/src/main/java/org/project/item/consumables/ManaFlask.java @@ -0,0 +1,21 @@ +package org.project.item.consumables; + +import org.project.entity.Entity; +import org.project.entity.players.Player; +import org.project.location.NarrativeConsole; + +public class ManaFlask extends Flask { + public ManaFlask() { + super("Mana Flask",30); //30% mana increasing + } + + @Override + public void use(Entity target) { + if (target instanceof Player) { + Player player = (Player) target; + int manaAmount = player.getMaxMP() / 3; + player.setMp(Math.min(player.getMp() + manaAmount, player.getMaxMP())); + NarrativeConsole.printMana("💙 Restored " + manaAmount + " Mana!"); + } + } +} \ No newline at end of file diff --git a/Java-Knight/src/main/java/org/project/item/weapons/BoneDagger.java b/Java-Knight/src/main/java/org/project/item/weapons/BoneDagger.java new file mode 100644 index 0000000..cc92cf8 --- /dev/null +++ b/Java-Knight/src/main/java/org/project/item/weapons/BoneDagger.java @@ -0,0 +1,8 @@ +package org.project.item.weapons; + +//The skeleton's weapon +public class BoneDagger extends Weapon { + public BoneDagger() { + super(10, 5); + } +} \ No newline at end of file diff --git a/Java-Knight/src/main/java/org/project/item/weapons/Dagger.java b/Java-Knight/src/main/java/org/project/item/weapons/Dagger.java new file mode 100644 index 0000000..62e5c84 --- /dev/null +++ b/Java-Knight/src/main/java/org/project/item/weapons/Dagger.java @@ -0,0 +1,12 @@ +package org.project.item.weapons; + +import org.project.item.Item; + +//The assassin's weapon +public class Dagger extends Weapon { + int abilityCharge; + + public Dagger() { + super(15, 10); + } +} \ No newline at end of file diff --git a/Java-Knight/src/main/java/org/project/item/weapons/DragonClaw.java b/Java-Knight/src/main/java/org/project/item/weapons/DragonClaw.java new file mode 100644 index 0000000..3908eae --- /dev/null +++ b/Java-Knight/src/main/java/org/project/item/weapons/DragonClaw.java @@ -0,0 +1,8 @@ +package org.project.item.weapons; + +//The dragon's weapon +public class DragonClaw extends Weapon { + public DragonClaw() { + super(25, 20); + } +} \ No newline at end of file diff --git a/Java-Knight/src/main/java/org/project/item/weapons/Rapier.java b/Java-Knight/src/main/java/org/project/item/weapons/Rapier.java new file mode 100644 index 0000000..675ae77 --- /dev/null +++ b/Java-Knight/src/main/java/org/project/item/weapons/Rapier.java @@ -0,0 +1,8 @@ +package org.project.item.weapons; + +//The vampire's weapon +public class Rapier extends Weapon { + public Rapier() { + super(20, 10); + } +} \ No newline at end of file diff --git a/Java-Knight/src/main/java/org/project/item/weapons/Sword.java b/Java-Knight/src/main/java/org/project/item/weapons/Sword.java index 96226ee..2cbf432 100644 --- a/Java-Knight/src/main/java/org/project/item/weapons/Sword.java +++ b/Java-Knight/src/main/java/org/project/item/weapons/Sword.java @@ -1,26 +1,32 @@ package org.project.item.weapons; import org.project.entity.Entity; +import org.project.entity.enemies.Enemy; +import org.project.item.Item; import java.util.ArrayList; -// TODO: UPDATE IMPLEMENTATION -public class Sword { - /* - THIS IS AN EXAMPLE OF A WEAPON DESIGN. - */ - - int abilityCharge; +//The knight's weapon +public class Sword extends Weapon { + private int abilityCharge; public Sword() { - // TODO: DESIGN SWORD'S ATTRIBUTES IMPLEMENT THE CONSTRUCTOR + super(10, 8); + this.abilityCharge = 0; } - // TODO: (BONUS) UPDATE THE UNIQUE ABILITY - public void uniqueAbility(ArrayList targets) { + //Bonus method + public void uniqueAbility(Entity target) { abilityCharge += 2; - for (Entity target : targets) { - target.takeDamage(getDamage()); + int totalDamage = getDamage() + (abilityCharge / 2); + + target.takeDamage(totalDamage); + if (target instanceof Enemy) { + ((Enemy) target).setStunned(true); } } -} + + public int getAbilityCharge() { + return abilityCharge; + } +} \ No newline at end of file diff --git a/Java-Knight/src/main/java/org/project/item/weapons/ToothedHook.java b/Java-Knight/src/main/java/org/project/item/weapons/ToothedHook.java new file mode 100644 index 0000000..f9ad15b --- /dev/null +++ b/Java-Knight/src/main/java/org/project/item/weapons/ToothedHook.java @@ -0,0 +1,8 @@ +package org.project.item.weapons; + +//The goblin's weapon +public class ToothedHook extends Weapon { + public ToothedHook() { + super(15, 6); + } +} \ No newline at end of file diff --git a/Java-Knight/src/main/java/org/project/item/weapons/Wand.java b/Java-Knight/src/main/java/org/project/item/weapons/Wand.java new file mode 100644 index 0000000..4440e86 --- /dev/null +++ b/Java-Knight/src/main/java/org/project/item/weapons/Wand.java @@ -0,0 +1,10 @@ +package org.project.item.weapons; + +//The wizard's weapon +public class Wand extends Weapon{ + int abilityCharge; + + public Wand() { + super(12, 6); + } +} \ No newline at end of file diff --git a/Java-Knight/src/main/java/org/project/item/weapons/Weapon.java b/Java-Knight/src/main/java/org/project/item/weapons/Weapon.java index cb9fcf2..16b5a95 100644 --- a/Java-Knight/src/main/java/org/project/item/weapons/Weapon.java +++ b/Java-Knight/src/main/java/org/project/item/weapons/Weapon.java @@ -1,16 +1,12 @@ package org.project.item.weapons; import org.project.entity.Entity; +import org.project.item.Item; -// TODO: UPDATE IMPLEMENTATION -public abstract class Weapon { +public abstract class Weapon implements Item { private int damage; private int manaCost; - /* - TODO: ADD OTHER REQUIRED AND BONUS ATTRIBUTES - */ - public Weapon(int damage, int manaCost) { this.damage = damage; this.manaCost = manaCost; @@ -29,7 +25,11 @@ public abstract class Weapon { return manaCost; } - /* - TODO: ADD OTHER REQUIRED AND BONUS METHODS - */ + public void setDamage(int damage) { + this.damage = damage; + } + + public void setManaCost(int manaCost) { + this.manaCost = manaCost; + } } diff --git a/Java-Knight/src/main/java/org/project/location/AnsiColors.java b/Java-Knight/src/main/java/org/project/location/AnsiColors.java new file mode 100644 index 0000000..4064d6b --- /dev/null +++ b/Java-Knight/src/main/java/org/project/location/AnsiColors.java @@ -0,0 +1,30 @@ +package org.project.location; + +public class AnsiColors { + // Reset + public static final String RESET = "\u001B[0m"; + + // Regular Colors + public static final String BLACK = "\u001B[30m"; + public static final String RED = "\u001B[31m"; + public static final String GREEN = "\u001B[32m"; + public static final String YELLOW = "\u001B[33m"; + public static final String BLUE = "\u001B[34m"; + public static final String PURPLE = "\u001B[35m"; + public static final String CYAN = "\u001B[36m"; + public static final String WHITE = "\u001B[37m"; + + // Bold Colors + public static final String BOLD_RED = "\u001B[1;31m"; + public static final String BOLD_GREEN = "\u001B[1;32m"; + public static final String BOLD_YELLOW = "\u001B[1;33m"; + public static final String BOLD_BLUE = "\u001B[1;34m"; + public static final String BOLD_PURPLE = "\u001B[1;35m"; + public static final String BOLD_CYAN = "\u001B[1;36m"; + + // Background Colors + public static final String BG_RED = "\u001B[41m"; + public static final String BG_GREEN = "\u001B[42m"; + public static final String BG_YELLOW = "\u001B[43m"; + public static final String BG_BLUE = "\u001B[44m"; +} diff --git a/Java-Knight/src/main/java/org/project/location/Location.java b/Java-Knight/src/main/java/org/project/location/Location.java index b0b4b98..468d8b8 100644 --- a/Java-Knight/src/main/java/org/project/location/Location.java +++ b/Java-Knight/src/main/java/org/project/location/Location.java @@ -1,28 +1,72 @@ package org.project.location; -import org.project.entity.enemies.Enemy; - +import org.project.entity.enemies.*; import java.util.ArrayList; +import java.util.Random; public class Location { + private String name; + private String description; + private ArrayList possibleEnemies; + private Enemy currentEnemy; + private Random random; - private ArrayList enemies; - - public Location(ArrayList locations, ArrayList enemies) { - this.locations = locations; - this.enemies = enemies; + public Location(String name, String description) { + this.name = name; + this.description = description; + this.possibleEnemies = new ArrayList<>(); + this.random = new Random(); } + //Adding enemy to location + public void addEnemy(Enemy enemy) { + possibleEnemies.add(enemy); + } + + //Spawning a random enemy from among the enemies in this location + public void spawnRandomEnemy() { + if (possibleEnemies.isEmpty()) { + //If no enemy was defined + addDefaultEnemies(); + } + + int index = random.nextInt(possibleEnemies.size()); + currentEnemy = copyEnemy(possibleEnemies.get(index)); + } + + private void addDefaultEnemies() { + possibleEnemies.add(new Goblin()); + possibleEnemies.add(new Skeleton()); + possibleEnemies.add(new Vampire()); + } + + //Copying the enemy to have a new instance each time + private Enemy copyEnemy(Enemy original) { + if (original instanceof Goblin) return new Goblin(); + if (original instanceof Skeleton) return new Skeleton(); + if (original instanceof Vampire) return new Vampire(); + return new Goblin(); + } + + public String getName() { return name; } - public ArrayList getLocations() { - return locations; + public String getDescription() { + return description; } - public ArrayList getEnemies() { - return enemies; + public Enemy getCurrentEnemy() { + return currentEnemy; } -} + + public void setCurrentEnemy(Enemy enemy) { + this.currentEnemy = enemy; + } + + public boolean hasEnemy() { + return currentEnemy != null && currentEnemy.isAlive(); + } +} \ No newline at end of file diff --git a/Java-Knight/src/main/java/org/project/location/LocationManager.java b/Java-Knight/src/main/java/org/project/location/LocationManager.java new file mode 100644 index 0000000..ec9c572 --- /dev/null +++ b/Java-Knight/src/main/java/org/project/location/LocationManager.java @@ -0,0 +1,66 @@ +package org.project.location; + +import org.project.entity.enemies.*; +import java.util.ArrayList; +import java.util.Random; + +public class LocationManager { + + private ArrayList locations; + private Location currentLocation; + private Random random; + + public LocationManager() { + locations = new ArrayList<>(); + random = new Random(); + createLocations(); + } + + private void createLocations() { + //Creating different game locations + Location forest = new Location("Dark Forest", "A mysterious forest filled with dangerous creatures"); + forest.addEnemy(new Goblin()); + forest.addEnemy(new Skeleton()); + + Location crypt = new Location("Ancient Crypt", "An old crypt where skeletons roam"); + crypt.addEnemy(new Skeleton()); + crypt.addEnemy(new Vampire()); + + Location castleGate = new Location("Castle Gate", "The entrance to the Dragon's castle"); + castleGate.addEnemy(new Goblin()); + castleGate.addEnemy(new Vampire()); + + locations.add(forest); + locations.add(crypt); + locations.add(castleGate); + } + + public void moveToRandomLocation() { + int index = random.nextInt(locations.size()); + currentLocation = locations.get(index); + currentLocation.spawnRandomEnemy(); + } + + public void moveToLocation(int index) { + if (index >= 0 && index < locations.size()) { + currentLocation = locations.get(index); + currentLocation.spawnRandomEnemy(); + } + } + + public Location getCurrentLocation() { + return currentLocation; + } + + public void displayLocations() { + NarrativeConsole.printInfo("\n=== Available Locations ==="); + for (int i = 0; i < locations.size(); i++) { + NarrativeConsole.printInfo((i + 1) + ". " + locations.get(i).getName()); + NarrativeConsole.printInfo(" " + locations.get(i).getDescription()); + } + } + + public ArrayList getLocations() { + return locations; + } +} \ No newline at end of file diff --git a/Java-Knight/src/main/java/org/project/location/NarrativeConsole.java b/Java-Knight/src/main/java/org/project/location/NarrativeConsole.java new file mode 100644 index 0000000..d93f46e --- /dev/null +++ b/Java-Knight/src/main/java/org/project/location/NarrativeConsole.java @@ -0,0 +1,53 @@ +package org.project.location; + +public class NarrativeConsole { + //Normal + public static void printNormal(String message) { + System.out.println(AnsiColors.WHITE + "⭐ " + message + AnsiColors.RESET); + } + + //Damage + public static void printDamage(String message) { + System.out.println(AnsiColors.RED + "💥 " + message + AnsiColors.RESET); + } + + //Heal + public static void printHeal(String message) { + System.out.println(AnsiColors.GREEN + "💚 " + message + AnsiColors.RESET); + } + + //Mana + public static void printMana(String message) { + System.out.println(AnsiColors.BLUE + "💙 " + message + AnsiColors.RESET); + } + + //Warning + public static void printWarning(String message) { + System.out.println(AnsiColors.YELLOW + "⚠️ " + message + AnsiColors.RESET); + } + + //Success + public static void printSuccess(String message) { + System.out.println(AnsiColors.BOLD_GREEN + "✨ " + message + AnsiColors.RESET); + } + + //Info + public static void printInfo(String message) { + System.out.println(AnsiColors.CYAN + "ℹ️ " + message + AnsiColors.RESET); + } + + //Error + public static void printError(String message) { + System.out.println(AnsiColors.BOLD_RED + "❌ " + message + AnsiColors.RESET); + } + + //Combat + public static void printCombat(String message) { + System.out.println(AnsiColors.PURPLE + "⚔️ " + message + AnsiColors.RESET); + } + + //Special + public static void printSpecial(String message) { + System.out.println(AnsiColors.BOLD_YELLOW + "⭐ " + message + AnsiColors.RESET); + } +} \ No newline at end of file diff --git a/Java-Knight/target/classes/org/project/Main.class b/Java-Knight/target/classes/org/project/Main.class new file mode 100644 index 0000000..13fd6e9 Binary files /dev/null and b/Java-Knight/target/classes/org/project/Main.class differ diff --git a/Java-Knight/target/classes/org/project/entity/Entity.class b/Java-Knight/target/classes/org/project/entity/Entity.class new file mode 100644 index 0000000..ba5f0fb Binary files /dev/null and b/Java-Knight/target/classes/org/project/entity/Entity.class differ diff --git a/Java-Knight/target/classes/org/project/entity/enemies/Dragon.class b/Java-Knight/target/classes/org/project/entity/enemies/Dragon.class new file mode 100644 index 0000000..41222e4 Binary files /dev/null and b/Java-Knight/target/classes/org/project/entity/enemies/Dragon.class differ diff --git a/Java-Knight/target/classes/org/project/entity/enemies/Enemy.class b/Java-Knight/target/classes/org/project/entity/enemies/Enemy.class new file mode 100644 index 0000000..6ad9fcb Binary files /dev/null and b/Java-Knight/target/classes/org/project/entity/enemies/Enemy.class differ diff --git a/Java-Knight/target/classes/org/project/entity/enemies/Goblin.class b/Java-Knight/target/classes/org/project/entity/enemies/Goblin.class new file mode 100644 index 0000000..36720a1 Binary files /dev/null and b/Java-Knight/target/classes/org/project/entity/enemies/Goblin.class differ diff --git a/Java-Knight/target/classes/org/project/entity/enemies/Skeleton.class b/Java-Knight/target/classes/org/project/entity/enemies/Skeleton.class new file mode 100644 index 0000000..9ec2c64 Binary files /dev/null and b/Java-Knight/target/classes/org/project/entity/enemies/Skeleton.class differ diff --git a/Java-Knight/target/classes/org/project/entity/enemies/Vampire.class b/Java-Knight/target/classes/org/project/entity/enemies/Vampire.class new file mode 100644 index 0000000..258fdbb Binary files /dev/null and b/Java-Knight/target/classes/org/project/entity/enemies/Vampire.class differ diff --git a/Java-Knight/target/classes/org/project/entity/players/Assassin.class b/Java-Knight/target/classes/org/project/entity/players/Assassin.class new file mode 100644 index 0000000..544265d Binary files /dev/null and b/Java-Knight/target/classes/org/project/entity/players/Assassin.class differ diff --git a/Java-Knight/target/classes/org/project/entity/players/ICombatActions.class b/Java-Knight/target/classes/org/project/entity/players/ICombatActions.class new file mode 100644 index 0000000..ffd9894 Binary files /dev/null and b/Java-Knight/target/classes/org/project/entity/players/ICombatActions.class differ diff --git a/Java-Knight/target/classes/org/project/entity/players/Knight.class b/Java-Knight/target/classes/org/project/entity/players/Knight.class new file mode 100644 index 0000000..e5051fb Binary files /dev/null and b/Java-Knight/target/classes/org/project/entity/players/Knight.class differ diff --git a/Java-Knight/target/classes/org/project/entity/players/Player.class b/Java-Knight/target/classes/org/project/entity/players/Player.class new file mode 100644 index 0000000..2464b9c Binary files /dev/null and b/Java-Knight/target/classes/org/project/entity/players/Player.class differ diff --git a/Java-Knight/target/classes/org/project/entity/players/Wizard.class b/Java-Knight/target/classes/org/project/entity/players/Wizard.class new file mode 100644 index 0000000..413e2f4 Binary files /dev/null and b/Java-Knight/target/classes/org/project/entity/players/Wizard.class differ diff --git a/Java-Knight/target/classes/org/project/item/Item.class b/Java-Knight/target/classes/org/project/item/Item.class new file mode 100644 index 0000000..3db1242 Binary files /dev/null and b/Java-Knight/target/classes/org/project/item/Item.class differ diff --git a/Java-Knight/target/classes/org/project/item/armors/Armor.class b/Java-Knight/target/classes/org/project/item/armors/Armor.class new file mode 100644 index 0000000..5df2fde Binary files /dev/null and b/Java-Knight/target/classes/org/project/item/armors/Armor.class differ diff --git a/Java-Knight/target/classes/org/project/item/armors/AssassinMask.class b/Java-Knight/target/classes/org/project/item/armors/AssassinMask.class new file mode 100644 index 0000000..2883e83 Binary files /dev/null and b/Java-Knight/target/classes/org/project/item/armors/AssassinMask.class differ diff --git a/Java-Knight/target/classes/org/project/item/armors/KnightArmor.class b/Java-Knight/target/classes/org/project/item/armors/KnightArmor.class new file mode 100644 index 0000000..250ca3e Binary files /dev/null and b/Java-Knight/target/classes/org/project/item/armors/KnightArmor.class differ diff --git a/Java-Knight/target/classes/org/project/item/armors/WizardRobe.class b/Java-Knight/target/classes/org/project/item/armors/WizardRobe.class new file mode 100644 index 0000000..014eb18 Binary files /dev/null and b/Java-Knight/target/classes/org/project/item/armors/WizardRobe.class differ diff --git a/Java-Knight/target/classes/org/project/item/consumables/Consumable.class b/Java-Knight/target/classes/org/project/item/consumables/Consumable.class new file mode 100644 index 0000000..4edc46a Binary files /dev/null and b/Java-Knight/target/classes/org/project/item/consumables/Consumable.class differ diff --git a/Java-Knight/target/classes/org/project/item/consumables/Flask.class b/Java-Knight/target/classes/org/project/item/consumables/Flask.class new file mode 100644 index 0000000..0cc2948 Binary files /dev/null and b/Java-Knight/target/classes/org/project/item/consumables/Flask.class differ diff --git a/Java-Knight/target/classes/org/project/item/consumables/GreatFlask.class b/Java-Knight/target/classes/org/project/item/consumables/GreatFlask.class new file mode 100644 index 0000000..102d29e Binary files /dev/null and b/Java-Knight/target/classes/org/project/item/consumables/GreatFlask.class differ diff --git a/Java-Knight/target/classes/org/project/item/consumables/HealthFlask.class b/Java-Knight/target/classes/org/project/item/consumables/HealthFlask.class new file mode 100644 index 0000000..47aff07 Binary files /dev/null and b/Java-Knight/target/classes/org/project/item/consumables/HealthFlask.class differ diff --git a/Java-Knight/target/classes/org/project/item/consumables/ManaFlask.class b/Java-Knight/target/classes/org/project/item/consumables/ManaFlask.class new file mode 100644 index 0000000..a36a720 Binary files /dev/null and b/Java-Knight/target/classes/org/project/item/consumables/ManaFlask.class differ diff --git a/Java-Knight/target/classes/org/project/item/weapons/BoneDagger.class b/Java-Knight/target/classes/org/project/item/weapons/BoneDagger.class new file mode 100644 index 0000000..82fa269 Binary files /dev/null and b/Java-Knight/target/classes/org/project/item/weapons/BoneDagger.class differ diff --git a/Java-Knight/target/classes/org/project/item/weapons/Dagger.class b/Java-Knight/target/classes/org/project/item/weapons/Dagger.class new file mode 100644 index 0000000..58fbffb Binary files /dev/null and b/Java-Knight/target/classes/org/project/item/weapons/Dagger.class differ diff --git a/Java-Knight/target/classes/org/project/item/weapons/DragonClaw.class b/Java-Knight/target/classes/org/project/item/weapons/DragonClaw.class new file mode 100644 index 0000000..b48b96b Binary files /dev/null and b/Java-Knight/target/classes/org/project/item/weapons/DragonClaw.class differ diff --git a/Java-Knight/target/classes/org/project/item/weapons/Rapier.class b/Java-Knight/target/classes/org/project/item/weapons/Rapier.class new file mode 100644 index 0000000..899ebf3 Binary files /dev/null and b/Java-Knight/target/classes/org/project/item/weapons/Rapier.class differ diff --git a/Java-Knight/target/classes/org/project/item/weapons/Sword.class b/Java-Knight/target/classes/org/project/item/weapons/Sword.class new file mode 100644 index 0000000..d8b4161 Binary files /dev/null and b/Java-Knight/target/classes/org/project/item/weapons/Sword.class differ diff --git a/Java-Knight/target/classes/org/project/item/weapons/ToothedHook.class b/Java-Knight/target/classes/org/project/item/weapons/ToothedHook.class new file mode 100644 index 0000000..9de6964 Binary files /dev/null and b/Java-Knight/target/classes/org/project/item/weapons/ToothedHook.class differ diff --git a/Java-Knight/target/classes/org/project/item/weapons/Wand.class b/Java-Knight/target/classes/org/project/item/weapons/Wand.class new file mode 100644 index 0000000..d8c9018 Binary files /dev/null and b/Java-Knight/target/classes/org/project/item/weapons/Wand.class differ diff --git a/Java-Knight/target/classes/org/project/item/weapons/Weapon.class b/Java-Knight/target/classes/org/project/item/weapons/Weapon.class new file mode 100644 index 0000000..7d247ec Binary files /dev/null and b/Java-Knight/target/classes/org/project/item/weapons/Weapon.class differ diff --git a/Java-Knight/target/classes/org/project/location/AnsiColors.class b/Java-Knight/target/classes/org/project/location/AnsiColors.class new file mode 100644 index 0000000..7202aba Binary files /dev/null and b/Java-Knight/target/classes/org/project/location/AnsiColors.class differ diff --git a/Java-Knight/target/classes/org/project/location/Location.class b/Java-Knight/target/classes/org/project/location/Location.class new file mode 100644 index 0000000..483b8a0 Binary files /dev/null and b/Java-Knight/target/classes/org/project/location/Location.class differ diff --git a/Java-Knight/target/classes/org/project/location/LocationManager.class b/Java-Knight/target/classes/org/project/location/LocationManager.class new file mode 100644 index 0000000..0b48b97 Binary files /dev/null and b/Java-Knight/target/classes/org/project/location/LocationManager.class differ diff --git a/Java-Knight/target/classes/org/project/location/NarrativeConsole.class b/Java-Knight/target/classes/org/project/location/NarrativeConsole.class new file mode 100644 index 0000000..bbb2505 Binary files /dev/null and b/Java-Knight/target/classes/org/project/location/NarrativeConsole.class differ