[LCI] Implement Deeproot Pilgrimage (#11350)

This commit is contained in:
Susucre 2023-10-26 18:06:10 +02:00 committed by GitHub
parent 77b9faad84
commit 27b8d3e198
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 298 additions and 4 deletions

View file

@ -0,0 +1,48 @@
package mage.abilities.common;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
import mage.constants.Zone;
import mage.filter.FilterPermanent;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.TappedBatchEvent;
/**
* @author Susucr
*/
public class BecomesTappedOneOrMoreTriggeredAbility extends TriggeredAbilityImpl {
protected FilterPermanent filter;
public BecomesTappedOneOrMoreTriggeredAbility(Zone zone, Effect effect, boolean optional, FilterPermanent filter) {
super(zone, effect, optional);
this.filter = filter;
setTriggerPhrase("Whenever one or more " + filter.getMessage() + " become tapped, ");
}
protected BecomesTappedOneOrMoreTriggeredAbility(final BecomesTappedOneOrMoreTriggeredAbility ability) {
super(ability);
this.filter = ability.filter.copy();
}
@Override
public BecomesTappedOneOrMoreTriggeredAbility copy() {
return new BecomesTappedOneOrMoreTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.TAPPED_BATCH;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
TappedBatchEvent batchEvent = (TappedBatchEvent) event;
return batchEvent
.getTargets()
.stream()
.map(game::getPermanent)
.anyMatch(p -> filter.match(p, getControllerId(), this, game));
}
}

View file

@ -1,5 +1,6 @@
package mage.game;
import static java.util.Collections.emptyList;
import mage.MageObject;
import mage.MageObjectReference;
import mage.abilities.*;
@ -44,8 +45,6 @@ import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import static java.util.Collections.emptyList;
/**
* @author BetaSteward_at_googlemail.com
* <p>
@ -860,6 +859,27 @@ public class GameState implements Serializable, Copyable<GameState> {
}
}
public void addSimultaneousTapped(TappedEvent tappedEvent, Game game) {
// Combine multiple tapped events in the single event (batch)
boolean isTappedBatchUsed = false;
for (GameEvent event : simultaneousEvents) {
if (event instanceof TappedBatchEvent) {
// Adding to the existing batch
((TappedBatchEvent) event).addEvent(tappedEvent);
isTappedBatchUsed = true;
break;
}
}
// new batch
if (!isTappedBatchUsed) {
TappedBatchEvent batch = new TappedBatchEvent();
batch.addEvent(tappedEvent);
addSimultaneousEvent(batch, game);
}
}
public void handleEvent(GameEvent event, Game game) {
watchers.watch(event, game);
delayed.checkTriggers(event, game);

View file

@ -350,12 +350,17 @@ public class GameEvent implements Serializable {
flag is it tapped for combat
*/
TAPPED,
TAPPED_FOR_MANA,
/* TAPPED_FOR_MANA
During calculation of the available mana for a player the "TappedForMana" event is fired to simulate triggered mana production.
By checking the inCheckPlayableState these events are handled to give back only the available mana of instead really producing mana.
IMPORTANT: Triggered non mana abilities have to ignore the event if game.inCheckPlayableState is true.
*/
TAPPED_FOR_MANA,
/* TAPPED_BATCH
combine all TAPPED events occuring at the same time in a single event
*/
TAPPED_BATCH,
UNTAP, UNTAPPED,
FLIP, FLIPPED,
TRANSFORMING, TRANSFORMED,

View file

@ -0,0 +1,56 @@
package mage.game.events;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
/**
* @author Susucr
*/
public class TappedBatchEvent extends GameEvent implements BatchGameEvent<TappedEvent> {
private final Set<TappedEvent> events = new HashSet<>();
public TappedBatchEvent() {
super(EventType.TAPPED_BATCH, null, null, null);
}
@Override
public Set<TappedEvent> getEvents() {
return events;
}
@Override
public Set<UUID> getTargets() {
return events.stream()
.map(GameEvent::getTargetId)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
}
@Override
public int getAmount() {
return events
.stream()
.mapToInt(GameEvent::getAmount)
.sum();
}
@Override
@Deprecated // events can store a diff value, so search it from events list instead
public UUID getTargetId() {
throw new IllegalStateException("Wrong code usage. Must search value from a getEvents list or use CardUtil.getEventTargets(event)");
}
@Override
@Deprecated // events can store a diff value, so search it from events list instead
public UUID getSourceId() {
throw new IllegalStateException("Wrong code usage. Must search value from a getEvents list.");
}
public void addEvent(TappedEvent event) {
this.events.add(event);
}
}

View file

@ -0,0 +1,14 @@
package mage.game.events;
import mage.abilities.Ability;
import java.util.UUID;
/**
* @author Susucr
*/
public class TappedEvent extends GameEvent {
public TappedEvent(UUID targetId, Ability source, UUID playerId, boolean forCombat) {
super(EventType.TAPPED, targetId, source, playerId, 0, forCombat);
}
}

View file

@ -561,7 +561,9 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
//20091005 - 701.15a
if (!tapped && !replaceEvent(EventType.TAP, game)) {
this.tapped = true;
game.fireEvent(new GameEvent(GameEvent.EventType.TAPPED, objectId, source, source == null ? null : source.getControllerId(), 0, forCombat));
TappedEvent event = new TappedEvent(objectId, source, source == null ? null : source.getControllerId(), forCombat);
game.fireEvent(event);
game.getState().addSimultaneousTapped(event, game);
return true;
}
return false;