mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 04:38:00 +00:00
- updates and fixes to damage prevention.
- Added the keyword Absorb. - More AI improvements to handle damage prevention. - Added Lymph Sliver.
This commit is contained in:
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -2761,6 +2761,7 @@ res/cardsfolder/lure.txt -text svneol=native#text/plain
|
||||
res/cardsfolder/lurking_informant.txt -text svneol=native#text/plain
|
||||
res/cardsfolder/lurking_nightstalker.txt -text svneol=native#text/plain
|
||||
res/cardsfolder/lux_cannon.txt -text svneol=native#text/plain
|
||||
res/cardsfolder/lymph_sliver.txt -text svneol=native#text/plain
|
||||
res/cardsfolder/lynx.txt -text svneol=native#text/plain
|
||||
res/cardsfolder/lys_alana_huntmaster.txt -text svneol=native#text/plain
|
||||
res/cardsfolder/ma_chao_western_warrior.txt -text svneol=native#text/plain
|
||||
|
||||
9
res/cardsfolder/lymph_sliver.txt
Normal file
9
res/cardsfolder/lymph_sliver.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
Name:Lymph Sliver
|
||||
ManaCost:4 W
|
||||
Types:Creature Sliver
|
||||
Text:no text
|
||||
PT:3/3
|
||||
K:stPumpAll:Creature.Sliver:0/0/Absorb 1:no Condition:All Sliver creatures have absorb 1. (If a source would deal damage to a Sliver, prevent 1 of that damage.)
|
||||
SVar:Rarity:Common
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/lymph_sliver.jpg
|
||||
End
|
||||
@@ -175,9 +175,10 @@ import java.util.Random;
|
||||
}
|
||||
|
||||
private boolean shouldTgtP(int d, final boolean noPrevention) {
|
||||
int restDamage = d;
|
||||
|
||||
if (AllZone.HumanPlayer.preventAllDamageToPlayer(AF.getHostCard(), false)
|
||||
|| !AllZone.HumanPlayer.canTarget(AF.getHostCard())) return false;
|
||||
if (!noPrevention)
|
||||
restDamage = AllZone.HumanPlayer.staticDamagePrevention(restDamage,AF.getHostCard(),false);
|
||||
|
||||
PlayerZone compHand = AllZone.getZone(Constant.Zone.Hand, AllZone.ComputerPlayer);
|
||||
CardList hand = new CardList(compHand.getCards());
|
||||
@@ -197,10 +198,12 @@ import java.util.Random;
|
||||
CardList hPlay = new CardList(human.getCards());
|
||||
hPlay = hPlay.filter(new CardListFilter() {
|
||||
public boolean addCard(Card c) {
|
||||
int restDamage = d;
|
||||
if (!noPrevention)
|
||||
restDamage = c.staticDamagePrevention(d,AF.getHostCard(),false);
|
||||
// will include creatures already dealt damage
|
||||
return c.isCreature() && (c.getKillDamage() <= d)
|
||||
return c.isCreature() && (c.getKillDamage() <= restDamage)
|
||||
&& CardFactoryUtil.canTarget(AF.getHostCard(), c)
|
||||
&& !(c.preventAllDamageToCard(AF.getHostCard(),false) && !noPrevention)
|
||||
&& !c.getKeyword().contains("Indestructible")
|
||||
&& !(c.getSVar("SacMe").length() > 0);
|
||||
}
|
||||
|
||||
@@ -2216,11 +2216,11 @@ public class Card extends MyObservable {
|
||||
}
|
||||
|
||||
// This is for keywords with a number like Bushido, Annihilator and Rampage. It returns the total.
|
||||
public int getKeywordMagnitute(String k) {
|
||||
public int getKeywordMagnitude(String k) {
|
||||
int count = 0;
|
||||
ArrayList<String> keywords = getKeyword();
|
||||
for(String kw:keywords) {
|
||||
if(kw.contains(k)) {
|
||||
if(kw.startsWith(k)) {
|
||||
String[] parse = kw.split(" ");
|
||||
String s = parse[1];
|
||||
count += Integer.parseInt(s);
|
||||
@@ -2661,10 +2661,8 @@ public class Card extends MyObservable {
|
||||
return getNetDefense() + preventNextDamage - getDamage();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void setDamage(int n) {
|
||||
if(this.getKeyword().contains("Prevent all damage that would be dealt to CARDNAME.")) n = 0;
|
||||
//if(this.getKeyword().contains("Prevent all damage that would be dealt to CARDNAME.")) n = 0;
|
||||
damage = n;
|
||||
}
|
||||
|
||||
@@ -2761,46 +2759,58 @@ public class Card extends MyObservable {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean preventAllDamageToCard(Card source, boolean isCombat) {
|
||||
boolean reduce = false;
|
||||
//This should be also usable by the AI to forecast an effect (so it must not change the game state)
|
||||
public int staticDamagePrevention(final int damage, final Card source, final boolean isCombat) {
|
||||
int restDamage = damage;
|
||||
|
||||
if(isCombat) {
|
||||
reduce = reduce || getKeyword().contains("Prevent all combat damage that would be dealt to and dealt by CARDNAME.");
|
||||
reduce = reduce || getKeyword().contains("Prevent all combat damage that would be dealt to CARDNAME.");
|
||||
reduce = reduce || source.getKeyword().contains("Prevent all combat damage that would be dealt to and dealt by CARDNAME.");
|
||||
reduce = reduce || source.getKeyword().contains("Prevent all combat damage that would be dealt by CARDNAME.");
|
||||
if(getKeyword().contains("Prevent all combat damage that would be dealt to and dealt by CARDNAME."))return 0;
|
||||
if(getKeyword().contains("Prevent all combat damage that would be dealt to CARDNAME."))return 0;
|
||||
if(source.getKeyword().contains("Prevent all combat damage that would be dealt to and dealt by CARDNAME."))return 0;
|
||||
if(source.getKeyword().contains("Prevent all combat damage that would be dealt by CARDNAME."))return 0;
|
||||
}
|
||||
if(getKeyword().contains("Prevent all damage that would be dealt to CARDNAME."))return 0;
|
||||
if(getKeyword().contains("Prevent all damage that would be dealt to and dealt by CARDNAME."))return 0;
|
||||
if(source.getKeyword().contains("Prevent all damage that would be dealt to and dealt by CARDNAME."))return 0;
|
||||
if(source.getKeyword().contains("Prevent all damage that would be dealt by CARDNAME."))return 0;
|
||||
|
||||
if(hasStartOfKeyword("Absorb")) {
|
||||
int absorbed = this.getKeywordMagnitude("Absorb");
|
||||
if (restDamage > absorbed) restDamage = restDamage - absorbed;
|
||||
else return 0;
|
||||
}
|
||||
reduce = reduce || getKeyword().contains("Prevent all damage that would be dealt to CARDNAME.");
|
||||
reduce = reduce || getKeyword().contains("Prevent all damage that would be dealt to and dealt by CARDNAME.");
|
||||
reduce = reduce || source.getKeyword().contains("Prevent all damage that would be dealt to and dealt by CARDNAME.");
|
||||
reduce = reduce || source.getKeyword().contains("Prevent all damage that would be dealt by CARDNAME.");
|
||||
|
||||
//more specific prevents here:
|
||||
reduce = reduce || (getKeyword().contains("Prevent all damage that would be dealt to CARDNAME by artifact creatures.")
|
||||
&& source.isCreature() && source.isArtifact());
|
||||
reduce = reduce || (getKeyword().contains("Prevent all damage that would be dealt to CARDNAME by artifacts.")
|
||||
&& source.isArtifact());
|
||||
reduce = reduce || (getKeyword().contains("Prevent all damage that would be dealt to CARDNAME by creatures.")
|
||||
&& source.isCreature());
|
||||
if((getKeyword().contains("Prevent all damage that would be dealt to CARDNAME by artifact creatures.")
|
||||
&& source.isCreature() && source.isArtifact()))return 0;
|
||||
if((getKeyword().contains("Prevent all damage that would be dealt to CARDNAME by artifacts.")
|
||||
&& source.isArtifact()))return 0;
|
||||
if((getKeyword().contains("Prevent all damage that would be dealt to CARDNAME by creatures.")
|
||||
&& source.isCreature()))return 0;
|
||||
|
||||
// specific Cards
|
||||
reduce = reduce || (this.isCreature() && source.isCreature() &&
|
||||
AllZoneUtil.isCardInPlay("Well-Laid Plans") && source.sharesColorWith(this));
|
||||
reduce = reduce || (!isCombat && AllZoneUtil.isCardInPlay("Mark of Asylum", getController()));
|
||||
reduce = reduce || (source.getController() == getController() && AllZoneUtil.isCardInPlay("Light of Sanction", getController()));
|
||||
return reduce;
|
||||
if(!isCreature()) { //and not a planeswalker
|
||||
if((this.isCreature() && source.isCreature() &&
|
||||
AllZoneUtil.isCardInPlay("Well-Laid Plans") && source.sharesColorWith(this)))return 0;
|
||||
|
||||
if((!isCombat && AllZoneUtil.isCardInPlay("Mark of Asylum", getController())))return 0;
|
||||
|
||||
if((source.getController().isPlayer(getController()) && AllZoneUtil.isCardInPlay("Light of Sanction", getController())))
|
||||
return 0;
|
||||
|
||||
if (AllZoneUtil.isCardInPlay("Plated Pegasus") && source.isSpell()
|
||||
&& restDamage > 0) restDamage = restDamage - 1;
|
||||
} //Creature end
|
||||
|
||||
if (AllZoneUtil.isCardInPlay("Energy Storm") && source.isSpell()) return 0;
|
||||
|
||||
return restDamage;
|
||||
}
|
||||
|
||||
public int preventDamage(final int damage, Card source, boolean isCombat) {
|
||||
int restDamage = damage;
|
||||
|
||||
if (AllZoneUtil.isCardInPlay("Energy Storm") && source.isSpell()) return 0;
|
||||
|
||||
if( preventAllDamageToCard(source, isCombat)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (AllZoneUtil.isCardInPlay("Plated Pegasus") && source.isSpell()
|
||||
&& restDamage > 0) restDamage = restDamage - 1;
|
||||
restDamage = staticDamagePrevention(restDamage, source, isCombat);
|
||||
|
||||
if(restDamage >= preventNextDamage) {
|
||||
restDamage = restDamage - preventNextDamage;
|
||||
|
||||
@@ -454,7 +454,7 @@ public class CardFactoryUtil {
|
||||
|
||||
//Battle stats increasing keywords
|
||||
if (c.hasKeyword("Double Strike")) value += power * 15;
|
||||
value += c.getKeywordMagnitute("Bushido") * 20;
|
||||
value += c.getKeywordMagnitude("Bushido") * 20;
|
||||
value += c.getAmountOfKeyword("Flanking") * 20;
|
||||
|
||||
//Other good keywords
|
||||
@@ -465,8 +465,8 @@ public class CardFactoryUtil {
|
||||
if (c.hasKeyword("Trample")) value += power * 3;
|
||||
if (c.hasKeyword("Vigilance")) value += power * 5 + toughness * 5;
|
||||
if (c.hasKeyword("Wither")) value += power * 10;
|
||||
value += c.getKeywordMagnitute("Rampage");
|
||||
value += c.getKeywordMagnitute("Annihilator") * 30;
|
||||
value += c.getKeywordMagnitude("Rampage");
|
||||
value += c.getKeywordMagnitude("Annihilator") * 30;
|
||||
if (c.hasKeyword("Changeling")) value += 5;
|
||||
if (c.hasKeyword("Whenever CARDNAME becomes blocked by a creature, destroy that creature at end of combat") && power > 0) value += 15;
|
||||
if (c.hasKeyword("Whenever a creature dealt damage by CARDNAME this turn is put into a graveyard, put a +1/+1 counter on CARDNAME.") && power > 0) value += 2;
|
||||
@@ -4495,19 +4495,6 @@ public class CardFactoryUtil {
|
||||
return list;
|
||||
}
|
||||
|
||||
public static int getTotalBushidoMagnitude(Card c) {
|
||||
int count = 0;
|
||||
ArrayList<String> keywords = c.getKeyword();
|
||||
for(String kw:keywords) {
|
||||
if(kw.contains("Bushido")) {
|
||||
String[] parse = kw.split(" ");
|
||||
String s = parse[1];
|
||||
count += Integer.parseInt(s);
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
public static ArrayList<Ability> getBushidoEffects(Card c) {
|
||||
ArrayList<String> keywords = c.getKeyword();
|
||||
ArrayList<Ability> list = new ArrayList<Ability>();
|
||||
|
||||
@@ -471,8 +471,8 @@ public class CombatUtil {
|
||||
|
||||
if(!CardFactoryUtil.canDamage(defender, attacker)) return false;
|
||||
|
||||
int defBushidoMagnitude = CardFactoryUtil.getTotalBushidoMagnitude(defender);
|
||||
int attBushidoMagnitude = CardFactoryUtil.getTotalBushidoMagnitude(attacker);
|
||||
int defBushidoMagnitude = defender.getKeywordMagnitude("Bushido");
|
||||
int attBushidoMagnitude = attacker.getKeywordMagnitude("Bushido");
|
||||
|
||||
int defenderDamage = defender.getNetAttack() - flankingMagnitude + defBushidoMagnitude;
|
||||
int attackerDamage = attacker.getNetAttack() + attBushidoMagnitude;
|
||||
@@ -576,8 +576,8 @@ public class CombatUtil {
|
||||
|
||||
if(!CardFactoryUtil.canDamage(attacker,defender)) return false;
|
||||
|
||||
int defBushidoMagnitude = CardFactoryUtil.getTotalBushidoMagnitude(defender);
|
||||
int attBushidoMagnitude = CardFactoryUtil.getTotalBushidoMagnitude(attacker);
|
||||
int defBushidoMagnitude = defender.getKeywordMagnitude("Bushido");
|
||||
int attBushidoMagnitude = attacker.getKeywordMagnitude("Bushido");
|
||||
|
||||
int defenderDamage = defender.getNetAttack() - flankingMagnitude + defBushidoMagnitude;
|
||||
int attackerDamage = attacker.getNetAttack() + attBushidoMagnitude;
|
||||
|
||||
@@ -218,42 +218,22 @@ public abstract class Player extends MyObservable{
|
||||
GameActionUtil.executePlayerDamageEffects(this, source, damageToDo, false);
|
||||
}
|
||||
|
||||
public boolean preventAllDamageToPlayer(final Card source, final boolean isCombat) {
|
||||
boolean reduce = false;
|
||||
//This should be also usable by the AI to forecast an effect (so it must not change the game state)
|
||||
public int staticDamagePrevention(final int damage, final Card source, final boolean isCombat) {
|
||||
int restDamage = damage;
|
||||
|
||||
if(isCombat) {
|
||||
reduce = reduce || source.getKeyword().contains("Prevent all combat damage that would be dealt to and dealt by CARDNAME.");
|
||||
reduce = reduce || source.getKeyword().contains("Prevent all combat damage that would be dealt by CARDNAME.");
|
||||
if(source.getKeyword().contains("Prevent all combat damage that would be dealt to and dealt by CARDNAME.")) return 0;
|
||||
if(source.getKeyword().contains("Prevent all combat damage that would be dealt by CARDNAME.")) return 0;
|
||||
if (AllZoneUtil.isCardInPlay("Purity", this)) return 0;
|
||||
}
|
||||
reduce = reduce || source.getKeyword().contains("Prevent all damage that would be dealt to and dealt by CARDNAME.");
|
||||
reduce = reduce || source.getKeyword().contains("Prevent all damage that would be dealt by CARDNAME.");
|
||||
|
||||
//Spirit of Resistance
|
||||
if(AllZoneUtil.isCardInPlay("Spirit of Resistance", this)) {
|
||||
if( AllZoneUtil.getPlayerColorInPlay(this, Constant.Color.Black).size() > 0
|
||||
&& AllZoneUtil.getPlayerColorInPlay(this, Constant.Color.Blue).size() > 0
|
||||
&& AllZoneUtil.getPlayerColorInPlay(this, Constant.Color.Green).size() > 0
|
||||
&& AllZoneUtil.getPlayerColorInPlay(this, Constant.Color.Red).size() > 0
|
||||
&& AllZoneUtil.getPlayerColorInPlay(this, Constant.Color.White).size() > 0) {
|
||||
reduce = true;
|
||||
}
|
||||
}
|
||||
return reduce;
|
||||
}
|
||||
|
||||
public int preventDamage(final int damage, Card source, boolean isCombat) {
|
||||
int restDamage = damage;
|
||||
if(source.getKeyword().contains("Prevent all damage that would be dealt to and dealt by CARDNAME.")) return 0;
|
||||
if(source.getKeyword().contains("Prevent all damage that would be dealt by CARDNAME.")) return 0;
|
||||
|
||||
if (AllZoneUtil.isCardInPlay("Purity", this) && !isCombat) {
|
||||
gainLife(restDamage,null);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//specific cards
|
||||
if (AllZoneUtil.isCardInPlay("Energy Storm") && source.isSpell()) return 0;
|
||||
|
||||
if( preventAllDamageToPlayer(source, isCombat)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (AllZoneUtil.isCardInPlay("Spirit of Resistance", this) && !source.getController().equals(this)
|
||||
&& restDamage > 0) restDamage = restDamage - 1;
|
||||
|
||||
@@ -283,6 +263,29 @@ public abstract class Player extends MyObservable{
|
||||
else return 0;
|
||||
}
|
||||
if (AllZoneUtil.isCardInPlay("Urza's Armor", this) && restDamage > 0) restDamage = restDamage - 1;
|
||||
|
||||
if(AllZoneUtil.isCardInPlay("Spirit of Resistance", this)) {
|
||||
if( AllZoneUtil.getPlayerColorInPlay(this, Constant.Color.Black).size() > 0
|
||||
&& AllZoneUtil.getPlayerColorInPlay(this, Constant.Color.Blue).size() > 0
|
||||
&& AllZoneUtil.getPlayerColorInPlay(this, Constant.Color.Green).size() > 0
|
||||
&& AllZoneUtil.getPlayerColorInPlay(this, Constant.Color.Red).size() > 0
|
||||
&& AllZoneUtil.getPlayerColorInPlay(this, Constant.Color.White).size() > 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return restDamage;
|
||||
}
|
||||
|
||||
public int preventDamage(final int damage, Card source, boolean isCombat) {
|
||||
int restDamage = damage;
|
||||
|
||||
// Purity has to stay here because it changes the game state
|
||||
if (AllZoneUtil.isCardInPlay("Purity", this) && !isCombat) {
|
||||
gainLife(restDamage,null);
|
||||
return 0;
|
||||
}
|
||||
|
||||
restDamage = staticDamagePrevention(restDamage, source, isCombat);
|
||||
|
||||
|
||||
if(restDamage >= preventNextDamage) {
|
||||
|
||||
Reference in New Issue
Block a user