[STX] Implemented Strict Proctor

This commit is contained in:
Evan Kranzler 2021-04-16 18:48:40 -04:00
parent 3ba320257b
commit f9467d5142
18 changed files with 140 additions and 27 deletions

View file

@ -48,7 +48,7 @@ public interface Ability extends Controllable, Serializable {
*
* @see mage.players.PlayerImpl#playAbility(mage.abilities.ActivatedAbility,
* mage.game.Game)
* @see mage.game.GameImpl#addTriggeredAbility(mage.abilities.TriggeredAbility)
* @see Game#addTriggeredAbility(TriggeredAbility, GameEvent)
* @see mage.game.GameImpl#addDelayedTriggeredAbility(mage.abilities.DelayedTriggeredAbility)
*/
void newId();
@ -58,7 +58,7 @@ public interface Ability extends Controllable, Serializable {
*
* @see mage.players.PlayerImpl#playAbility(mage.abilities.ActivatedAbility,
* mage.game.Game)
* @see mage.game.GameImpl#addTriggeredAbility(mage.abilities.TriggeredAbility)
* @see Game#addTriggeredAbility(TriggeredAbility, GameEvent)
* @see mage.game.GameImpl#addDelayedTriggeredAbility(mage.abilities.DelayedTriggeredAbility)
*/
void newOriginalId();

View file

@ -37,7 +37,7 @@ public class DelayedTriggeredAbilities extends AbilitiesImpl<DelayedTriggeredAbi
continue;
}
if (ability.checkTrigger(event, game)) {
ability.trigger(game, ability.controllerId);
ability.trigger(game, ability.controllerId, event);
if (ability.getTriggerOnlyOnce()) {
it.remove();
}

View file

@ -31,10 +31,10 @@ public abstract class StateTriggeredAbility extends TriggeredAbilityImpl {
}
@Override
public void trigger(Game game, UUID controllerId) {
public void trigger(Game game, UUID controllerId, GameEvent triggeringEvent) {
//20100716 - 603.8
game.getState().setValue(this.getSourceId().toString() + "triggered", Boolean.TRUE);
super.trigger(game, controllerId);
super.trigger(game, controllerId, triggeringEvent);
}
@Override

View file

@ -95,7 +95,7 @@ public class TriggeredAbilities extends ConcurrentHashMap<String, TriggeredAbili
NumberOfTriggersEvent numberOfTriggersEvent = new NumberOfTriggersEvent(ability, event);
if (!game.replaceEvent(numberOfTriggersEvent)) {
for (int i = 0; i < numberOfTriggersEvent.getAmount(); i++) {
ability.trigger(game, ability.getControllerId());
ability.trigger(game, ability.getControllerId(), event);
}
}
}

View file

@ -11,7 +11,7 @@ import java.util.UUID;
*/
public interface TriggeredAbility extends Ability {
void trigger(Game game, UUID controllerId);
void trigger(Game game, UUID controllerId, GameEvent event);
/**
* This check for the relevant event types is called at first to prevent
@ -52,4 +52,7 @@ public interface TriggeredAbility extends Ability {
@Override
TriggeredAbility copy();
void setTriggerEvent(GameEvent event);
GameEvent getTriggerEvent();
}

View file

@ -24,6 +24,7 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge
protected boolean optional;
protected boolean leavesTheBattlefieldTrigger;
private boolean triggersOnce = false;
private GameEvent triggerEvent = null;
public TriggeredAbilityImpl(Zone zone, Effect effect) {
this(zone, effect, false);
@ -53,15 +54,15 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge
}
@Override
public void trigger(Game game, UUID controllerId) {
public void trigger(Game game, UUID controllerId, GameEvent triggeringEvent) {
//20091005 - 603.4
if (checkInterveningIfClause(game)) {
addthing(game);
game.addTriggeredAbility(this);
setLastTrigger(game);
game.addTriggeredAbility(this, triggeringEvent);
}
}
private final void addthing(Game game) {
private final void setLastTrigger(Game game) {
if (!triggersOnce) {
return;
}
@ -70,6 +71,16 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge
), game.getTurnNum());
}
@Override
public void setTriggerEvent(GameEvent triggerEvent) {
this.triggerEvent = triggerEvent;
}
@Override
public GameEvent getTriggerEvent() {
return triggerEvent;
}
@Override
public boolean checkTriggeredAlready(Game game) {
if (!triggersOnce) {

View file

@ -11,6 +11,7 @@ import mage.constants.SubType;
import mage.filter.FilterCard;
import mage.filter.predicate.mageobject.ConvertedManaCostPredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.target.common.TargetCardInYourGraveyard;
import java.util.UUID;
@ -46,14 +47,14 @@ public class SoulshiftAbility extends DiesSourceTriggeredAbility {
}
@Override
public void trigger(Game game, UUID controllerId) {
public void trigger(Game game, UUID controllerId, GameEvent triggeringEvent) {
this.getTargets().clear();
int intValue = amount.calculate(game, this, null);
FilterCard filter = new FilterCard("Spirit card with converted mana cost " + intValue + " or less from your graveyard");
filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, intValue + 1));
filter.add(SubType.SPIRIT.getPredicate());
this.addTarget(new TargetCardInYourGraveyard(filter));
super.trigger(game, controllerId); //To change body of generated methods, choose Tools | Templates.
super.trigger(game, controllerId, triggeringEvent); //To change body of generated methods, choose Tools | Templates.
}
@Override

View file

@ -421,7 +421,7 @@ public interface Game extends MageItem, Serializable {
Card copyCard(Card cardToCopy, Ability source, UUID newController);
void addTriggeredAbility(TriggeredAbility ability);
void addTriggeredAbility(TriggeredAbility ability, GameEvent triggeringEvent);
UUID addDelayedTriggeredAbility(DelayedTriggeredAbility delayedAbility);

View file

@ -1742,9 +1742,10 @@ public abstract class GameImpl implements Game, Serializable {
* For internal use only
*
* @param ability
* @param triggeringEvent
*/
@Override
public void addTriggeredAbility(TriggeredAbility ability) {
public void addTriggeredAbility(TriggeredAbility ability, GameEvent triggeringEvent) {
if (ability.getControllerId() == null) {
String sourceName = "no sourceId";
if (ability.getSourceId() != null) {
@ -1770,6 +1771,7 @@ public abstract class GameImpl implements Game, Serializable {
if (newAbility.getSourceObjectZoneChangeCounter() == 0) {
newAbility.setSourceObjectZoneChangeCounter(getState().getZoneChangeCounter(ability.getSourceId()));
}
newAbility.setTriggerEvent(triggeringEvent);
state.addTriggeredAbility(newAbility);
}
}

View file

@ -188,6 +188,7 @@ public class GameEvent implements Serializable {
playerId player that tries to use this ability
*/
TRIGGERED_ABILITY,
ABILITY_TRIGGERED,
RESOLVING_ABILITY,
/* COPY_STACKOBJECT
targetId id of the spell/ability to copy

View file

@ -780,7 +780,7 @@ public abstract class PlayerImpl implements Player, Serializable {
Cards toDiscard = new CardsImpl();
Cards hand = getHand().copy();
for (int i = 0; i < amount; i++) {
if(hand.isEmpty()){
if (hand.isEmpty()) {
break;
}
Card card = hand.getRandom(game);
@ -1496,6 +1496,7 @@ public abstract class PlayerImpl implements Player, Serializable {
if (sourceObject != null) {
sourceObject.adjustTargets(ability, game);
}
UUID triggerId = null;
if (ability.canChooseTarget(game, playerId)) {
if (ability.isUsesStack()) {
game.getStack().push(new StackAbility(ability, playerId));
@ -1509,14 +1510,23 @@ public abstract class PlayerImpl implements Player, Serializable {
if (!ability.isUsesStack()) {
ability.resolve(game);
} else {
game.fireEvent(new GameEvent(GameEvent.EventType.TRIGGERED_ABILITY,
ability.getId(), ability, ability.getControllerId()));
game.fireEvent(new GameEvent(
GameEvent.EventType.TRIGGERED_ABILITY,
ability.getId(), ability, ability.getControllerId()
));
triggerId = ability.getId();
}
game.removeBookmark(bookmark);
return true;
}
}
restoreState(bookmark, triggeredAbility.getRule(), game); // why restore is needed here? (to remove the triggered ability from the stack because of no possible targets)
GameEvent event = new GameEvent(
GameEvent.EventType.ABILITY_TRIGGERED,
triggerId, ability, ability.getControllerId()
);
game.getState().setValue(event.getId().toString(), ability.getTriggerEvent());
game.fireEvent(event);
return false;
}