Merge pull request #2570 from tool4ever/NPEfixes

Fix 4 NPE from Sentry
This commit is contained in:
Anthony Calosa
2023-02-26 18:05:01 +08:00
committed by GitHub
6 changed files with 10 additions and 9 deletions

View File

@@ -816,6 +816,7 @@ public class AiAttackController {
if (combat.getAttackConstraints().getRequirements().get(attacker) == null) continue;
// check defenders in order of maximum requirements
for (Pair<GameEntity, Integer> e : combat.getAttackConstraints().getRequirements().get(attacker).getSortedRequirements()) {
// TODO check if desired defender would also have the same amount
if (e.getRight() == 0) continue;
GameEntity mustAttackDefMaybe = e.getLeft();
// Gideon Jura returns LKI

View File

@@ -1324,9 +1324,9 @@ public class ComputerUtilMana {
public static ManaCostBeingPaid calculateManaCost(final SpellAbility sa, final boolean test, final int extraMana) {
Card card = sa.getHostCard();
Zone castFromBackup = null;
if (test && sa.isSpell()) {
if (test && sa.isSpell() && !card.isInZone(ZoneType.Stack)) {
castFromBackup = card.getCastFrom();
sa.getHostCard().setCastFrom(card.getZone() != null ? card.getZone() : null);
card.setCastFrom(card.getZone() != null ? card.getZone() : null);
}
Cost payCosts = CostAdjustment.adjust(sa.getPayCosts(), sa);

View File

@@ -37,7 +37,7 @@ public class PermanentNoncreatureAi extends PermanentAi {
// Check for valid targets before casting
if (host.hasSVar("OblivionRing")) {
SpellAbility effectExile = AbilityFactory.getAbility(host.getSVar("TrigExile"), host);
final ZoneType origin = ZoneType.listValueOf(effectExile.getParam("Origin")).get(0);
final ZoneType origin = ZoneType.listValueOf(effectExile.getParamOrDefault("Origin", "Battlefield")).get(0);
effectExile.setActivatingPlayer(ai, true);
CardCollection targets = CardLists.getTargetableCards(game.getCardsIn(origin), effectExile);
if (sourceName.equals("Suspension Field")

View File

@@ -188,7 +188,7 @@ public class ForgeScript {
} else if (property.startsWith("XCost")) {
String comparator = property.substring(5, 7);
int y = AbilityUtils.calculateAmount(sa.getHostCard(), property.substring(7), sa);
return Expressions.compare(sa.getXManaCostPaid(), comparator, y);
return Expressions.compare(sa.getXManaCostPaid() == null ? 0 : sa.getXManaCostPaid(), comparator, y);
} else if (property.equals("hasTapCost")) {
Cost cost = sa.getPayCosts();
return cost != null && cost.hasTapCost();

View File

@@ -42,6 +42,7 @@ import forge.game.GameEntityCounterTable;
import forge.game.GameLogEntryType;
import forge.game.GameObjectMap;
import forge.game.ability.AbilityKey;
import forge.game.ability.ApiType;
import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.card.CardCollectionView;
@@ -795,7 +796,7 @@ public class Combat {
assigningPlayer = orderedBlockers.get(0).getController();
}
final SpellAbility emptySA = new SpellAbility.EmptySa(attacker);
final SpellAbility emptySA = new SpellAbility.EmptySa(ApiType.Cleanup, attacker);
boolean assignToPlayer = false;
if (StaticAbilityAssignCombatDamageAsUnblocked.assignCombatDamageAsUnblocked(attacker, false)) {
@@ -846,8 +847,7 @@ public class Combat {
// If the Attacker is unblocked, or it's a trampler and has 0 blockers, deal damage to defender
if (defender instanceof Card && attacker.hasKeyword("Trample:Planeswalker")) {
if (orderedBlockers == null || orderedBlockers.isEmpty()) {
CardCollection cc = new CardCollection();
cc.add((Card)defender);
CardCollection cc = new CardCollection((Card) defender);
orderedBlockers = cc;
} else {
orderedBlockers.add((Card) defender);
@@ -862,7 +862,7 @@ public class Combat {
attackers.remove(attacker);
if (assignCombatDamageToCreature) {
Card chosen = attacker.getController().getController().chooseCardsForEffect(getDefendersCreatures(),
null, Localizer.getInstance().getMessage("lblChooseCreature"), 1, 1, false, null).get(0);
emptySA, Localizer.getInstance().getMessage("lblChooseCreature"), 1, 1, false, null).get(0);
damageMap.put(attacker, chosen, damageDealt);
} else if (trampler || !band.isBlocked()) { // this is called after declare blockers, no worries 'bout nulls in isBlocked
damageMap.put(attacker, defender, damageDealt);

View File

@@ -2,7 +2,7 @@ Name:Detention Sphere
ManaCost:1 W U
Types:Enchantment
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | OptionalDecider$ You | Execute$ TrigExile | TriggerDescription$ When CARDNAME enters the battlefield, you may exile target nonland permanent not named Detention Sphere and all other permanents with the same name as that permanent.
SVar:TrigExile:DB$ Pump | ValidTgts$ Permanent.nonLand+notnamedDetention Sphere | TgtPrompt$ Choose target nonland permanent not named Detention Sphere | SubAbility$ DBChangeZoneAll
SVar:TrigExile:DB$ Pump | ValidTgts$ Permanent.nonLand+notnamedDetention Sphere | IsCurse$ True | TgtPrompt$ Choose target nonland permanent not named Detention Sphere | SubAbility$ DBChangeZoneAll
SVar:DBChangeZoneAll:DB$ ChangeZoneAll | ChangeType$ Targeted.Self,Targeted.sameName | Origin$ Battlefield | Destination$ Exile | RememberChanged$ True | ForgetOtherRemembered$ True
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Any | ValidCard$ Card.Self | Execute$ TrigReturn | TriggerDescription$ When CARDNAME leaves the battlefield, return the exiled cards to the battlefield under their owner's control.
SVar:TrigReturn:DB$ ChangeZoneAll | ChangeType$ Card.IsRemembered | Origin$ Exile | Destination$ Battlefield