Try to keep original card and not migrate to new card

This commit is contained in:
Lyu Zong-Hong
2021-02-08 22:36:20 +09:00
parent 610d712b11
commit 0eef317c42
12 changed files with 53 additions and 111 deletions

View File

@@ -338,13 +338,10 @@ public class GameAction {
}
// update state for view
copied.updateStateForView();
if (copied.isMerged()) {
if (copied.getMergedToCard() != null) {
copied.getMergedToCard().updateStateForView();
} else {
copied.getMergedCards().get(0).updateStateForView();
}
copied.getMergedToCard().updateStateForView();
} else {
copied.updateStateForView();
}
if (fromBattlefield) {

View File

@@ -47,17 +47,17 @@ public class MutateEffect extends SpellAbilityEffect {
);
final boolean putOnTop = (topCard == host);
host.setMergedToCard(target);
// If first time mutate, add target first.
if (target.getMergedCards().isEmpty()) {
target.addMergedCard(target);
}
if (putOnTop) {
host.addMergedCard(target);
host.addMergedCards(target.getMergedCards());
target.clearMergedCards();
target.setMergedToCard(host);
target.addMergedCardToTop(host);
} else {
target.addMergedCard(host);
host.setMergedToCard(target);
}
// First remove current mutated states
if (target.getMutatedTimestamp() != -1) {
target.removeCloneState(target.getMutatedTimestamp());
@@ -66,27 +66,21 @@ public class MutateEffect extends SpellAbilityEffect {
// Now add all abilities from bottom cards
final Long ts = game.getNextTimestamp();
if (topCard.getCurrentStateName() != CardStateName.FaceDown) {
final CardCloneStates mutatedStates = CardFactory.getMutatedCloneStates(topCard, sa);
topCard.addCloneState(mutatedStates, ts);
topCard.setMutatedTimestamp(ts);
}
if (topCard == target) {
// Re-register triggers for target card
game.getTriggerHandler().clearActiveTriggers(target, null);
game.getTriggerHandler().registerActiveTrigger(target, false);
final CardCloneStates mutatedStates = CardFactory.getMutatedCloneStates(target, sa);
target.addCloneState(mutatedStates, ts);
target.setMutatedTimestamp(ts);
}
// Re-register triggers for target card
game.getTriggerHandler().clearActiveTriggers(target, null);
game.getTriggerHandler().registerActiveTrigger(target, false);
game.getAction().moveToPlay(host, p, sa);
if (topCard == host) {
CardFactory.migrateTopCard(host, target);
} else {
host.setTapped(target.isTapped());
host.setFlipped(target.isFlipped());
}
topCard.setTimesMutated(topCard.getTimesMutated() + 1);
host.setTapped(target.isTapped());
host.setFlipped(target.isFlipped());
target.setTimesMutated(target.getTimesMutated() + 1);
game.getTriggerHandler().runTrigger(TriggerType.Mutates, AbilityKey.mapFromCard(topCard), false);
game.getTriggerHandler().runTrigger(TriggerType.Mutates, AbilityKey.mapFromCard(target), false);
}
}

View File

@@ -1010,8 +1010,9 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
public final void addMergedCard(final Card c) {
mergedCards = view.addCard(mergedCards, c, TrackableProperty.MergedCards);
}
public final void addMergedCards(final Iterable<Card> cards) {
mergedCards = view.addCards(mergedCards, cards, TrackableProperty.MergedCards);
public final void addMergedCardToTop(final Card c) {
mergedCards.add(0, c);
view.setCards(mergedCards, mergedCards, TrackableProperty.MergedCards);
}
public final void removeMergedCard(final Card c) {
mergedCards = view.removeCard(mergedCards, c, TrackableProperty.MergedCards);
@@ -1028,7 +1029,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
}
public final boolean isMerged() {
return !getMergedCards().isEmpty() || getMergedToCard() != null;
return getMergedToCard() != null;
}
public final boolean isMutated() {
@@ -3740,9 +3741,6 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
if (tapped == tapped0) { return; }
tapped = tapped0;
view.updateTapped(this);
for (final Card c : getMergedCards()) {
c.setTapped(tapped0);
}
}
public final void tap() {

View File

@@ -823,49 +823,23 @@ public class CardFactory {
}
public static CardCloneStates getMutatedCloneStates(final Card card, final CardTraitBase sa) {
final CardStateName state = card.getCurrentStateName();
final Card top = card.getMergedCards().get(0);
final CardStateName state = top.getCurrentStateName();
final CardState ret = new CardState(card, state);
ret.copyFrom(card.getState(state, true), false);
ret.copyFrom(top.getState(state, true), false);
boolean first = true;
for (final Card c : card.getMergedCards()) {
if (first) {
first = false;
continue;
}
ret.addAbilitiesFrom(c.getCurrentState(), false);
}
final CardCloneStates result = new CardCloneStates(card, sa);
final CardCloneStates result = new CardCloneStates(top, sa);
result.put(state, ret);
return result;
}
public static void migrateTopCard(final Card host, final Card target) {
// Copy all status from target card and migrate all counters
// Also update all reference of target card to new top card
// TODO: find out all necessary status that should be copied
host.setTapped(target.isTapped());
host.setSickness(target.isFirstTurnControlled());
host.setFlipped(target.isFlipped());
host.setDamage(target.getDamage());
host.setTimesMutated(target.getTimesMutated());
host.setMonstrous(target.isMonstrous());
host.setRenowned(target.isRenowned());
// Migrate counters
Map<CounterType, Integer> counters = target.getCounters();
if (!counters.isEmpty()) {
host.setCounters(Maps.newHashMap(counters));
}
target.clearCounters();
// Migrate attached cards
CardCollectionView attached = target.getAttachedCards();
for (final Card c : attached) {
c.setEntityAttachedTo(host);
}
target.setAttachedCards(null);
host.setAttachedCards(attached);
// TODO: move all remembered, imprinted objects to new top card
// and possibly many other needs to be migrated.
}
} // end class AbstractCardFactory

View File

@@ -470,7 +470,7 @@ public class PlayerView extends GameEntityView {
void updateZone(PlayerZone zone) {
TrackableProperty prop = getZoneProp(zone.getZoneType());
if (prop == null) { return; }
set(prop, CardView.getCollection(zone.getCards(false, false)));
set(prop, CardView.getCollection(zone.getCards(false, true)));
//update delirium
if (ZoneType.Graveyard == zone.getZoneType())

View File

@@ -685,21 +685,6 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
}
toPanel.getAttachedPanels().clear();
// Treat merged cards like attached cards
if (card.hasMergedCards()) {
final Iterable<CardView> merged = card.getMergedCards();
for (final CardView c : merged) {
final CardPanel cardC = getCardPanel(c.getId());
if (cardC != null) {
if (cardC.getAttachedToPanel() != toPanel) {
cardC.setAttachedToPanel(toPanel);
needLayoutRefresh = true; //ensure layout refreshed if any attachments change
}
toPanel.getAttachedPanels().add(cardC);
}
}
}
if (card.hasCardAttachments()) {
final Iterable<CardView> enchants = card.getAttachedCards();
for (final CardView e : enchants) {
@@ -714,13 +699,11 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
}
}
// Treat merged cards like attached cards
CardPanel attachedToPanel;
if (card.getMergedTo() != null) {
attachedToPanel = getCardPanel(card.getMergedTo().getId());
} else if (card.getAttachedTo() != null) {
if (card.getAttachedTo() != null) {
attachedToPanel = getCardPanel(card.getAttachedTo().getId());
} else {
}
else {
attachedToPanel = null;
}
if (toPanel.getAttachedToPanel() != attachedToPanel) {

View File

@@ -62,7 +62,7 @@ public abstract class VCardDisplayArea extends VDisplayArea implements ActivateH
}
if (isVisible()) { //only revalidate if currently visible
revalidate();
if (newCardPanel != null) { //if new cards added, ensure first new card is scrolled into view
scrollIntoView(newCardPanel);
}
@@ -286,17 +286,6 @@ public abstract class VCardDisplayArea extends VDisplayArea implements ActivateH
attachedPanels.clear();
// Treat merged cards like attached cards
if (card.hasMergedCards()) {
final Iterable<CardView> merged = card.getMergedCards();
for (final CardView c : merged) {
final CardAreaPanel cardC = CardAreaPanel.get(c);
if (cardC != null) {
attachedPanels.add(cardC);
}
}
}
if (card.hasCardAttachments()) {
final Iterable<CardView> enchants = card.getAttachedCards();
for (final CardView e : enchants) {
@@ -306,11 +295,8 @@ public abstract class VCardDisplayArea extends VDisplayArea implements ActivateH
}
}
}
if (card.getMergedTo() != null ) {
setAttachedToPanel(CardAreaPanel.get(card.getMergedTo()));
}
else if (card.getAttachedTo() != null) {
if (card.getAttachedTo() != null) {
setAttachedToPanel(CardAreaPanel.get(card.getAttachedTo()));
}
else {

View File

@@ -6,4 +6,4 @@ K:Mutate:3 U
K:Flying
T:Mode$ Mutates | ValidCard$ Card.Self | Execute$ TrigDraw | TriggerDescription$ Whenever this creature mutates, draw a card.
SVar:TrigDraw:DB$ Draw | NumCards$ 1
Oracle:Mutate {3}{U} (If you cast this spell for its mutate cost, put it over or under target non-Human creature you own. They mutate into the creature on top plus all abilities from under it.)\nFlying\nWhenever this creature mutates, draw a card.
Oracle:Mutate {3}{U} (If you cast this spell for its mutate cost, put it over or under target non-Human creature you own. They mutate into the creature on top plus all abilities from under it.)\nFlying\nWhenever this creature mutates, draw a card.

View File

@@ -8,4 +8,4 @@ T:Mode$ Mutates | ValidCard$ Card.Self | Execute$ TrigLoseLife | TriggerDescript
SVar:TrigLoseLife:DB$ LoseLife | Defined$ Opponent | LifeAmount$ X | References$ X | SubAbility$ DBGainLife
SVar:DBGainLife:DB$ GainLife | Defined$ You | LifeAmount$ X | References$ X
SVar:X:Count$TimesMutated
Oracle:Mutate {2}{B} (If you cast this spell for its mutate cost, put it over or under target non-Human creature you own. They mutate into the creature on top plus all abilities from under it.)\nDeathtouch\nWhenever this creature mutates, each opponent loses X life and you gain X life, where X is the number of times this creature has mutated.
Oracle:Mutate {2}{B} (If you cast this spell for its mutate cost, put it over or under target non-Human creature you own. They mutate into the creature on top plus all abilities from under it.)\nDeathtouch\nWhenever this creature mutates, each opponent loses X life and you gain X life, where X is the number of times this creature has mutated.

View File

@@ -4,4 +4,4 @@ Types:Creature Elemental Beast
PT:2/4
K:Mutate:G U
A:AB$ Dig | Cost$ 1 T | DigNum$ 1 | ChangeNum$ 1 | ChangeValid$ Land | Optional$ True | DestinationZone$ Battlefield | DestinationZone2$ Hand | StackDescription$ SpellDescription | SpellDescription$ Look at the top card of your library. If it's a land card, you may put it onto the battlefield. If you don't put the card onto the battlefield, put it into your hand.
Oracle:Mutate {G}{U} (If you cast this spell for its mutate cost, put it over or under target non-Human creature you own. They mutate into the creature on top plus all abilities from under it.)\n{1}, {T}: Look at the top card of your library. If it's a land card, you may put it onto the battlefield. If you don't put the card onto the battlefield, put it into your hand.
Oracle:Mutate {G}{U} (If you cast this spell for its mutate cost, put it over or under target non-Human creature you own. They mutate into the creature on top plus all abilities from under it.)\n{1}, {T}: Look at the top card of your library. If it's a land card, you may put it onto the battlefield. If you don't put the card onto the battlefield, put it into your hand.

View File

@@ -0,0 +1,10 @@
Name:Pollywog Symbiote
ManaCost:1 U
Types:Creature Frog
PT:1/3
S:Mode$ ReduceCost | ValidCard$ Creature.withMutate | Type$ Spell | Activator$ You | Amount$ 1 | Description$ Each creature spell you cast costs {1} less to cast if it has mutate.
T:Mode$ SpellCast | ValidCard$ Creature.withMutate | ValidActivatingPlayer$ You | Execute$ TrigLoot | TriggerZones$ Battlefield | TriggerDescription$ Whenever you cast a creature spell, if it has mutate, draw a card, then discard a card.
SVar:TrigLoot:DB$ Draw | Defined$ You | NumCards$ 1 | SubAbility$ DBDiscard
SVar:DBDiscard:DB$ Discard | Defined$ You | NumCards$ 1 | Mode$ TgtChoose
SVar:BuffedBy:Card.withMutate
Oracle:Each creature spell you cast costs {1} less to cast if it has mutate.\nWhenever you cast a creature spell, if it has mutate, draw a card, then discard a card.

View File

@@ -6,4 +6,4 @@ K:Mutate:2 W
K:Flying
T:Mode$ Mutates | ValidCard$ Card.Self | TriggerZones$ Battlefield | Execute$ TrigPutCounter | TriggerDescription$ Whenever this creature mutates, put a +1/+1 counter on it.
SVar:TrigPutCounter:DB$ PutCounter | Defined$ TriggeredCardLKICopy | CounterType$ P1P1 | CounterNum$ 1
Oracle:Mutate {2}{W} (If you cast this spell for its mutate cost, put it over or under target non-Human creature you own. They mutate into the creature on top plus all abilities from under it.)\nFlying\nWhenever this creature mutates, put a +1/+1 counter on it.
Oracle:Mutate {2}{W} (If you cast this spell for its mutate cost, put it over or under target non-Human creature you own. They mutate into the creature on top plus all abilities from under it.)\nFlying\nWhenever this creature mutates, put a +1/+1 counter on it.