mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 12:18:00 +00:00
Merge branch 'fixstuff' into 'master'
Some smaller fixes Closes #1868 See merge request core-developers/forge!4806
This commit is contained in:
@@ -313,7 +313,6 @@ public class AiController {
|
|||||||
// need to set TriggeredObject
|
// need to set TriggeredObject
|
||||||
exSA.setTriggeringObject(AbilityKey.Card, card);
|
exSA.setTriggeringObject(AbilityKey.Card, card);
|
||||||
|
|
||||||
|
|
||||||
// for trigger test, need to ignore the conditions
|
// for trigger test, need to ignore the conditions
|
||||||
SpellAbilityCondition cons = exSA.getConditions();
|
SpellAbilityCondition cons = exSA.getConditions();
|
||||||
if (cons != null) {
|
if (cons != null) {
|
||||||
|
|||||||
@@ -881,7 +881,7 @@ public class ComputerUtilCard {
|
|||||||
public boolean apply(Deck d) {
|
public boolean apply(Deck d) {
|
||||||
for (Entry<DeckSection, CardPool> cp: d) {
|
for (Entry<DeckSection, CardPool> cp: d) {
|
||||||
for (Entry<PaperCard, Integer> e : cp.getValue()) {
|
for (Entry<PaperCard, Integer> e : cp.getValue()) {
|
||||||
if ( e.getKey().getRules().getAiHints().getRemAIDecks() )
|
if (e.getKey().getRules().getAiHints().getRemAIDecks())
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ public abstract class SpellAbilityAi {
|
|||||||
* Handles the AI decision to play a triggered SpellAbility
|
* Handles the AI decision to play a triggered SpellAbility
|
||||||
*/
|
*/
|
||||||
protected boolean doTriggerAINoCost(final Player aiPlayer, final SpellAbility sa, final boolean mandatory) {
|
protected boolean doTriggerAINoCost(final Player aiPlayer, final SpellAbility sa, final boolean mandatory) {
|
||||||
if (canPlayWithoutRestrict(aiPlayer, sa)) {
|
if (canPlayWithoutRestrict(aiPlayer, sa) && (!mandatory || sa.isTargetNumberValid())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -400,7 +400,6 @@ public class PumpAi extends PumpAiBase {
|
|||||||
if (ComputerUtilCard.shouldPumpCard(ai, sa, card, defense, attack, keywords, false)) {
|
if (ComputerUtilCard.shouldPumpCard(ai, sa, card, defense, attack, keywords, false)) {
|
||||||
return true;
|
return true;
|
||||||
} else if (containsUsefulKeyword(ai, keywords, card, sa, attack)) {
|
} else if (containsUsefulKeyword(ai, keywords, card, sa, attack)) {
|
||||||
|
|
||||||
Card pumped = ComputerUtilCard.getPumpedCreature(ai, sa, card, 0, 0, keywords);
|
Card pumped = ComputerUtilCard.getPumpedCreature(ai, sa, card, 0, 0, keywords);
|
||||||
if (game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_ATTACKERS, ai)
|
if (game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_ATTACKERS, ai)
|
||||||
|| game.getPhaseHandler().is(PhaseType.COMBAT_BEGIN, ai)) {
|
|| game.getPhaseHandler().is(PhaseType.COMBAT_BEGIN, ai)) {
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ public abstract class PumpAiBase extends SpellAbilityAi {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean grantsUsefulExtraBlockOpts(final Player ai, final SpellAbility sa, final Card card, List<String> keywords) {
|
public boolean grantsUsefulExtraBlockOpts(final Player ai, final SpellAbility sa, final Card card, List<String> keywords) {
|
||||||
PhaseHandler ph = ai.getGame().getPhaseHandler();
|
PhaseHandler ph = ai.getGame().getPhaseHandler();
|
||||||
Card pumped = ComputerUtilCard.getPumpedCreature(ai, sa, card, 0, 0, keywords);
|
Card pumped = ComputerUtilCard.getPumpedCreature(ai, sa, card, 0, 0, keywords);
|
||||||
@@ -506,7 +505,6 @@ public abstract class PumpAiBase extends SpellAbilityAi {
|
|||||||
else {
|
else {
|
||||||
final boolean addsKeywords = !keywords.isEmpty();
|
final boolean addsKeywords = !keywords.isEmpty();
|
||||||
if (addsKeywords) {
|
if (addsKeywords) {
|
||||||
|
|
||||||
// If the keyword can prevent a creature from attacking, see if there's some kind of viable prioritization
|
// If the keyword can prevent a creature from attacking, see if there's some kind of viable prioritization
|
||||||
if (keywords.contains("CARDNAME can't attack.") || keywords.contains("CARDNAME can't attack or block.")
|
if (keywords.contains("CARDNAME can't attack.") || keywords.contains("CARDNAME can't attack or block.")
|
||||||
|| keywords.contains("HIDDEN CARDNAME can't attack.") || keywords.contains("HIDDEN CARDNAME can't attack or block.")) {
|
|| keywords.contains("HIDDEN CARDNAME can't attack.") || keywords.contains("HIDDEN CARDNAME can't attack or block.")) {
|
||||||
|
|||||||
@@ -151,6 +151,12 @@ public class PumpAllAi extends PumpAiBase {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
|
||||||
|
// important to call canPlay first so targets are added if needed
|
||||||
|
return canPlayAI(ai, sa) || mandatory;
|
||||||
|
}
|
||||||
|
|
||||||
boolean pumpAgainstRemoval(Player ai, SpellAbility sa, List<Card> comp) {
|
boolean pumpAgainstRemoval(Player ai, SpellAbility sa, List<Card> comp) {
|
||||||
final List<GameObject> objects = ComputerUtil.predictThreatenedObjects(sa.getActivatingPlayer(), sa, true);
|
final List<GameObject> objects = ComputerUtil.predictThreatenedObjects(sa.getActivatingPlayer(), sa, true);
|
||||||
for (final Card c : comp) {
|
for (final Card c : comp) {
|
||||||
|
|||||||
@@ -39,6 +39,4 @@ public class TapOrUntapAi extends TapAiBase {
|
|||||||
return randomReturn;
|
return randomReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -772,7 +772,6 @@ public final class CardDb implements ICardDatabase, IDeckGenPool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public PaperCard createUnsupportedCard(String cardName) {
|
public PaperCard createUnsupportedCard(String cardName) {
|
||||||
|
|
||||||
CardRequest request = CardRequest.fromString(cardName);
|
CardRequest request = CardRequest.fromString(cardName);
|
||||||
CardEdition cardEdition = CardEdition.UNKNOWN;
|
CardEdition cardEdition = CardEdition.UNKNOWN;
|
||||||
CardRarity cardRarity = CardRarity.Unknown;
|
CardRarity cardRarity = CardRarity.Unknown;
|
||||||
@@ -813,7 +812,6 @@ public final class CardDb implements ICardDatabase, IDeckGenPool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return new PaperCard(CardRules.getUnsupportedCardNamed(request.cardName), cardEdition.getCode(), cardRarity, 1);
|
return new PaperCard(CardRules.getUnsupportedCardNamed(request.cardName), cardEdition.getCode(), cardRarity, 1);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Editor editor = new Editor();
|
private final Editor editor = new Editor();
|
||||||
|
|||||||
@@ -244,7 +244,6 @@ public class SpellAbilityCondition extends SpellAbilityVariables {
|
|||||||
* @return a boolean.
|
* @return a boolean.
|
||||||
*/
|
*/
|
||||||
public final boolean areMet(final SpellAbility sa) {
|
public final boolean areMet(final SpellAbility sa) {
|
||||||
|
|
||||||
Player activator = sa.getActivatingPlayer();
|
Player activator = sa.getActivatingPlayer();
|
||||||
if (activator == null) {
|
if (activator == null) {
|
||||||
activator = sa.getHostCard().getController();
|
activator = sa.getHostCard().getController();
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ ManaCost:5 R
|
|||||||
Types:Creature Elemental
|
Types:Creature Elemental
|
||||||
PT:6/6
|
PT:6/6
|
||||||
S:Mode$ ReduceCost | ValidCard$ Card.Self | Type$ Spell | Amount$ X | EffectZone$ All | Description$ This spell costs {X} less to cast, where X is the total amount of noncombat damage dealt to your opponents this turn.
|
S:Mode$ ReduceCost | ValidCard$ Card.Self | Type$ Spell | Amount$ X | EffectZone$ All | Description$ This spell costs {X} less to cast, where X is the total amount of noncombat damage dealt to your opponents this turn.
|
||||||
SVar:X:PlayerCountOpponents$NonCombatDamageDealtThisTurn
|
SVar:X:PlayerCountRegisteredOpponents$NonCombatDamageDealtThisTurn
|
||||||
K:Trample
|
K:Trample
|
||||||
T:Mode$ DamageDone | ValidSource$ Card.YouCtrl,Emblem.YouCtrl | ValidTarget$ Opponent | CombatDamage$ False | TriggerZones$ Battlefield | Execute$ TrigDmg | TriggerDescription$ Whenever a source you control deals noncombat damage to an opponent, CARDNAME deals that much damage to target creature or planeswalker that player controls.
|
T:Mode$ DamageDone | ValidSource$ Card.YouCtrl,Emblem.YouCtrl | ValidTarget$ Opponent | CombatDamage$ False | TriggerZones$ Battlefield | Execute$ TrigDmg | TriggerDescription$ Whenever a source you control deals noncombat damage to an opponent, CARDNAME deals that much damage to target creature or planeswalker that player controls.
|
||||||
SVar:TrigDmg:DB$ DealDamage | ValidTgts$ Creature,Planeswalker | TgtPrompt$ Select target creature or planeswalker that player controls | TargetsWithDefinedController$ TriggeredTarget | NumDmg$ Y
|
SVar:TrigDmg:DB$ DealDamage | ValidTgts$ Creature,Planeswalker | TgtPrompt$ Select target creature or planeswalker that player controls | TargetsWithDefinedController$ TriggeredTarget | NumDmg$ Y
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ Name:Draconic Intervention
|
|||||||
ManaCost:2 R R
|
ManaCost:2 R R
|
||||||
Types:Sorcery
|
Types:Sorcery
|
||||||
A:SP$ DamageAll | Cost$ 2 R R ExileFromGrave<1/Instant;Sorcery> | NumDmg$ X | ValidCards$ Creature.nonDragon | RememberDamaged$ True | ReplaceDyingDefined$ Remembered | SubAbility$ DBCleanup | SpellDescription$ CARDNAME deals X damage to each non-Dragon creature, where X is the exiled card’s mana value. If a creature dealt damage this way would die this turn, exile it instead.
|
A:SP$ DamageAll | Cost$ 2 R R ExileFromGrave<1/Instant;Sorcery> | NumDmg$ X | ValidCards$ Creature.nonDragon | RememberDamaged$ True | ReplaceDyingDefined$ Remembered | SubAbility$ DBCleanup | SpellDescription$ CARDNAME deals X damage to each non-Dragon creature, where X is the exiled card’s mana value. If a creature dealt damage this way would die this turn, exile it instead.
|
||||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True | SubAbility$ DBChange
|
||||||
|
SVar:DBChange:DB$ ChangeZone | Origin$ Stack | Destination$ Exile
|
||||||
SVar:X:Exiled$CardManaCost
|
SVar:X:Exiled$CardManaCost
|
||||||
Oracle:As an additional cost to cast this spell, exile an instant or sorcery card from your graveyard.\nDraconic Intervention deals X damage to each non-Dragon creature, where X is the exiled card's mana value. If a creature dealt damage this way would die this turn, exile it instead.\nExile Draconic Intervention.
|
Oracle:As an additional cost to cast this spell, exile an instant or sorcery card from your graveyard.\nDraconic Intervention deals X damage to each non-Dragon creature, where X is the exiled card's mana value. If a creature dealt damage this way would die this turn, exile it instead.\nExile Draconic Intervention.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
Name:Giant Opportunity
|
Name:Giant Opportunity
|
||||||
ManaCost:2 G
|
ManaCost:2 G
|
||||||
Types:Sorcery
|
Types:Sorcery
|
||||||
A:SP$ Sacrifice | Cost$ 2 G | SacValid$ Food | Defined$ You | Amount$ 2 | Optional$ True | StrictAmount$ True | RememberSacrificed$ True | SubAbility$ DBToken | SpellDescription$ You may sacrifice two Foods. If you do, create a 7/7 green Giant creature token. Otherwise, create three Food tokens. (They're artifacts with "{2}, {T}, Sacrifice this artifact: You gain 3 life.")
|
A:SP$ Sacrifice | Cost$ 2 G | SacValid$ Food | Defined$ You | Amount$ 2 | OptionalSacrifice$ True | StrictAmount$ True | RememberSacrificed$ True | SubAbility$ DBToken | SpellDescription$ You may sacrifice two Foods. If you do, create a 7/7 green Giant creature token. Otherwise, create three Food tokens. (They're artifacts with "{2}, {T}, Sacrifice this artifact: You gain 3 life.")
|
||||||
SVar:DBToken:DB$ Token | TokenAmount$ 1 | TokenScript$ g_7_7_giant | TokenOwner$ You | ConditionDefined$ RememberedLKI | ConditionPresent$ Food | ConditionCompare$ EQ2 | SubAbility$ DBToken2
|
SVar:DBToken:DB$ Token | TokenAmount$ 1 | TokenScript$ g_7_7_giant | TokenOwner$ You | ConditionDefined$ RememberedLKI | ConditionPresent$ Food | ConditionCompare$ EQ2 | SubAbility$ DBToken2
|
||||||
SVar:DBToken2:DB$ Token | TokenAmount$ 3 | TokenScript$ c_a_food_sac | TokenOwner$ You | ConditionDefined$ RememberedLKI | ConditionPresent$ Food | ConditionCompare$ EQ0 | SubAbility$ DBCleanup
|
SVar:DBToken2:DB$ Token | TokenAmount$ 3 | TokenScript$ c_a_food_sac | TokenOwner$ You | ConditionDefined$ RememberedLKI | ConditionPresent$ Food | ConditionCompare$ EQ0 | SubAbility$ DBCleanup
|
||||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||||
|
|||||||
@@ -5,5 +5,5 @@ A:SP$ Pump | Cost$ R | ValidTgts$ Creature.OppCtrl | AILogic$ PowerDmg | TgtProm
|
|||||||
SVar:MutinyDamage:DB$ DealDamage | ValidTgts$ Creature.OppCtrl | TargetUnique$ True | AILogic$ PowerDmg | NumDmg$ X | DamageSource$ ParentTarget
|
SVar:MutinyDamage:DB$ DealDamage | ValidTgts$ Creature.OppCtrl | TargetUnique$ True | AILogic$ PowerDmg | NumDmg$ X | DamageSource$ ParentTarget
|
||||||
SVar:X:ParentTargeted$CardPower
|
SVar:X:ParentTargeted$CardPower
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/mutiny.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/mutiny.jpg
|
||||||
//Not perfect yet, there seems to be no check whether the creature's controller is the same?
|
//TODO Not perfect yet, there seems to be no check whether the creature's controller is the same?
|
||||||
Oracle:Target creature an opponent controls deals damage equal to its power to another target creature that player controls.
|
Oracle:Target creature an opponent controls deals damage equal to its power to another target creature that player controls.
|
||||||
@@ -4,6 +4,6 @@ Types:Legendary Creature Merfolk Rogue
|
|||||||
PT:1/3
|
PT:1/3
|
||||||
T:Mode$ Phase | Phase$ End of Turn | TriggerZones$ Battlefield | Execute$ TrigDraw | OptionalDecider$ You | CheckSVar$ X | SVarCompare$ GE3 | TriggerDescription$ At the beginning of each end step, if an opponent lost 3 or more life this turn, you may draw a card. (Damage causes loss of life.)
|
T:Mode$ Phase | Phase$ End of Turn | TriggerZones$ Battlefield | Execute$ TrigDraw | OptionalDecider$ You | CheckSVar$ X | SVarCompare$ GE3 | TriggerDescription$ At the beginning of each end step, if an opponent lost 3 or more life this turn, you may draw a card. (Damage causes loss of life.)
|
||||||
SVar:TrigDraw:DB$ Draw | Defined$ You | NumCards$ 1
|
SVar:TrigDraw:DB$ Draw | Defined$ You | NumCards$ 1
|
||||||
SVar:X:PlayerCountOpponents$HighestLifeLostThisTurn
|
SVar:X:PlayerCountRegisteredOpponents$HighestLifeLostThisTurn
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/sygg_river_cutthroat.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/sygg_river_cutthroat.jpg
|
||||||
Oracle:At the beginning of each end step, if an opponent lost 3 or more life this turn, you may draw a card. (Damage causes loss of life.)
|
Oracle:At the beginning of each end step, if an opponent lost 3 or more life this turn, you may draw a card. (Damage causes loss of life.)
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ public abstract class InputPayMana extends InputSyncronizedBase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onStop() {
|
protected void onStop() {
|
||||||
|
if (!isFinished()) {
|
||||||
// Clear current Mana cost being paid for SA
|
// Clear current Mana cost being paid for SA
|
||||||
saPaidFor.setManaCostBeingPaid(null);
|
saPaidFor.setManaCostBeingPaid(null);
|
||||||
player.popPaidForSA();
|
player.popPaidForSA();
|
||||||
@@ -74,6 +75,7 @@ public abstract class InputPayMana extends InputSyncronizedBase {
|
|||||||
getController().getGui().hideManaPool(PlayerView.get(player));
|
getController().getGui().hideManaPool(PlayerView.get(player));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean onCardSelected(final Card card, final List<Card> otherCardsToSelect, final ITriggerEvent triggerEvent) {
|
protected boolean onCardSelected(final Card card, final List<Card> otherCardsToSelect, final ITriggerEvent triggerEvent) {
|
||||||
|
|||||||
@@ -36,8 +36,6 @@ public abstract class InputSyncronizedBase extends InputBase implements InputSyn
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected final void stop() {
|
protected final void stop() {
|
||||||
onStop();
|
|
||||||
|
|
||||||
// ensure input won't accept any user actions.
|
// ensure input won't accept any user actions.
|
||||||
FThreads.invokeInEdtNowOrLater(new Runnable() {
|
FThreads.invokeInEdtNowOrLater(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
@@ -46,6 +44,8 @@ public abstract class InputSyncronizedBase extends InputBase implements InputSyn
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
onStop();
|
||||||
|
|
||||||
// thread irrelevant
|
// thread irrelevant
|
||||||
if (getController().getInputQueue().getInput() != null) {
|
if (getController().getInputQueue().getInput() != null) {
|
||||||
getController().getInputQueue().removeInput(InputSyncronizedBase.this);
|
getController().getInputQueue().removeInput(InputSyncronizedBase.this);
|
||||||
|
|||||||
Reference in New Issue
Block a user