mirror of
https://github.com/magefree/mage.git
synced 2025-12-20 02:30:08 -08:00
[ACR] Implement Ratonhnhaketon
This commit is contained in:
parent
0e36541cf8
commit
8f9f317c19
6 changed files with 255 additions and 127 deletions
|
|
@ -1,10 +1,8 @@
|
|||
package mage.cards.k;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.condition.common.SourceHasntDealtDamageThisGameCondition;
|
||||
import mage.abilities.decorator.ConditionalContinuousEffect;
|
||||
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
|
|
@ -15,14 +13,8 @@ import mage.cards.CardImpl;
|
|||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.WatcherScope;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.watchers.Watcher;
|
||||
import mage.watchers.common.DealtDamageThisGameWatcher;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
|
|
@ -49,8 +41,9 @@ public final class KarakykGuardian extends CardImpl {
|
|||
// This creature has hexproof if it hasn't dealt damage yet.
|
||||
this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect(
|
||||
new GainAbilitySourceEffect(HexproofAbility.getInstance()),
|
||||
KarakykGuardianCondition.instance, "{this} has hexproof if it hasn't dealt damage yet"
|
||||
)), new KarakykGuardianWatcher());
|
||||
SourceHasntDealtDamageThisGameCondition.instance,
|
||||
"{this} has hexproof if it hasn't dealt damage yet"
|
||||
)).addHint(SourceHasntDealtDamageThisGameCondition.getHint()), new DealtDamageThisGameWatcher());
|
||||
}
|
||||
|
||||
private KarakykGuardian(final KarakykGuardian card) {
|
||||
|
|
@ -62,49 +55,3 @@ public final class KarakykGuardian extends CardImpl {
|
|||
return new KarakykGuardian(this);
|
||||
}
|
||||
}
|
||||
|
||||
enum KarakykGuardianCondition implements Condition {
|
||||
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
KarakykGuardianWatcher watcher = game.getState().getWatcher(KarakykGuardianWatcher.class);
|
||||
return permanent != null && !watcher.getDamagers().contains(new MageObjectReference(permanent, game));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{this} hasn't dealt damage yet";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class KarakykGuardianWatcher extends Watcher {
|
||||
|
||||
private final Set<MageObjectReference> damagers = new HashSet<>();
|
||||
|
||||
public KarakykGuardianWatcher() {
|
||||
super(WatcherScope.GAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void watch(GameEvent event, Game game) {
|
||||
switch (event.getType()) {
|
||||
case DAMAGED_PERMANENT:
|
||||
case DAMAGED_PLAYER:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
Permanent permanent = game.getPermanent(event.getSourceId());
|
||||
if (permanent != null) {
|
||||
damagers.add(new MageObjectReference(permanent, game));
|
||||
}
|
||||
}
|
||||
|
||||
public Set<MageObjectReference> getDamagers() {
|
||||
return damagers;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,8 @@
|
|||
package mage.cards.p;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.condition.common.SourceHasntDealtDamageThisGameCondition;
|
||||
import mage.abilities.decorator.ConditionalContinuousEffect;
|
||||
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
|
|
@ -19,15 +14,11 @@ import mage.cards.CardSetInfo;
|
|||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.constants.WatcherScope;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.watchers.Watcher;
|
||||
import mage.watchers.common.DealtDamageThisGameWatcher;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class PalladiaMorsTheRuiner extends CardImpl {
|
||||
|
|
@ -51,13 +42,11 @@ public final class PalladiaMorsTheRuiner extends CardImpl {
|
|||
this.addAbility(TrampleAbility.getInstance());
|
||||
|
||||
// Palladia-Mors, the Ruiner has hexproof if it hasn't dealt damage yet.
|
||||
this.addAbility(new SimpleStaticAbility(
|
||||
new ConditionalContinuousEffect(
|
||||
new GainAbilitySourceEffect(HexproofAbility.getInstance()),
|
||||
PalladiaMorsTheRuinerCondition.instance,
|
||||
"{this} has hexproof if it hasn't dealt damage yet"
|
||||
)
|
||||
), new PalladiaMorsTheRuinerWatcher());
|
||||
this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect(
|
||||
new GainAbilitySourceEffect(HexproofAbility.getInstance()),
|
||||
SourceHasntDealtDamageThisGameCondition.instance,
|
||||
"{this} has hexproof if it hasn't dealt damage yet"
|
||||
)).addHint(SourceHasntDealtDamageThisGameCondition.getHint()), new DealtDamageThisGameWatcher());
|
||||
}
|
||||
|
||||
private PalladiaMorsTheRuiner(final PalladiaMorsTheRuiner card) {
|
||||
|
|
@ -69,49 +58,3 @@ public final class PalladiaMorsTheRuiner extends CardImpl {
|
|||
return new PalladiaMorsTheRuiner(this);
|
||||
}
|
||||
}
|
||||
|
||||
enum PalladiaMorsTheRuinerCondition implements Condition {
|
||||
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
PalladiaMorsTheRuinerWatcher watcher = game.getState().getWatcher(PalladiaMorsTheRuinerWatcher.class);
|
||||
return permanent != null && !watcher.getDamagers().contains(new MageObjectReference(permanent, game));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{this} hasn't dealt damage yet";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class PalladiaMorsTheRuinerWatcher extends Watcher {
|
||||
|
||||
private final Set<MageObjectReference> damagers = new HashSet<>();
|
||||
|
||||
public PalladiaMorsTheRuinerWatcher() {
|
||||
super(WatcherScope.GAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void watch(GameEvent event, Game game) {
|
||||
switch (event.getType()) {
|
||||
case DAMAGED_PERMANENT:
|
||||
case DAMAGED_PLAYER:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
Permanent permanent = game.getPermanent(event.getSourceId());
|
||||
if (permanent != null) {
|
||||
damagers.add(new MageObjectReference(permanent, game));
|
||||
}
|
||||
}
|
||||
|
||||
public Set<MageObjectReference> getDamagers() {
|
||||
return damagers;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
152
Mage.Sets/src/mage/cards/r/Ratonhnhaketon.java
Normal file
152
Mage.Sets/src/mage/cards/r/Ratonhnhaketon.java
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
package mage.cards.r;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
|
||||
import mage.abilities.condition.common.SourceHasntDealtDamageThisGameCondition;
|
||||
import mage.abilities.decorator.ConditionalContinuousEffect;
|
||||
import mage.abilities.decorator.ConditionalRestrictionEffect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.combat.CantBeBlockedSourceEffect;
|
||||
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
|
||||
import mage.abilities.keyword.HexproofAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.permanent.token.AssassinMenaceToken;
|
||||
import mage.game.permanent.token.Token;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetCardInYourGraveyard;
|
||||
import mage.util.CardUtil;
|
||||
import mage.watchers.common.DealtDamageThisGameWatcher;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class Ratonhnhaketon extends CardImpl {
|
||||
|
||||
public Ratonhnhaketon(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}{U}{B}");
|
||||
|
||||
this.supertype.add(SuperType.LEGENDARY);
|
||||
this.subtype.add(SubType.HUMAN);
|
||||
this.subtype.add(SubType.ASSASSIN);
|
||||
this.power = new MageInt(3);
|
||||
this.toughness = new MageInt(3);
|
||||
|
||||
// As long as Ratonhnhaketon hasn't dealt damage yet, it has hexproof and can't be blocked.
|
||||
Ability ability = new SimpleStaticAbility(new ConditionalContinuousEffect(
|
||||
new GainAbilitySourceEffect(HexproofAbility.getInstance()),
|
||||
SourceHasntDealtDamageThisGameCondition.instance,
|
||||
"as long as {this} hasn't dealt damage yet, it has hexproof"
|
||||
));
|
||||
ability.addEffect(new ConditionalRestrictionEffect(
|
||||
new CantBeBlockedSourceEffect(),
|
||||
SourceHasntDealtDamageThisGameCondition.instance,
|
||||
"and can't be blocked"
|
||||
));
|
||||
this.addAbility(ability.addHint(SourceHasntDealtDamageThisGameCondition.getHint()), new DealtDamageThisGameWatcher());
|
||||
|
||||
// Whenever Ratonhnhaketon deals combat damage to a player, create a 1/1 black Assassin creature token with menace. When you do, return target Equipment card from your graveyard to the battlefield, then attach it to that token.
|
||||
this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new RatonhnhaketonTokenEffect()));
|
||||
}
|
||||
|
||||
private Ratonhnhaketon(final Ratonhnhaketon card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ratonhnhaketon copy() {
|
||||
return new Ratonhnhaketon(this);
|
||||
}
|
||||
}
|
||||
|
||||
class RatonhnhaketonTokenEffect extends OneShotEffect {
|
||||
|
||||
private static final FilterCard filter = new FilterCard("Equipment card from your graveyard");
|
||||
|
||||
static {
|
||||
filter.add(SubType.EQUIPMENT.getPredicate());
|
||||
}
|
||||
|
||||
RatonhnhaketonTokenEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "create a 1/1 black Assassin creature token with menace. When you do, return " +
|
||||
"target Equipment card from your graveyard to the battlefield, then attach it to that token";
|
||||
}
|
||||
|
||||
private RatonhnhaketonTokenEffect(final RatonhnhaketonTokenEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RatonhnhaketonTokenEffect copy() {
|
||||
return new RatonhnhaketonTokenEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Token token = new AssassinMenaceToken();
|
||||
token.putOntoBattlefield(1, game, source);
|
||||
for (UUID tokenId : token.getLastAddedTokenIds()) {
|
||||
Permanent permanent = game.getPermanent(tokenId);
|
||||
if (permanent == null) {
|
||||
continue;
|
||||
}
|
||||
ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility(
|
||||
new RatonhnhaketonReturnEffect(tokenId), false
|
||||
);
|
||||
ability.addTarget(new TargetCardInYourGraveyard(filter));
|
||||
game.fireReflexiveTriggeredAbility(ability, source);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class RatonhnhaketonReturnEffect extends OneShotEffect {
|
||||
|
||||
private final UUID tokenId;
|
||||
|
||||
RatonhnhaketonReturnEffect(UUID tokenId) {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "return target Equipment card from your graveyard to the battlefield, then attach it to that token";
|
||||
this.tokenId = tokenId;
|
||||
}
|
||||
|
||||
private RatonhnhaketonReturnEffect(final RatonhnhaketonReturnEffect effect) {
|
||||
super(effect);
|
||||
this.tokenId = effect.tokenId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RatonhnhaketonReturnEffect copy() {
|
||||
return new RatonhnhaketonReturnEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
Card card = game.getCard(getTargetPointer().getFirst(game, source));
|
||||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
player.moveCards(card, Zone.BATTLEFIELD, source, game);
|
||||
Permanent permanent = CardUtil.getPermanentFromCardPutToBattlefield(card, game);
|
||||
if (permanent == null) {
|
||||
return false;
|
||||
}
|
||||
Optional.ofNullable(tokenId)
|
||||
.map(game::getPermanent)
|
||||
.ifPresent(p -> p.addAttachment(permanent.getId(), source, game));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -237,9 +237,9 @@ public final class AssassinsCreed extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Poison-Blade Mentor", 288, Rarity.UNCOMMON, mage.cards.p.PoisonBladeMentor.class));
|
||||
cards.add(new SetCardInfo("Propaganda", 195, Rarity.UNCOMMON, mage.cards.p.Propaganda.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Propaganda", 85, Rarity.UNCOMMON, mage.cards.p.Propaganda.class, NON_FULL_USE_VARIOUS));
|
||||
//cards.add(new SetCardInfo("Ratonhnhake:ton", 150, Rarity.RARE, mage.cards.r.Ratonhnhaketon.class, NON_FULL_USE_VARIOUS));
|
||||
//cards.add(new SetCardInfo("Ratonhnhake:ton", 244, Rarity.RARE, mage.cards.r.Ratonhnhaketon.class, NON_FULL_USE_VARIOUS));
|
||||
//cards.add(new SetCardInfo("Ratonhnhake:ton", 62, Rarity.RARE, mage.cards.r.Ratonhnhakton.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Ratonhnhaketon", 150, Rarity.RARE, mage.cards.r.Ratonhnhaketon.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Ratonhnhaketon", 244, Rarity.RARE, mage.cards.r.Ratonhnhaketon.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Ratonhnhaketon", 62, Rarity.RARE, mage.cards.r.Ratonhnhaketon.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Raven Clan War-Axe", 297, Rarity.RARE, mage.cards.r.RavenClanWarAxe.class));
|
||||
cards.add(new SetCardInfo("Reconnaissance", 179, Rarity.UNCOMMON, mage.cards.r.Reconnaissance.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Reconnaissance", 82, Rarity.UNCOMMON, mage.cards.r.Reconnaissance.class, NON_FULL_USE_VARIOUS));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
package mage.abilities.condition.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.hint.ConditionHint;
|
||||
import mage.abilities.hint.Hint;
|
||||
import mage.game.Game;
|
||||
import mage.watchers.common.DealtDamageThisGameWatcher;
|
||||
|
||||
/**
|
||||
* requires DealtDamageThisGameWatcher
|
||||
*
|
||||
* @author TheElk801
|
||||
*/
|
||||
public enum SourceHasntDealtDamageThisGameCondition implements Condition {
|
||||
instance;
|
||||
private static final Hint hint = new ConditionHint(
|
||||
instance, "This creature hasn't dealt damage yet this game"
|
||||
);
|
||||
|
||||
public static Hint getHint() {
|
||||
return hint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return DealtDamageThisGameWatcher.checkCreature(game, source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{this} hasn't dealt damage yet";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
package mage.watchers.common;
|
||||
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.Ability;
|
||||
import mage.constants.WatcherScope;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.watchers.Watcher;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public class DealtDamageThisGameWatcher extends Watcher {
|
||||
|
||||
private final Set<MageObjectReference> damagers = new HashSet<>();
|
||||
|
||||
public DealtDamageThisGameWatcher() {
|
||||
super(WatcherScope.GAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void watch(GameEvent event, Game game) {
|
||||
switch (event.getType()) {
|
||||
case BEGINNING_PHASE_PRE:
|
||||
// keep the stored values from getting too big, especially since it doesn't reset between games
|
||||
damagers.removeIf(mor -> !mor.zoneCounterIsCurrent(game));
|
||||
return;
|
||||
case DAMAGED_PERMANENT:
|
||||
case DAMAGED_PLAYER:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
Permanent permanent = game.getPermanent(event.getSourceId());
|
||||
if (permanent != null) {
|
||||
damagers.add(new MageObjectReference(permanent, game));
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean checkCreature(Game game, Ability source) {
|
||||
return game
|
||||
.getState()
|
||||
.getWatcher(DealtDamageThisGameWatcher.class)
|
||||
.damagers
|
||||
.stream()
|
||||
.noneMatch(mor -> mor.refersTo(source.getSourcePermanentOrLKI(game), game));
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue