Fixed some possible null pointer exceptions (found in server log). Market Festival, Kindred Summons, Profane Processions, New Blood, Kindred Charge , Bishop of Binding, Metzal Tower of Triumph, Chrome Mox

This commit is contained in:
LevelX2 2018-01-11 06:12:27 +01:00
parent a38ec84581
commit 2685d9f8b4
10 changed files with 62 additions and 38 deletions

View file

@ -132,9 +132,11 @@ class BishopOfBindingExiledCardsPowerCount implements DynamicValue {
@Override
public int calculate(Game game, Ability sourceAbility, Effect effect) {
ExileZone exileZone = game.getExile().getExileZone(CardUtil.getExileZoneId(game, sourceAbility.getSourceId(), sourceAbility.getSourceObjectZoneChangeCounter()));
Card exiledCard = exileZone.getRandom(game);
if (exiledCard != null) {
return exiledCard.getPower().getValue();
if (exileZone != null) {
Card exiledCard = exileZone.getRandom(game);
if (exiledCard != null) {
return exiledCard.getPower().getValue();
}
}
return 0;
}

View file

@ -182,7 +182,14 @@ class ChromeMoxManaEffect extends ManaEffect {
if (choice.getChoices().size() == 1) {
choice.setChoice(choice.getChoices().iterator().next());
} else {
player.choose(outcome, choice, game);
while (!player.choose(outcome, choice, game)) {
if (!player.canRespond()) {
return false;
}
}
if (choice.getChoice() == null) {
return false;
}
}
switch (choice.getChoice()) {
case "Black":

View file

@ -34,10 +34,10 @@ import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbil
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ChooseCreatureTypeEffect;
import mage.abilities.effects.common.CreateTokenCopyTargetEffect;
import mage.abilities.effects.common.ExileTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.abilities.effects.common.ExileTargetEffect;
import mage.abilities.effects.common.CreateTokenCopyTargetEffect;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
@ -57,7 +57,7 @@ public class KindredCharge extends CardImpl {
public KindredCharge(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{R}{R}");
// Choose a creature type. For each creature you control of the chosen type, create a token that's a copy of that creature.
// Choose a creature type. For each creature you control of the chosen type, create a token that's a copy of that creature.
// Those tokens gain haste. Exile them at the beginning of the next end step.
this.getSpellAbility().addEffect(new ChooseCreatureTypeEffect(Outcome.Copy));
this.getSpellAbility().addEffect(new KindredChargeEffect());
@ -95,7 +95,11 @@ class KindredChargeEffect extends OneShotEffect {
Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = game.getObject(source.getSourceId());
if (controller != null && sourceObject != null) {
String creatureType = game.getState().getValue(sourceObject.getId() + "_type").toString();
Object object = game.getState().getValue(sourceObject.getId() + "_type");
if (object == null) {
return false;
}
String creatureType = object.toString();
FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("creature you control of the chosen type");
filter.add(new SubtypePredicate(SubType.byDescription(creatureType)));
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, controller.getId(), game)) {

View file

@ -34,9 +34,9 @@ import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ChooseCreatureTypeEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.Card;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.CardType;
@ -48,6 +48,7 @@ import mage.filter.common.FilterCreatureCard;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.game.Game;
import mage.players.Player;
/**
*
* @author Saga
@ -55,10 +56,10 @@ import mage.players.Player;
public class KindredSummons extends CardImpl {
public KindredSummons(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{5}{G}{G}");
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{5}{G}{G}");
// Choose a creature type. Reveal cards from the top of your library until you reveal X creature cards of the chosen type,
// where X is the number of creatures you control of that type. Put those cards onto the battlefield,
// Choose a creature type. Reveal cards from the top of your library until you reveal X creature cards of the chosen type,
// where X is the number of creatures you control of that type. Put those cards onto the battlefield,
// then shuffle the rest of the revealed cards into your library.
this.getSpellAbility().addEffect(new ChooseCreatureTypeEffect(Outcome.PutCreatureInPlay));
this.getSpellAbility().addEffect(new KindredSummonsEffect());
@ -78,8 +79,8 @@ class KindredSummonsEffect extends OneShotEffect {
public KindredSummonsEffect() {
super(Outcome.PutCreatureInPlay);
this.staticText = "Reveal cards from the top of your library until you reveal X creature cards of the chosen type, " +
"where X is the number of creatures you control of that type. Put those cards onto the battlefield, "
this.staticText = "Reveal cards from the top of your library until you reveal X creature cards of the chosen type, "
+ "where X is the number of creatures you control of that type. Put those cards onto the battlefield, "
+ "then shuffle the rest of the revealed cards into your library";
}
@ -97,7 +98,11 @@ class KindredSummonsEffect extends OneShotEffect {
Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = source.getSourceObject(game);
if (controller != null && sourceObject != null) {
String creatureType = game.getState().getValue(sourceObject.getId() + "_type").toString();
Object object = game.getState().getValue(sourceObject.getId() + "_type");
if (object == null) {
return false;
}
String creatureType = object.toString();
FilterControlledCreaturePermanent filterPermanent = new FilterControlledCreaturePermanent("creature you control of the chosen type");
filterPermanent.add(new SubtypePredicate(SubType.byDescription(creatureType)));
int numberOfCards = game.getBattlefield().countAll(filterPermanent, source.getControllerId(), game);

View file

@ -39,8 +39,8 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.choices.ChoiceColor;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
@ -57,10 +57,9 @@ import mage.target.common.TargetLandPermanent;
public class MarketFestival extends CardImpl {
public MarketFestival(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{3}{G}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{G}");
this.subtype.add(SubType.AURA);
// Enchant land
TargetPermanent auraTarget = new TargetLandPermanent();
this.getSpellAbility().addTarget(auraTarget);
@ -108,14 +107,12 @@ class MarketFestivalTriggeredAbility extends TriggeredManaAbility {
return enchantment != null && event.getSourceId().equals(enchantment.getAttachedTo());
}
@Override
public String getRule() {
return "Whenever enchanted land is tapped for mana, its controller adds two mana in any combination of colors to his or her mana pool <i>(in addition to the mana the land produces)</i>.";
}
}
class MarketFestivalManaEffect extends ManaEffect {
public MarketFestivalManaEffect() {
@ -152,7 +149,9 @@ class MarketFestivalManaEffect extends ManaEffect {
return false;
}
}
if (choiceColor.getChoice() == null) { // Possible after reconnect?
return false;
}
choiceColor.increaseMana(mana);
}
checkToFirePossibleEvents(mana, game, source);

View file

@ -126,9 +126,11 @@ class MetzaliTowerOfTriumphEffect extends OneShotEffect {
available.add(permanent);
}
}
Permanent permanent = available.get(RandomUtil.nextInt(available.size()));
if (permanent != null) {
permanent.destroy(source.getSourceId(), game, false);
if (!available.isEmpty()) {
Permanent permanent = available.get(RandomUtil.nextInt(available.size()));
if (permanent != null) {
permanent.destroy(source.getSourceId(), game, false);
}
}
return true;
}

View file

@ -27,6 +27,7 @@
*/
package mage.cards.n;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.Mode;
@ -52,10 +53,6 @@ import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.common.TargetCreaturePermanent;
import mage.target.targetpointer.FixedTarget;
import java.util.LinkedHashSet;
import java.util.UUID;
import java.util.stream.Collectors;
/**
*
* @author LevelX2
@ -124,7 +121,7 @@ class NewBloodEffect extends OneShotEffect {
class ChangeCreatureTypeTargetEffect extends ContinuousEffectImpl {
private SubType fromSubType;
private SubType toSubType;
private final SubType toSubType;
public ChangeCreatureTypeTargetEffect(SubType fromSubType, SubType toSubType, Duration duration) {
super(duration, Layer.TextChangingEffects_3, SubLayer.NA, Outcome.Benefit);
@ -153,6 +150,7 @@ class ChangeCreatureTypeTargetEffect extends ContinuousEffectImpl {
}
}
if (typeChoice.getChoice() == null) {
discard();
return;
}
fromSubType = SubType.byDescription(typeChoice.getChoice());

View file

@ -105,7 +105,7 @@ class ProfaneProcessionEffect extends OneShotEffect {
new ExileTargetEffect(exileId, sourceObject.getIdName()).setTargetPointer(targetPointer).apply(game, source);
game.applyEffects();
ExileZone exileZone = game.getExile().getExileZone(exileId);
if (exileZone.size() > 2) {
if (exileZone != null && exileZone.size() > 2) {
new TransformSourceEffect(true).apply(game, source);
}
return true;

View file

@ -27,11 +27,12 @@
*/
package mage.abilities.common;
import mage.constants.Zone;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
import mage.game.events.EntersTheBattlefieldEvent;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent;
@ -51,7 +52,7 @@ public class CreatureEntersBattlefieldTriggeredAbility extends TriggeredAbilityI
/**
* optional = false<br>
* opponentController = false
*
*
* @param effect
*/
public CreatureEntersBattlefieldTriggeredAbility(Effect effect) {
@ -60,7 +61,7 @@ public class CreatureEntersBattlefieldTriggeredAbility extends TriggeredAbilityI
/**
* opponentController = false
*
*
* @param effect
* @param optional
*/
@ -69,7 +70,7 @@ public class CreatureEntersBattlefieldTriggeredAbility extends TriggeredAbilityI
}
/**
*
*
* @param effect
* @param optional
* @param opponentController
@ -78,7 +79,7 @@ public class CreatureEntersBattlefieldTriggeredAbility extends TriggeredAbilityI
this(Zone.BATTLEFIELD, effect, optional, opponentController);
}
/**
* @param zone
* @param effect
@ -104,7 +105,6 @@ public class CreatureEntersBattlefieldTriggeredAbility extends TriggeredAbilityI
}
}
public CreatureEntersBattlefieldTriggeredAbility(CreatureEntersBattlefieldTriggeredAbility ability) {
super(ability);
this.opponentController = ability.opponentController;
@ -118,7 +118,7 @@ public class CreatureEntersBattlefieldTriggeredAbility extends TriggeredAbilityI
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Permanent permanent = game.getPermanent(event.getTargetId());
Permanent permanent = ((EntersTheBattlefieldEvent) event).getTarget();
if (filter.match(permanent, sourceId, controllerId, game)
&& (permanent.getControllerId().equals(this.controllerId) ^ opponentController)) {
if (!this.getTargets().isEmpty()) {
@ -137,7 +137,7 @@ public class CreatureEntersBattlefieldTriggeredAbility extends TriggeredAbilityI
@Override
public String getRule() {
return "Whenever a " + filter.getMessage() +" enters the battlefield under "
return "Whenever a " + filter.getMessage() + " enters the battlefield under "
+ (opponentController ? "an opponent's control, " : "your control, ")
+ super.getRule();
}

View file

@ -60,12 +60,15 @@ import mage.target.TargetCard;
import mage.util.CardUtil;
import mage.util.GameLog;
import mage.util.ThreadLocalStringBuilder;
import org.apache.log4j.Logger;
/**
* @author BetaSteward_at_googlemail.com
*/
public abstract class PermanentImpl extends CardImpl implements Permanent {
private static final Logger logger = Logger.getLogger(PermanentImpl.class);
public class MarkedDamageInfo {
public MarkedDamageInfo(Counter counter, MageObject sourceObject) {
@ -699,6 +702,10 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
}
}
}
if (getSpellAbility() == null) {
logger.info("FATAL : no spell ability for attach to permanent: " + getName());
return;
}
if (!getSpellAbility().getTargets().isEmpty() && (getSpellAbility().getTargets().get(0) instanceof TargetCard)) {
Card attachedToCard = game.getCard(this.getAttachedTo());
if (attachedToCard != null) {