Merge branch 'master' into Attractions

This commit is contained in:
Jetz
2024-06-23 11:23:47 -04:00
426 changed files with 921 additions and 108 deletions

View File

@@ -485,7 +485,7 @@ public class DamageDealAi extends DamageAiBase {
return false;
}
return damageChoosingTargets(ai, saMe, tgt, dmg, false, immediately);
return damageChoosingTargets(ai, saMe, tgt, dmg, saMe.isMandatory(), immediately);
}
/**

View File

@@ -174,6 +174,21 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
return cp != null && !cp.isEmpty();
}
public PaperCard removeCardName(String name) {
PaperCard paperCard;
for (Entry<DeckSection, CardPool> kv : parts.entrySet()) {
CardPool pool = kv.getValue();
for (Entry<PaperCard, Integer> pc : pool) {
if (pc.getKey().getName().equalsIgnoreCase(name)) {
paperCard = pc.getKey();
pool.remove(paperCard);
return paperCard;
}
}
}
return null;
}
// will return new if it was absent
public CardPool getOrCreate(DeckSection deckSection) {
CardPool p = get(deckSection);

View File

@@ -22,10 +22,7 @@ package forge.game;
*/
public enum GlobalRuleChange {
attackerChoosesBlockers ("The attacking player chooses how each creature blocks each combat."),
onlyOneBlocker ("No more than one creature can block each combat."),
onlyOneBlockerPerOpponent ("Each opponent can't block with more than one creature."),
onlyTwoBlockers ("No more than two creatures can block each combat.");
attackerChoosesBlockers ("The attacking player chooses how each creature blocks each combat.");
private final String ruleText;

View File

@@ -2133,6 +2133,9 @@ public class CardProperty {
List<String> nameList = Lists.newArrayList(names.split(";"));
return nameList.contains(card.getName());
} else if (property.equals("NotedGuessPhantasm")) {
String names = sourceController.getDraftNotes().get("Spire Phantasm");
return names != null && !names.isEmpty();
} else if (property.equals("NotedTypes")) {
// Should Paliano Vanguard be hardcoded here or part of the property?
String types = sourceController.getDraftNotes().get("Paliano Vanguard");

View File

@@ -24,7 +24,6 @@ import com.google.common.collect.Lists;
import forge.card.mana.ManaCost;
import forge.game.Game;
import forge.game.GameEntity;
import forge.game.GlobalRuleChange;
import forge.game.ability.AbilityKey;
import forge.game.card.*;
import forge.game.cost.Cost;
@@ -36,6 +35,7 @@ import forge.game.player.Player;
import forge.game.player.PlayerController.ManaPaymentPurpose;
import forge.game.spellability.SpellAbility;
import forge.game.staticability.StaticAbility;
import forge.game.staticability.StaticAbilityBlockRestrict;
import forge.game.staticability.StaticAbilityCantAttackBlock;
import forge.game.staticability.StaticAbilityMustBlock;
import forge.game.trigger.TriggerType;
@@ -457,21 +457,11 @@ public class CombatUtil {
if (!canBlockMoreCreatures(blocker, combat.getAttackersBlockedBy(blocker))) {
return false;
}
final Game game = blocker.getGame();
final int blockers = combat.getAllBlockers().size();
if (blockers > 1 && game.getStaticEffects().getGlobalRuleChange(GlobalRuleChange.onlyTwoBlockers)) {
return false;
}
if (blockers > 0 && game.getStaticEffects().getGlobalRuleChange(GlobalRuleChange.onlyOneBlocker)) {
return false;
}
CardCollection allOtherBlockers = combat.getAllBlockers();
allOtherBlockers.remove(blocker);
final int blockersFromOnePlayer = CardLists.count(allOtherBlockers, CardPredicates.isController(blocker.getController()));
if (blockersFromOnePlayer > 0 && game.getStaticEffects().getGlobalRuleChange(GlobalRuleChange.onlyOneBlockerPerOpponent)) {
if (blockersFromOnePlayer >= StaticAbilityBlockRestrict.blockRestrictNum(blocker.getController())) {
return false;
}

View File

@@ -2134,12 +2134,8 @@ public class Player extends GameEntity implements Comparable<Player> {
return lost;
}
public final boolean hasProwl(final Set<String> types) {
StringBuilder sb = new StringBuilder();
for (String type : types) {
sb.append("Card.YouCtrl+").append(type).append(",");
}
return !game.getDamageDoneThisTurn(true, true, sb.toString(), "Player", null, this, null).isEmpty();
public final boolean hasProwl(final SpellAbility sa) {
return !game.getDamageDoneThisTurn(true, true, "Card.YouCtrl+sharesCreatureTypeWith", "Player", sa.getHostCard(), this, sa).isEmpty();
}
public final boolean hasFreerunning() {

View File

@@ -440,7 +440,7 @@ public class SpellAbilityRestriction extends SpellAbilityVariables {
}
}
if (sa.isProwl()) {
if (!activator.hasProwl(c.getType().getCreatureTypes())) {
if (!activator.hasProwl(sa)) {
return false;
}
}

View File

@@ -0,0 +1,39 @@
package forge.game.staticability;
import forge.game.Game;
import forge.game.ability.AbilityUtils;
import forge.game.card.Card;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
public class StaticAbilityBlockRestrict {
static String MODE = "BlockRestrict";
static public int blockRestrictNum(Player defender) {
final Game game = defender.getGame();
int num = Integer.MAX_VALUE;
for (final Card ca : game.getCardsIn(ZoneType.STATIC_ABILITIES_SOURCE_ZONES)) {
for (final StaticAbility stAb : ca.getStaticAbilities()) {
if (!stAb.checkConditions(MODE)) {
continue;
}
if (blockRestrict(stAb, defender)) {
int stNum = AbilityUtils.calculateAmount(stAb.getHostCard(),
stAb.getParamOrDefault("MaxBlockers", "1"), stAb);
if (stNum < num) {
num = stNum;
}
}
}
}
return num;
}
static public boolean blockRestrict(StaticAbility stAb, Player defender) {
if (!stAb.matchesValidParam("ValidDefender", defender)) {
return false;
}
return true;
}
}

View File

@@ -116,12 +116,21 @@ public class CEditorDraftingProcess extends ACEditorBase<PaperCard, DeckGroup> i
// can only draft one at a time, regardless of the requested quantity
PaperCard card = items.iterator().next().getKey();
if (boosterDraft.getHumanPlayer().shouldSkipThisPick()) {
System.out.println(card + " not drafted because we're skipping this pick");
showPackToDraft();
return;
}
// Verify if card is in the activate pack?
this.getDeckManager().addItem(card, 1);
// get next booster pack
// get next booster pack if we aren't picking again from this pack
this.boosterDraft.setChoice(card);
showPackToDraft();
}
protected void showPackToDraft() {
boolean nextChoice = this.boosterDraft.hasNextChoice();
ItemPool<PaperCard> pool = null;
if (nextChoice) {

View File

@@ -58,10 +58,15 @@ public class BoosterDraftTest implements IBoosterDraft {
return result;
}
/** {@inheritDoc} */
/**
* {@inheritDoc}
*
* @return
*/
@Override
public void setChoice(final PaperCard c) {
public boolean setChoice(final PaperCard c) {
System.out.println(c.getName());
return false;
}
@Override

View File

@@ -132,3 +132,4 @@ Alchemy: Ixalan, 3/6/LCI, YLCI
Ravnica Remastered, 3/6/RAV, RVR
Murders at Karlov Manor, 3/6/MKM, MKM
Outlaws of Thunder Junction, 3/6/OTJ, OTJ
Modern Horizons 3, 3/6/MH3, MH3

View File

@@ -0,0 +1,7 @@
Name:Agent of Acquisitions
ManaCost:2
Types:Artifact Creature Construct
PT:2/1
Draft:Draft CARDNAME face up.
Draft:Instead of drafting a card from a booster pack, you may draft each card in that booster pack, one at a time. If you do, turn CARDNAME face down and you cant draft cards for the rest of this draft round. (You may look at booster packs passed to you.)
Oracle:Draft Agent of Acquisitions face up.\nInstead of drafting a card from a booster pack, you may draft each card in that booster pack, one at a time. If you do, turn Agent of Acquisitions face down and you cant draft cards for the rest of this draft round. (You may look at booster packs passed to you.)

View File

@@ -4,6 +4,6 @@ Types:Creature Human
PT:3/1
K:Squad:2
K:CARDNAME can't block.
A:AB$ Pump | PrecostDesc$ Endurant — | Cost$ PayLife<3> | KW$ Indestructible | SpellDescription$ CARDNAME gains indestructible until end of turn.
A:AB$ Pump | PrecostDesc$ Endurant — | Cost$ PayLife<3> | KW$ Indestructible | Defined$ Self | SpellDescription$ CARDNAME gains indestructible until end of turn.
DeckHas:Ability$Token
Oracle:Squad {2} (As an additional cost to cast this spell, you may pay {2} any number of times. When this creature enters the battlefield, create that many tokens that are copies of it.)\nArco-Flagellant can't block.\nEndurant — Pay 3 life: Arco-Flagellant gains indestructible until end of turn.

View File

@@ -2,7 +2,7 @@ Name:Astral Arena
ManaCost:no cost
Types:Plane Kolbahan
S:Mode$ AttackRestrict | EffectZone$ Command | MaxAttackers$ 1 | Description$ No more than one creature can attack each combat.
S:Mode$ Continuous | EffectZone$ Command | GlobalRule$ No more than one creature can block each combat. | Description$ No more than one creature can block each combat.
S:Mode$ BlockRestrict | EffectZone$ Command | MaxBlockers$ 1 | Description$ No more than one creature can block each combat.
T:Mode$ ChaosEnsues | TriggerZones$ Command | Execute$ RolledChaos | TriggerDescription$ Whenever chaos ensues, CARDNAME deals 2 damage to each creature.
SVar:RolledChaos:DB$ DamageAll | NumDmg$ 2 | ValidCards$ Creature
SVar:AIRollPlanarDieParams:Mode$ Random | MinTurn$ 5

View File

@@ -4,7 +4,7 @@ Types:Creature Elemental Knight
PT:5/6
K:Reach
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDig | TriggerDescription$ When CARDNAME enters the battlefield, reveal the top five cards of your library. Put a land card from among them onto the battlefield and the rest into your graveyard.
SVar:TrigDig:DB$ Dig | DigNum$ 5 | ChangeNum$ 1 | ChangeValid$ Land | Optional$ True | DestinationZone$ Battlefield | DestinationZone2$ Graveyard
SVar:TrigDig:DB$ Dig | DigNum$ 5 | ChangeNum$ 1 | ChangeValid$ Land | DestinationZone$ Battlefield | DestinationZone2$ Graveyard
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigExile | TriggerDescription$ When CARDNAME dies, you may exile it. If you do, put another target card from your graveyard on top of your library.
SVar:TrigExile:AB$ ChangeZone | Cost$ ExileAnyGrave<1/Card.TriggeredNewCard> | Origin$ Graveyard | Destination$ Library | ValidTgts$ Card.YouOwn+Other | TgtPrompt$ Select another target card from your graveyard | AITgts$ Card.Other
DeckHas:Ability$Graveyard

View File

@@ -2,7 +2,7 @@ Name:Caverns of Despair
ManaCost:2 R R
Types:World Enchantment
S:Mode$ AttackRestrict | MaxAttackers$ 2 | Description$ No more than two creatures can attack each combat.
S:Mode$ Continuous | GlobalRule$ No more than two creatures can block each combat. | Description$ No more than two creatures can block each combat.
S:Mode$ BlockRestrict | MaxBlockers$ 2 | Description$ No more than two creatures can block each combat.
SVar:NonStackingEffect:True
AI:RemoveDeck:Random
DeckHints:Type$Planeswalker|Artifact|Enchantment|Aura|Equipment

View File

@@ -0,0 +1,7 @@
Name:Cogwork Librarian
ManaCost:4
Types:Artifact Creature Construct
PT:3/3
Draft:Draft CARDNAME face up.
Draft:As you draft a card, you may draft an additional card from that booster pack. If you do, put CARDNAME into that booster pack.
Oracle:Draft Cogwork Librarian face up.\nAs you draft a card, you may draft an additional card from that booster pack. If you do, put Cogwork Librarian into that booster pack.

View File

@@ -2,6 +2,6 @@ Name:Dueling Grounds
ManaCost:1 G W
Types:Enchantment
S:Mode$ AttackRestrict | MaxAttackers$ 1 | Description$ No more than one creature can attack each combat.
S:Mode$ Continuous | GlobalRule$ No more than one creature can block each combat. | Description$ No more than one creature can block each combat.
S:Mode$ BlockRestrict | MaxBlockers$ 1 | Description$ No more than one creature can block each combat.
AI:RemoveDeck:Random
Oracle:No more than one creature can attack each combat.\nNo more than one creature can block each combat.

Some files were not shown because too many files have changed in this diff Show More