Merge pull request #2716 from tool4ever/charmFix

Fix NPE when trying to build Charm description
This commit is contained in:
Anthony Calosa
2023-03-21 07:03:55 +08:00
committed by GitHub
7 changed files with 21 additions and 28 deletions

View File

@@ -26,7 +26,7 @@ public class CharmAi extends SpellAbilityAi {
@Override @Override
protected boolean checkApiLogic(Player ai, SpellAbility sa) { protected boolean checkApiLogic(Player ai, SpellAbility sa) {
final Card source = sa.getHostCard(); final Card source = sa.getHostCard();
List<AbilitySub> choices = CharmEffect.makePossibleOptions(sa); List<AbilitySub> choices = CharmEffect.makePossibleOptions(sa, false);
final int num; final int num;
final int min; final int min;

View File

@@ -380,6 +380,8 @@ public final class GameActionUtil {
return costs; return costs;
} }
sa.clearPipsToReduce();
Card source = sa.getHostCard(); Card source = sa.getHostCard();
final Game game = source.getGame(); final Game game = source.getGame();
boolean lkicheck = false; boolean lkicheck = false;

View File

@@ -20,7 +20,7 @@ import forge.util.collect.FCollection;
public class CharmEffect extends SpellAbilityEffect { public class CharmEffect extends SpellAbilityEffect {
public static List<AbilitySub> makePossibleOptions(final SpellAbility sa) { public static List<AbilitySub> makePossibleOptions(final SpellAbility sa, boolean forDesc) {
final Card source = sa.getHostCard(); final Card source = sa.getHostCard();
List<String> restriction = null; List<String> restriction = null;
@@ -29,16 +29,19 @@ public class CharmEffect extends SpellAbilityEffect {
} }
List<AbilitySub> choices = Lists.newArrayList(sa.getAdditionalAbilityList("Choices")); List<AbilitySub> choices = Lists.newArrayList(sa.getAdditionalAbilityList("Choices"));
List<AbilitySub> toRemove = Lists.newArrayList();
for (AbilitySub ch : choices) { if (!forDesc) {
// 603.3c If one of the modes would be illegal, that mode can't be chosen. List<AbilitySub> toRemove = Lists.newArrayList();
if ((ch.usesTargeting() && ch.isTrigger() && ch.getMinTargets() > 0 && for (AbilitySub ch : choices) {
ch.getTargetRestrictions().getNumCandidates(ch, true) == 0) || // 603.3c If one of the modes would be illegal, that mode can't be chosen.
(restriction != null && restriction.contains(ch.getDescription()))) { if ((ch.usesTargeting() && ch.isTrigger() && ch.getMinTargets() > 0 &&
toRemove.add(ch); ch.getTargetRestrictions().getNumCandidates(ch, true) == 0) ||
(restriction != null && restriction.contains(ch.getDescription()))) {
toRemove.add(ch);
}
} }
choices.removeAll(toRemove);
} }
choices.removeAll(toRemove);
int indx = 0; int indx = 0;
// set CharmOrder // set CharmOrder
@@ -52,7 +55,7 @@ public class CharmEffect extends SpellAbilityEffect {
public static String makeFormatedDescription(SpellAbility sa) { public static String makeFormatedDescription(SpellAbility sa) {
Card source = sa.getHostCard(); Card source = sa.getHostCard();
List<AbilitySub> list = CharmEffect.makePossibleOptions(sa); List<AbilitySub> list = CharmEffect.makePossibleOptions(sa, true);
final int num; final int num;
boolean additionalDesc = sa.hasParam("AdditionalDescription"); boolean additionalDesc = sa.hasParam("AdditionalDescription");
boolean optional = sa.hasParam("Optional"); boolean optional = sa.hasParam("Optional");
@@ -166,7 +169,7 @@ public class CharmEffect extends SpellAbilityEffect {
//this resets all previous choices //this resets all previous choices
sa.setSubAbility(null); sa.setSubAbility(null);
List<AbilitySub> choices = makePossibleOptions(sa); List<AbilitySub> choices = makePossibleOptions(sa, false);
// Entwine does use all Choices // Entwine does use all Choices
if (sa.isEntwine()) { if (sa.isEntwine()) {

View File

@@ -258,7 +258,7 @@ public class CopyPermanentEffect extends TokenEffectBase {
game.updateCombatForView(); game.updateCombatForView();
game.fireEvent(new GameEventCombatChanged()); game.fireEvent(new GameEventCombatChanged());
} }
} // end resolve }
public static Card getProtoType(final SpellAbility sa, final Card original, final Player newOwner) { public static Card getProtoType(final SpellAbility sa, final Card original, final Player newOwner) {
final Card host = sa.getHostCard(); final Card host = sa.getHostCard();

View File

@@ -22,7 +22,6 @@ import java.util.Set;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import forge.card.CardType;
import forge.game.ability.AbilityKey; import forge.game.ability.AbilityKey;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.card.CardCollection; import forge.game.card.CardCollection;
@@ -106,11 +105,7 @@ public class CostDiscard extends CostPartWithList {
desc.append("card"); desc.append("card");
} }
else { else {
if (this.getTypeDescription() == null) { desc.append(this.getDescriptiveType());
desc.append(CardType.CoreType.isValidEnum(this.getType()) ? this.getType().toLowerCase() : this.getType());
} else {
desc.append(this.getTypeDescription());
}
desc.append(" card"); desc.append(" card");
} }

View File

@@ -17,7 +17,6 @@
*/ */
package forge.game.cost; package forge.game.cost;
import forge.card.CardType;
import forge.game.Game; import forge.game.Game;
import forge.game.ability.SpellAbilityEffect; import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card; import forge.game.card.Card;
@@ -85,10 +84,7 @@ public class CostExile extends CostPartWithList {
@Override @Override
public final String toString() { public final String toString() {
final Integer i = this.convertAmount(); final Integer i = this.convertAmount();
String desc = this.getTypeDescription() == null ? this.getType() : this.getTypeDescription(); String desc = this.getDescriptiveType();
if (CardType.CoreType.isValidEnum(desc)) {
desc = desc.toLowerCase();
}
String origin = this.from.name().toLowerCase(); String origin = this.from.name().toLowerCase();
if (this.payCostFromSource()) { if (this.payCostFromSource()) {

View File

@@ -404,10 +404,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
} }
public boolean canPlayWithOptionalCost(OptionalCostValue opt) { public boolean canPlayWithOptionalCost(OptionalCostValue opt) {
SpellAbility saOpt = GameActionUtil.addOptionalCosts(this, Lists.newArrayList(opt)); return GameActionUtil.addOptionalCosts(this, Lists.newArrayList(opt)).canPlay();
boolean result = saOpt.canPlay();
saOpt.clearPipsToReduce();
return result;
} }
public boolean isPossible() { public boolean isPossible() {