1
0
Fork 0
mirror of https://github.com/correl/mage.git synced 2025-04-03 01:08:59 -09:00

[CMR] Implemented Malcolm, Keen-Eyed Navigator

This commit is contained in:
Evan Kranzler 2020-11-10 20:31:54 -05:00
parent ea46afbe62
commit 8b3064fc17
10 changed files with 213 additions and 8 deletions

View file

@ -0,0 +1,106 @@
package mage.cards.m;
import mage.MageInt;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.PartnerAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.DamagedEvent;
import mage.game.events.DamagedPlayerBatchEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.TreasureToken;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class MalcolmKeenEyedNavigator extends CardImpl {
public MalcolmKeenEyedNavigator(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}");
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.SIREN);
this.subtype.add(SubType.PIRATE);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// Flying
this.addAbility(FlyingAbility.getInstance());
// Whenever one or more Pirates you control deal damage to your opponents, you create a Treasure token for each opponent dealt damage.
this.addAbility(new MalcolmKeenEyedNavigatorTriggeredAbility());
// Partner
this.addAbility(PartnerAbility.getInstance());
}
private MalcolmKeenEyedNavigator(final MalcolmKeenEyedNavigator card) {
super(card);
}
@Override
public MalcolmKeenEyedNavigator copy() {
return new MalcolmKeenEyedNavigator(this);
}
}
class MalcolmKeenEyedNavigatorTriggeredAbility extends TriggeredAbilityImpl {
MalcolmKeenEyedNavigatorTriggeredAbility() {
super(Zone.BATTLEFIELD, null);
}
private MalcolmKeenEyedNavigatorTriggeredAbility(final MalcolmKeenEyedNavigatorTriggeredAbility ability) {
super(ability);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGED_PLAYER_BATCH;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
DamagedPlayerBatchEvent dEvent = (DamagedPlayerBatchEvent) event;
Set<UUID> opponents = new HashSet<>();
for (DamagedEvent damagedEvent : dEvent.getEvents()) {
Permanent permanent = game.getPermanent(damagedEvent.getSourceId());
if (permanent == null
|| !permanent.isControlledBy(getControllerId())
|| !permanent.hasSubtype(SubType.PIRATE, game)
|| !game.getOpponents(getControllerId()).contains(damagedEvent.getTargetId())) {
continue;
}
opponents.add(damagedEvent.getTargetId());
}
if (opponents.size() < 1) {
return false;
}
this.getEffects().clear();
this.addEffect(new CreateTokenEffect(new TreasureToken(), opponents.size()));
return true;
}
@Override
public MalcolmKeenEyedNavigatorTriggeredAbility copy() {
return new MalcolmKeenEyedNavigatorTriggeredAbility(this);
}
@Override
public String getRule() {
return "Whenever one or more Pirates you control deal damage to your opponents, " +
"you create a Treasure token for each opponent dealt damage.";
}
}

View file

@ -287,6 +287,7 @@ public final class CommanderLegends extends ExpansionSet {
cards.add(new SetCardInfo("Magus of the Order", 242, Rarity.RARE, mage.cards.m.MagusOfTheOrder.class));
cards.add(new SetCardInfo("Make a Stand", 32, Rarity.UNCOMMON, mage.cards.m.MakeAStand.class));
cards.add(new SetCardInfo("Makeshift Munitions", 191, Rarity.COMMON, mage.cards.m.MakeshiftMunitions.class));
cards.add(new SetCardInfo("Malcolm, Keen-Eyed Navigator", 79, Rarity.UNCOMMON, mage.cards.m.MalcolmKeenEyedNavigator.class));
cards.add(new SetCardInfo("Mana Confluence", 721, Rarity.MYTHIC, mage.cards.m.ManaConfluence.class));
cards.add(new SetCardInfo("Mana Drain", 80, Rarity.MYTHIC, mage.cards.m.ManaDrain.class));
cards.add(new SetCardInfo("Marath, Will of the Wild", 527, Rarity.MYTHIC, mage.cards.m.MarathWillOfTheWild.class));

View file

@ -18,9 +18,7 @@ import mage.game.combat.CombatGroup;
import mage.game.command.Command;
import mage.game.command.CommandObject;
import mage.game.command.Plane;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent;
import mage.game.events.ZoneChangeGroupEvent;
import mage.game.events.*;
import mage.game.permanent.Battlefield;
import mage.game.permanent.Permanent;
import mage.game.permanent.PermanentToken;
@ -732,6 +730,21 @@ public class GameState implements Serializable, Copyable<GameState> {
return !simultaneousEvents.isEmpty();
}
public void addSimultaneousDamage(DamagedEvent damagedEvent, Game game) {
boolean flag = false;
for (GameEvent event : simultaneousEvents) {
if ((event instanceof DamagedBatchEvent)
&& ((DamagedBatchEvent) event).getDamageClazz().isInstance(damagedEvent)) {
((DamagedBatchEvent) event).addEvent(damagedEvent);
flag = true;
break;
}
}
if (!flag) {
addSimultaneousEvent(DamagedBatchEvent.makeEvent(damagedEvent), game);
}
}
public void handleEvent(GameEvent event, Game game) {
watchers.watch(event, game);
delayed.checkTriggers(event, game);

View file

@ -0,0 +1,45 @@
package mage.game.events;
import java.util.HashSet;
import java.util.Set;
/**
* @author TheElk801
*/
public abstract class DamagedBatchEvent extends GameEvent {
private final Class<? extends DamagedEvent> damageClazz;
private final Set<DamagedEvent> events = new HashSet<>();
public DamagedBatchEvent(EventType type, Class<? extends DamagedEvent> damageClazz) {
super(EventType.DAMAGED_PLAYER_BATCH, null, null, null);
this.damageClazz = damageClazz;
}
public Set<DamagedEvent> getEvents() {
return events;
}
public void addEvent(DamagedEvent event) {
this.events.add(event);
}
public Class<? extends DamagedEvent> getDamageClazz() {
return damageClazz;
}
public static DamagedBatchEvent makeEvent(DamagedEvent damagedEvent) {
DamagedBatchEvent event = null;
if (damagedEvent instanceof DamagedPlayerEvent) {
event = new DamagedPlayerBatchEvent();
event.addEvent(damagedEvent);
} else if (damagedEvent instanceof DamagedCreatureEvent) {
event = new DamagedCreatureBatchEvent();
event.addEvent(damagedEvent);
} else if (damagedEvent instanceof DamagedPlaneswalkerEvent) {
event = new DamagedPlaneswalkerBatchEvent();
event.addEvent(damagedEvent);
}
return event;
}
}

View file

@ -0,0 +1,11 @@
package mage.game.events;
/**
* @author TheElk801
*/
public class DamagedCreatureBatchEvent extends DamagedBatchEvent {
public DamagedCreatureBatchEvent() {
super(EventType.DAMAGED_CREATURE_BATCH, DamagedCreatureEvent.class);
}
}

View file

@ -0,0 +1,11 @@
package mage.game.events;
/**
* @author TheElk801
*/
public class DamagedPlaneswalkerBatchEvent extends DamagedBatchEvent {
public DamagedPlaneswalkerBatchEvent() {
super(EventType.DAMAGED_PLANESWALKER_BATCH, DamagedPlaneswalkerEvent.class);
}
}

View file

@ -0,0 +1,11 @@
package mage.game.events;
/**
* @author TheElk801
*/
public class DamagedPlayerBatchEvent extends DamagedBatchEvent {
public DamagedPlayerBatchEvent() {
super(EventType.DAMAGED_PLAYER_BATCH, DamagedPlayerEvent.class);
}
}

View file

@ -100,6 +100,7 @@ public class GameEvent implements Serializable {
flag true = comabat damage - other damage = false
*/
DAMAGED_PLAYER,
DAMAGED_PLAYER_BATCH,
DAMAGE_CAUSES_LIFE_LOSS,
PLAYER_LIFE_CHANGE,
GAIN_LIFE, GAINED_LIFE,
@ -311,8 +312,8 @@ public class GameEvent implements Serializable {
flag not used for this event
*/
OPTION_USED,
DAMAGE_CREATURE, DAMAGED_CREATURE,
DAMAGE_PLANESWALKER, DAMAGED_PLANESWALKER,
DAMAGE_CREATURE, DAMAGED_CREATURE, DAMAGED_CREATURE_BATCH,
DAMAGE_PLANESWALKER, DAMAGED_PLANESWALKER, DAMAGED_PLANESWALKER_BATCH,
DESTROY_PERMANENT,
/* DESTROY_PERMANENT_BY_LEGENDARY_RULE
targetId id of the permanent to destroy

View file

@ -980,7 +980,9 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
countersToRemove = getCounters(game).getCount(CounterType.LOYALTY);
}
removeCounters(CounterType.LOYALTY.getName(), countersToRemove, game);
game.fireEvent(new DamagedPlaneswalkerEvent(objectId, sourceId, controllerId, actualDamage, combat));
DamagedEvent damagedEvent = new DamagedPlaneswalkerEvent(objectId, sourceId, controllerId, actualDamage, combat);
game.fireEvent(damagedEvent);
game.getState().addSimultaneousDamage(damagedEvent, game);
return actualDamage;
}
}
@ -1011,7 +1013,9 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
} else {
this.damage = CardUtil.addWithOverflowCheck(this.damage, actualDamage);
}
game.fireEvent(new DamagedCreatureEvent(objectId, sourceId, controllerId, actualDamage, combat));
DamagedEvent damagedEvent = new DamagedCreatureEvent(objectId, sourceId, controllerId, actualDamage, combat);
game.fireEvent(damagedEvent);
game.getState().addSimultaneousDamage(damagedEvent, game);
return actualDamage;
}
}

View file

@ -2157,7 +2157,9 @@ public abstract class PlayerImpl implements Player, Serializable {
Player player = game.getPlayer(sourceControllerId);
new SquirrelToken().putOntoBattlefield(actualDamage, game, sourceId, player.getId());
}
game.fireEvent(new DamagedPlayerEvent(playerId, sourceId, playerId, actualDamage, combatDamage));
DamagedEvent damagedEvent = new DamagedPlayerEvent(playerId, sourceId, playerId, actualDamage, combatDamage);
game.fireEvent(damagedEvent);
game.getState().addSimultaneousDamage(damagedEvent, game);
return actualDamage;
}
}