mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 03:08:02 +00:00
- Added support for damage prevention shields with effects.
- Added: Candles' Glow, Temper, Test of Faith and Vengeful Archon
This commit is contained in:
4
.gitattributes
vendored
4
.gitattributes
vendored
@@ -707,6 +707,7 @@ res/cardsfolder/a/azors_elocutors.txt -text
|
|||||||
res/cardsfolder/a/azure_drake.txt svneol=native#text/plain
|
res/cardsfolder/a/azure_drake.txt svneol=native#text/plain
|
||||||
res/cardsfolder/a/azure_mage.txt svneol=native#text/plain
|
res/cardsfolder/a/azure_mage.txt svneol=native#text/plain
|
||||||
res/cardsfolder/a/azusa_lost_but_seeking.txt svneol=native#text/plain
|
res/cardsfolder/a/azusa_lost_but_seeking.txt svneol=native#text/plain
|
||||||
|
res/cardsfolder/a/vengeful_archon.txt -text
|
||||||
res/cardsfolder/b/back_from_the_brink.txt -text
|
res/cardsfolder/b/back_from_the_brink.txt -text
|
||||||
res/cardsfolder/b/back_to_basics.txt svneol=native#text/plain
|
res/cardsfolder/b/back_to_basics.txt svneol=native#text/plain
|
||||||
res/cardsfolder/b/back_to_nature.txt svneol=native#text/plain
|
res/cardsfolder/b/back_to_nature.txt svneol=native#text/plain
|
||||||
@@ -1496,6 +1497,7 @@ res/cardsfolder/c/caltrops.txt svneol=native#text/plain
|
|||||||
res/cardsfolder/c/camel.txt -text
|
res/cardsfolder/c/camel.txt -text
|
||||||
res/cardsfolder/c/cancel.txt svneol=native#text/plain
|
res/cardsfolder/c/cancel.txt svneol=native#text/plain
|
||||||
res/cardsfolder/c/candelabra_of_tawnos.txt svneol=native#text/plain
|
res/cardsfolder/c/candelabra_of_tawnos.txt svneol=native#text/plain
|
||||||
|
res/cardsfolder/c/candles_glow.txt -text
|
||||||
res/cardsfolder/c/candles_of_leng.txt -text svneol=unset#text/plain
|
res/cardsfolder/c/candles_of_leng.txt -text svneol=unset#text/plain
|
||||||
res/cardsfolder/c/canker_abomination.txt svneol=native#text/plain
|
res/cardsfolder/c/canker_abomination.txt svneol=native#text/plain
|
||||||
res/cardsfolder/c/cankerous_thirst.txt -text
|
res/cardsfolder/c/cankerous_thirst.txt -text
|
||||||
@@ -11142,6 +11144,7 @@ res/cardsfolder/t/telimtors_edict.txt svneol=native#text/plain
|
|||||||
res/cardsfolder/t/teller_of_tales.txt svneol=native#text/plain
|
res/cardsfolder/t/teller_of_tales.txt svneol=native#text/plain
|
||||||
res/cardsfolder/t/telling_time.txt svneol=native#text/plain
|
res/cardsfolder/t/telling_time.txt svneol=native#text/plain
|
||||||
res/cardsfolder/t/tember_city.txt -text
|
res/cardsfolder/t/tember_city.txt -text
|
||||||
|
res/cardsfolder/t/temper.txt -text
|
||||||
res/cardsfolder/t/tempered_steel.txt svneol=native#text/plain
|
res/cardsfolder/t/tempered_steel.txt svneol=native#text/plain
|
||||||
res/cardsfolder/t/tempest_drake.txt svneol=native#text/plain
|
res/cardsfolder/t/tempest_drake.txt svneol=native#text/plain
|
||||||
res/cardsfolder/t/tempest_of_light.txt svneol=native#text/plain
|
res/cardsfolder/t/tempest_of_light.txt svneol=native#text/plain
|
||||||
@@ -11197,6 +11200,7 @@ res/cardsfolder/t/territorial_dispute.txt -text
|
|||||||
res/cardsfolder/t/terror.txt svneol=native#text/plain
|
res/cardsfolder/t/terror.txt svneol=native#text/plain
|
||||||
res/cardsfolder/t/terrus_wurm.txt -text
|
res/cardsfolder/t/terrus_wurm.txt -text
|
||||||
res/cardsfolder/t/test_of_endurance.txt svneol=native#text/plain
|
res/cardsfolder/t/test_of_endurance.txt svneol=native#text/plain
|
||||||
|
res/cardsfolder/t/test_of_faith.txt -text
|
||||||
res/cardsfolder/t/testament_of_faith.txt svneol=native#text/plain
|
res/cardsfolder/t/testament_of_faith.txt svneol=native#text/plain
|
||||||
res/cardsfolder/t/tethered_griffin.txt svneol=native#text/plain
|
res/cardsfolder/t/tethered_griffin.txt svneol=native#text/plain
|
||||||
res/cardsfolder/t/tethered_skirge.txt svneol=native#text/plain
|
res/cardsfolder/t/tethered_skirge.txt svneol=native#text/plain
|
||||||
|
|||||||
13
res/cardsfolder/a/vengeful_archon.txt
Normal file
13
res/cardsfolder/a/vengeful_archon.txt
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
Name:Vengeful Archon
|
||||||
|
ManaCost:4 W W W
|
||||||
|
Types:Creature Archon
|
||||||
|
PT:7/7
|
||||||
|
K:Flying
|
||||||
|
A:AB$ Pump | Cost$ X | ValidTgts$ Player | TgtPrompt$ Select target player damaged by shield effect | IsCurse$ True | References$ X | RememberObjects$ Targeted | SubAbility$ ArchonPrevention | StackDescription$ none | SpellDescription$ Prevent the next X damage that would be dealt to you this turn. If damage is prevented this way, CARDNAME deals that much damage to target player.
|
||||||
|
SVar:ArchonPrevention:DB$ PreventDamage | Defined$ You | Amount$ X | References$ X | PreventionSubAbility$ ArchonsVengeance | ShieldEffectTarget$ Remembered | SubAbility$ DBCleanup
|
||||||
|
SVar:ArchonsVengeance:AB$ DealDamage | Cost$ 0 | Defined$ ShieldEffectTarget | NumDmg$ PreventedDamage | SpellDescription$ CARDNAME deals damage to target player for each damage prevented this way.
|
||||||
|
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||||
|
SVar:X:Count$xPaid
|
||||||
|
SVar:RemAIDeck:True
|
||||||
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/vengeful_archon.jpg
|
||||||
|
Oracle:Flying\n{X}: Prevent the next X damage that would be dealt to you this turn. If damage is prevented this way, Vengeful Archon deals that much damage to target player.
|
||||||
8
res/cardsfolder/c/candles_glow.txt
Normal file
8
res/cardsfolder/c/candles_glow.txt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
Name:Candles' Glow
|
||||||
|
ManaCost:1 W
|
||||||
|
Types:Instant Arcane
|
||||||
|
A:SP$ PreventDamage | Cost$ 1 W | ValidTgts$ Player,Creature | Amount$ 3 | PreventionSubAbility$ GlowOfLife | References$ GlowOfLife | ShieldEffectTarget$ You | TgtPrompt$ Select target creature or player | SpellDescription$ Prevent the next 3 damage that would be dealt to target creature or player this turn. You gain life equal to the damage prevented this way.
|
||||||
|
SVar:GlowOfLife:AB$ GainLife | Cost$ 0 | Defined$ ShieldEffectTarget | LifeAmount$ PreventedDamage | SpellDescription$ You gain life equal to the damage prevented this way.
|
||||||
|
K:Splice onto Arcane 1 W
|
||||||
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/candles_glow.jpg
|
||||||
|
Oracle:Prevent the next 3 damage that would be dealt to target creature or player this turn. You gain life equal to the damage prevented this way.\nSplice onto Arcane {1}{W} (As you cast an Arcane spell, you may reveal this card from your hand and pay its splice cost. If you do, add this card's effects to that spell.)
|
||||||
8
res/cardsfolder/t/temper.txt
Normal file
8
res/cardsfolder/t/temper.txt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
Name:Temper
|
||||||
|
ManaCost:X 1 W
|
||||||
|
Types:Instant
|
||||||
|
A:SP$ PreventDamage | Cost$ X 1 W | ValidTgts$ Creature | Amount$ X | References$ X | PreventionSubAbility$ EvenTemper | ShieldEffectTarget$ Targeted | TgtPrompt$ Select target creature | SpellDescription$ Prevent the next X damage that would be dealt to target creature this turn. For each 1 damage prevented this way, put a +1/+1 counter on that creature.
|
||||||
|
SVar:EvenTemper:AB$ PutCounter | Cost$ 0 | Defined$ ShieldEffectTarget | CounterType$ P1P1 | CounterNum$ PreventedDamage | SpellDescription$ Put a +1/+1 counter on this creature for each 1 damage prevented this way.
|
||||||
|
SVar:X:Count$xPaid
|
||||||
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/temper.jpg
|
||||||
|
Oracle:Prevent the next X damage that would be dealt to target creature this turn. For each 1 damage prevented this way, put a +1/+1 counter on that creature.
|
||||||
7
res/cardsfolder/t/test_of_faith.txt
Normal file
7
res/cardsfolder/t/test_of_faith.txt
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
Name:Test of Faith
|
||||||
|
ManaCost:1 W
|
||||||
|
Types:Instant
|
||||||
|
A:SP$ PreventDamage | Cost$ 1 W | ValidTgts$ Creature | Amount$ 3 | PreventionSubAbility$ FaithsReward | ShieldEffectTarget$ Targeted | TgtPrompt$ Select target creature | SpellDescription$ Prevent the next 3 damage that would be dealt to target creature this turn, and put a +1/+1 counter on that creature for each 1 damage prevented this way.
|
||||||
|
SVar:FaithsReward:AB$ PutCounter | Cost$ 0 | Defined$ ShieldEffectTarget | CounterType$ P1P1 | CounterNum$ PreventedDamage | SpellDescription$ Put a +1/+1 counter on this creature for each 1 damage prevented this way.
|
||||||
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/test_of_faith.jpg
|
||||||
|
Oracle:Prevent the next 3 damage that would be dealt to target creature this turn, and put a +1/+1 counter on that creature for each 1 damage prevented this way.
|
||||||
@@ -48,6 +48,7 @@ import forge.card.CardRarity;
|
|||||||
import forge.card.CardRules;
|
import forge.card.CardRules;
|
||||||
import forge.card.ColorSet;
|
import forge.card.ColorSet;
|
||||||
import forge.card.MagicColor;
|
import forge.card.MagicColor;
|
||||||
|
import forge.card.ability.AbilityFactory;
|
||||||
import forge.card.ability.AbilityUtils;
|
import forge.card.ability.AbilityUtils;
|
||||||
import forge.card.ability.ApiType;
|
import forge.card.ability.ApiType;
|
||||||
import forge.card.cardfactory.CardFactoryUtil;
|
import forge.card.cardfactory.CardFactoryUtil;
|
||||||
@@ -7341,6 +7342,66 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
|
|
||||||
int restDamage = damage;
|
int restDamage = damage;
|
||||||
|
|
||||||
|
boolean DEBUGShieldsWithEffects = false;
|
||||||
|
while (!this.getPreventNextDamageWithEffect().isEmpty() && restDamage != 0) {
|
||||||
|
TreeMap<Card, Map<String, String>> shieldMap = this.getPreventNextDamageWithEffect();
|
||||||
|
List<Card> preventionEffectSources = new ArrayList<Card>(shieldMap.keySet());
|
||||||
|
Card shieldSource = preventionEffectSources.get(0);
|
||||||
|
if (preventionEffectSources.size() > 1) {
|
||||||
|
Map<String, Card> choiceMap = new TreeMap<String, Card>();
|
||||||
|
List<String> choices = new ArrayList<String>();
|
||||||
|
for (final Card key : preventionEffectSources) {
|
||||||
|
String effDesc = shieldMap.get(key).get("EffectString");
|
||||||
|
int descIndex = effDesc.indexOf("SpellDescription");
|
||||||
|
effDesc = effDesc.substring(descIndex + 18);
|
||||||
|
String shieldDescription = key.toString() + " - " + shieldMap.get(key).get("ShieldAmount")
|
||||||
|
+ " shields - " + effDesc;
|
||||||
|
choices.add(shieldDescription);
|
||||||
|
choiceMap.put(shieldDescription, key);
|
||||||
|
}
|
||||||
|
shieldSource = this.getController().getController().chooseProtectionShield(this, choices, choiceMap);
|
||||||
|
}
|
||||||
|
if (DEBUGShieldsWithEffects) {
|
||||||
|
System.out.println("Prevention shield source: " + shieldSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
int shieldAmount = Integer.valueOf(shieldMap.get(shieldSource).get("ShieldAmount"));
|
||||||
|
int dmgToBePrevented = Math.min(restDamage, shieldAmount);
|
||||||
|
if (DEBUGShieldsWithEffects) {
|
||||||
|
System.out.println("Selected source initial shield amount: " + shieldAmount);
|
||||||
|
System.out.println("Incoming damage: " + restDamage);
|
||||||
|
System.out.println("Damage to be prevented: " + dmgToBePrevented);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Set up ability
|
||||||
|
SpellAbility shieldSA = null;
|
||||||
|
String effectAbString = shieldMap.get(shieldSource).get("EffectString");
|
||||||
|
effectAbString = effectAbString.replace("PreventedDamage", Integer.toString(dmgToBePrevented));
|
||||||
|
effectAbString = effectAbString.replace("ShieldEffectTarget", shieldMap.get(shieldSource).get("ShieldEffectTarget"));
|
||||||
|
if (DEBUGShieldsWithEffects) {
|
||||||
|
System.out.println("Final shield ability string: " + effectAbString);
|
||||||
|
}
|
||||||
|
shieldSA = AbilityFactory.getAbility(effectAbString, shieldSource);
|
||||||
|
if (shieldSA.usesTargeting()) {
|
||||||
|
System.err.println(shieldSource + " - Targeting for prevention shield's effect should be done with initial spell");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (restDamage >= shieldAmount) {
|
||||||
|
this.getController().getController().playSpellAbilityNoStack(this.getController(), shieldSA);
|
||||||
|
this.subtractPreventNextDamageWithEffect(shieldSource, restDamage);
|
||||||
|
restDamage = restDamage - shieldAmount;
|
||||||
|
} else {
|
||||||
|
this.subtractPreventNextDamageWithEffect(shieldSource, restDamage);
|
||||||
|
this.getController().getController().playSpellAbilityNoStack(this.getController(), shieldSA);
|
||||||
|
restDamage = 0;
|
||||||
|
}
|
||||||
|
if (DEBUGShieldsWithEffects) {
|
||||||
|
System.out.println("Remaining shields: "
|
||||||
|
+ (shieldMap.containsKey(shieldSource) ? shieldMap.get(shieldSource).get("ShieldAmount") : "all shields used"));
|
||||||
|
System.out.println("Remaining damage: " + restDamage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (this.getName().equals("Swans of Bryn Argoll")) {
|
if (this.getName().equals("Swans of Bryn Argoll")) {
|
||||||
source.getController().drawCards(restDamage);
|
source.getController().drawCards(restDamage);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -8228,6 +8289,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
public void onCleanupPhase(final Player turn) {
|
public void onCleanupPhase(final Player turn) {
|
||||||
setDamage(0);
|
setDamage(0);
|
||||||
resetPreventNextDamage();
|
resetPreventNextDamage();
|
||||||
|
resetPreventNextDamageWithEffect();
|
||||||
resetReceivedDamageFromThisTurn();
|
resetReceivedDamageFromThisTurn();
|
||||||
resetDealtDamageToThisTurn();
|
resetDealtDamageToThisTurn();
|
||||||
resetDealtDamageToPlayerThisTurn();
|
resetDealtDamageToPlayerThisTurn();
|
||||||
|
|||||||
@@ -18,6 +18,8 @@
|
|||||||
package forge;
|
package forge;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
@@ -34,6 +36,7 @@ import forge.util.MyObservable;
|
|||||||
public abstract class GameEntity extends MyObservable implements ITargetable {
|
public abstract class GameEntity extends MyObservable implements ITargetable {
|
||||||
private String name = "";
|
private String name = "";
|
||||||
private int preventNextDamage = 0;
|
private int preventNextDamage = 0;
|
||||||
|
private TreeMap<Card, Map<String, String>> preventionShieldsWithEffects = new TreeMap<Card, Map<String, String>>();
|
||||||
|
|
||||||
/** The enchanted by. */
|
/** The enchanted by. */
|
||||||
private ArrayList<Card> enchantedBy = new ArrayList<Card>();
|
private ArrayList<Card> enchantedBy = new ArrayList<Card>();
|
||||||
@@ -255,6 +258,78 @@ public abstract class GameEntity extends MyObservable implements ITargetable {
|
|||||||
this.preventNextDamage = 0;
|
this.preventNextDamage = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PreventNextDamageWithEffect
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Gets the map of damage prevention shields with effects.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @return the map of damage prevention shields with effects.
|
||||||
|
*/
|
||||||
|
public TreeMap<Card, Map<String, String>> getPreventNextDamageWithEffect() {
|
||||||
|
return this.preventionShieldsWithEffects;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Adds a damage prevention shield with an effect that happens at time of prevention.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param shieldSource The source card which generated the shield
|
||||||
|
* @param effectMap A map of the effect occurring with the damage prevention
|
||||||
|
*/
|
||||||
|
public void addPreventNextDamageWithEffect(final Card shieldSource, TreeMap<String, String> effectMap) {
|
||||||
|
if (this.preventionShieldsWithEffects.containsKey(shieldSource)) {
|
||||||
|
int currentShields = Integer.valueOf(this.preventionShieldsWithEffects.get(shieldSource).get("ShieldAmount"));
|
||||||
|
currentShields += Integer.valueOf(effectMap.get("ShieldAmount"));
|
||||||
|
effectMap.put("ShieldAmount", Integer.toString(currentShields));
|
||||||
|
this.preventionShieldsWithEffects.put(shieldSource, effectMap);
|
||||||
|
} else {
|
||||||
|
this.preventionShieldsWithEffects.put(shieldSource, effectMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* subtractPreventNextDamageWithEffect.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param shieldSource The source card which generated the shield
|
||||||
|
* @param n The number of shields to remove originating from shieldSource
|
||||||
|
*/
|
||||||
|
public void subtractPreventNextDamageWithEffect(final Card shieldSource, final int n) {
|
||||||
|
int currentShields = Integer.valueOf(this.preventionShieldsWithEffects.get(shieldSource).get("ShieldAmount"));
|
||||||
|
if (currentShields > n) {
|
||||||
|
this.preventionShieldsWithEffects.get(shieldSource).put("ShieldAmount", String.valueOf(currentShields - n));
|
||||||
|
} else {
|
||||||
|
this.preventionShieldsWithEffects.remove(shieldSource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* resetPreventNextDamageWithEffect.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public void resetPreventNextDamageWithEffect() {
|
||||||
|
this.preventionShieldsWithEffects = new TreeMap<Card, Map<String, String>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Gets the total amount of damage prevention shields.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @return the number of damage prevention shields with and without effects.
|
||||||
|
*/
|
||||||
|
public int getPreventNextDamageTotalShields() {
|
||||||
|
int shields = this.preventNextDamage;
|
||||||
|
for (final Map<String, String> value : this.preventionShieldsWithEffects.values()) {
|
||||||
|
shields += Integer.valueOf(value.get("ShieldAmount"));
|
||||||
|
}
|
||||||
|
return shields;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks for keyword.
|
* Checks for keyword.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -166,6 +166,10 @@ public final class AbilityFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mapParams.containsKey("PreventionSubAbility")) {
|
||||||
|
spellAbility.setSVar(mapParams.get("PreventionSubAbility"), hostCard.getSVar(mapParams.get("PreventionSubAbility")));
|
||||||
|
}
|
||||||
|
|
||||||
if (mapParams.containsKey("SubAbility")) {
|
if (mapParams.containsKey("SubAbility")) {
|
||||||
spellAbility.setSubAbility(getSubAbility(hostCard, hostCard.getSVar(mapParams.get("SubAbility"))));
|
spellAbility.setSubAbility(getSubAbility(hostCard, hostCard.getSVar(mapParams.get("SubAbility"))));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -204,6 +204,14 @@ public class AbilityUtils {
|
|||||||
for (final Card chosen : hostCard.getChosenCard()) {
|
for (final Card chosen : hostCard.getChosenCard()) {
|
||||||
cards.add(game.getCardState(chosen));
|
cards.add(game.getCardState(chosen));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else if (defined.startsWith("CardUID_")) {
|
||||||
|
String idString = defined.substring(8);
|
||||||
|
for (final Card cardByID : game.getCardsInGame()) {
|
||||||
|
if (cardByID.getUniqueNumber() == Integer.valueOf(idString)) {
|
||||||
|
cards.add(game.getCardState(cardByID));
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
List<Card> list = null;
|
List<Card> list = null;
|
||||||
if (defined.startsWith("Sacrificed")) {
|
if (defined.startsWith("Sacrificed")) {
|
||||||
@@ -905,6 +913,13 @@ public class AbilityUtils {
|
|||||||
if (!players.contains(p)) {
|
if (!players.contains(p)) {
|
||||||
players.add(p);
|
players.add(p);
|
||||||
}
|
}
|
||||||
|
} else if (defined.startsWith("PlayerNamed_")) {
|
||||||
|
for (Player p : game.getPlayers()) {
|
||||||
|
System.out.println("Named player " + defined.substring(12));
|
||||||
|
if (p.getName().equals(defined.substring(12))) {
|
||||||
|
players.add(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (defined.startsWith("Flipped")) {
|
} else if (defined.startsWith("Flipped")) {
|
||||||
for (Player p : game.getPlayers()) {
|
for (Player p : game.getPlayers()) {
|
||||||
if (null != sa.getSourceCard().getFlipResult(p)) {
|
if (null != sa.getSourceCard().getFlipResult(p)) {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package forge.card.ability.effects;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
import forge.Card;
|
import forge.Card;
|
||||||
import forge.CardUtil;
|
import forge.CardUtil;
|
||||||
@@ -86,19 +87,62 @@ public class DamagePreventEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final boolean targeted = (sa.usesTargeting());
|
final boolean targeted = (sa.usesTargeting());
|
||||||
|
final boolean preventionWithEffect = sa.hasParam("PreventionSubAbility");
|
||||||
|
|
||||||
for (final Object o : tgts) {
|
for (final Object o : tgts) {
|
||||||
numDam = (sa.usesTargeting() && sa.hasParam("DividedAsYouChoose")) ? sa.getTargetRestrictions().getDividedValue(o) : numDam;
|
numDam = (sa.usesTargeting() && sa.hasParam("DividedAsYouChoose")) ? sa.getTargetRestrictions().getDividedValue(o) : numDam;
|
||||||
if (o instanceof Card) {
|
if (o instanceof Card) {
|
||||||
final Card c = (Card) o;
|
final Card c = (Card) o;
|
||||||
if (c.isInPlay() && (!targeted || c.canBeTargetedBy(sa))) {
|
if (c.isInPlay() && (!targeted || c.canBeTargetedBy(sa))) {
|
||||||
c.addPreventNextDamage(numDam);
|
if (preventionWithEffect) {
|
||||||
|
TreeMap<String, String> effectMap = new TreeMap<String, String>();
|
||||||
|
effectMap.put("EffectString", sa.getSVar(sa.getParam("PreventionSubAbility")));
|
||||||
|
effectMap.put("ShieldAmount", String.valueOf(numDam));
|
||||||
|
if (sa.hasParam("ShieldEffectTarget")) {
|
||||||
|
String effTgtString = "";
|
||||||
|
List<ITargetable> effTgts = new ArrayList<ITargetable>();
|
||||||
|
effTgts = AbilityUtils.getDefinedObjects(host, sa.getParam("ShieldEffectTarget"), sa);
|
||||||
|
for (final Object effTgt : effTgts) {
|
||||||
|
if (effTgt instanceof Card) {
|
||||||
|
effTgtString = String.valueOf(((Card) effTgt).getUniqueNumber());
|
||||||
|
effectMap.put("ShieldEffectTarget", "CardUID_" + effTgtString);
|
||||||
|
} else if (effTgt instanceof Player) {
|
||||||
|
effTgtString = ((Player) effTgt).getName();
|
||||||
|
effectMap.put("ShieldEffectTarget", "PlayerNamed_" + effTgtString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.addPreventNextDamageWithEffect(host, effectMap);
|
||||||
|
} else {
|
||||||
|
c.addPreventNextDamage(numDam);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (o instanceof Player) {
|
} else if (o instanceof Player) {
|
||||||
final Player p = (Player) o;
|
final Player p = (Player) o;
|
||||||
if (!targeted || p.canBeTargetedBy(sa)) {
|
if (!targeted || p.canBeTargetedBy(sa)) {
|
||||||
p.addPreventNextDamage(numDam);
|
if (preventionWithEffect) {
|
||||||
|
TreeMap<String, String> effectMap = new TreeMap<String, String>();
|
||||||
|
effectMap.put("EffectString", sa.getSVar(sa.getParam("PreventionSubAbility")));
|
||||||
|
effectMap.put("ShieldAmount", String.valueOf(numDam));
|
||||||
|
if (sa.hasParam("ShieldEffectTarget")) {
|
||||||
|
String effTgtString = "";
|
||||||
|
List<ITargetable> effTgts = new ArrayList<ITargetable>();
|
||||||
|
effTgts = AbilityUtils.getDefinedObjects(host, sa.getParam("ShieldEffectTarget"), sa);
|
||||||
|
for (final Object effTgt : effTgts) {
|
||||||
|
if (effTgt instanceof Card) {
|
||||||
|
effTgtString = String.valueOf(((Card) effTgt).getUniqueNumber());
|
||||||
|
effectMap.put("ShieldEffectTarget", "CardUID_" + effTgtString);
|
||||||
|
} else if (effTgt instanceof Player) {
|
||||||
|
effTgtString = ((Player) effTgt).getName();
|
||||||
|
effectMap.put("ShieldEffectTarget", "PlayerNamed_" + effTgtString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.addPreventNextDamageWithEffect(host, effectMap);
|
||||||
|
} else {
|
||||||
|
p.addPreventNextDamage(numDam);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -240,12 +240,7 @@ public class ReplacementHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Player player = replacementEffect.getHostCard().getController();
|
Player player = replacementEffect.getHostCard().getController();
|
||||||
//player.getController().playNoStack()
|
player.getController().playSpellAbilityNoStack(player, effectSA);
|
||||||
if (player.isHuman()) {
|
|
||||||
HumanPlay.playSpellAbilityNoStack(player, effectSA);
|
|
||||||
} else {
|
|
||||||
ComputerUtil.playNoStack(player, effectSA, game);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ReplacementResult.Replaced;
|
return ReplacementResult.Replaced;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1828,10 +1828,10 @@ public class ComputerUtilCombat {
|
|||||||
* @return a int.
|
* @return a int.
|
||||||
*/
|
*/
|
||||||
public final static int getDamageToKill(final Card c) {
|
public final static int getDamageToKill(final Card c) {
|
||||||
int killDamage = c.getLethalDamage() + c.getPreventNextDamage();
|
int killDamage = c.getLethalDamage() + c.getPreventNextDamageTotalShields();
|
||||||
if ((killDamage > c.getPreventNextDamage())
|
if ((killDamage > c.getPreventNextDamageTotalShields())
|
||||||
&& c.hasStartOfKeyword("When CARDNAME is dealt damage, destroy it.")) {
|
&& c.hasStartOfKeyword("When CARDNAME is dealt damage, destroy it.")) {
|
||||||
killDamage = 1 + c.getPreventNextDamage();
|
killDamage = 1 + c.getPreventNextDamageTotalShields();
|
||||||
}
|
}
|
||||||
|
|
||||||
return killDamage;
|
return killDamage;
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
@@ -887,6 +888,66 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
|
|
||||||
int restDamage = damage;
|
int restDamage = damage;
|
||||||
|
|
||||||
|
boolean DEBUGShieldsWithEffects = false;
|
||||||
|
while (!this.getPreventNextDamageWithEffect().isEmpty() && restDamage != 0) {
|
||||||
|
TreeMap<Card, Map<String, String>> shieldMap = this.getPreventNextDamageWithEffect();
|
||||||
|
List<Card> preventionEffectSources = new ArrayList<Card>(shieldMap.keySet());
|
||||||
|
Card shieldSource = preventionEffectSources.get(0);
|
||||||
|
if (preventionEffectSources.size() > 1) {
|
||||||
|
Map<String, Card> choiceMap = new TreeMap<String, Card>();
|
||||||
|
List<String> choices = new ArrayList<String>();
|
||||||
|
for (final Card key : preventionEffectSources) {
|
||||||
|
String effDesc = shieldMap.get(key).get("EffectString");
|
||||||
|
int descIndex = effDesc.indexOf("SpellDescription");
|
||||||
|
effDesc = effDesc.substring(descIndex + 18);
|
||||||
|
String shieldDescription = key.toString() + " - " + shieldMap.get(shieldSource).get("ShieldAmount")
|
||||||
|
+ " shields - " + effDesc;
|
||||||
|
choices.add(shieldDescription);
|
||||||
|
choiceMap.put(shieldDescription, key);
|
||||||
|
}
|
||||||
|
shieldSource = this.getController().chooseProtectionShield(this, choices, choiceMap);
|
||||||
|
}
|
||||||
|
if (DEBUGShieldsWithEffects) {
|
||||||
|
System.out.println("Prevention shield source: " + shieldSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
int shieldAmount = Integer.valueOf(shieldMap.get(shieldSource).get("ShieldAmount"));
|
||||||
|
int dmgToBePrevented = Math.min(restDamage, shieldAmount);
|
||||||
|
if (DEBUGShieldsWithEffects) {
|
||||||
|
System.out.println("Selected source initial shield amount: " + shieldAmount);
|
||||||
|
System.out.println("Incoming damage: " + restDamage);
|
||||||
|
System.out.println("Damage to be prevented: " + dmgToBePrevented);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Set up ability
|
||||||
|
SpellAbility shieldSA = null;
|
||||||
|
String effectAbString = shieldMap.get(shieldSource).get("EffectString");
|
||||||
|
effectAbString = effectAbString.replace("PreventedDamage", Integer.toString(dmgToBePrevented));
|
||||||
|
effectAbString = effectAbString.replace("ShieldEffectTarget", shieldMap.get(shieldSource).get("ShieldEffectTarget"));
|
||||||
|
if (DEBUGShieldsWithEffects) {
|
||||||
|
System.out.println("Final shield ability string: " + effectAbString);
|
||||||
|
}
|
||||||
|
shieldSA = AbilityFactory.getAbility(effectAbString, shieldSource);
|
||||||
|
if (shieldSA.usesTargeting()) {
|
||||||
|
System.err.println(shieldSource + " - Targeting for prevention shield's effect should be done with initial spell");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (restDamage >= shieldAmount) {
|
||||||
|
this.getController().playSpellAbilityNoStack(this, shieldSA);
|
||||||
|
this.subtractPreventNextDamageWithEffect(shieldSource, restDamage);
|
||||||
|
restDamage = restDamage - shieldAmount;
|
||||||
|
} else {
|
||||||
|
this.subtractPreventNextDamageWithEffect(shieldSource, restDamage);
|
||||||
|
this.getController().playSpellAbilityNoStack(this, shieldSA);
|
||||||
|
restDamage = 0;
|
||||||
|
}
|
||||||
|
if (DEBUGShieldsWithEffects) {
|
||||||
|
System.out.println("Remaining shields: "
|
||||||
|
+ (shieldMap.containsKey(shieldSource) ? shieldMap.get(shieldSource).get("ShieldAmount") : "all shields used"));
|
||||||
|
System.out.println("Remaining damage: " + restDamage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
final HashMap<String, Object> repParams = new HashMap<String, Object>();
|
final HashMap<String, Object> repParams = new HashMap<String, Object>();
|
||||||
repParams.put("Event", "DamageDone");
|
repParams.put("Event", "DamageDone");
|
||||||
repParams.put("Affected", this);
|
repParams.put("Affected", this);
|
||||||
@@ -2757,6 +2818,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
c.setDrawnThisTurn(false);
|
c.setDrawnThisTurn(false);
|
||||||
}
|
}
|
||||||
resetPreventNextDamage();
|
resetPreventNextDamage();
|
||||||
|
resetPreventNextDamageWithEffect();
|
||||||
resetNumDrawnThisTurn();
|
resetNumDrawnThisTurn();
|
||||||
resetNumDiscardedThisTurn();
|
resetNumDiscardedThisTurn();
|
||||||
setAttackedWithCreatureThisTurn(false);
|
setAttackedWithCreatureThisTurn(false);
|
||||||
|
|||||||
@@ -96,6 +96,7 @@ public abstract class PlayerController {
|
|||||||
//public abstract void playFromSuspend(Card c);
|
//public abstract void playFromSuspend(Card c);
|
||||||
public abstract boolean playCascade(Card cascadedCard, Card sourceCard);
|
public abstract boolean playCascade(Card cascadedCard, Card sourceCard);
|
||||||
public abstract void playSpellAbilityForFree(SpellAbility copySA, boolean mayChoseNewTargets);
|
public abstract void playSpellAbilityForFree(SpellAbility copySA, boolean mayChoseNewTargets);
|
||||||
|
public abstract void playSpellAbilityNoStack(Player player, SpellAbility effectSA);
|
||||||
|
|
||||||
public abstract Deck sideboard(final Deck deck, GameType gameType);
|
public abstract Deck sideboard(final Deck deck, GameType gameType);
|
||||||
|
|
||||||
@@ -157,5 +158,6 @@ public abstract class PlayerController {
|
|||||||
|
|
||||||
public abstract boolean chooseBinary(SpellAbility sa, String question, boolean isCoin);
|
public abstract boolean chooseBinary(SpellAbility sa, String question, boolean isCoin);
|
||||||
public abstract boolean chooseFilpResult(SpellAbility sa, Player flipper, boolean[] results, boolean call);
|
public abstract boolean chooseFilpResult(SpellAbility sa, Player flipper, boolean[] results, boolean call);
|
||||||
|
public abstract Card chooseProtectionShield(GameEntity entityBeingDamaged, List<String> options, Map<String, Card> choiceMap);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -248,6 +248,11 @@ public class PlayerControllerAi extends PlayerController {
|
|||||||
ComputerUtil.playSpellAbilityForFree(player, copySA);
|
ComputerUtil.playSpellAbilityForFree(player, copySA);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void playSpellAbilityNoStack(Player player, SpellAbility effectSA) {
|
||||||
|
ComputerUtil.playNoStack(player, effectSA, game);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void playMiracle(SpellAbility miracle, Card card) {
|
public void playMiracle(SpellAbility miracle, Card card) {
|
||||||
getAi().chooseAndPlaySa(false, false, miracle);
|
getAi().chooseAndPlaySa(false, false, miracle);
|
||||||
@@ -412,4 +417,10 @@ public class PlayerControllerAi extends PlayerController {
|
|||||||
public boolean chooseBinary(SpellAbility sa, String question, boolean isCoin) {
|
public boolean chooseBinary(SpellAbility sa, String question, boolean isCoin) {
|
||||||
return MyRandom.getRandom().nextBoolean();
|
return MyRandom.getRandom().nextBoolean();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Card chooseProtectionShield(GameEntity entityBeingDamaged, List<String> options, Map<String, Card> choiceMap) {
|
||||||
|
int i = MyRandom.getRandom().nextInt(options.size());
|
||||||
|
return choiceMap.get(options.get(i));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -121,6 +121,11 @@ public class PlayerControllerHuman extends PlayerController {
|
|||||||
HumanPlay.playSaWithoutPayingManaCost(player.getGame(), copySA, mayChoseNewTargets);
|
HumanPlay.playSaWithoutPayingManaCost(player.getGame(), copySA, mayChoseNewTargets);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void playSpellAbilityNoStack(Player player, SpellAbility effectSA) {
|
||||||
|
HumanPlay.playSpellAbilityNoStack(player, effectSA);
|
||||||
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see forge.game.player.PlayerController#sideboard(forge.deck.Deck)
|
* @see forge.game.player.PlayerController#sideboard(forge.deck.Deck)
|
||||||
*/
|
*/
|
||||||
@@ -645,6 +650,12 @@ public class PlayerControllerHuman extends PlayerController {
|
|||||||
return GuiChoose.one(sa.getSourceCard().getName() + " - Choose a result", strResults) == labelsSrc[0];
|
return GuiChoose.one(sa.getSourceCard().getName() + " - Choose a result", strResults) == labelsSrc[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Card chooseProtectionShield(GameEntity entityBeingDamaged, List<String> options, Map<String, Card> choiceMap) {
|
||||||
|
String title = entityBeingDamaged + " - select which prevention shield to use";
|
||||||
|
return choiceMap.get(GuiChoose.one(title, options));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Pair<SpellAbilityStackInstance, ITargetable> chooseTarget(SpellAbility saSpellskite, List<Pair<SpellAbilityStackInstance, ITargetable>> allTargets) {
|
public Pair<SpellAbilityStackInstance, ITargetable> chooseTarget(SpellAbility saSpellskite, List<Pair<SpellAbilityStackInstance, ITargetable>> allTargets) {
|
||||||
|
|||||||
@@ -400,7 +400,7 @@ public class CardDetailPanel extends FPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Damage Prevention
|
// Damage Prevention
|
||||||
final int preventNextDamage = card.getPreventNextDamage();
|
final int preventNextDamage = card.getPreventNextDamageTotalShields();
|
||||||
if (preventNextDamage > 0) {
|
if (preventNextDamage > 0) {
|
||||||
area.append("\n");
|
area.append("\n");
|
||||||
area.append("Prevent the next ").append(preventNextDamage).append(" damage that would be dealt to ");
|
area.append("Prevent the next ").append(preventNextDamage).append(" damage that would be dealt to ");
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ public enum VPlayers implements IVDoc<CPlayers> {
|
|||||||
+ String.valueOf(p0.getPoisonCounters()));
|
+ String.valueOf(p0.getPoisonCounters()));
|
||||||
temp[2].setText("Maximum hand size: " + String.valueOf(p0.getMaxHandSize()));
|
temp[2].setText("Maximum hand size: " + String.valueOf(p0.getMaxHandSize()));
|
||||||
temp[3].setText("Cards drawn this turn: " + String.valueOf(p0.getNumDrawnThisTurn()));
|
temp[3].setText("Cards drawn this turn: " + String.valueOf(p0.getNumDrawnThisTurn()));
|
||||||
temp[4].setText("Damage Prevention: " + String.valueOf(p0.getPreventNextDamage()));
|
temp[4].setText("Damage Prevention: " + String.valueOf(p0.getPreventNextDamageTotalShields()));
|
||||||
if (!p0.getKeywords().isEmpty()) {
|
if (!p0.getKeywords().isEmpty()) {
|
||||||
temp[5].setText(p0.getKeywords().toString());
|
temp[5].setText(p0.getKeywords().toString());
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user