Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fa56a58cea |
Generated
+1
-3
@@ -8,7 +8,5 @@
|
|||||||
</list>
|
</list>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" project-jdk-name="25" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" default="true" project-jdk-name="21" project-jdk-type="JavaSDK" />
|
||||||
<output url="file://$PROJECT_DIR$/out" />
|
|
||||||
</component>
|
|
||||||
</project>
|
</project>
|
||||||
Generated
-8
@@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="ProjectModuleManager">
|
|
||||||
<modules>
|
|
||||||
<module fileurl="file://$PROJECT_DIR$/.idea/HW-04-JAVA-KNIGHT.iml" filepath="$PROJECT_DIR$/.idea/HW-04-JAVA-KNIGHT.iml" />
|
|
||||||
</modules>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package org.project;
|
||||||
|
|
||||||
|
import org.project.entity.players.Player;
|
||||||
|
import org.project.location.Location;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class GameState implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private Player player;
|
||||||
|
private Location currentLocation;
|
||||||
|
|
||||||
|
public GameState(Player player, Location currentLocation) {
|
||||||
|
this.player = player;
|
||||||
|
this.currentLocation = currentLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Player getPlayer() {
|
||||||
|
return player;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Location getCurrentLocation() {
|
||||||
|
return currentLocation;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,15 +1,301 @@
|
|||||||
package org.project;
|
package org.project;
|
||||||
|
|
||||||
|
import org.project.combat.CombatSystem;
|
||||||
|
import org.project.entity.Entity;
|
||||||
|
import org.project.entity.enemies.Dragon;
|
||||||
|
import org.project.entity.enemies.Goblin;
|
||||||
|
import org.project.entity.enemies.Skeleton;
|
||||||
|
import org.project.entity.enemies.Vampire;
|
||||||
|
import org.project.entity.players.*;
|
||||||
import org.project.location.Location;
|
import org.project.location.Location;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.Random;
|
||||||
import java.util.List;
|
import java.util.Scanner;
|
||||||
|
|
||||||
public class Main {
|
public class Main {
|
||||||
public static void main(String[] args) {
|
|
||||||
// TODO: ADD LOCATIONS TO YOUR GAME
|
|
||||||
List<Location> locations = new ArrayList<>();
|
|
||||||
|
|
||||||
// TODO: IMPLEMENT GAMEPLAY
|
private static final Scanner scanner = new Scanner(System.in);
|
||||||
|
private static Location currentLocation;
|
||||||
|
|
||||||
|
public static final String RESET = "\u001B[0m";
|
||||||
|
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 void main(String[] args) {
|
||||||
|
|
||||||
|
initializeMap();
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
|
||||||
|
System.out.println(CYAN + "\n===============================" + RESET);
|
||||||
|
System.out.println(YELLOW + " ⚔ JAVA KNIGHT ⚔" + RESET);
|
||||||
|
System.out.println(CYAN + "===============================" + RESET);
|
||||||
|
|
||||||
|
System.out.println("1. Start Game");
|
||||||
|
System.out.println("2. How To Play");
|
||||||
|
System.out.println("3. Exit");
|
||||||
|
|
||||||
|
System.out.print("> ");
|
||||||
|
int option = scanner.nextInt();
|
||||||
|
|
||||||
|
switch (option) {
|
||||||
|
case 1 -> startGame();
|
||||||
|
case 2 -> showHelpMenu();
|
||||||
|
case 3 -> {
|
||||||
|
System.out.println(GREEN + "Farewell hero!" + RESET);
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
|
default -> System.out.println(RED + "Invalid option!" + RESET);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void startGame()
|
||||||
|
{
|
||||||
|
|
||||||
|
showIntro();
|
||||||
|
|
||||||
|
System.out.print("Enter your name: ");
|
||||||
|
String name = scanner.next();
|
||||||
|
|
||||||
|
System.out.println("\nChoose your class:");
|
||||||
|
System.out.println(BLUE + "1. Knight 🛡" + RESET);
|
||||||
|
System.out.println(PURPLE + "2. Wizard 🔮" + RESET);
|
||||||
|
System.out.println(YELLOW + "3. Assassin 🗡" + RESET);
|
||||||
|
|
||||||
|
int choice = scanner.nextInt();
|
||||||
|
Player player;
|
||||||
|
|
||||||
|
switch (choice) {
|
||||||
|
case 1 -> player = new Knight(name);
|
||||||
|
case 2 -> player = new Wizard(name);
|
||||||
|
case 3 -> player = new Assassin(name);
|
||||||
|
default -> player = new Knight(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
player.resetKeys();
|
||||||
|
System.out.println(GREEN + "\nWelcome " + name + " to Javanest!" + RESET);
|
||||||
|
|
||||||
|
currentLocation.enter();
|
||||||
|
gameLoop(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void gameLoop(Player player)
|
||||||
|
{
|
||||||
|
|
||||||
|
Random random = new Random();
|
||||||
|
|
||||||
|
|
||||||
|
while (player.isAlive())
|
||||||
|
{
|
||||||
|
|
||||||
|
showPlayerStatus(player);
|
||||||
|
|
||||||
|
System.out.println(CYAN + "\n===== LOCATION: " + currentLocation.getName() + " =====" + RESET);
|
||||||
|
System.out.println("1. Fight Enemy");
|
||||||
|
System.out.println("2. Move Location");
|
||||||
|
|
||||||
|
if (player.hasAllKeys() && currentLocation.getName().equals("Vampire Crypt"))
|
||||||
|
{
|
||||||
|
System.out.println(RED + "3. Enter Dragon Castle 🐉" + RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.print("> ");
|
||||||
|
int option = scanner.nextInt();
|
||||||
|
|
||||||
|
if (option == 1) {
|
||||||
|
Entity enemy = currentLocation.spawnEnemy();
|
||||||
|
|
||||||
|
System.out.println(RED + "\nA wild " + enemy.getName() + " appears!" + RESET);
|
||||||
|
|
||||||
|
CombatSystem combat = new CombatSystem();
|
||||||
|
combat.startBattle(player, enemy);
|
||||||
|
|
||||||
|
if (!player.isAlive()) {
|
||||||
|
System.out.println(RED + "\nYou have fallen..." + RESET);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
tryToDropKey(player, enemy, random);
|
||||||
|
recoverPlayer(player);
|
||||||
|
|
||||||
|
} else if (option == 2) {
|
||||||
|
|
||||||
|
moveLocation();
|
||||||
|
|
||||||
|
} else if (option == 3 &&
|
||||||
|
player.hasAllKeys() &&
|
||||||
|
currentLocation.getName().equals("Vampire Crypt")) {
|
||||||
|
|
||||||
|
System.out.println(RED + "\nYou enter the Dragon Castle..." + RESET);
|
||||||
|
|
||||||
|
CombatSystem combat = new CombatSystem();
|
||||||
|
combat.startBattle(player, new Dragon());
|
||||||
|
|
||||||
|
if (player.isAlive()) {
|
||||||
|
System.out.println(GREEN + "\n🏆 YOU SAVED JAVANEST!" + RESET);
|
||||||
|
} else {
|
||||||
|
System.out.println(RED + "\nThe Dragon has defeated you..." + RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
showProjectFeatures();
|
||||||
|
break;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
System.out.println(RED + "Invalid option!" + RESET);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void showPlayerStatus(Player player) {
|
||||||
|
|
||||||
|
System.out.println(YELLOW + "\n===== PLAYER STATUS =====" + RESET);
|
||||||
|
|
||||||
|
printBar("HP ", player.getHP(), player.getMaxHP(), RED);
|
||||||
|
printBar("MP ", player.getMP(), player.getMaxMP(), BLUE);
|
||||||
|
System.out.println("XP: " + player.getXP());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void printBar(String label, int value, int max, String color)
|
||||||
|
{
|
||||||
|
|
||||||
|
int totalBars = 20;
|
||||||
|
int filled = (int)((double)value / max * totalBars);
|
||||||
|
|
||||||
|
StringBuilder bar = new StringBuilder();
|
||||||
|
|
||||||
|
for (int i = 0; i < filled; i++) bar.append("█");
|
||||||
|
for (int i = filled; i < totalBars; i++) bar.append("░");
|
||||||
|
|
||||||
|
System.out.println(label + " " + color + bar + RESET + " " + value + "/" + max);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void moveLocation()
|
||||||
|
{
|
||||||
|
|
||||||
|
System.out.println(YELLOW + "\nWhere do you want to go?" + RESET);
|
||||||
|
|
||||||
|
int index = 1;
|
||||||
|
for (Location loc : currentLocation.getConnectedLocations())
|
||||||
|
{
|
||||||
|
System.out.println(index + ". " + loc.getName());
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.print("> ");
|
||||||
|
int choice = scanner.nextInt();
|
||||||
|
|
||||||
|
if (choice < 1 || choice > currentLocation.getConnectedLocations().size())
|
||||||
|
{
|
||||||
|
System.out.println(RED + "Invalid location!" + RESET);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentLocation = currentLocation.getConnectedLocations().get(choice - 1);
|
||||||
|
currentLocation.enter();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void tryToDropKey(Player player, Entity enemy, Random random)
|
||||||
|
{
|
||||||
|
|
||||||
|
int chance = random.nextInt(100) + 1;
|
||||||
|
|
||||||
|
if (chance <= 20)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (enemy instanceof Goblin && !player.hasGoblinKey())
|
||||||
|
{
|
||||||
|
player.obtainGoblinKey();
|
||||||
|
System.out.println(YELLOW + "You obtained the Goblin Key!" + RESET);
|
||||||
|
} else if (enemy instanceof Skeleton && !player.hasSkeletonKey()) {
|
||||||
|
player.obtainSkeletonKey();
|
||||||
|
System.out.println(YELLOW + "You obtained the Skeleton Key!" + RESET);
|
||||||
|
} else if (enemy instanceof Vampire && !player.hasVampireKey()) {
|
||||||
|
player.obtainVampireKey();
|
||||||
|
System.out.println(YELLOW + "You obtained the Vampire Key!" + RESET);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void recoverPlayer(Player player)
|
||||||
|
{
|
||||||
|
player.setHealth(player.getMaxHP());
|
||||||
|
player.setMana(player.getMaxMP());
|
||||||
|
System.out.println(GREEN + "You recovered your HP and Mana." + RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void showIntro()
|
||||||
|
{
|
||||||
|
System.out.println(PURPLE + "\n====================================" + RESET);
|
||||||
|
System.out.println(YELLOW + " LEGEND OF JAVANEST" + RESET);
|
||||||
|
System.out.println(PURPLE + "====================================" + RESET);
|
||||||
|
System.out.println("Defeat enemies, collect keys,");
|
||||||
|
System.out.println("and face the mighty Dragon!");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void showHelpMenu()
|
||||||
|
{
|
||||||
|
System.out.println(YELLOW + "\nHOW TO PLAY:" + RESET);
|
||||||
|
System.out.println("- Fight enemies to gain XP.");
|
||||||
|
System.out.println("- Collect 3 keys.");
|
||||||
|
System.out.println("- Unlock Dragon Castle.");
|
||||||
|
System.out.println("- Defeat the Dragon to win.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void showProjectFeatures()
|
||||||
|
{
|
||||||
|
|
||||||
|
System.out.println(CYAN + "\n====================================" + RESET);
|
||||||
|
System.out.println(YELLOW + " PROJECT FEATURES" + RESET);
|
||||||
|
System.out.println(CYAN + "====================================" + RESET);
|
||||||
|
|
||||||
|
System.out.println(GREEN + "✔ Multiple Player Classes" + RESET);
|
||||||
|
System.out.println(GREEN + "✔ Location System" + RESET);
|
||||||
|
System.out.println(GREEN + "✔ Key Collection System" + RESET);
|
||||||
|
System.out.println(GREEN + "✔ Combat System" + RESET);
|
||||||
|
System.out.println(GREEN + "✔ Final Boss Battle" + RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void initializeMap()
|
||||||
|
{
|
||||||
|
|
||||||
|
Location forest = new Location(
|
||||||
|
"Forest",
|
||||||
|
"A dark forest full of goblins.",
|
||||||
|
1
|
||||||
|
);
|
||||||
|
|
||||||
|
Location graveyard = new Location(
|
||||||
|
"Graveyard",
|
||||||
|
"An abandoned graveyard with skeletons.",
|
||||||
|
2
|
||||||
|
);
|
||||||
|
|
||||||
|
Location vampireCrypt = new Location(
|
||||||
|
"Vampire Crypt",
|
||||||
|
"A cursed crypt where vampires sleep.",
|
||||||
|
3
|
||||||
|
);
|
||||||
|
|
||||||
|
Location dragonCastle = new Location(
|
||||||
|
"Dragon Castle",
|
||||||
|
"The castle of the ancient dragon.",
|
||||||
|
4
|
||||||
|
);
|
||||||
|
|
||||||
|
forest.connectLocation(graveyard);
|
||||||
|
graveyard.connectLocation(forest);
|
||||||
|
|
||||||
|
graveyard.connectLocation(vampireCrypt);
|
||||||
|
vampireCrypt.connectLocation(graveyard);
|
||||||
|
|
||||||
|
vampireCrypt.connectLocation(dragonCastle);
|
||||||
|
|
||||||
|
currentLocation = forest;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,166 @@
|
|||||||
|
package org.project.combat;
|
||||||
|
|
||||||
|
import org.project.entity.players.Player;
|
||||||
|
import org.project.entity.Entity;
|
||||||
|
import org.project.entity.enemies.Goblin;
|
||||||
|
import org.project.entity.enemies.Skeleton;
|
||||||
|
import org.project.entity.enemies.Vampire;
|
||||||
|
|
||||||
|
import java.util.Scanner;
|
||||||
|
|
||||||
|
public class CombatSystem
|
||||||
|
{
|
||||||
|
|
||||||
|
private static final String RESET = "\u001B[0m";
|
||||||
|
private static final String RED = "\u001B[31m";
|
||||||
|
private static final String GREEN = "\u001B[32m";
|
||||||
|
private static final String YELLOW = "\u001B[33m";
|
||||||
|
private static final String BLUE = "\u001B[34m";
|
||||||
|
|
||||||
|
private Scanner scanner = new Scanner(System.in);
|
||||||
|
|
||||||
|
public void startBattle(Player player, Entity enemy)
|
||||||
|
{
|
||||||
|
|
||||||
|
System.out.println(RED + "\n⚔️ A battle has started!" + RESET);
|
||||||
|
System.out.println(YELLOW + "Enemy: " + enemy.getName() + RESET);
|
||||||
|
|
||||||
|
while (player.isAlive() && enemy.isAlive())
|
||||||
|
{
|
||||||
|
|
||||||
|
System.out.println("\n" + BLUE + "----- YOUR TURN -----" + RESET);
|
||||||
|
System.out.println("1. Light Attack");
|
||||||
|
System.out.println("2. Heavy Attack");
|
||||||
|
System.out.println("3. Defend");
|
||||||
|
System.out.println("4. Heal");
|
||||||
|
System.out.println("5. Special Ability");
|
||||||
|
System.out.println("6. Exit Game");
|
||||||
|
|
||||||
|
while (!scanner.hasNextInt())
|
||||||
|
{
|
||||||
|
scanner.next();
|
||||||
|
System.out.println("❌ Please enter a number between 1-6");
|
||||||
|
}
|
||||||
|
|
||||||
|
int choice = scanner.nextInt();
|
||||||
|
|
||||||
|
switch (choice)
|
||||||
|
{
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
player.lightAttack(enemy);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
player.heavyAttack(enemy);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
player.defend();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
player.specialAbility(enemy);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5:
|
||||||
|
if (player.getMP() >= 6)
|
||||||
|
{
|
||||||
|
player.heal(10);
|
||||||
|
player.fillMana(-6);
|
||||||
|
System.out.println("💚 You restored 10 HP at the cost of 6 MP!");
|
||||||
|
} else {
|
||||||
|
System.out.println("❌ Not enough MP to heal!");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 6:
|
||||||
|
if (player.getXP() >= 10)
|
||||||
|
{
|
||||||
|
player.gainXP(-10);
|
||||||
|
player.fillMana(20);
|
||||||
|
System.out.println("🔮 +20 MP restored (Cost: 10 XP)");
|
||||||
|
} else {
|
||||||
|
System.out.println("❌ Not enough XP to restore mana!");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 7:
|
||||||
|
if (player.getXP() >= 50)
|
||||||
|
{
|
||||||
|
player.gainXP(-50);
|
||||||
|
player.heal(30);
|
||||||
|
System.out.println("❤️ +30 HP restored (Cost: 50 XP)");
|
||||||
|
} else {
|
||||||
|
System.out.println("❌ Not enough XP to restore HP!");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 8:
|
||||||
|
System.out.println("👋 Exiting game...");
|
||||||
|
System.exit(0);
|
||||||
|
|
||||||
|
default:
|
||||||
|
System.out.println("❌ Invalid choice!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!enemy.isAlive())
|
||||||
|
{
|
||||||
|
|
||||||
|
System.out.println(GREEN + "\n✅ Enemy defeated!" + RESET);
|
||||||
|
|
||||||
|
player.gainXP(50);
|
||||||
|
|
||||||
|
dropKey(player, enemy);
|
||||||
|
|
||||||
|
recoverPlayer(player);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println(RED + "\n👹 ENEMY TURN!" + RESET);
|
||||||
|
|
||||||
|
enemy.attack(player);
|
||||||
|
|
||||||
|
if (!player.isAlive())
|
||||||
|
{
|
||||||
|
System.out.println(RED + "\n💀 You were defeated..." + RESET);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void dropKey(Player player, Entity enemy)
|
||||||
|
{
|
||||||
|
|
||||||
|
double chance = Math.random();
|
||||||
|
|
||||||
|
if (chance > 0.20) return;
|
||||||
|
|
||||||
|
if (enemy instanceof Goblin && !player.hasGoblinKey())
|
||||||
|
{
|
||||||
|
System.out.println(YELLOW + "🗝️ Goblin Key obtained!" + RESET);
|
||||||
|
player.obtainGoblinKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (enemy instanceof Skeleton && !player.hasSkeletonKey())
|
||||||
|
{
|
||||||
|
System.out.println(YELLOW + "🗝️ Skeleton Key obtained!" + RESET);
|
||||||
|
player.obtainSkeletonKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (enemy instanceof Vampire && !player.hasVampireKey())
|
||||||
|
{
|
||||||
|
System.out.println(YELLOW + "🗝️ Vampire Key obtained!" + RESET);
|
||||||
|
player.obtainVampireKey();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void recoverPlayer(Player player)
|
||||||
|
{
|
||||||
|
|
||||||
|
player.setHealth(player.getMaxHP());
|
||||||
|
player.setMana(player.getMaxMP());
|
||||||
|
|
||||||
|
System.out.println("\u001B[32m✨ Your HP and Mana have been fully restored!\u001B[0m");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package org.project.entity;
|
package org.project.entity;
|
||||||
|
|
||||||
public interface Entity {
|
public interface Entity
|
||||||
|
{
|
||||||
void attack(Entity target);
|
void attack(Entity target);
|
||||||
|
|
||||||
void defend();
|
void defend();
|
||||||
@@ -11,9 +12,22 @@ public interface Entity {
|
|||||||
|
|
||||||
void takeDamage(int damage);
|
void takeDamage(int damage);
|
||||||
|
|
||||||
|
int getHP();
|
||||||
|
int getMP();
|
||||||
int getMaxHP();
|
int getMaxHP();
|
||||||
|
|
||||||
int getMaxMP();
|
int getMaxMP();
|
||||||
|
int getLevel();
|
||||||
|
String getName();
|
||||||
|
|
||||||
|
void setStunned(boolean value);
|
||||||
|
boolean isStunned();
|
||||||
|
|
||||||
|
void setInvisible(boolean value);
|
||||||
|
boolean isInvisible();
|
||||||
|
|
||||||
|
boolean isAlive();
|
||||||
|
|
||||||
|
void gainXP(int xp);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TODO: ADD OTHER REQUIRED AND BONUS METHODS
|
TODO: ADD OTHER REQUIRED AND BONUS METHODS
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package org.project.entity.enemies;
|
||||||
|
|
||||||
|
import org.project.entity.Entity;
|
||||||
|
import org.project.item.weapons.BasicWeapon;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class Dragon extends Enemy
|
||||||
|
{
|
||||||
|
|
||||||
|
private Random random = new Random();
|
||||||
|
|
||||||
|
public Dragon()
|
||||||
|
{
|
||||||
|
super("Dragon", 200, 50, new BasicWeapon("Flame Breath", 25));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void attack(Entity target)
|
||||||
|
{
|
||||||
|
|
||||||
|
int damage;
|
||||||
|
|
||||||
|
if (random.nextBoolean())
|
||||||
|
{
|
||||||
|
damage = weapon.getDamage() + 20;
|
||||||
|
System.out.println(RED + "🔥 Dragon uses FIRE BREATH!" + RESET);
|
||||||
|
} else {
|
||||||
|
damage = weapon.getDamage();
|
||||||
|
System.out.println(YELLOW + "🐉 Dragon claws viciously!" + RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
target.takeDamage(damage);
|
||||||
|
|
||||||
|
System.out.println(RED + "💥 Dragon deals "
|
||||||
|
+ damage + " damage!" + RESET);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,34 +1,140 @@
|
|||||||
package org.project.entity.enemies;
|
package org.project.entity.enemies;
|
||||||
|
|
||||||
|
import org.project.entity.Entity;
|
||||||
import org.project.item.weapons.Weapon;
|
import org.project.item.weapons.Weapon;
|
||||||
|
|
||||||
// TODO: UPDATE IMPLEMENTATION
|
public abstract class Enemy implements Entity
|
||||||
public abstract class Enemy {
|
{
|
||||||
Weapon weapon;
|
|
||||||
private int hp;
|
|
||||||
private int mp;
|
|
||||||
|
|
||||||
public Enemy(int hp, int mp, Weapon weapon) {
|
protected String name;
|
||||||
|
protected int hp;
|
||||||
|
protected int mp;
|
||||||
|
protected int maxHp;
|
||||||
|
protected int maxMp;
|
||||||
|
protected int level;
|
||||||
|
protected boolean stunned;
|
||||||
|
protected boolean invisible;
|
||||||
|
protected Weapon weapon;
|
||||||
|
|
||||||
|
protected static final String RESET = "\u001B[0m";
|
||||||
|
protected static final String RED = "\u001B[31m";
|
||||||
|
protected static final String YELLOW = "\u001B[33m";
|
||||||
|
protected static final String PURPLE = "\u001B[35m";
|
||||||
|
|
||||||
|
public Enemy(String name, int hp, int mp, Weapon weapon)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
this.hp = hp;
|
this.hp = hp;
|
||||||
this.mp = mp;
|
this.mp = mp;
|
||||||
|
this.maxHp = hp;
|
||||||
|
this.maxMp = mp;
|
||||||
|
this.level = 1;
|
||||||
|
this.stunned = false;
|
||||||
|
this.invisible = false;
|
||||||
this.weapon = weapon;
|
this.weapon = weapon;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void takeDamage(int damage) {
|
public void defend()
|
||||||
hp -= damage;
|
{
|
||||||
|
System.out.println(name + " defends.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getHp() {
|
@Override
|
||||||
|
public void heal(int health)
|
||||||
|
{
|
||||||
|
if (health <= 0) return;
|
||||||
|
hp += health;
|
||||||
|
if (hp > maxHp) hp = maxHp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fillMana(int mana)
|
||||||
|
{
|
||||||
|
if (mana <= 0) return;
|
||||||
|
mp += mana;
|
||||||
|
if (mp > maxMp) mp = maxMp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void takeDamage(int damage)
|
||||||
|
{
|
||||||
|
if (damage <= 0) return;
|
||||||
|
hp -= damage;
|
||||||
|
if (hp < 0) hp = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getHP()
|
||||||
|
{
|
||||||
return hp;
|
return hp;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getMp() {
|
@Override
|
||||||
|
public int getMP()
|
||||||
|
{
|
||||||
return mp;
|
return mp;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Weapon getWeapon() {
|
@Override
|
||||||
return weapon;
|
public int getMaxHP()
|
||||||
|
{
|
||||||
|
return maxHp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaxMP()
|
||||||
|
{
|
||||||
|
return maxMp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getLevel()
|
||||||
|
{
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName()
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setStunned(boolean value)
|
||||||
|
{
|
||||||
|
this.stunned = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isStunned()
|
||||||
|
{
|
||||||
|
return stunned;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setInvisible(boolean value)
|
||||||
|
{
|
||||||
|
this.invisible = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isInvisible()
|
||||||
|
{
|
||||||
|
return invisible;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAlive()
|
||||||
|
{
|
||||||
|
return hp > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void gainXP(int xp)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public abstract void attack(Entity target);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package org.project.entity.enemies;
|
||||||
|
|
||||||
|
import org.project.entity.Entity;
|
||||||
|
import org.project.item.weapons.BasicWeapon;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class Goblin extends Enemy
|
||||||
|
{
|
||||||
|
|
||||||
|
private Random random = new Random();
|
||||||
|
|
||||||
|
private static final String RESET = "\u001B[0m";
|
||||||
|
private static final String RED = "\u001B[31m";
|
||||||
|
private static final String PURPLE = "\u001B[35m";
|
||||||
|
|
||||||
|
public Goblin() {
|
||||||
|
super("Goblin", 60, 20, new BasicWeapon("Rusty Dagger", 12));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void attack(Entity target)
|
||||||
|
{
|
||||||
|
|
||||||
|
int damage = weapon.getDamage();
|
||||||
|
|
||||||
|
if (random.nextInt(100) < 25)
|
||||||
|
{
|
||||||
|
damage *= 2;
|
||||||
|
System.out.println(PURPLE + "💀 Goblin CRITICAL strike!" + RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
target.takeDamage(damage);
|
||||||
|
|
||||||
|
System.out.println(RED + "👹 Goblin attacks for " + damage + " damage!" + RESET);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,46 @@
|
|||||||
package org.project.entity.enemies;
|
package org.project.entity.enemies;
|
||||||
|
|
||||||
// TODO: UPDATE IMPLEMENTATION
|
import org.project.entity.Entity;
|
||||||
public class Skeleton {
|
import org.project.item.weapons.BasicWeapon;
|
||||||
// TODO: DESIGN ENEMY AND IMPLEMENT THE CONSTRUCTOR
|
|
||||||
}
|
public class Skeleton extends Enemy
|
||||||
|
{
|
||||||
|
|
||||||
|
private boolean revived = false;
|
||||||
|
|
||||||
|
private static final String RESET = "\u001B[0m";
|
||||||
|
private static final String RED = "\u001B[31m";
|
||||||
|
private static final String YELLOW = "\u001B[33m";
|
||||||
|
|
||||||
|
public Skeleton()
|
||||||
|
{
|
||||||
|
super("Skeleton", 70, 10, new BasicWeapon("Bone Sword", 15));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void attack(Entity target)
|
||||||
|
{
|
||||||
|
|
||||||
|
int damage = weapon.getDamage();
|
||||||
|
|
||||||
|
target.takeDamage(damage);
|
||||||
|
|
||||||
|
System.out.println(RED + "☠ Skeleton slashes for " + damage + " damage!" + RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void takeDamage(int damage)
|
||||||
|
{
|
||||||
|
|
||||||
|
super.takeDamage(damage);
|
||||||
|
|
||||||
|
if (!isAlive() && !revived)
|
||||||
|
{
|
||||||
|
|
||||||
|
revived = true;
|
||||||
|
this.hp = 40;
|
||||||
|
|
||||||
|
System.out.println(YELLOW + "⚠ Skeleton reassembles itself!" + RESET);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package org.project.entity.enemies;
|
||||||
|
|
||||||
|
import org.project.entity.Entity;
|
||||||
|
import org.project.item.weapons.BasicWeapon;
|
||||||
|
|
||||||
|
public class Vampire extends Enemy
|
||||||
|
{
|
||||||
|
|
||||||
|
public Vampire()
|
||||||
|
{
|
||||||
|
super("Vampire", 90, 30, new BasicWeapon("Dark Claws", 18));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void attack(Entity target)
|
||||||
|
{
|
||||||
|
|
||||||
|
int damage = weapon.getDamage();
|
||||||
|
target.takeDamage(damage);
|
||||||
|
|
||||||
|
int healAmount = damage / 2;
|
||||||
|
this.hp += healAmount;
|
||||||
|
|
||||||
|
System.out.println(RED + "🧛 Vampire drains "
|
||||||
|
+ damage + " HP!" + RESET);
|
||||||
|
|
||||||
|
System.out.println(YELLOW + "🩸 Vampire heals "
|
||||||
|
+ healAmount + " HP!" + RESET);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
package org.project.entity.players;
|
||||||
|
|
||||||
|
import org.project.entity.Entity;
|
||||||
|
import org.project.item.weapons.BasicWeapon;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class Assassin extends Player
|
||||||
|
{
|
||||||
|
|
||||||
|
private static final int HEAVY_COST = 15;
|
||||||
|
private static final int SPECIAL_COST = 25;
|
||||||
|
|
||||||
|
private static final String RESET = "\u001B[0m";
|
||||||
|
private static final String RED = "\u001B[31m";
|
||||||
|
private static final String GREEN = "\u001B[32m";
|
||||||
|
private static final String YELLOW = "\u001B[33m";
|
||||||
|
private static final String BLUE = "\u001B[34m";
|
||||||
|
private static final String PURPLE = "\u001B[35m";
|
||||||
|
|
||||||
|
private Random random = new Random();
|
||||||
|
|
||||||
|
public Assassin(String name) {
|
||||||
|
super(name, 90, 80, new BasicWeapon("Dagger", 18));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void lightAttack(Entity target)
|
||||||
|
{
|
||||||
|
|
||||||
|
int dmg = weapon.getDamage() + 12;
|
||||||
|
|
||||||
|
// 25% critical chance
|
||||||
|
if (random.nextInt(100) < 25)
|
||||||
|
{
|
||||||
|
dmg *= 2;
|
||||||
|
System.out.println(PURPLE + "💀 CRITICAL HIT!" + RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
target.takeDamage(dmg);
|
||||||
|
|
||||||
|
System.out.println(YELLOW + "🗡️ " + name +
|
||||||
|
" strikes for " + dmg + " damage!" + RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void heavyAttack(Entity target)
|
||||||
|
{
|
||||||
|
if (mp < HEAVY_COST) {
|
||||||
|
System.out.println(RED + "❌ Not enough MP!" + RESET);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp -= HEAVY_COST;
|
||||||
|
int dmg = weapon.getDamage() + 30;
|
||||||
|
target.takeDamage(dmg);
|
||||||
|
|
||||||
|
System.out.println(PURPLE + "⚡ Shadow Slash deals " +
|
||||||
|
dmg + " damage!" + RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void defendAction()
|
||||||
|
{
|
||||||
|
defend();
|
||||||
|
System.out.println(BLUE + "🛡️ Quick dodge stance!" + RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void healAction()
|
||||||
|
{
|
||||||
|
heal(20);
|
||||||
|
System.out.println(GREEN + "💖 " + name +
|
||||||
|
" uses bandage restoring 20 HP!" + RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void specialAbility(Entity target)
|
||||||
|
{
|
||||||
|
if (mp < SPECIAL_COST)
|
||||||
|
{
|
||||||
|
System.out.println(RED + "❌ Not enough MP!" + RESET);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp -= SPECIAL_COST;
|
||||||
|
|
||||||
|
setInvisible(true);
|
||||||
|
|
||||||
|
int dmg = weapon.getDamage() + 50;
|
||||||
|
target.takeDamage(dmg);
|
||||||
|
|
||||||
|
System.out.println(BLUE + "🌑 SHADOW STRIKE deals " +
|
||||||
|
dmg + " damage!" + RESET);
|
||||||
|
|
||||||
|
System.out.println(YELLOW + "👤 " + name +
|
||||||
|
" becomes INVISIBLE!" + RESET);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package org.project.entity.players;
|
||||||
|
|
||||||
|
import org.project.entity.Entity;
|
||||||
|
|
||||||
|
public interface ICombatActions
|
||||||
|
{
|
||||||
|
|
||||||
|
// 1. Light Attack
|
||||||
|
void lightAttack(Entity target);
|
||||||
|
|
||||||
|
// 2. Heavy Attack
|
||||||
|
void heavyAttack(Entity target);
|
||||||
|
|
||||||
|
// 3. Defend
|
||||||
|
void defendAction();
|
||||||
|
|
||||||
|
// 4. Heal
|
||||||
|
void healAction();
|
||||||
|
|
||||||
|
// 5. Special Ability
|
||||||
|
void specialAbility(Entity target);
|
||||||
|
}
|
||||||
@@ -1,6 +1,101 @@
|
|||||||
package org.project.entity.players;
|
package org.project.entity.players;
|
||||||
|
|
||||||
// TODO: UPDATE IMPLEMENTATION
|
import org.project.entity.Entity;
|
||||||
public class Knight {
|
import org.project.item.armors.KnightArmor;
|
||||||
// TODO: DESIGN KNIGHT'S WEAPON AND ARMOR AND IMPLEMENT THE CONSTRUCTOR
|
import org.project.item.weapons.Sword;
|
||||||
}
|
|
||||||
|
public class Knight extends Player {
|
||||||
|
|
||||||
|
private static final int LIGHT_BONUS = 15;
|
||||||
|
private static final int HEAVY_COST = 10;
|
||||||
|
private static final int SPECIAL_COST = 25;
|
||||||
|
|
||||||
|
private static final String RESET = "\u001B[0m";
|
||||||
|
private static final String RED = "\u001B[31m";
|
||||||
|
private static final String GREEN = "\u001B[32m";
|
||||||
|
private static final String YELLOW = "\u001B[33m";
|
||||||
|
private static final String BLUE = "\u001B[34m";
|
||||||
|
private static final String PURPLE = "\u001B[35m";
|
||||||
|
|
||||||
|
public Knight(String name)
|
||||||
|
{
|
||||||
|
super(name, 150, 40, new Sword());
|
||||||
|
new KnightArmor();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void lightAttack(Entity target)
|
||||||
|
{
|
||||||
|
int dmg = weapon.getDamage() + LIGHT_BONUS;
|
||||||
|
target.takeDamage(dmg);
|
||||||
|
|
||||||
|
((Sword) weapon).addCharge(1);
|
||||||
|
|
||||||
|
System.out.println(
|
||||||
|
YELLOW + "⚔️ " + name +
|
||||||
|
" slashes the enemy for " + dmg + " damage!" +
|
||||||
|
RESET
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void heavyAttack(Entity target)
|
||||||
|
{
|
||||||
|
if (mp < HEAVY_COST)
|
||||||
|
{
|
||||||
|
System.out.println(RED + "❌ Not enough MP for heavy attack!" + RESET);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp -= HEAVY_COST;
|
||||||
|
int dmg = weapon.getDamage() + 30;
|
||||||
|
target.takeDamage(dmg);
|
||||||
|
|
||||||
|
((Sword) weapon).addCharge(2);
|
||||||
|
|
||||||
|
System.out.println(PURPLE + "💥 " + name +
|
||||||
|
" performs a HEAVY STRIKE for " + dmg + " damage!" + RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void defendAction()
|
||||||
|
{
|
||||||
|
defend();
|
||||||
|
System.out.println(BLUE + "🛡️ " + name +
|
||||||
|
" raises his shield!" + RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void healAction()
|
||||||
|
{
|
||||||
|
heal(30);
|
||||||
|
System.out.println(GREEN + "💖 " + name +
|
||||||
|
" heals for 30 HP!" + RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void specialAbility(Entity target)
|
||||||
|
{
|
||||||
|
if (mp < SPECIAL_COST)
|
||||||
|
{
|
||||||
|
System.out.println(RED + "❌ Not enough MP!" + RESET);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp -= SPECIAL_COST;
|
||||||
|
|
||||||
|
int dmg = weapon.getDamage() + 45;
|
||||||
|
target.takeDamage(dmg);
|
||||||
|
target.setStunned(true);
|
||||||
|
|
||||||
|
((Sword) weapon).addCharge(3);
|
||||||
|
|
||||||
|
System.out.println(
|
||||||
|
BLUE + "🌋 " + name +
|
||||||
|
" uses EARTH SHATTERING STRIKE dealing " + dmg + " damage!" +
|
||||||
|
RESET
|
||||||
|
);
|
||||||
|
|
||||||
|
System.out.println(YELLOW + "⚠️ The enemy is STUNNED!" + RESET);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,89 +1,159 @@
|
|||||||
package org.project.entity.players;
|
package org.project.entity.players;
|
||||||
|
|
||||||
import org.project.entity.Entity;
|
import org.project.entity.Entity;
|
||||||
import org.project.item.armors.Armor;
|
|
||||||
import org.project.item.weapons.Weapon;
|
import org.project.item.weapons.Weapon;
|
||||||
|
|
||||||
// TODO: UPDATE IMPLEMENTATION
|
import java.io.Serializable;
|
||||||
public abstract class Player {
|
|
||||||
|
public abstract class Player implements Entity, ICombatActions, Serializable
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
protected String name;
|
protected String name;
|
||||||
Weapon weapon;
|
protected int hp, maxHP;
|
||||||
Armor armor;
|
protected int mp, maxMP;
|
||||||
private int hp;
|
protected int level = 1;
|
||||||
private int maxHP;
|
protected int xp = 0;
|
||||||
private int mp;
|
|
||||||
private int maxMP;
|
|
||||||
|
|
||||||
public Player(String name, int hp, int mp, Weapon weapon, Armor armor) {
|
protected boolean stunned = false;
|
||||||
|
protected boolean invisible = false;
|
||||||
|
protected boolean defending = false;
|
||||||
|
|
||||||
|
private boolean goblinKey = false;
|
||||||
|
private boolean skeletonKey = false;
|
||||||
|
private boolean vampireKey = false;
|
||||||
|
|
||||||
|
protected Weapon weapon;
|
||||||
|
|
||||||
|
private static final String RESET = "\u001B[0m";
|
||||||
|
private static final String RED = "\u001B[31m";
|
||||||
|
private static final String GREEN = "\u001B[32m";
|
||||||
|
private static final String YELLOW = "\u001B[33m";
|
||||||
|
private static final String BLUE = "\u001B[34m";
|
||||||
|
private static final String PURPLE = "\u001B[35m";
|
||||||
|
|
||||||
|
public Player(String name, int maxHP, int maxMP, Weapon weapon)
|
||||||
|
{
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.hp = hp;
|
this.maxHP = maxHP;
|
||||||
this.mp = mp;
|
this.hp = maxHP;
|
||||||
|
this.maxMP = maxMP;
|
||||||
|
this.mp = maxMP;
|
||||||
this.weapon = weapon;
|
this.weapon = weapon;
|
||||||
this.armor = armor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void attack(Entity target) {
|
public void attack(Entity target)
|
||||||
target.takeDamage(weapon.getDamage());
|
{
|
||||||
|
lightAttack(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void defend() {
|
public void defend()
|
||||||
// TODO
|
{
|
||||||
}
|
defending = true;
|
||||||
|
System.out.println(BLUE + "🛡️ " + name + " is defending!" + RESET);
|
||||||
|
|
||||||
@Override
|
|
||||||
public void takeDamage(int damage) {
|
|
||||||
hp -= damage - armor.getDefense();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void heal(int health) {
|
public void heal(int amount)
|
||||||
hp += health;
|
{
|
||||||
if (hp > maxHP) {
|
hp = Math.min(maxHP, hp + amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fillMana(int amount)
|
||||||
|
{
|
||||||
|
mp = Math.min(maxMP, mp + amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void takeDamage(int damage)
|
||||||
|
{
|
||||||
|
if (defending)
|
||||||
|
{
|
||||||
|
damage /= 2;
|
||||||
|
defending = false;
|
||||||
|
}
|
||||||
|
hp = Math.max(0, hp - damage);
|
||||||
|
System.out.println(RED + "💥 " + name + " took " + damage + " damage!" + RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getHP() { return hp; }
|
||||||
|
@Override
|
||||||
|
public int getMP() { return mp; }
|
||||||
|
@Override
|
||||||
|
public int getMaxHP() { return maxHP; }
|
||||||
|
@Override
|
||||||
|
public int getMaxMP() { return maxMP; }
|
||||||
|
@Override
|
||||||
|
public int getLevel() { return level; }
|
||||||
|
@Override
|
||||||
|
public String getName() { return name; }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setStunned(boolean v) { stunned = v; }
|
||||||
|
@Override
|
||||||
|
public boolean isStunned() { return stunned; }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setInvisible(boolean v) { invisible = v; }
|
||||||
|
@Override
|
||||||
|
public boolean isInvisible() { return invisible; }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAlive() { return hp > 0; }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void gainXP(int xp)
|
||||||
|
{
|
||||||
|
this.xp += xp;
|
||||||
|
if (this.xp >= level * 100)
|
||||||
|
{
|
||||||
|
level++;
|
||||||
|
this.xp = 0;
|
||||||
|
maxHP += 10;
|
||||||
|
maxMP += 5;
|
||||||
hp = maxHP;
|
hp = maxHP;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void fillMana(int mana) {
|
|
||||||
mp += mana;
|
|
||||||
if (mp > maxMP) {
|
|
||||||
mp = maxMP;
|
mp = maxMP;
|
||||||
|
|
||||||
|
System.out.println(GREEN + "⭐ " + name + " leveled up to level " + level + "!" + RESET);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasGoblinKey() { return goblinKey; }
|
||||||
|
public boolean hasSkeletonKey() { return skeletonKey; }
|
||||||
|
public boolean hasVampireKey() { return vampireKey; }
|
||||||
|
|
||||||
public String getName() {
|
public void obtainGoblinKey() { goblinKey = true; }
|
||||||
return name;
|
public void obtainSkeletonKey() { skeletonKey = true; }
|
||||||
|
public void obtainVampireKey() { vampireKey = true; }
|
||||||
|
|
||||||
|
public boolean hasAllKeys()
|
||||||
|
{
|
||||||
|
return goblinKey && skeletonKey && vampireKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getHp() {
|
public void resetKeys()
|
||||||
return hp;
|
{
|
||||||
|
goblinKey = false;
|
||||||
|
skeletonKey = false;
|
||||||
|
vampireKey = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void setHealth(int hp)
|
||||||
public int getMaxHP() {
|
{
|
||||||
return maxHP;
|
this.hp = Math.min(hp, maxHP);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getMp() {
|
public void setMana(int mp)
|
||||||
return mp;
|
{
|
||||||
|
this.mp = Math.min(mp, maxMP);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public int getXP()
|
||||||
public int getMaxMP() {
|
{
|
||||||
return maxMP;
|
return xp;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public Weapon getWeapon() {
|
|
||||||
return weapon;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Armor getArmor() {
|
|
||||||
return armor;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
package org.project.entity.players;
|
||||||
|
|
||||||
|
import org.project.entity.Entity;
|
||||||
|
import org.project.item.weapons.BasicWeapon;
|
||||||
|
|
||||||
|
public class Wizard extends Player
|
||||||
|
{
|
||||||
|
|
||||||
|
private static final int LIGHT_COST = 5;
|
||||||
|
private static final int HEAVY_COST = 15;
|
||||||
|
private static final int SPECIAL_COST = 30;
|
||||||
|
|
||||||
|
private static final String RESET = "\u001B[0m";
|
||||||
|
private static final String RED = "\u001B[31m";
|
||||||
|
private static final String GREEN = "\u001B[32m";
|
||||||
|
private static final String YELLOW = "\u001B[33m";
|
||||||
|
private static final String BLUE = "\u001B[34m";
|
||||||
|
private static final String PURPLE = "\u001B[35m";
|
||||||
|
|
||||||
|
public Wizard(String name) {
|
||||||
|
super(name, 100, 120, new BasicWeapon("Magic Staff", 20));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void lightAttack(Entity target)
|
||||||
|
{
|
||||||
|
if (mp < LIGHT_COST)
|
||||||
|
{
|
||||||
|
System.out.println(RED + "❌ Not enough MP!" + RESET);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp -= LIGHT_COST;
|
||||||
|
int dmg = weapon.getDamage() + 10;
|
||||||
|
target.takeDamage(dmg);
|
||||||
|
|
||||||
|
System.out.println(YELLOW + "✨ " + name + " casts Magic Bolt for " + dmg + " damage!" + RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void heavyAttack(Entity target)
|
||||||
|
{
|
||||||
|
if (mp < HEAVY_COST)
|
||||||
|
{
|
||||||
|
System.out.println(RED + "❌ Not enough MP!" + RESET);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp -= HEAVY_COST;
|
||||||
|
int dmg = weapon.getDamage() + 35;
|
||||||
|
target.takeDamage(dmg);
|
||||||
|
|
||||||
|
System.out.println(PURPLE + "🔥 " + name +
|
||||||
|
" casts FIREBALL for " + dmg + " damage!" + RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void defendAction()
|
||||||
|
{
|
||||||
|
defend();
|
||||||
|
System.out.println(BLUE + "🔮 Magical barrier activated!" + RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void healAction()
|
||||||
|
{
|
||||||
|
if (mp < 20)
|
||||||
|
{
|
||||||
|
System.out.println(RED + "❌ Not enough MP to heal!" + RESET);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp -= 20;
|
||||||
|
heal(40);
|
||||||
|
System.out.println(GREEN + "💖 " + name +
|
||||||
|
" casts HEAL restoring 40 HP!" + RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void specialAbility(Entity target)
|
||||||
|
{
|
||||||
|
if (mp < SPECIAL_COST)
|
||||||
|
{
|
||||||
|
System.out.println(RED + "❌ Not enough MP!" + RESET);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp -= SPECIAL_COST;
|
||||||
|
|
||||||
|
int dmg = weapon.getDamage() + 60;
|
||||||
|
target.takeDamage(dmg);
|
||||||
|
|
||||||
|
System.out.println(BLUE + "🌪️ ARCANE BURST hits for " +
|
||||||
|
dmg + " damage!" + RESET);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,10 +2,14 @@ package org.project.item;
|
|||||||
|
|
||||||
import org.project.entity.Entity;
|
import org.project.entity.Entity;
|
||||||
|
|
||||||
public interface Item {
|
public interface Item
|
||||||
|
{
|
||||||
void use(Entity target);
|
void use(Entity target);
|
||||||
|
|
||||||
/*
|
String getName();
|
||||||
TODO: ADD OTHER REQUIRED AND BONUS METHODS
|
|
||||||
*/
|
String getDescription();
|
||||||
|
|
||||||
|
int getValue();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,36 +7,67 @@ public abstract class Armor {
|
|||||||
private int durability;
|
private int durability;
|
||||||
private int maxDurability;
|
private int maxDurability;
|
||||||
|
|
||||||
private boolean isBroke;
|
private boolean isBroken;
|
||||||
|
|
||||||
public Armor(int defense, int durability) {
|
public Armor(int defense, int durability) {
|
||||||
this.defense = defense;
|
this.defense = defense;
|
||||||
|
this.maxDefense = defense;
|
||||||
this.durability = durability;
|
this.durability = durability;
|
||||||
|
this.maxDurability = durability;
|
||||||
|
this.isBroken = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void checkBreak() {
|
public void takeHit(int damage)
|
||||||
|
{
|
||||||
|
durability -= damage;
|
||||||
|
|
||||||
|
if (durability < 0)
|
||||||
|
{
|
||||||
|
durability = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkBroken();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkBroken() {
|
||||||
if (durability <= 0) {
|
if (durability <= 0) {
|
||||||
isBroke = true;
|
isBroken = true;
|
||||||
defense = 0;
|
defense = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: (BONUS) UPDATE THE REPAIR METHOD
|
// TODO: (BONUS) UPDATE THE REPAIR METHOD
|
||||||
public void repair() {
|
public void repair()
|
||||||
isBroke = false;
|
{
|
||||||
|
isBroken = false;
|
||||||
defense = maxDefense;
|
defense = maxDefense;
|
||||||
durability = maxDurability;
|
durability = maxDurability;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getDefense() {
|
public int getDefense()
|
||||||
|
{
|
||||||
return defense;
|
return defense;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getDurability() {
|
public int getDurability()
|
||||||
|
{
|
||||||
return durability;
|
return durability;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isBroke() {
|
public int getMaxDefense()
|
||||||
return isBroke;
|
{
|
||||||
|
return maxDefense;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getMaxDurability()
|
||||||
|
{
|
||||||
|
return maxDurability;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isBroken()
|
||||||
|
{
|
||||||
|
return isBroken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract String getArmorName();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,16 @@
|
|||||||
package org.project.item.armors;
|
package org.project.item.armors;
|
||||||
|
|
||||||
// TODO: UPDATE IMPLEMENTATION
|
public class KnightArmor extends Armor
|
||||||
public class KnightArmor {
|
{
|
||||||
// TODO: DESIGN ARMOR'S ATTRIBUTES IMPLEMENT THE CONSTRUCTOR
|
|
||||||
}
|
public KnightArmor()
|
||||||
|
{
|
||||||
|
super(30, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getArmorName()
|
||||||
|
{
|
||||||
|
return "Knight's Plate Armor";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,8 +1,50 @@
|
|||||||
package org.project.item.consumables;
|
package org.project.item.consumables;
|
||||||
|
|
||||||
// TODO: UPDATE IMPLEMENTATION
|
import org.project.entity.Entity;
|
||||||
public abstract class Consumable {
|
|
||||||
/*
|
public abstract class Consumable
|
||||||
TODO: ADD OTHER REQUIRED AND BONUS METHODS
|
{
|
||||||
*/
|
|
||||||
|
protected String name;
|
||||||
|
protected String description;
|
||||||
|
protected int restoreAmount;
|
||||||
|
protected boolean percentageBased;
|
||||||
|
|
||||||
|
public Consumable(String name, String description, int restoreAmount, boolean percentageBased)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
this.description = description;
|
||||||
|
this.restoreAmount = restoreAmount;
|
||||||
|
this.percentageBased = percentageBased;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public abstract void use(Entity target);
|
||||||
|
|
||||||
|
|
||||||
|
public String getName()
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRestoreAmount()
|
||||||
|
{
|
||||||
|
return restoreAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription()
|
||||||
|
{
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPercentageBased()
|
||||||
|
{
|
||||||
|
return percentageBased;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return name + " (" + description + ")";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,15 +2,44 @@ package org.project.item.consumables;
|
|||||||
|
|
||||||
import org.project.entity.Entity;
|
import org.project.entity.Entity;
|
||||||
|
|
||||||
// TODO: UPDATE IMPLEMENTATION
|
public class Flask extends Consumable
|
||||||
public class Flask {
|
{
|
||||||
/*
|
|
||||||
THIS IS AN EXAMPLE OF A CONSUMABLE DESIGN.
|
private static final int HEAL_AMOUNT = 30;
|
||||||
*/
|
|
||||||
|
public Flask()
|
||||||
|
{
|
||||||
|
super(
|
||||||
|
"Health Flask",
|
||||||
|
"A small flask that restores health.",
|
||||||
|
HEAL_AMOUNT,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: UPDATE USE METHOD
|
|
||||||
@Override
|
@Override
|
||||||
public void use(Entity target) {
|
public void use(Entity target)
|
||||||
target.heal(target.getMaxHP() / 10);
|
{
|
||||||
|
|
||||||
|
int healValue;
|
||||||
|
|
||||||
|
if (percentageBased)
|
||||||
|
{
|
||||||
|
healValue = target.getMaxHP() * restoreAmount / 100;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
healValue = restoreAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
target.heal(healValue);
|
||||||
|
|
||||||
|
System.out.println(
|
||||||
|
target.getName() +
|
||||||
|
" used " +
|
||||||
|
name +
|
||||||
|
" and restored " +
|
||||||
|
healValue +
|
||||||
|
" HP!"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package org.project.item.weapons;
|
||||||
|
|
||||||
|
import org.project.entity.Entity;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class BasicWeapon extends Weapon implements Serializable
|
||||||
|
{
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public BasicWeapon(String name, int damage)
|
||||||
|
{
|
||||||
|
super(name, damage, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void uniqueAbility(ArrayList<Entity> targets) {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,26 +1,64 @@
|
|||||||
package org.project.item.weapons;
|
package org.project.item.weapons;
|
||||||
|
|
||||||
import org.project.entity.Entity;
|
import org.project.entity.Entity;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
// TODO: UPDATE IMPLEMENTATION
|
public class Sword extends Weapon implements Serializable
|
||||||
public class Sword {
|
{
|
||||||
/*
|
|
||||||
THIS IS AN EXAMPLE OF A WEAPON DESIGN.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int abilityCharge;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
public Sword() {
|
private int abilityCharge;
|
||||||
// TODO: DESIGN SWORD'S ATTRIBUTES IMPLEMENT THE CONSTRUCTOR
|
private static final int MAX_CHARGE = 10;
|
||||||
|
private static final int REQUIRED_CHARGE = 5;
|
||||||
|
|
||||||
|
public Sword()
|
||||||
|
{
|
||||||
|
super("Knight Sword", 20, 0);
|
||||||
|
this.abilityCharge = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: (BONUS) UPDATE THE UNIQUE ABILITY
|
@Override
|
||||||
public void uniqueAbility(ArrayList<Entity> targets) {
|
public void uniqueAbility(ArrayList<Entity> targets)
|
||||||
abilityCharge += 2;
|
{
|
||||||
for (Entity target : targets) {
|
if (abilityCharge < REQUIRED_CHARGE)
|
||||||
target.takeDamage(getDamage());
|
{
|
||||||
|
System.out.println("⚠️ Not enough charge for special ability! (" + abilityCharge + "/" + REQUIRED_CHARGE + ")");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isBroken)
|
||||||
|
{
|
||||||
|
System.out.println("⚠️ " + name + " is broken and can't use its special ability!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("⚔️ " + name + " special ability: Cleave!");
|
||||||
|
for (Entity target : targets)
|
||||||
|
{
|
||||||
|
if (target != null && target.isAlive())
|
||||||
|
{
|
||||||
|
target.takeDamage((int) (getDamage() * 1.5));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abilityCharge = 0;
|
||||||
|
reduceDurability(5);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public void addCharge(int amount)
|
||||||
|
{
|
||||||
|
this.abilityCharge = Math.min(this.abilityCharge + amount, MAX_CHARGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAbilityCharge()
|
||||||
|
{
|
||||||
|
return abilityCharge;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxCharge()
|
||||||
|
{
|
||||||
|
return MAX_CHARGE;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,35 +1,87 @@
|
|||||||
package org.project.item.weapons;
|
package org.project.item.weapons;
|
||||||
|
|
||||||
import org.project.entity.Entity;
|
import org.project.entity.Entity;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
// TODO: UPDATE IMPLEMENTATION
|
public abstract class Weapon implements Serializable
|
||||||
public abstract class Weapon {
|
{
|
||||||
private int damage;
|
|
||||||
private int manaCost;
|
|
||||||
|
|
||||||
/*
|
private static final long serialVersionUID = 1L;
|
||||||
TODO: ADD OTHER REQUIRED AND BONUS ATTRIBUTES
|
|
||||||
*/
|
|
||||||
|
|
||||||
public Weapon(int damage, int manaCost) {
|
protected String name;
|
||||||
|
protected int damage;
|
||||||
|
protected int manaCost;
|
||||||
|
protected int level;
|
||||||
|
protected int durability;
|
||||||
|
protected boolean isBroken;
|
||||||
|
|
||||||
|
public Weapon(String name, int damage, int manaCost)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
this.damage = damage;
|
this.damage = damage;
|
||||||
this.manaCost = manaCost;
|
this.manaCost = manaCost;
|
||||||
|
this.level = 1;
|
||||||
|
this.durability = 100;
|
||||||
|
this.isBroken = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void use(Entity target)
|
||||||
public void use(Entity target) {
|
{
|
||||||
|
if (isBroken)
|
||||||
|
{
|
||||||
|
System.out.println("⚠️ " + name + " is broken and can't be used!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
target.takeDamage(damage);
|
target.takeDamage(damage);
|
||||||
|
reduceDurability(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getDamage() {
|
public abstract void uniqueAbility(ArrayList<Entity> targets);
|
||||||
|
|
||||||
|
protected void reduceDurability(int amount)
|
||||||
|
{
|
||||||
|
durability = Math.max(0, durability - amount);
|
||||||
|
if (durability == 0)
|
||||||
|
{
|
||||||
|
isBroken = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void upgrade()
|
||||||
|
{
|
||||||
|
level++;
|
||||||
|
damage += 5;
|
||||||
|
System.out.println("🛠️ " + name + " upgraded to level " + level + "!");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDamage()
|
||||||
|
{
|
||||||
return damage;
|
return damage;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getManaCost() {
|
public int getManaCost()
|
||||||
|
{
|
||||||
return manaCost;
|
return manaCost;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
public int getLevel()
|
||||||
TODO: ADD OTHER REQUIRED AND BONUS METHODS
|
{
|
||||||
*/
|
return level;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getDurability()
|
||||||
|
{
|
||||||
|
return durability;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isBroken()
|
||||||
|
{
|
||||||
|
return isBroken;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,28 +1,64 @@
|
|||||||
package org.project.location;
|
package org.project.location;
|
||||||
|
|
||||||
import org.project.entity.enemies.Enemy;
|
import org.project.entity.enemies.*;
|
||||||
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
public class Location {
|
public class Location implements Serializable
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
|
private String description;
|
||||||
|
private int difficulty; // 1 = easy, 2 = medium, 3 = hard
|
||||||
|
private ArrayList<Location> connectedLocations;
|
||||||
|
|
||||||
private ArrayList<Enemy> enemies;
|
public Location(String name, String description, int difficulty)
|
||||||
|
{
|
||||||
public Location(ArrayList<Location> locations, ArrayList<Enemy> enemies) {
|
this.name = name;
|
||||||
this.locations = locations;
|
this.description = description;
|
||||||
this.enemies = enemies;
|
this.difficulty = difficulty;
|
||||||
|
this.connectedLocations = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public void connectLocation(Location location)
|
||||||
|
{
|
||||||
|
connectedLocations.add(location);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<Location> getConnectedLocations()
|
||||||
|
{
|
||||||
|
return connectedLocations;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName()
|
||||||
|
{
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArrayList<Location> getLocations() {
|
public int getDifficulty()
|
||||||
return locations;
|
{
|
||||||
|
return difficulty;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArrayList<Enemy> getEnemies() {
|
public void enter()
|
||||||
return enemies;
|
{
|
||||||
|
System.out.println("\n==============================");
|
||||||
|
System.out.println("📍 You arrived at: " + name);
|
||||||
|
System.out.println(description);
|
||||||
|
System.out.println("Difficulty: " + difficulty);
|
||||||
|
System.out.println("==============================\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Enemy spawnEnemy()
|
||||||
|
{
|
||||||
|
return switch (name)
|
||||||
|
{
|
||||||
|
case "Forest" -> new Goblin();
|
||||||
|
case "Graveyard" -> new Skeleton();
|
||||||
|
case "Vampire Crypt" -> new Vampire();
|
||||||
|
case "Dragon Castle" -> new Dragon();
|
||||||
|
default -> new Goblin();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package org.project.utils;
|
||||||
|
|
||||||
|
import org.project.GameState;
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public class SaveLoadManager {
|
||||||
|
|
||||||
|
public static void saveGame(GameState gameState, String filename) {
|
||||||
|
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filename))) {
|
||||||
|
oos.writeObject(gameState);
|
||||||
|
System.out.println("\u001B[34m\u2714\u001B[0m Game saved successfully.");
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.out.println("\u001B[31m\u2716\u001B[0m Error saving game: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GameState loadGame(String filename) {
|
||||||
|
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename))) {
|
||||||
|
GameState loadedState = (GameState) ois.readObject();
|
||||||
|
System.out.println("\u001B[32m\u2714\u001B[0m Game loaded successfully.");
|
||||||
|
return loadedState;
|
||||||
|
} catch (IOException | ClassNotFoundException e) {
|
||||||
|
System.out.println("\u001B[31m\u2716\u001B[0m Error loading game: " + e.getMessage());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+162
@@ -0,0 +1,162 @@
|
|||||||
|
# ⚔️ Java Knight: The Legend of Javanest
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
**Java Knight** is a text-based RPG game developed in Java.
|
||||||
|
Embark on an epic adventure through the lands of **Javanest**, battle dangerous enemies, collect ancient keys, and face the ultimate **Dragon Boss** to save the kingdom.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🌟 Core Features
|
||||||
|
|
||||||
|
- 🎭 **Multiple Playable Classes** (Knight, Wizard, Assassin)
|
||||||
|
- 🗺️ **Location-Based Exploration System**
|
||||||
|
- ⚔️ **Turn-Based Combat Mechanics**
|
||||||
|
- 🔑 **Key Collection & Progression System**
|
||||||
|
- 💾 **Save / Load Ready (Java Serialization)**
|
||||||
|
- 📊 **RPG Systems**: HP, MP, XP, Levels
|
||||||
|
- 🛡️ **Weapons, Armor & Durability**
|
||||||
|
- 🐉 **Final Boss Battle**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🛡️ Playable Classes
|
||||||
|
|
||||||
|
| Class | HP | MP | Starting Weapon | Playstyle |
|
||||||
|
|------|----|----|----------------|-----------|
|
||||||
|
| **Knight** | High | Low | Sword | Tank / Physical Damage |
|
||||||
|
| **Wizard** | Medium | High | Magic Staff | Magic & Healing |
|
||||||
|
| **Assassin** | Medium | Medium | Daggers | Stealth & Burst Damage |
|
||||||
|
|
||||||
|
Each class has **unique abilities**, different mana costs, and a distinct combat style.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🗺️ World Map
|
||||||
|
|
||||||
|
Explore the dangerous regions of Javanest:
|
||||||
|
|
||||||
|
1. **Forest (Difficulty 1)**
|
||||||
|
_A dark forest full of Goblins._
|
||||||
|
|
||||||
|
2. **Graveyard (Difficulty 2)**
|
||||||
|
_An abandoned graveyard haunted by Skeletons._
|
||||||
|
|
||||||
|
3. **Vampire Crypt (Difficulty 3)**
|
||||||
|
_A cursed crypt ruled by Vampires._
|
||||||
|
|
||||||
|
4. **Dragon Castle (Difficulty 4)**
|
||||||
|
_The final destination and home of the Dragon._
|
||||||
|
|
||||||
|
Locations are connected, allowing the player to move freely between unlocked areas.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎮 Game Flow
|
||||||
|
|
||||||
|
1. Start the game
|
||||||
|
2. Enter your player name
|
||||||
|
3. Choose a class
|
||||||
|
4. Begin in the **Forest**
|
||||||
|
5. Fight enemies and gain XP
|
||||||
|
6. Collect special keys
|
||||||
|
7. Unlock the **Dragon Castle**
|
||||||
|
8. Defeat the Dragon and save Javanest
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧭 Main Menu
|
||||||
|
|
||||||
|
At launch, the player is presented with the main menu:
|
||||||
|
```text
|
||||||
|
===============================
|
||||||
|
⚔ JAVA KNIGHT ⚔
|
||||||
|
===============================
|
||||||
|
1. Start Game
|
||||||
|
2. How To Play
|
||||||
|
3. Exit
|
||||||
|
Menu Options
|
||||||
|
Start Game – Begin a new adventure
|
||||||
|
How To Play – Learn the rules and objective
|
||||||
|
Exit – Close the game
|
||||||
|
🏰 In-Game Menu
|
||||||
|
While exploring a location, the player can choose:
|
||||||
|
|
||||||
|
text
|
||||||
|
1. Fight Enemy
|
||||||
|
2. Move Location
|
||||||
|
3. Enter Dragon Castle (if unlocked)
|
||||||
|
Fight Enemy – Starts a battle based on the current location
|
||||||
|
Move Location – Travel to connected locations
|
||||||
|
Enter Dragon Castle – Available only after collecting all keys
|
||||||
|
⚔️ Combat System
|
||||||
|
Combat is turn-based and class-dependent.
|
||||||
|
|
||||||
|
Available Actions
|
||||||
|
Light Attack
|
||||||
|
Heavy Attack
|
||||||
|
Defend
|
||||||
|
Heal
|
||||||
|
Special Ability
|
||||||
|
Exit Battle
|
||||||
|
Combat Rules
|
||||||
|
Attacks may consume MP
|
||||||
|
Special abilities are unique per class
|
||||||
|
Enemies attack after the player’s turn
|
||||||
|
Winning a battle grants XP
|
||||||
|
Enemies may drop keys
|
||||||
|
🔑 Key System
|
||||||
|
To unlock the final area, the player must collect:
|
||||||
|
|
||||||
|
🗝️ Goblin Key
|
||||||
|
🗝️ Skeleton Key
|
||||||
|
🗝️ Vampire Key
|
||||||
|
Each key drops from enemies in its respective location.
|
||||||
|
|
||||||
|
Once all keys are collected, the Dragon Castle becomes accessible.
|
||||||
|
|
||||||
|
📈 Progression System
|
||||||
|
HP (Health Points)
|
||||||
|
MP (Mana Points)
|
||||||
|
XP (Experience Points)
|
||||||
|
Level System
|
||||||
|
Weapon Durability
|
||||||
|
Progression rewards strategic combat and exploration.
|
||||||
|
|
||||||
|
💾 Save & Load System
|
||||||
|
The project is prepared for game saving using Java Serialization.
|
||||||
|
|
||||||
|
Serializable Components
|
||||||
|
Player
|
||||||
|
Location
|
||||||
|
Weapon
|
||||||
|
GameState
|
||||||
|
This allows the game to be saved and restored at any point.
|
||||||
|
|
||||||
|
🚀 Getting Started
|
||||||
|
Requirements
|
||||||
|
Java JDK 17 or higher
|
||||||
|
Terminal or Java IDE (IntelliJ IDEA, Eclipse, VS Code)
|
||||||
|
Run the Game
|
||||||
|
bash
|
||||||
|
javac -d out src/org/project/**/*.java
|
||||||
|
java -cp out org.project.Main
|
||||||
|
Or simply run Main.java from your IDE.
|
||||||
|
|
||||||
|
🛠️ Project Architecture
|
||||||
|
Object-Oriented Design
|
||||||
|
Clean separation of concerns
|
||||||
|
Interfaces & abstract classes
|
||||||
|
Easily extendable structure
|
||||||
|
Console-based UI with ANSI colors
|
||||||
|
🔮 Future Improvements
|
||||||
|
Inventory management menu
|
||||||
|
More weapons and consumables
|
||||||
|
Enhanced armor mechanics
|
||||||
|
Expanded world map
|
||||||
|
Graphical UI (JavaFX / Swing)
|
||||||
|
📜 License
|
||||||
|
This project is licensed under the MIT License.
|
||||||
|
|
||||||
Reference in New Issue
Block a user