forked from External/mage
[AFR] Implementing dungeon mechanic (ready for review) (#7937)
* added dungeon and dungeon room class * [AFR] Implemented Tomb of Annihilation * [AFR] Implemented Shortcut Seeker * [AFR] Implemented Gloom Stalker * [AFR] Implemented Nadaar, Selfless Paladin * added room triggers * added more venturing code, currently untested * fixed error * moved venture into dungeon from player class to game class * removed unnecessary sourceobject from dungeon * fixed npe error * added dungeon completion * fixed concurrent modification exception * added logging * added proper copy methods * added views * updated room text generation * added some missing code * finished implementing CompletedDungeonCondition * [AFR] Implemented Ellywick Tumblestrum * [AFR] Implemented Lost Mine of Phandelver * added choice dialog for dungeons * [AFR] Implemented Dungeon of the Mad Mage * small text fix * added initial dungeon test * [AFR] Implemented Cloister Gargoyle * [AFR] Implemented Dungeon Crawler * small text change for dungeon rooms * added more tests * some simplification to dungeon props * updated testing helper functions * added currently failing test for venturing on separate steps and turns * added tests for dungeon completion * fixed missing trigger visual and dungeons not persisting through turns * some text updates * added rollback test * added a test for multiple dungeons at once * added one more condition test
This commit is contained in:
parent
c6d08ce344
commit
bb591dd038
42 changed files with 2481 additions and 144 deletions
|
|
@ -38,10 +38,7 @@ import mage.filter.common.FilterCreaturePermanent;
|
|||
import mage.filter.predicate.mageobject.NamePredicate;
|
||||
import mage.filter.predicate.permanent.ControllerIdPredicate;
|
||||
import mage.game.combat.Combat;
|
||||
import mage.game.command.CommandObject;
|
||||
import mage.game.command.Commander;
|
||||
import mage.game.command.Emblem;
|
||||
import mage.game.command.Plane;
|
||||
import mage.game.command.*;
|
||||
import mage.game.events.*;
|
||||
import mage.game.events.TableEvent.EventType;
|
||||
import mage.game.mulligan.Mulligan;
|
||||
|
|
@ -355,7 +352,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
if (item.getId().equals(objectId)) {
|
||||
return item;
|
||||
}
|
||||
if (item.getSourceId().equals(objectId) && item instanceof Spell) {
|
||||
if (item instanceof Spell && item.getSourceId().equals(objectId)) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
|
@ -431,6 +428,59 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dungeon getDungeon(UUID objectId) {
|
||||
return state
|
||||
.getCommand()
|
||||
.stream()
|
||||
.filter(commandObject -> commandObject.getId().equals(objectId))
|
||||
.filter(Dungeon.class::isInstance)
|
||||
.map(Dungeon.class::cast)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dungeon getPlayerDungeon(UUID playerId) {
|
||||
return state
|
||||
.getCommand()
|
||||
.stream()
|
||||
.filter(commandObject -> commandObject.isControlledBy(playerId))
|
||||
.filter(Dungeon.class::isInstance)
|
||||
.map(Dungeon.class::cast)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
private void removeDungeon(Dungeon dungeon) {
|
||||
if (dungeon == null) {
|
||||
return;
|
||||
}
|
||||
Player player = getPlayer(dungeon.getControllerId());
|
||||
if (player != null) {
|
||||
informPlayers(player.getLogName() + " has completed " + dungeon.getLogName());
|
||||
}
|
||||
state.getCommand().remove(dungeon);
|
||||
fireEvent(GameEvent.getEvent(
|
||||
GameEvent.EventType.DUNGEON_COMPLETED, dungeon.getId(), null,
|
||||
dungeon.getControllerId(), dungeon.getName(), 0
|
||||
));
|
||||
}
|
||||
|
||||
private Dungeon getOrCreateDungeon(UUID playerId) {
|
||||
Dungeon dungeon = this.getPlayerDungeon(playerId);
|
||||
if (dungeon != null && dungeon.hasNextRoom()) {
|
||||
return dungeon;
|
||||
}
|
||||
removeDungeon(dungeon);
|
||||
return this.addDungeon(Dungeon.selectDungeon(playerId, this), playerId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ventureIntoDungeon(UUID playerId) {
|
||||
this.getOrCreateDungeon(playerId).moveToNextRoom(playerId, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getOwnerId(UUID objectId) {
|
||||
return getOwnerId(getObject(objectId));
|
||||
|
|
@ -1658,6 +1708,13 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
state.addCommandObject(commander);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dungeon addDungeon(Dungeon dungeon, UUID playerId) {
|
||||
dungeon.setControllerId(playerId);
|
||||
state.addCommandObject(dungeon);
|
||||
return dungeon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPermanent(Permanent permanent, int createOrder) {
|
||||
if (createOrder == 0) {
|
||||
|
|
@ -1902,6 +1959,34 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
}
|
||||
}
|
||||
|
||||
// If a Dungeon is on its last room and is not the source of any triggered abilities, it is removed
|
||||
Set<Dungeon> dungeonsToRemove = new HashSet<>();
|
||||
for (CommandObject commandObject : state.getCommand()) {
|
||||
if (!(commandObject instanceof Dungeon)) {
|
||||
continue;
|
||||
}
|
||||
Dungeon dungeon = (Dungeon) commandObject;
|
||||
boolean removeDungeon = !dungeon.hasNextRoom()
|
||||
&& this.getStack()
|
||||
.stream()
|
||||
.filter(DungeonRoom::isRoomTrigger)
|
||||
.map(StackObject::getSourceId)
|
||||
.noneMatch(dungeon.getId()::equals)
|
||||
&& this.state
|
||||
.getTriggered(dungeon.getControllerId())
|
||||
.stream()
|
||||
.filter(DungeonRoom::isRoomTrigger)
|
||||
.map(Ability::getSourceId)
|
||||
.noneMatch(dungeon.getId()::equals);
|
||||
if (removeDungeon) {
|
||||
dungeonsToRemove.add(dungeon);
|
||||
}
|
||||
}
|
||||
for (Dungeon dungeon : dungeonsToRemove) {
|
||||
this.removeDungeon(dungeon);
|
||||
somethingHappened = true;
|
||||
}
|
||||
|
||||
// If a commander is in a graveyard or in exile and that card was put into that zone
|
||||
// since the last time state-based actions were checked, its owner may put it into the command zone.
|
||||
// signature spells goes to command zone all the time
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue