feat: add thanos into the handling
This commit is contained in:
parent
1ba5410fd6
commit
9a9fe4ae97
@ -46,6 +46,9 @@ public class Character extends Entity {
|
|||||||
super(id, position);
|
super(id, position);
|
||||||
solid = false;
|
solid = false;
|
||||||
opaque = true;
|
opaque = true;
|
||||||
|
if(id.type == EntityType.NPC && id.id == 2) {
|
||||||
|
solid = true; //characters cannot walk into thanos
|
||||||
|
}
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.hp = new Stat(StatType.HP, hp);
|
this.hp = new Stat(StatType.HP, hp);
|
||||||
this.mp = new Stat(StatType.MP, mp);
|
this.mp = new Stat(StatType.MP, mp);
|
||||||
@ -65,7 +68,7 @@ public class Character extends Entity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Character clone() {
|
public Character clone() {
|
||||||
Character clone = new Character(id, position, name, hp.max, mp.max, ap.max, attackRange, rangedDamage, meleeDamage);
|
Character clone = new Character(id, position, name, hp.getMax(), mp.getMax(), ap.getMax(), attackRange, rangedDamage, meleeDamage);
|
||||||
for(StoneType stone: inventory) {
|
for(StoneType stone: inventory) {
|
||||||
clone.inventory.addStone(stone);
|
clone.inventory.addStone(stone);
|
||||||
}
|
}
|
||||||
|
@ -2,26 +2,8 @@ package uulm.teamname.marvelous.gamelibrary.entities;
|
|||||||
|
|
||||||
import uulm.teamname.marvelous.gamelibrary.IntVector2;
|
import uulm.teamname.marvelous.gamelibrary.IntVector2;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
/** Represents an NPC inside the game. */
|
/** Represents an NPC inside the game. */
|
||||||
public class NPC extends Entity {
|
public class NPC extends Entity {
|
||||||
/** The {@link Inventory} of the NPC */
|
|
||||||
public final Inventory inventory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new {@link NPC}.
|
|
||||||
* @param id The {@link EntityID} of the NPC
|
|
||||||
* @param position The position of the NPC
|
|
||||||
* @param inventory The starting inventory the NPC should have
|
|
||||||
*/
|
|
||||||
public NPC(EntityID id, IntVector2 position, ArrayList<StoneType> inventory) {
|
|
||||||
super(id, position);
|
|
||||||
solid = false;
|
|
||||||
opaque = true;
|
|
||||||
this.inventory = new Inventory(inventory);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new {@link NPC} with an empty inventory.
|
* Constructs a new {@link NPC} with an empty inventory.
|
||||||
* @param id The {@link EntityID} of the NPC
|
* @param id The {@link EntityID} of the NPC
|
||||||
@ -29,15 +11,12 @@ public class NPC extends Entity {
|
|||||||
*/
|
*/
|
||||||
public NPC(EntityID id, IntVector2 position) {
|
public NPC(EntityID id, IntVector2 position) {
|
||||||
super(id, position);
|
super(id, position);
|
||||||
this.inventory = new Inventory();
|
solid = false;
|
||||||
|
opaque = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NPC clone() {
|
public NPC clone() {
|
||||||
NPC clone = new NPC(id, position);
|
return new NPC(id, position);
|
||||||
for(StoneType stone: inventory) {
|
|
||||||
clone.inventory.addStone(stone);
|
|
||||||
}
|
|
||||||
return clone;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ public class Stat {
|
|||||||
public final StatType type;
|
public final StatType type;
|
||||||
|
|
||||||
/** The maximum value of the stat */
|
/** The maximum value of the stat */
|
||||||
public final int max;
|
private int max;
|
||||||
|
|
||||||
/** The current value of the stat */
|
/** The current value of the stat */
|
||||||
private int value;
|
private int value;
|
||||||
@ -40,25 +40,33 @@ public class Stat {
|
|||||||
this.value -= value;
|
this.value -= value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getMax() {
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMax(int max) {
|
||||||
|
this.max = max;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
Stat stat = (Stat) o;
|
Stat stat = (Stat) o;
|
||||||
return max == stat.max && value == stat.value && type == stat.type;
|
return getMax() == stat.getMax() && value == stat.value && type == stat.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(type, max, value);
|
return Objects.hash(type, getMax(), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Stat{" +
|
return "Stat{" +
|
||||||
"type=" + type +
|
"type=" + type +
|
||||||
", max=" + max +
|
", max=" + getMax() +
|
||||||
", value=" + value +
|
", value=" + value +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
|
@ -141,7 +141,7 @@ class GameLogic {
|
|||||||
}
|
}
|
||||||
case TimeStone -> {
|
case TimeStone -> {
|
||||||
Character origin = (Character)state.entities.findEntity(data.originEntity);
|
Character origin = (Character)state.entities.findEntity(data.originEntity);
|
||||||
int ap = origin.ap.max - origin.ap.getValue();
|
int ap = origin.ap.getMax() - origin.ap.getValue();
|
||||||
if(ap < 0) {
|
if(ap < 0) {
|
||||||
result.add(new EventBuilder(EventType.ConsumedAPEvent)
|
result.add(new EventBuilder(EventType.ConsumedAPEvent)
|
||||||
.withTargetEntity(data.originEntity)
|
.withTargetEntity(data.originEntity)
|
||||||
@ -149,7 +149,7 @@ class GameLogic {
|
|||||||
.withAmount(ap)
|
.withAmount(ap)
|
||||||
.buildEntityEvent());
|
.buildEntityEvent());
|
||||||
}
|
}
|
||||||
int mp = origin.mp.max - origin.mp.getValue();
|
int mp = origin.mp.getMax() - origin.mp.getValue();
|
||||||
if(mp < 0) {
|
if(mp < 0) {
|
||||||
result.add(new EventBuilder(EventType.ConsumedMPEvent)
|
result.add(new EventBuilder(EventType.ConsumedMPEvent)
|
||||||
.withTargetEntity(data.originEntity)
|
.withTargetEntity(data.originEntity)
|
||||||
@ -163,7 +163,7 @@ class GameLogic {
|
|||||||
result.add(new EventBuilder(EventType.HealedEvent)
|
result.add(new EventBuilder(EventType.HealedEvent)
|
||||||
.withTargetEntity(data.targetEntity)
|
.withTargetEntity(data.targetEntity)
|
||||||
.withTargetField(data.targetField)
|
.withTargetField(data.targetField)
|
||||||
.withAmount(target.hp.max)
|
.withAmount(target.hp.getMax())
|
||||||
.buildEntityEvent());
|
.buildEntityEvent());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -364,7 +364,7 @@ class GameLogic {
|
|||||||
*/
|
*/
|
||||||
private static Character getCharacter(GameState state, IntVector2 position, EntityID entityID) throws InvalidRequestException {
|
private static Character getCharacter(GameState state, IntVector2 position, EntityID entityID) throws InvalidRequestException {
|
||||||
Entity entity = state.entities.findEntity(entityID);
|
Entity entity = state.entities.findEntity(entityID);
|
||||||
if(entity == null || entity.getPosition() != position || !(entity instanceof Character)) {
|
if(entity == null || entity.getPosition() != position || !(entity instanceof Character) || entity.id.type == EntityType.NPC) {
|
||||||
throw new InvalidRequestException();
|
throw new InvalidRequestException();
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
@ -629,6 +629,10 @@ class GameLogic {
|
|||||||
ArrayList<EntityID> alive = new ArrayList<>();
|
ArrayList<EntityID> alive = new ArrayList<>();
|
||||||
|
|
||||||
for (EntityID id: state.turnOrder) {
|
for (EntityID id: state.turnOrder) {
|
||||||
|
if(id.type == EntityType.NPC) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
Character character = ((Character)state.entities.findEntity(id));
|
Character character = ((Character)state.entities.findEntity(id));
|
||||||
|
|
||||||
if(character.hp.getValue() > 0){
|
if(character.hp.getValue() > 0){
|
||||||
@ -682,7 +686,9 @@ class GameLogic {
|
|||||||
result.addAll(handleStan(state, revived));
|
result.addAll(handleStan(state, revived));
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: add handling for thanos
|
if(state.roundNumber == state.partyConfig.maxRounds + 1) {
|
||||||
|
result.addAll(spawnThanos(state));
|
||||||
|
}
|
||||||
|
|
||||||
Collections.shuffle(state.turnOrder);
|
Collections.shuffle(state.turnOrder);
|
||||||
|
|
||||||
@ -783,11 +789,11 @@ class GameLogic {
|
|||||||
if(character.hp.getValue() == 0) {
|
if(character.hp.getValue() == 0) {
|
||||||
revived.add(character.id);
|
revived.add(character.id);
|
||||||
}
|
}
|
||||||
if(character.hp.getValue() != character.hp.max) {
|
if(character.hp.getValue() != character.hp.getMax()) {
|
||||||
result.add(new EventBuilder(EventType.HealedEvent)
|
result.add(new EventBuilder(EventType.HealedEvent)
|
||||||
.withTargetEntity(character.id)
|
.withTargetEntity(character.id)
|
||||||
.withTargetField(character.getPosition())
|
.withTargetField(character.getPosition())
|
||||||
.withAmount(character.hp.max - character.hp.getValue())
|
.withAmount(character.hp.getMax() - character.hp.getValue())
|
||||||
.buildEntityEvent());
|
.buildEntityEvent());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -801,6 +807,49 @@ class GameLogic {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spawns Thanos at the beginning of the first overtime round.
|
||||||
|
* @param state The game state to work on
|
||||||
|
* @return The list of resulting {@link Event}s
|
||||||
|
*/
|
||||||
|
public static ArrayList<Event> spawnThanos(GameState state) {
|
||||||
|
ArrayList<Event> result = new ArrayList<>();
|
||||||
|
|
||||||
|
ArrayList<IntVector2> free = getFreeFields(state);
|
||||||
|
IntVector2 position = free.get(rand.nextInt(free.size()));
|
||||||
|
|
||||||
|
int maxMP = -1;
|
||||||
|
for(EntityID id: state.turnOrder) {
|
||||||
|
Character character = (Character)state.entities.findEntity(id);
|
||||||
|
|
||||||
|
if(character.mp.getValue() > maxMP) {
|
||||||
|
maxMP = character.mp.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EntityID thanos = new EntityID(EntityType.NPC, 2);
|
||||||
|
result.add(new EventBuilder(EventType.SpawnEntityEvent)
|
||||||
|
.withEntity(new Character(thanos, position, "Thanos", 1, maxMP, 0, 0, 0, 0))
|
||||||
|
.buildEntityEvent());
|
||||||
|
|
||||||
|
state.turnOrder.add(thanos);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles Thanos' AI.
|
||||||
|
* @param state The game state to work on
|
||||||
|
* @return The list of resulting {@link Event}s
|
||||||
|
*/
|
||||||
|
public static ArrayList<Event> handleThanos(GameState state, Character thanos) {
|
||||||
|
ArrayList<Event> result = new ArrayList<>();
|
||||||
|
|
||||||
|
//TODO: implement thanos ai
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles everything that happens at the beginning of a turn.
|
* Handles everything that happens at the beginning of a turn.
|
||||||
* @param state The game state to work on
|
* @param state The game state to work on
|
||||||
@ -812,19 +861,24 @@ class GameLogic {
|
|||||||
state.turnNumber++;
|
state.turnNumber++;
|
||||||
|
|
||||||
Character activeCharacter = (Character)state.entities.findEntity(state.activeCharacter);
|
Character activeCharacter = (Character)state.entities.findEntity(state.activeCharacter);
|
||||||
|
boolean isThanos = state.activeCharacter.type == EntityType.NPC && state.activeCharacter.id == 2;
|
||||||
|
|
||||||
if(activeCharacter.ap.getValue() != activeCharacter.ap.max) {
|
if(isThanos && state.roundNumber > state.partyConfig.maxRounds + 1) {
|
||||||
|
activeCharacter.mp.setMax(activeCharacter.mp.getMax() + 1);//TODO: use event for this...
|
||||||
|
}
|
||||||
|
|
||||||
|
if(activeCharacter.ap.getValue() != activeCharacter.ap.getMax()) {
|
||||||
result.add(new EventBuilder(EventType.ConsumedAPEvent)
|
result.add(new EventBuilder(EventType.ConsumedAPEvent)
|
||||||
.withTargetEntity(state.activeCharacter)
|
.withTargetEntity(state.activeCharacter)
|
||||||
.withTargetField(activeCharacter.getPosition())
|
.withTargetField(activeCharacter.getPosition())
|
||||||
.withAmount(activeCharacter.ap.getValue() - activeCharacter.ap.max)
|
.withAmount(activeCharacter.ap.getValue() - activeCharacter.ap.getMax())
|
||||||
.buildGameEvent());
|
.buildGameEvent());
|
||||||
}
|
}
|
||||||
if(activeCharacter.mp.getValue() != activeCharacter.mp.max) {
|
if(activeCharacter.mp.getValue() != activeCharacter.mp.getMax()) {
|
||||||
result.add(new EventBuilder(EventType.ConsumedMPEvent)
|
result.add(new EventBuilder(EventType.ConsumedMPEvent)
|
||||||
.withTargetEntity(state.activeCharacter)
|
.withTargetEntity(state.activeCharacter)
|
||||||
.withTargetField(activeCharacter.getPosition())
|
.withTargetField(activeCharacter.getPosition())
|
||||||
.withAmount(activeCharacter.mp.getValue() - activeCharacter.mp.max)
|
.withAmount(activeCharacter.mp.getValue() - activeCharacter.mp.getMax())
|
||||||
.buildGameEvent());
|
.buildGameEvent());
|
||||||
}
|
}
|
||||||
result.add(new EventBuilder(EventType.TurnEvent)
|
result.add(new EventBuilder(EventType.TurnEvent)
|
||||||
@ -832,6 +886,10 @@ class GameLogic {
|
|||||||
.withNextCharacter(state.activeCharacter)
|
.withNextCharacter(state.activeCharacter)
|
||||||
.buildGameEvent());
|
.buildGameEvent());
|
||||||
|
|
||||||
|
if(isThanos) {
|
||||||
|
result.addAll(handleThanos(state, activeCharacter));
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,8 +62,7 @@ class EventBuilderTest {
|
|||||||
25),
|
25),
|
||||||
new NPC(
|
new NPC(
|
||||||
new EntityID(EntityType.NPC, 1),
|
new EntityID(EntityType.NPC, 1),
|
||||||
new IntVector2(11, 14),
|
new IntVector2(11, 14)
|
||||||
new ArrayList<>()
|
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4,9 +4,7 @@ import net.jqwik.api.*;
|
|||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import uulm.teamname.marvelous.gamelibrary.IntVector2;
|
import uulm.teamname.marvelous.gamelibrary.IntVector2;
|
||||||
import uulm.teamname.marvelous.gamelibrary.entities.*;
|
import uulm.teamname.marvelous.gamelibrary.entities.*;
|
||||||
import uulm.teamname.marvelous.gamelibrary.entities.Character;
|
|
||||||
import uulm.teamname.marvelous.gamelibrary.events.Event;
|
import uulm.teamname.marvelous.gamelibrary.events.Event;
|
||||||
import uulm.teamname.marvelous.gamelibrary.events.EventBuilder;
|
|
||||||
import uulm.teamname.marvelous.gamelibrary.json.config.CharacterConfig;
|
import uulm.teamname.marvelous.gamelibrary.json.config.CharacterConfig;
|
||||||
import uulm.teamname.marvelous.gamelibrary.json.config.PartyConfig;
|
import uulm.teamname.marvelous.gamelibrary.json.config.PartyConfig;
|
||||||
import uulm.teamname.marvelous.gamelibrary.json.config.ScenarioConfig;
|
import uulm.teamname.marvelous.gamelibrary.json.config.ScenarioConfig;
|
||||||
@ -14,10 +12,6 @@ import uulm.teamname.marvelous.gamelibrary.requests.*;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ThreadLocalRandom;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.*;
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
class GameLogicTest {
|
class GameLogicTest {
|
||||||
|
|
||||||
@ -85,7 +79,7 @@ class GameLogicTest {
|
|||||||
.as(Stat::new);
|
.as(Stat::new);
|
||||||
return Combinators.combine(stats, Arbitraries.integers().greaterOrEqual(0))
|
return Combinators.combine(stats, Arbitraries.integers().greaterOrEqual(0))
|
||||||
.as((stat, decrease) -> {
|
.as((stat, decrease) -> {
|
||||||
stat.decreaseValue(decrease % (stat.max + 1));
|
stat.decreaseValue(decrease % (stat.getMax() + 1));
|
||||||
return stat;
|
return stat;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user