mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 11:18:01 +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_faerie_avatar.txt -text
|
||||||
forge-gui/res/cardsfolder/d/diamond_kaleidoscope.txt svneol=native#text/plain
|
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/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/dichotomancy.txt -text
|
||||||
forge-gui/res/cardsfolder/d/didgeridoo.txt svneol=native#text/plain
|
forge-gui/res/cardsfolder/d/didgeridoo.txt svneol=native#text/plain
|
||||||
forge-gui/res/cardsfolder/d/diligent_farmhand.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.ComputerUtil;
|
||||||
import forge.ai.ComputerUtilCard;
|
import forge.ai.ComputerUtilCard;
|
||||||
import forge.ai.SpellAbilityAi;
|
import forge.ai.SpellAbilityAi;
|
||||||
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.card.CardLists;
|
import forge.game.card.CardLists;
|
||||||
import forge.game.card.CardPredicates.Presets;
|
import forge.game.card.CardPredicates.Presets;
|
||||||
@@ -49,6 +50,11 @@ public class CopyPermanentAi extends SpellAbilityAi {
|
|||||||
final TargetRestrictions abTgt = sa.getTargetRestrictions();
|
final TargetRestrictions abTgt = sa.getTargetRestrictions();
|
||||||
|
|
||||||
if (abTgt != null) {
|
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<Card> list = aiPlayer.getGame().getCardsIn(ZoneType.Battlefield);
|
||||||
list = CardLists.getValidCards(list, abTgt.getValidTgts(), source.getController(), source);
|
list = CardLists.getValidCards(list, abTgt.getValidTgts(), source.getController(), source);
|
||||||
list = CardLists.getTargetableCards(list, sa);
|
list = CardLists.getTargetableCards(list, sa);
|
||||||
@@ -59,7 +65,6 @@ public class CopyPermanentAi extends SpellAbilityAi {
|
|||||||
return !vars.containsKey("RemAIDeck");
|
return !vars.containsKey("RemAIDeck");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
sa.resetTargets();
|
|
||||||
// target loop
|
// target loop
|
||||||
while (sa.getTargets().getNumTargeted() < abTgt.getMaxTargets(sa.getHostCard(), sa)) {
|
while (sa.getTargets().getNumTargeted() < abTgt.getMaxTargets(sa.getHostCard(), sa)) {
|
||||||
if (list.isEmpty()) {
|
if (list.isEmpty()) {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import forge.ai.ComputerUtilCard;
|
|||||||
import forge.ai.ComputerUtilCost;
|
import forge.ai.ComputerUtilCost;
|
||||||
import forge.ai.SpellAbilityAi;
|
import forge.ai.SpellAbilityAi;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
|
import forge.game.ability.ApiType;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.card.CardLists;
|
import forge.game.card.CardLists;
|
||||||
import forge.game.card.CounterType;
|
import forge.game.card.CounterType;
|
||||||
@@ -44,6 +45,7 @@ public class DestroyAi extends SpellAbilityAi {
|
|||||||
final TargetRestrictions abTgt = sa.getTargetRestrictions();
|
final TargetRestrictions abTgt = sa.getTargetRestrictions();
|
||||||
final Card source = sa.getHostCard();
|
final Card source = sa.getHostCard();
|
||||||
final boolean noRegen = sa.hasParam("NoRegen");
|
final boolean noRegen = sa.hasParam("NoRegen");
|
||||||
|
final String logic = sa.getParam("AILogic");
|
||||||
List<Card> list;
|
List<Card> list;
|
||||||
|
|
||||||
if (abCost != null) {
|
if (abCost != null) {
|
||||||
@@ -66,6 +68,10 @@ public class DestroyAi extends SpellAbilityAi {
|
|||||||
// Targeting
|
// Targeting
|
||||||
if (abTgt != null) {
|
if (abTgt != null) {
|
||||||
sa.resetTargets();
|
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.getTargetableCards(ai.getOpponent().getCardsIn(ZoneType.Battlefield), sa);
|
||||||
list = CardLists.getValidCards(list, abTgt.getValidTgts(), source.getController(), source);
|
list = CardLists.getValidCards(list, abTgt.getValidTgts(), source.getController(), source);
|
||||||
if (sa.hasParam("AITgts")) {
|
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 the targets are only of one type, take the best
|
||||||
if (CardLists.getNotType(list, "Creature").isEmpty()) {
|
if (CardLists.getNotType(list, "Creature").isEmpty()) {
|
||||||
choice = ComputerUtilCard.getBestCreatureAI(list);
|
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()) {
|
} else if (CardLists.getNotType(list, "Land").isEmpty()) {
|
||||||
choice = ComputerUtilCard.getBestLandAI(list);
|
choice = ComputerUtilCard.getBestLandAI(list);
|
||||||
} else {
|
} else {
|
||||||
@@ -162,14 +174,12 @@ public class DestroyAi extends SpellAbilityAi {
|
|||||||
} else {
|
} else {
|
||||||
if (sa.hasParam("Defined")) {
|
if (sa.hasParam("Defined")) {
|
||||||
list = new ArrayList<Card>(AbilityUtils.getDefinedCards(source, sa.getParam("Defined"), sa));
|
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)
|
if ("WillSkipTurn".equals(logic) && !sa.getHostCard().getController().equals(ai)
|
||||||
&& (ai.getCreaturesInPlay().size() >= ai.getOpponent().getCreaturesInPlay().size() || ai.getLife() > 5)) {
|
&& (ai.getCreaturesInPlay().size() >= ai.getOpponent().getCreaturesInPlay().size() || ai.getLife() > 5)) {
|
||||||
// Basic ai logic for Lethal Vapors
|
// Basic ai logic for Lethal Vapors
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (list.isEmpty()
|
if (list.isEmpty()
|
||||||
|| !CardLists.filterControlledBy(list, ai).isEmpty()
|
|| !CardLists.filterControlledBy(list, ai).isEmpty()
|
||||||
|| CardLists.getNotKeyword(list, "Indestructible").isEmpty()) {
|
|| CardLists.getNotKeyword(list, "Indestructible").isEmpty()) {
|
||||||
@@ -251,7 +261,13 @@ public class DestroyAi extends SpellAbilityAi {
|
|||||||
} else {
|
} else {
|
||||||
Card c;
|
Card c;
|
||||||
if (CardLists.getNotType(list, "Creature").isEmpty()) {
|
if (CardLists.getNotType(list, "Creature").isEmpty()) {
|
||||||
|
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);
|
c = ComputerUtilCard.getWorstCreatureAI(list);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
c = ComputerUtilCard.getCheapestPermanentAI(list, sa, false);
|
c = ComputerUtilCard.getCheapestPermanentAI(list, sa, false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -258,6 +258,9 @@ public final class AbilityFactory {
|
|||||||
if (mapParams.containsKey("TargetsWithRelatedProperty")) {
|
if (mapParams.containsKey("TargetsWithRelatedProperty")) {
|
||||||
abTgt.setRelatedProperty(mapParams.get("TargetsWithRelatedProperty"));
|
abTgt.setRelatedProperty(mapParams.get("TargetsWithRelatedProperty"));
|
||||||
}
|
}
|
||||||
|
if (mapParams.containsKey("TargetingPlayer")) {
|
||||||
|
abTgt.setMandatory(true);
|
||||||
|
}
|
||||||
return abTgt;
|
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(" (").append(o.getValue()).append(" times)");
|
||||||
sb.append("\n");
|
sb.append("\n");
|
||||||
}
|
}
|
||||||
|
if (!sa.getUniqueTargets().isEmpty()) {
|
||||||
|
sb.append("Parent Targeted:");
|
||||||
|
sb.append(sa.getUniqueTargets()).append("\n");
|
||||||
|
}
|
||||||
sb.append(sa.getHostCard() + " - " + tgt.getVTSelection());
|
sb.append(sa.getHostCard() + " - " + tgt.getVTSelection());
|
||||||
|
|
||||||
int maxTargets = tgt.getMaxTargets(sa.getHostCard(), sa);
|
int maxTargets = tgt.getMaxTargets(sa.getHostCard(), sa);
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import forge.game.zone.Zone;
|
|||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -139,8 +140,15 @@ public class HumanPlaySpellAbility {
|
|||||||
TargetRestrictions tgt = currentAbility.getTargetRestrictions();
|
TargetRestrictions tgt = currentAbility.getTargetRestrictions();
|
||||||
if (tgt != null && tgt.doesTarget()) {
|
if (tgt != null && tgt.doesTarget()) {
|
||||||
clearTargets(currentAbility);
|
clearTargets(currentAbility);
|
||||||
Player targetingPlayer = ability.hasParam("TargetingPlayer") ?
|
Player targetingPlayer;
|
||||||
AbilityUtils.getDefinedPlayers(source, ability.getParam("TargetingPlayer"), currentAbility).get(0) : ability.getActivatingPlayer();
|
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))
|
if (!targetingPlayer.getController().chooseTargetsFor(currentAbility))
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
Reference in New Issue
Block a user