mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 12:48:00 +00:00
- Fixed Pit Scorpion.
- Fixed some of the "Sacrifice a creature" spells ("destroy" effects would sometimes not happen).
- Added a few cards: Propaganda, Ghostly Prison, Windborn Muse, Arctic Nishoba, Peacekeeper, Marsh Viper.
- Yet another fix to Force of Will.
This commit is contained in:
@@ -1,3 +1,41 @@
|
||||
Windborn Muse
|
||||
3 W
|
||||
Creature Spirit
|
||||
Creatures can't attack you unless their controller pays 2 for each creature he or she controls that's attacking you.
|
||||
2/3
|
||||
Flying
|
||||
|
||||
Ghostly Prison
|
||||
2 W
|
||||
Enchantment
|
||||
Creatures can't attack you unless their controller pays 2 for each creature he or she controls that's attacking you.
|
||||
|
||||
Propaganda
|
||||
2 U
|
||||
Enchantment
|
||||
Creatures can't attack you unless their controller pays 2 for each creature he or she controls that's attacking you.
|
||||
|
||||
Peacekeeper
|
||||
2 W
|
||||
Creature Human
|
||||
Creatures can't attack
|
||||
1/1
|
||||
Upkeep:1 W
|
||||
|
||||
Arctic Nishoba
|
||||
5 G
|
||||
Creature Cat
|
||||
When Arctic Nishoba is put into a graveyard from the battlefield, you gain 2 life for each age counter on it.
|
||||
6/6
|
||||
Trample
|
||||
Cumulative upkeep:GW
|
||||
|
||||
Marsh Viper
|
||||
3 G
|
||||
Creature Snake
|
||||
Whenever Marsh Viper deals damage to an opponent, that player gets two poison counters.
|
||||
1/2
|
||||
|
||||
Force of Will
|
||||
3 U U
|
||||
Instant
|
||||
@@ -705,8 +743,9 @@ no text
|
||||
Pit Scorpion
|
||||
2 B
|
||||
Creature Scorpion
|
||||
Whenever this creature deals damage to a player, that player gets a poison counter.
|
||||
no text
|
||||
1/1
|
||||
Whenever this creature deals damage to a player, that player gets a poison counter.
|
||||
|
||||
Bridge from Below
|
||||
B B B
|
||||
|
||||
@@ -339,7 +339,7 @@
|
||||
<int>255</int>
|
||||
<int>533</int>
|
||||
<int>901</int>
|
||||
<int>145</int>
|
||||
<int>146</int>
|
||||
</object>
|
||||
</void>
|
||||
<void property="name">
|
||||
@@ -358,7 +358,7 @@
|
||||
<void property="bounds">
|
||||
<object class="java.awt.Rectangle">
|
||||
<int>255</int>
|
||||
<int>678</int>
|
||||
<int>679</int>
|
||||
<int>901</int>
|
||||
<int>10</int>
|
||||
</object>
|
||||
@@ -373,9 +373,9 @@
|
||||
<void property="bounds">
|
||||
<object class="java.awt.Rectangle">
|
||||
<int>255</int>
|
||||
<int>688</int>
|
||||
<int>689</int>
|
||||
<int>901</int>
|
||||
<int>139</int>
|
||||
<int>138</int>
|
||||
</object>
|
||||
</void>
|
||||
<void property="name">
|
||||
|
||||
@@ -17904,7 +17904,8 @@ return land.size() > 1 && CardFactoryUtil.AI_isMainPhase();
|
||||
public void selectButtonCancel() {stop();}
|
||||
public void selectCard(Card c, PlayerZone zone)
|
||||
{
|
||||
if(CardUtil.getColors(c).contains(Constant.Color.Blue) && zone.is(Constant.Zone.Hand))
|
||||
if(CardUtil.getColors(c).contains(Constant.Color.Blue) && zone.is(Constant.Zone.Hand) &&
|
||||
!c.equals(card))
|
||||
{
|
||||
AllZone.GameAction.removeFromGame(c);
|
||||
String player = card.getController();
|
||||
|
||||
@@ -505,8 +505,8 @@ public class CardFactoryUtil
|
||||
{
|
||||
if(choices.contains(card))
|
||||
{
|
||||
AllZone.getZone(card).remove(card);
|
||||
AllZone.GameAction.moveToGraveyard(card);
|
||||
//AllZone.getZone(card).remove(card);
|
||||
AllZone.GameAction.sacrifice(card);
|
||||
stop();
|
||||
}
|
||||
}
|
||||
@@ -3025,7 +3025,6 @@ public class CardFactoryUtil
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
public static CardList getFastbonds(String player)
|
||||
{
|
||||
CardList list = new CardList(AllZone.getZone(Constant.Zone.Play, player).getCards());
|
||||
@@ -3033,6 +3032,28 @@ public class CardFactoryUtil
|
||||
return list;
|
||||
}
|
||||
|
||||
//total cost to pay for an attacker c, cards like Propaganda, Ghostly Prison, Collective Restraint, ...
|
||||
public static String getPropagandaCost(Card c)
|
||||
{
|
||||
String s = "";
|
||||
|
||||
PlayerZone play = AllZone.getZone(Constant.Zone.Play, AllZone.GameAction.getOpponent(c.getController()));
|
||||
CardList list = new CardList(play.getCards());
|
||||
list = list.filter(new CardListFilter()
|
||||
{
|
||||
public boolean addCard(Card c)
|
||||
{
|
||||
return c.getName().equals("Propaganda") || c.getName().equals("Windborn Muse") || c.getName().equals("Ghostly Prison");
|
||||
}
|
||||
});
|
||||
int cost = list.size() * 2;
|
||||
|
||||
s = Integer.toString(cost);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
//do card1 and card2 share any colors?
|
||||
public static boolean sharesColorWith(Card card1, Card card2)
|
||||
{
|
||||
|
||||
@@ -19368,7 +19368,7 @@ public class CardFactory_Creatures {
|
||||
|
||||
}//*************** END ************ END **************************
|
||||
|
||||
//*************** END ************ END **************************
|
||||
//*************** START *********** START **************************
|
||||
else if (cardName.equals("Lockjaw Snapper"))
|
||||
{
|
||||
|
||||
@@ -19408,8 +19408,34 @@ public class CardFactory_Creatures {
|
||||
}
|
||||
};//command
|
||||
card.addDestroyCommand(destroy);
|
||||
}//*************** START *********** START **************************
|
||||
}//*************** END ************ END **************************
|
||||
|
||||
//*************** START *********** START **************************
|
||||
else if (cardName.equals("Arctic Nishoba"))
|
||||
{
|
||||
final Ability ability = new Ability(card, "0")
|
||||
{
|
||||
public void resolve()
|
||||
{
|
||||
int lifeGain = card.getCounters(Counters.AGE) * 2;
|
||||
AllZone.GameAction.getPlayerLife(card.getController()).addLife(lifeGain);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
Command destroy = new Command()
|
||||
{
|
||||
private static final long serialVersionUID = 1863551466234257411L;
|
||||
|
||||
public void execute()
|
||||
{
|
||||
ability.setStackDescription(card.getName()+ " - gain 2 life for each age counter on it.");
|
||||
AllZone.Stack.add(ability);
|
||||
}
|
||||
};//command
|
||||
|
||||
card.addDestroyCommand(destroy);
|
||||
}//*************** END ************ END **************************
|
||||
// Cards with Cycling abilities
|
||||
// -1 means keyword "Cycling" not found
|
||||
if (shouldCycle(card) != -1)
|
||||
|
||||
@@ -145,7 +145,7 @@ public class Combat
|
||||
public void addAttackingDamage(int n) {attackingDamage += n;}
|
||||
public int getAttackingDamage() {return attackingDamage;}
|
||||
|
||||
public void addAttacker(Card c) {map.put(c, new CardList()); declaredAttackers++;}
|
||||
public void addAttacker(Card c) {map.put(c, new CardList()); declaredAttackers++; }
|
||||
public void resetAttackers() {map.clear();}
|
||||
public Card[] getAttackers()
|
||||
{
|
||||
|
||||
@@ -17,11 +17,6 @@ public class CombatUtil
|
||||
&& blocker.getKeyword().contains("This creature can block creatures with shadow as though they didn't have shadow."))
|
||||
return false;
|
||||
|
||||
/*
|
||||
if(attacker.getKeyword().contains("Shadow"))
|
||||
return blocker.getKeyword().contains("Shadow") ||
|
||||
blocker.getKeyword().contains("This creature can block creatures with shadow as though they didn't have shadow.");
|
||||
*/
|
||||
if (attacker.getKeyword().contains("Shadow") && !blocker.getKeyword().contains("Shadow")
|
||||
&& !blocker.getKeyword().contains("This creature can block creatures with shadow as though they didn't have shadow.") )
|
||||
return false;
|
||||
@@ -194,13 +189,14 @@ public class CombatUtil
|
||||
public static boolean canAttack(Card c)
|
||||
{
|
||||
|
||||
if (isPeaceKeeperInPlay())
|
||||
return false;
|
||||
|
||||
boolean moatPrevented = false;
|
||||
if (isMoatInPlay() || isMagusMoatInPlay())
|
||||
{
|
||||
if (!c.getKeyword().contains("Flying"))
|
||||
{
|
||||
moatPrevented = true;
|
||||
}
|
||||
}
|
||||
|
||||
PlayerZone play = AllZone.getZone(Constant.Zone.Play,AllZone.GameAction.getOpponent(c.getController()));
|
||||
@@ -661,6 +657,16 @@ public class CombatUtil
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isPeaceKeeperInPlay()
|
||||
{
|
||||
CardList all = new CardList();
|
||||
all.addAll(AllZone.Human_Play.getCards());
|
||||
all.addAll(AllZone.Computer_Play.getCards());
|
||||
|
||||
all = all.getName("Peacekeeper");
|
||||
return all.size() > 0;
|
||||
}
|
||||
|
||||
public static boolean isMoatInPlay()
|
||||
{
|
||||
CardList all = new CardList();
|
||||
@@ -687,6 +693,68 @@ public class CombatUtil
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean checkPropagandaEffects(Card c)
|
||||
{
|
||||
if (CardFactoryUtil.getPropagandaCost(c).equals("0"))
|
||||
return true;
|
||||
|
||||
final Card crd = c;
|
||||
final boolean[] canAttack = new boolean[1];
|
||||
canAttack[0] = false;
|
||||
//if (AllZone.Phase.getPhase().equals(Constant.Phase.Combat_Declare_Attackers))
|
||||
if (AllZone.Phase.getPhase().equals("Declare Blockers") ||
|
||||
AllZone.Phase.getPhase().equals(Constant.Phase.Combat_Declare_Attackers_InstantAbility))
|
||||
{
|
||||
//if (!c.getCreatureAttackedThisTurn())
|
||||
//{
|
||||
String cost = CardFactoryUtil.getPropagandaCost(c);
|
||||
if (!cost.equals("0"))
|
||||
{
|
||||
final Ability ability = new Ability(c, cost)
|
||||
{
|
||||
public void resolve()
|
||||
{
|
||||
canAttack[0] = true;
|
||||
}
|
||||
};
|
||||
|
||||
final Command unpaidCommand = new Command() {
|
||||
|
||||
private static final long serialVersionUID = -6483405139208343935L;
|
||||
|
||||
public void execute() {
|
||||
//AllZone.GameAction.sacrifice(c);
|
||||
canAttack[0] = false;
|
||||
AllZone.Combat.removeFromCombat(crd);
|
||||
crd.untap();
|
||||
}
|
||||
};
|
||||
|
||||
final Command paidCommand = new Command() {
|
||||
private static final long serialVersionUID = -8303368287601871955L;
|
||||
|
||||
public void execute() {
|
||||
canAttack[0] = true;
|
||||
}
|
||||
};
|
||||
|
||||
if (c.getController().equals(Constant.Player.Human)) {
|
||||
AllZone.InputControl.setInput(new Input_PayManaCost_Ability("Propaganda "+ c +"\r\n", ability.getManaCost(), paidCommand, unpaidCommand));
|
||||
}
|
||||
else //computer
|
||||
{
|
||||
if (ComputerUtil.canPayCost(ability))
|
||||
ComputerUtil.playNoStack(ability);
|
||||
else
|
||||
canAttack[0] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
//c.setCreatureAttackedThisTurn(true);
|
||||
//}
|
||||
return canAttack[0];
|
||||
}
|
||||
|
||||
public static void checkDeclareAttackers(Card c) //this method checks triggered effects of attacking creatures, right before defending player declares blockers
|
||||
{
|
||||
//human does not have an "attackers_instantAbility" phase during his turn (yet), so triggers will happen at the beginning of declare blockers
|
||||
|
||||
@@ -4108,9 +4108,11 @@ public class GameActionUtil
|
||||
{
|
||||
|
||||
if (c.getKeyword().contains("Whenever this creature deals damage to a player, that player gets a poison counter."))
|
||||
playerCombatDamage_PoisonCounter(c);
|
||||
playerCombatDamage_PoisonCounter(c, 1);
|
||||
|
||||
if (c.getName().equals("Hypnotic Specter"))
|
||||
if (c.getName().equals("Marsh Viper"))
|
||||
playerCombatDamage_PoisonCounter(c, 2);
|
||||
else if (c.getName().equals("Hypnotic Specter"))
|
||||
playerCombatDamage_Hypnotic_Specter(c);
|
||||
else if (c.getName().equals("Dimir Cutpurse"))
|
||||
playerCombatDamage_Dimir_Cutpurse(c);
|
||||
@@ -4207,15 +4209,15 @@ public class GameActionUtil
|
||||
}
|
||||
*/
|
||||
|
||||
private static void playerCombatDamage_PoisonCounter(Card c)
|
||||
private static void playerCombatDamage_PoisonCounter(Card c, int n)
|
||||
{
|
||||
final String player = c.getController();
|
||||
final String opponent = AllZone.GameAction.getOpponent(player);
|
||||
|
||||
if (opponent.equals(Constant.Player.Human))
|
||||
AllZone.Human_PoisonCounter.addPoisonCounters(1);
|
||||
AllZone.Human_PoisonCounter.addPoisonCounters(n);
|
||||
else
|
||||
AllZone.Computer_PoisonCounter.addPoisonCounters(1);
|
||||
AllZone.Computer_PoisonCounter.addPoisonCounters(n);
|
||||
}
|
||||
|
||||
private static void playerCombatDamage_Oros(Card c)
|
||||
@@ -5134,6 +5136,7 @@ public class GameActionUtil
|
||||
|
||||
|
||||
|
||||
|
||||
private static void upkeep_AEther_Vial()
|
||||
{
|
||||
final String player = AllZone.Phase.getActivePlayer();
|
||||
|
||||
@@ -89,10 +89,12 @@ import java.util.*;
|
||||
CardList list = new CardList();
|
||||
list.addAll(AllZone.Combat.getAttackers());
|
||||
list.addAll(AllZone.pwCombat.getAttackers());
|
||||
|
||||
for (Card c : list)
|
||||
CombatUtil.checkPropagandaEffects(c);
|
||||
|
||||
for (Card c : list)
|
||||
{
|
||||
CombatUtil.checkDeclareAttackers(c);
|
||||
}
|
||||
|
||||
return new Input_Attack_Instant();
|
||||
}
|
||||
@@ -296,6 +298,10 @@ import java.util.*;
|
||||
CardList list = new CardList();
|
||||
list.addAll(AllZone.Combat.getAttackers());
|
||||
list.addAll(AllZone.pwCombat.getAttackers());
|
||||
for (Card c : list)
|
||||
{
|
||||
CombatUtil.checkPropagandaEffects(c);
|
||||
}
|
||||
for (Card c : list)
|
||||
{
|
||||
CombatUtil.checkDeclareAttackers(c);
|
||||
|
||||
@@ -17,6 +17,7 @@ public void showMessage()
|
||||
Card c = creats.get(i);
|
||||
if (CombatUtil.canAttack(c) && c.getKeyword().contains("This card attacks each turn if able."))
|
||||
{
|
||||
|
||||
AllZone.Combat.addAttacker(c);
|
||||
if (!c.getKeyword().contains("Vigilance"))
|
||||
c.tap();
|
||||
@@ -62,15 +63,15 @@ public void showMessage()
|
||||
CombatUtil.canAttack(card)
|
||||
)
|
||||
{
|
||||
|
||||
if(! card.getKeyword().contains("Vigilance"))
|
||||
{
|
||||
card.tap();
|
||||
|
||||
//otherwise cards stay untapped, not sure why this is needed but it works
|
||||
AllZone.Human_Play.updateObservers();
|
||||
}
|
||||
AllZone.Combat.addAttacker(card);
|
||||
|
||||
|
||||
//for Castle Raptors, since it gets a bonus if untapped
|
||||
for (String effect : AllZone.StateBasedEffects.getStateBasedMap().keySet() ) {
|
||||
Command com = GameActionUtil.commands.get(effect);
|
||||
|
||||
@@ -65,9 +65,11 @@ public class Input_PayManaCost_Ability extends Input
|
||||
//tappedLand.clear();
|
||||
AllZone.ManaPool.paid();
|
||||
|
||||
//Command MUST BE AFTER, for Urborg Syphon-Mage - tap, mana, discard abilit
|
||||
stopSetNext(new ComputerAI_StackNotEmpty());
|
||||
//Command MUST BE AFTER, for Urborg Syphon-Mage - tap, mana, discard ability
|
||||
//does it really have to be after?
|
||||
paidCommand.execute();
|
||||
stopSetNext(new ComputerAI_StackNotEmpty());
|
||||
//paidCommand.execute();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user