mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 03:08:02 +00:00
- Added Diaochan, Artful Beauty
This commit is contained in:
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -3495,6 +3495,7 @@ forge-gui/res/cardsfolder/d/diamond_faerie.txt svneol=native#text/plain
|
||||
forge-gui/res/cardsfolder/d/diamond_faerie_avatar.txt -text
|
||||
forge-gui/res/cardsfolder/d/diamond_kaleidoscope.txt svneol=native#text/plain
|
||||
forge-gui/res/cardsfolder/d/diamond_valley.txt svneol=native#text/plain
|
||||
forge-gui/res/cardsfolder/d/diaochan_artful_beauty.txt -text
|
||||
forge-gui/res/cardsfolder/d/dichotomancy.txt -text
|
||||
forge-gui/res/cardsfolder/d/didgeridoo.txt svneol=native#text/plain
|
||||
forge-gui/res/cardsfolder/d/diligent_farmhand.txt svneol=native#text/plain
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.google.common.base.Predicate;
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates.Presets;
|
||||
@@ -49,6 +50,11 @@ public class CopyPermanentAi extends SpellAbilityAi {
|
||||
final TargetRestrictions abTgt = sa.getTargetRestrictions();
|
||||
|
||||
if (abTgt != null) {
|
||||
sa.resetTargets();
|
||||
if (sa.hasParam("TargetingPlayer")) {
|
||||
Player targetingPlayer = AbilityUtils.getDefinedPlayers(source, sa.getParam("TargetingPlayer"), sa).get(0);
|
||||
return targetingPlayer.getController().chooseTargetsFor(sa);
|
||||
}
|
||||
List<Card> list = aiPlayer.getGame().getCardsIn(ZoneType.Battlefield);
|
||||
list = CardLists.getValidCards(list, abTgt.getValidTgts(), source.getController(), source);
|
||||
list = CardLists.getTargetableCards(list, sa);
|
||||
@@ -59,7 +65,6 @@ public class CopyPermanentAi extends SpellAbilityAi {
|
||||
return !vars.containsKey("RemAIDeck");
|
||||
}
|
||||
});
|
||||
sa.resetTargets();
|
||||
// target loop
|
||||
while (sa.getTargets().getNumTargeted() < abTgt.getMaxTargets(sa.getHostCard(), sa)) {
|
||||
if (list.isEmpty()) {
|
||||
|
||||
@@ -7,6 +7,7 @@ import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.ComputerUtilCost;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.ApiType;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CounterType;
|
||||
@@ -44,6 +45,7 @@ public class DestroyAi extends SpellAbilityAi {
|
||||
final TargetRestrictions abTgt = sa.getTargetRestrictions();
|
||||
final Card source = sa.getHostCard();
|
||||
final boolean noRegen = sa.hasParam("NoRegen");
|
||||
final String logic = sa.getParam("AILogic");
|
||||
List<Card> list;
|
||||
|
||||
if (abCost != null) {
|
||||
@@ -66,6 +68,10 @@ public class DestroyAi extends SpellAbilityAi {
|
||||
// Targeting
|
||||
if (abTgt != null) {
|
||||
sa.resetTargets();
|
||||
if (sa.hasParam("TargetingPlayer")) {
|
||||
Player targetingPlayer = AbilityUtils.getDefinedPlayers(source, sa.getParam("TargetingPlayer"), sa).get(0);
|
||||
return targetingPlayer.getController().chooseTargetsFor(sa);
|
||||
}
|
||||
list = CardLists.getTargetableCards(ai.getOpponent().getCardsIn(ZoneType.Battlefield), sa);
|
||||
list = CardLists.getValidCards(list, abTgt.getValidTgts(), source.getController(), source);
|
||||
if (sa.hasParam("AITgts")) {
|
||||
@@ -129,6 +135,12 @@ public class DestroyAi extends SpellAbilityAi {
|
||||
// If the targets are only of one type, take the best
|
||||
if (CardLists.getNotType(list, "Creature").isEmpty()) {
|
||||
choice = ComputerUtilCard.getBestCreatureAI(list);
|
||||
if ("OppDestroyYours".equals(logic)) {
|
||||
Card aiBest = ComputerUtilCard.getBestCreatureAI(ai.getCreaturesInPlay());
|
||||
if (ComputerUtilCard.evaluateCreature(aiBest) > ComputerUtilCard.evaluateCreature(choice) - 40) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else if (CardLists.getNotType(list, "Land").isEmpty()) {
|
||||
choice = ComputerUtilCard.getBestLandAI(list);
|
||||
} else {
|
||||
@@ -162,14 +174,12 @@ public class DestroyAi extends SpellAbilityAi {
|
||||
} else {
|
||||
if (sa.hasParam("Defined")) {
|
||||
list = new ArrayList<Card>(AbilityUtils.getDefinedCards(source, sa.getParam("Defined"), sa));
|
||||
if (sa.hasParam("AILogic")) {
|
||||
String logic = sa.getParam("AILogic");
|
||||
if ("WillSkipTurn".equals(logic) && !sa.getHostCard().getController().equals(ai)
|
||||
&& (ai.getCreaturesInPlay().size() >= ai.getOpponent().getCreaturesInPlay().size() || ai.getLife() > 5)) {
|
||||
// Basic ai logic for Lethal Vapors
|
||||
return true;
|
||||
}
|
||||
if ("WillSkipTurn".equals(logic) && !sa.getHostCard().getController().equals(ai)
|
||||
&& (ai.getCreaturesInPlay().size() >= ai.getOpponent().getCreaturesInPlay().size() || ai.getLife() > 5)) {
|
||||
// Basic ai logic for Lethal Vapors
|
||||
return true;
|
||||
}
|
||||
|
||||
if (list.isEmpty()
|
||||
|| !CardLists.filterControlledBy(list, ai).isEmpty()
|
||||
|| CardLists.getNotKeyword(list, "Indestructible").isEmpty()) {
|
||||
@@ -251,7 +261,13 @@ public class DestroyAi extends SpellAbilityAi {
|
||||
} else {
|
||||
Card c;
|
||||
if (CardLists.getNotType(list, "Creature").isEmpty()) {
|
||||
c = ComputerUtilCard.getWorstCreatureAI(list);
|
||||
if (!sa.getUniqueTargets().isEmpty() && sa.getParent().getApi() == ApiType.Destroy
|
||||
&& sa.getUniqueTargets().get(0) instanceof Card) {
|
||||
// basic ai for Diaochan
|
||||
c = (Card) sa.getUniqueTargets().get(0);
|
||||
} else {
|
||||
c = ComputerUtilCard.getWorstCreatureAI(list);
|
||||
}
|
||||
} else {
|
||||
c = ComputerUtilCard.getCheapestPermanentAI(list, sa, false);
|
||||
}
|
||||
|
||||
@@ -258,6 +258,9 @@ public final class AbilityFactory {
|
||||
if (mapParams.containsKey("TargetsWithRelatedProperty")) {
|
||||
abTgt.setRelatedProperty(mapParams.get("TargetsWithRelatedProperty"));
|
||||
}
|
||||
if (mapParams.containsKey("TargetingPlayer")) {
|
||||
abTgt.setMandatory(true);
|
||||
}
|
||||
return abTgt;
|
||||
}
|
||||
|
||||
|
||||
8
forge-gui/res/cardsfolder/d/diaochan_artful_beauty.txt
Normal file
8
forge-gui/res/cardsfolder/d/diaochan_artful_beauty.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
Name:Diaochan, Artful Beauty
|
||||
ManaCost:3 R
|
||||
Types:Legendary Creature Human Advisor
|
||||
PT:1/1
|
||||
A:AB$ Destroy | Cost$ T | ValidTgts$ Creature | SubAbility$ DBDestroy | AILogic$ OppDestroyYours | PlayerTurn$ True | ActivationPhases$ Upkeep->BeginCombat | SpellDescription$ Destroy target creature of your choice, then destroy target creature of an opponent's choice. Activate this ability only during your turn, before attackers are declared.
|
||||
SVar:DBDestroy:DB$ Destroy | ValidTgts$ Creature | TargetingPlayer$ Opponent
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/diaochan_artful_beauty.jpg
|
||||
Oracle:{T}: Destroy target creature of your choice, then destroy target creature of an opponent's choice. Activate this ability only during your turn, before attackers are declared.
|
||||
@@ -61,7 +61,10 @@ public final class InputSelectTargets extends InputSyncronizedBase {
|
||||
sb.append(" (").append(o.getValue()).append(" times)");
|
||||
sb.append("\n");
|
||||
}
|
||||
|
||||
if (!sa.getUniqueTargets().isEmpty()) {
|
||||
sb.append("Parent Targeted:");
|
||||
sb.append(sa.getUniqueTargets()).append("\n");
|
||||
}
|
||||
sb.append(sa.getHostCard() + " - " + tgt.getVTSelection());
|
||||
|
||||
int maxTargets = tgt.getMaxTargets(sa.getHostCard(), sa);
|
||||
|
||||
@@ -39,6 +39,7 @@ import forge.game.zone.Zone;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@@ -139,9 +140,16 @@ public class HumanPlaySpellAbility {
|
||||
TargetRestrictions tgt = currentAbility.getTargetRestrictions();
|
||||
if (tgt != null && tgt.doesTarget()) {
|
||||
clearTargets(currentAbility);
|
||||
Player targetingPlayer = ability.hasParam("TargetingPlayer") ?
|
||||
AbilityUtils.getDefinedPlayers(source, ability.getParam("TargetingPlayer"), currentAbility).get(0) : ability.getActivatingPlayer();
|
||||
|
||||
Player targetingPlayer;
|
||||
if (currentAbility.hasParam("TargetingPlayer")) {
|
||||
List<Player> candidates = AbilityUtils.getDefinedPlayers(source, currentAbility.getParam("TargetingPlayer"), currentAbility);
|
||||
// activator chooses targeting player
|
||||
targetingPlayer = ability.getActivatingPlayer().getController().chooseSingleEntityForEffect(
|
||||
candidates, currentAbility, "Choose the targeting player");
|
||||
} else {
|
||||
targetingPlayer = ability.getActivatingPlayer();
|
||||
}
|
||||
|
||||
if (!targetingPlayer.getController().chooseTargetsFor(currentAbility))
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user