Job + Spell merge #9

Merged
erns6604 merged 23 commits from Job into main 2025-10-27 12:18:22 +01:00
12 changed files with 192 additions and 27 deletions
Showing only changes of commit 9892a229dc - Show all commits

View File

@@ -0,0 +1,19 @@
package Action;
import Job.HasJob;
import Job.Wizard;
public class CastAction implements Action {
@Override
public void exectue(Actor actor) {
Wizard wizard = requireWizard(actor);
wizard.castSpell(actor);
}
private Wizard requireWizard(Actor actor) {
if (actor instanceof HasJob hasJob && hasJob.getJob() instanceof Wizard wizard) {
return wizard;
}
throw new IllegalStateException(actor + " cannot perform this action without being a Wizard!");
}
}

View File

@@ -2,5 +2,6 @@ package Combat;
public interface HasHealth { public interface HasHealth {
void setHealth(int health); void setHealth(int health);
int getHealth();
boolean isAlive(); boolean isAlive();
} }

View File

@@ -0,0 +1,6 @@
package Combat;
public interface HasMana {
void setMana(int mana);
int getMana();
}

View File

@@ -0,0 +1,18 @@
package Combat;
import Entity.Entity;
public class OffensiveDamageSpell extends Spell {
public OffensiveDamageSpell(String spellName, int cost, int potency) {
super(spellName, cost, potency);
}
@Override
public void cast(Entity source, Entity target) {
if(target instanceof HasHealth health && source instanceof HasMana mana) {
mana.setMana(mana.getMana() - this.getCost());
health.setHealth(health.getHealth() - this.getPotency());
}
}
}

View File

@@ -0,0 +1,54 @@
package Combat;
import Entity.Entity;
public abstract class Spell {
private final String spellName;
private int cost;
private int potency;
public Spell(String spellName, int cost, int potency) {
this.spellName = spellName;
this.cost = cost;
this.potency = potency;
}
public String getSpellName() {
return spellName;
}
public int getCost() {
return cost;
}
public int getPotency() {
return potency;
}
public abstract void cast(Entity source, Entity target);
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Spell spell = (Spell) o;
if (cost != spell.cost) return false;
if (potency != spell.potency) return false;
return spellName.equals(spell.spellName);
}
@Override
public int hashCode() {
int result = spellName.hashCode();
result = 31 * result + cost;
result = 31 * result + potency;
return result;
}
@Override
public String toString() {
return spellName + " (Cost: " + cost + ", Potency: " + potency + ")";
}
}

View File

@@ -3,6 +3,8 @@ package Entity;
import Action.Action; import Action.Action;
import Action.Actor; import Action.Actor;
import Combat.HasHealth; import Combat.HasHealth;
import Combat.HasMana;
import Combat.Spell;
import Job.Job; import Job.Job;
import Job.HasJob; import Job.HasJob;
import Inventory.HasInventory; import Inventory.HasInventory;
@@ -11,12 +13,13 @@ import Inventory.HasSpellBook;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
public class Player extends Entity implements Movable, Actor, HasInventory, HasJob, HasHealth { public class Player extends Entity implements Movable, Actor, HasInventory, HasSpellBook, HasJob, HasHealth, HasMana {
protected int health; protected int health;
protected int mana;
protected Job job; protected Job job;
protected Position position; protected Position position;
protected List<String> items = new LinkedList<>(); protected List<String> items = new LinkedList<>();
protected List<String> spells = new LinkedList<>(); protected List<Spell> spells = new LinkedList<>();
public Player(String name, Job job) { public Player(String name, Job job) {
super(name); super(name);
this.job = job; this.job = job;
@@ -51,7 +54,7 @@ public class Player extends Entity implements Movable, Actor, HasInventory, HasJ
return items; return items;
} }
public List<String> getSpellBook() {return spells;} public List<Spell> getSpellBook() {return spells;}
@Override @Override
public void performAction(Action action) { public void performAction(Action action) {
@@ -73,6 +76,15 @@ public class Player extends Entity implements Movable, Actor, HasInventory, HasJ
this.health = health; this.health = health;
} }
@Override
public int getHealth() {return health;}
@Override
public void setMana(int mana) {this.mana = mana;}
@Override
public int getMana() {return mana;}
@Override @Override
public boolean isAlive() { public boolean isAlive() {
return health > 0; return health > 0;

View File

@@ -1,7 +1,8 @@
package Inventory; package Inventory;
import java.util.List; import java.util.List;
import Combat.Spell;
public interface HasSpellBook { public interface HasSpellBook {
List<String> getSpellBook(); List<Spell> getSpellBook();
} }

View File

@@ -1,14 +1,53 @@
package Job; package Job;
import Action.Actor; import Action.Actor;
import Character.HasSpellBook; import Combat.HasMana;
import Combat.OffensiveDamageSpell;
import Entity.Entity;
import Inventory.HasSpellBook;
import Combat.Spell;
import java.util.Scanner;
public class Wizard extends Job { public class Wizard extends Job {
private static final Scanner scanner = new Scanner(System.in);
public Wizard() {super("Wizard");} public Wizard() {super("Wizard");}
public void learnSpell(Actor actor) { public void learnSpell(Actor actor) {
if(actor instanceof HasSpellBook a ) { if(actor instanceof HasSpellBook a ) {
a.getSpellBook().add("Fireball"); OffensiveDamageSpell defaultSpell = new OffensiveDamageSpell("fireball", 20, 20);
a.getSpellBook().add(defaultSpell);
}
}
public void castSpell(Actor actor) {
if(actor instanceof HasSpellBook spellbook && actor instanceof HasMana mana && actor instanceof Entity entity) {
if(spellbook.getSpellBook().isEmpty()){
System.out.println("You haven't learned any spells");
return;
}
System.out.println("Which spell do you want to cast?");
for(int i = 0; i < spellbook.getSpellBook().size(); i++){
System.out.println((i + 1) + ". " + spellbook.getSpellBook().get(i).toString());
}
int spellIndex = scanner.nextInt();
scanner.nextLine();
if(spellIndex < 1 || spellIndex > spellbook.getSpellBook().size()) {
System.out.println("Invalid choice!");
return;
}
Spell spell = spellbook.getSpellBook().get(spellIndex - 1);
if (mana.getMana() >= spell.getCost()){
spell.cast(entity, entity);
}
else{
System.out.println("Not enough mana!");
}
} }
} }

View File

@@ -1,18 +0,0 @@
public class Spell {
private final String spellName;
private int cost;
private int potency;
public Spell(String spellName, int cost, int potency) {
this.spellName = spellName;
this.cost = cost;
this.potency = potency;
}
public String getSpellName() {return spellName;}
public int getCost() {return cost;}
public int getPotency() {return potency;}
}

View File

@@ -1,5 +1,6 @@
import Action.DigAction; import Action.DigAction;
import Action.learnSpellAction; import Action.learnSpellAction;
import Combat.OffensiveDamageSpell;
import Entity.Position; import Entity.Position;
import Job.Miner; import Job.Miner;
import Entity.Player; import Entity.Player;
@@ -45,4 +46,15 @@ class PlayerTest {
p.performAction(new DigAction()); p.performAction(new DigAction());
assertTrue(p.getInventory().contains("Stone")); assertTrue(p.getInventory().contains("Stone"));
} }
@Test
void wizard_can_learn_spell() {
var p = new Player("Bob");
var job = new Wizard();
var defaultSpell = new OffensiveDamageSpell("fireball", 20, 20);
p.learnJob(job);
p.performAction(new learnSpellAction());
System.out.println(p.getSpellBook());
assertTrue(p.getSpellBook().contains(defaultSpell));
}
} }

View File

@@ -1,3 +1,5 @@
import Combat.OffensiveDamageSpell;
import Combat.Spell;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
@@ -5,19 +7,19 @@ import static org.junit.jupiter.api.Assertions.*;
public class SpellTest { public class SpellTest {
private Spell defaultSpell() { private Spell defaultSpell() {
return new Spell("fireball", 20, 40); return new OffensiveDamageSpell("fireball", 20, 40);
} }
@Test @Test
void setSpellNameOnCreation(){ void setSpellNameOnCreation(){
var spell = defaultSpell(); var spell = defaultSpell();
assertEquals("fireball", spell.getSpellName(), "Spell name should be set"); assertEquals("fireball", spell.getSpellName(), "Combat.Spell name should be set");
} }
@Test @Test
void setCostOnCreation() { void setCostOnCreation() {
var spell = defaultSpell(); var spell = defaultSpell();
assertEquals(20, spell.getCost(), "Spell cost should have been set"); assertEquals(20, spell.getCost(), "Combat.Spell cost should have been set");
} }
@Test @Test

View File

@@ -4,4 +4,23 @@ import static org.junit.jupiter.api.Assertions.*;
public class WizardTest { public class WizardTest {
@Test
void wizard_has_level() {
var job = new Wizard();
assertEquals(1, job.getLevel());
}
@Test
void wizard_can_level_up() {
var job = new Wizard();
job.levelUp();
assertEquals(2, job.getLevel());
}
@Test
void wizard_can_gain_xp(){
var job = new Wizard();
job.gainExperience(40);
assertEquals(40, job.getExperience());
}
} }