mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 11:18:01 +00:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<artifactId>forge</artifactId>
|
||||
<groupId>forge</groupId>
|
||||
<version>1.6.33-SNAPSHOT</version>
|
||||
<version>1.6.34-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>forge-ai</artifactId>
|
||||
|
||||
@@ -2323,7 +2323,7 @@ public class ComputerUtil {
|
||||
return chosen;
|
||||
}
|
||||
|
||||
public static Object vote(Player ai, List<Object> options, SpellAbility sa, Multimap<Object, Player> votes) {
|
||||
public static Object vote(Player ai, List<Object> options, SpellAbility sa, Multimap<Object, Player> votes, Player forPlayer) {
|
||||
final Card source = sa.getHostCard();
|
||||
final Player controller = source.getController();
|
||||
final Game game = controller.getGame();
|
||||
|
||||
@@ -513,8 +513,8 @@ public class PlayerControllerAi extends PlayerController {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object vote(SpellAbility sa, String prompt, List<Object> options, ListMultimap<Object, Player> votes) {
|
||||
return ComputerUtil.vote(player, options, sa, votes);
|
||||
public Object vote(SpellAbility sa, String prompt, List<Object> options, ListMultimap<Object, Player> votes, Player forPlayer) {
|
||||
return ComputerUtil.vote(player, options, sa, votes, forPlayer);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1295,6 +1295,26 @@ public class SpecialCardAi {
|
||||
}
|
||||
}
|
||||
|
||||
// Timmerian Fiends
|
||||
public static class TimmerianFiends {
|
||||
public static boolean consider(final Player ai, final SpellAbility sa) {
|
||||
final Card targeted = sa.getParentTargetingCard().getTargetCard();
|
||||
if (targeted == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (targeted.isCreature()) {
|
||||
if (ComputerUtil.aiLifeInDanger(ai, true, 0)) {
|
||||
return true; // do it, hoping to save a valuable potential blocker etc.
|
||||
}
|
||||
return ComputerUtilCard.evaluateCreature(targeted) >= 200; // might need tweaking
|
||||
} else {
|
||||
// TODO: this currently compares purely by CMC. To be somehow improved, especially for stuff like the Power Nine etc.
|
||||
return ComputerUtilCard.evaluatePermanentList(new CardCollection(targeted)) >= 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Volrath's Shapeshifter
|
||||
public static class VolrathsShapeshifter {
|
||||
public static boolean consider(final Player ai, final SpellAbility sa) {
|
||||
|
||||
@@ -1,15 +1,10 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.ComputerUtilMana;
|
||||
import forge.ai.SpecialCardAi;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.card.Card;
|
||||
@@ -24,6 +19,11 @@ import forge.game.spellability.SpellAbility;
|
||||
import forge.game.spellability.TargetRestrictions;
|
||||
import forge.game.zone.ZoneType;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class MillAi extends SpellAbilityAi {
|
||||
|
||||
@Override
|
||||
@@ -196,6 +196,10 @@ public class MillAi extends SpellAbilityAi {
|
||||
*/
|
||||
@Override
|
||||
public boolean confirmAction(Player player, SpellAbility sa, PlayerActionConfirmMode mode, String message) {
|
||||
if ("TimmerianFiends".equals(sa.getParam("AILogic"))) {
|
||||
return SpecialCardAi.TimmerianFiends.consider(player, sa);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -46,6 +46,12 @@ public class VoteAi extends SpellAbilityAi {
|
||||
|
||||
@Override
|
||||
public int chooseNumber(Player player, SpellAbility sa, int min, int max, Map<String, Object> params) {
|
||||
if (params.containsKey("Voter")) {
|
||||
Player p = (Player)params.get("Voter");
|
||||
if (p.isOpponentOf(player)) {
|
||||
return min;
|
||||
}
|
||||
}
|
||||
if (sa.getActivatingPlayer().isOpponentOf(player)) {
|
||||
return min;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<artifactId>forge</artifactId>
|
||||
<groupId>forge</groupId>
|
||||
<version>1.6.33-SNAPSHOT</version>
|
||||
<version>1.6.34-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>forge-core</artifactId>
|
||||
|
||||
@@ -6,6 +6,7 @@ import forge.card.CardRarity;
|
||||
import forge.card.CardRules;
|
||||
import forge.card.CardType.CoreType;
|
||||
import forge.card.MagicColor;
|
||||
import forge.util.PredicateCard;
|
||||
import forge.util.PredicateString;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
@@ -60,6 +61,8 @@ public interface IPaperCard extends InventoryItem {
|
||||
return new PredicateNames(what);
|
||||
}
|
||||
|
||||
public static PredicateCards cards(final List<PaperCard> what) { return new PredicateCards(what); }
|
||||
|
||||
private static final class PredicateColor implements Predicate<PaperCard> {
|
||||
|
||||
private final byte operand;
|
||||
@@ -161,6 +164,25 @@ public interface IPaperCard extends InventoryItem {
|
||||
}
|
||||
}
|
||||
|
||||
private static final class PredicateCards extends PredicateCard<PaperCard> {
|
||||
private final List<PaperCard> operand;
|
||||
|
||||
@Override
|
||||
public boolean apply(final PaperCard card) {
|
||||
for (final PaperCard element : this.operand) {
|
||||
if (this.op(card, element)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private PredicateCards(final List<PaperCard> operand) {
|
||||
super(StringOp.EQUALS);
|
||||
this.operand = operand;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pre-built predicates are stored here to allow their re-usage and
|
||||
* easier access from code.
|
||||
|
||||
@@ -566,12 +566,8 @@ public class BoosterGenerator {
|
||||
toAdd = IPaperCard.Predicates.printedInSets(sets);
|
||||
} else if (operator.startsWith("fromSheet(") && invert) {
|
||||
String sheetName = StringUtils.strip(operator.substring(9), "()\" ");
|
||||
Iterable<PaperCard> src = StaticData.instance().getPrintSheets().get(sheetName).toFlatList();
|
||||
List<String> cardNames = Lists.newArrayList();
|
||||
for (PaperCard card : src) {
|
||||
cardNames.add(card.getName());
|
||||
}
|
||||
toAdd = IPaperCard.Predicates.names(Lists.newArrayList(cardNames));
|
||||
Iterable<PaperCard> cards = StaticData.instance().getPrintSheets().get(sheetName).toFlatList();
|
||||
toAdd = IPaperCard.Predicates.cards(Lists.newArrayList(cards));
|
||||
}
|
||||
|
||||
if (toAdd == null) {
|
||||
|
||||
83
forge-core/src/main/java/forge/util/PredicateCard.java
Normal file
83
forge-core/src/main/java/forge/util/PredicateCard.java
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2020 Jamin W. Collins
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.util;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import forge.item.PaperCard;
|
||||
|
||||
/**
|
||||
* Special predicate class to perform string operations.
|
||||
*
|
||||
* @param <T>
|
||||
* the generic type
|
||||
*/
|
||||
public abstract class PredicateCard<T> implements Predicate<T> {
|
||||
/** Possible operators for string operands. */
|
||||
public enum StringOp {
|
||||
/** The EQUALS. */
|
||||
EQUALS,
|
||||
}
|
||||
|
||||
/** The operator. */
|
||||
private final StringOp operator;
|
||||
|
||||
/**
|
||||
* Op.
|
||||
*
|
||||
* @param op1
|
||||
* the op1
|
||||
* @param op2
|
||||
* the op2
|
||||
* @return true, if successful
|
||||
*/
|
||||
protected final boolean op(final PaperCard op1, final PaperCard op2) {
|
||||
switch (this.getOperator()) {
|
||||
case EQUALS:
|
||||
return op1.equals(op2);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new predicate string.
|
||||
*
|
||||
* @param operator
|
||||
* the operator
|
||||
*/
|
||||
public PredicateCard(final StringOp operator) {
|
||||
this.operator = operator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the operator
|
||||
*/
|
||||
public StringOp getOperator() {
|
||||
return operator;
|
||||
}
|
||||
|
||||
public static PredicateCard<PaperCard> equals(final PaperCard what) {
|
||||
return new PredicateCard<PaperCard>(StringOp.EQUALS) {
|
||||
@Override
|
||||
public boolean apply(PaperCard subject) {
|
||||
return op(subject, what);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<artifactId>forge</artifactId>
|
||||
<groupId>forge</groupId>
|
||||
<version>1.6.33-SNAPSHOT</version>
|
||||
<version>1.6.34-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>forge-game</artifactId>
|
||||
|
||||
@@ -914,4 +914,17 @@ public class Game {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Player getControlVote() {
|
||||
Player result = null;
|
||||
long maxValue = 0;
|
||||
for (Player p : getPlayers()) {
|
||||
Long v = p.getHighestControlVote();
|
||||
if (v != null && v > maxValue) {
|
||||
maxValue = v;
|
||||
result = p;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,7 +177,6 @@ public class StaticEffect {
|
||||
final CardCollectionView remove() {
|
||||
final CardCollectionView affectedCards = getAffectedCards();
|
||||
final List<Player> affectedPlayers = getAffectedPlayers();
|
||||
//final Map<String, String> params = getParams();
|
||||
|
||||
String changeColorWordsTo = null;
|
||||
|
||||
@@ -245,6 +244,10 @@ public class StaticEffect {
|
||||
|
||||
p.removeMaxLandPlays(getTimestamp());
|
||||
p.removeMaxLandPlaysInfinite(getTimestamp());
|
||||
|
||||
p.removeControlVote(getTimestamp());
|
||||
p.removeAdditionalVote(getTimestamp());
|
||||
p.removeAdditionalOptionalVote(getTimestamp());
|
||||
}
|
||||
|
||||
// modify the affected card
|
||||
|
||||
@@ -70,7 +70,7 @@ public class DebuffEffect extends SpellAbilityEffect {
|
||||
for (final Card tgtC : getTargetCards(sa)) {
|
||||
final List<String> addedKW = Lists.newArrayList();
|
||||
final List<String> removedKW = Lists.newArrayList();
|
||||
if (tgtC.isInPlay() && tgtC.canBeTargetedBy(sa)) {
|
||||
if (tgtC.isInPlay() && (!sa.usesTargeting() || tgtC.canBeTargetedBy(sa))) {
|
||||
if (sa.hasParam("AllSuffixKeywords")) {
|
||||
String suffix = sa.getParam("AllSuffixKeywords");
|
||||
for (final KeywordInterface kw : tgtC.getKeywords()) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package forge.game.ability.effects;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -9,9 +10,9 @@ import forge.game.ability.AbilityKey;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.ListMultimap;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.ability.AbilityFactory;
|
||||
@@ -19,10 +20,7 @@ import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.SpellAbilityEffect;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.player.PlayerCollection;
|
||||
import forge.game.player.PlayerPredicates;
|
||||
import forge.game.spellability.AbilitySub;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.trigger.TriggerType;
|
||||
@@ -67,33 +65,29 @@ public class VoteEffect extends SpellAbilityEffect {
|
||||
return;
|
||||
}
|
||||
|
||||
// starting with the activator
|
||||
int pSize = tgtPlayers.size();
|
||||
Player activator = sa.getActivatingPlayer();
|
||||
while (tgtPlayers.contains(activator) && !activator.equals(Iterables.getFirst(tgtPlayers, null))) {
|
||||
tgtPlayers.add(pSize - 1, tgtPlayers.remove(0));
|
||||
|
||||
// starting with the activator
|
||||
int aidx = tgtPlayers.indexOf(activator);
|
||||
if (aidx != -1) {
|
||||
Collections.rotate(tgtPlayers, -aidx);
|
||||
}
|
||||
|
||||
ListMultimap<Object, Player> votes = ArrayListMultimap.create();
|
||||
|
||||
Player voter = null;
|
||||
|
||||
PlayerCollection voters = game.getPlayers().filter(PlayerPredicates.hasKeyword("You choose how each player votes this turn."));
|
||||
|
||||
if (voters.size() > 1) {
|
||||
List<Card> illusions = CardLists.filter(voters.getCardsIn(ZoneType.Command), CardPredicates.nameEquals("Illusion of Choice Effect"));
|
||||
voter = Collections.max(illusions, CardPredicates.compareByTimestamp()).getController();
|
||||
} else if (voters.size() == 1) {
|
||||
voter = voters.get(0);
|
||||
}
|
||||
Player voter = game.getControlVote();
|
||||
|
||||
for (final Player p : tgtPlayers) {
|
||||
int voteAmount = p.getKeywords().getAmount("You get an additional vote.") + 1;
|
||||
int optionalVotes = p.getKeywords().getAmount("You may vote an additional time.");
|
||||
voteAmount += p.getController().chooseNumber(sa, Localizer.getInstance().getMessage("lblHowManyAdditionalVotesDoYouWant"), 0, optionalVotes);
|
||||
int voteAmount = p.getAdditionalVotesAmount() + 1;
|
||||
int optionalVotes = p.getAdditionalOptionalVotesAmount();
|
||||
Player realVoter = voter == null ? p : voter;
|
||||
|
||||
Map<String, Object> params = Maps.newHashMap();
|
||||
params.put("Voter", realVoter);
|
||||
voteAmount += p.getController().chooseNumber(sa, Localizer.getInstance().getMessage("lblHowManyAdditionalVotesDoYouWant"), 0, optionalVotes, params);
|
||||
|
||||
for (int i = 0; i < voteAmount; i++) {
|
||||
Object result = realVoter.getController().vote(sa, host + Localizer.getInstance().getMessage("lblVote") + ":", voteType, votes);
|
||||
Object result = realVoter.getController().vote(sa, host + Localizer.getInstance().getMessage("lblVote") + ":", voteType, votes, p);
|
||||
|
||||
votes.put(result, p);
|
||||
host.getGame().getAction().nofityOfValue(sa, p, result + "\r\n" + Localizer.getInstance().getMessage("lblCurrentVote") + ":" + votes, p);
|
||||
@@ -104,6 +98,20 @@ public class VoteEffect extends SpellAbilityEffect {
|
||||
runParams.put(AbilityKey.AllVotes, votes);
|
||||
game.getTriggerHandler().runTrigger(TriggerType.Vote, runParams, false);
|
||||
|
||||
if (sa.hasParam("EachVote")) {
|
||||
for (Map.Entry<Object, Collection<Player>> e : votes.asMap().entrySet()) {
|
||||
final SpellAbility action = AbilityFactory.getAbility(host, sa.getParam("Vote" + e.getKey().toString()));
|
||||
|
||||
action.setActivatingPlayer(sa.getActivatingPlayer());
|
||||
((AbilitySub) action).setParent(sa);
|
||||
|
||||
for (Player p : e.getValue()) {
|
||||
host.addRemembered(p);
|
||||
AbilityUtils.resolve(action);
|
||||
host.removeRemembered(p);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
List<String> subAbs = Lists.newArrayList();
|
||||
final List<Object> mostVotes = getMostVotes(votes);
|
||||
if (sa.hasParam("Tied") && mostVotes.size() > 1) {
|
||||
@@ -124,7 +132,7 @@ public class VoteEffect extends SpellAbilityEffect {
|
||||
}
|
||||
} else {
|
||||
for (final String subAb : subAbs) {
|
||||
final SpellAbility action = AbilityFactory.getAbility(host.getSVar(subAb), host);
|
||||
final SpellAbility action = AbilityFactory.getAbility(host, subAb);
|
||||
action.setActivatingPlayer(sa.getActivatingPlayer());
|
||||
((AbilitySub) action).setParent(sa);
|
||||
AbilityUtils.resolve(action);
|
||||
@@ -134,6 +142,7 @@ public class VoteEffect extends SpellAbilityEffect {
|
||||
host.clearRemembered();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static List<Object> getMostVotes(final ListMultimap<Object, Player> votes) {
|
||||
final List<Object> most = Lists.newArrayList();
|
||||
|
||||
@@ -3938,8 +3938,10 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
keywordsGrantedByTextChanges.add(newKw);
|
||||
}
|
||||
}
|
||||
if (!addKeywords.isEmpty() || !removeKeywords.isEmpty()) {
|
||||
addChangedCardKeywordsInternal(addKeywords, removeKeywords, false, false, timestamp, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateKeywordsOnRemoveChangedText(final KeywordsChange k) {
|
||||
if (k != null) {
|
||||
|
||||
@@ -162,6 +162,10 @@ public class Player extends GameEntity implements Comparable<Player> {
|
||||
private Card blessingEffect = null;
|
||||
private Card keywordEffect = null;
|
||||
|
||||
private Map<Long, Integer> additionalVotes = Maps.newHashMap();
|
||||
private Map<Long, Integer> additionalOptionalVotes = Maps.newHashMap();
|
||||
private SortedSet<Long> controlVotes = Sets.newTreeSet();
|
||||
|
||||
private final AchievementTracker achievementTracker = new AchievementTracker();
|
||||
private final PlayerView view;
|
||||
|
||||
@@ -3067,4 +3071,86 @@ public class Player extends GameEntity implements Comparable<Player> {
|
||||
this.updateZoneForView(com);
|
||||
return keywordEffect;
|
||||
}
|
||||
|
||||
public void addAdditionalVote(long timestamp, int value) {
|
||||
additionalVotes.put(timestamp, value);
|
||||
getView().updateAdditionalVote(this);
|
||||
getGame().fireEvent(new GameEventPlayerStatsChanged(this, false));
|
||||
}
|
||||
|
||||
public void removeAdditionalVote(long timestamp) {
|
||||
if (additionalVotes.remove(timestamp) != null) {
|
||||
getView().updateAdditionalVote(this);
|
||||
getGame().fireEvent(new GameEventPlayerStatsChanged(this, false));
|
||||
}
|
||||
}
|
||||
|
||||
public int getAdditionalVotesAmount() {
|
||||
int value = 0;
|
||||
for (Integer i : additionalVotes.values()) {
|
||||
value += i;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public void addAdditionalOptionalVote(long timestamp, int value) {
|
||||
additionalOptionalVotes.put(timestamp, value);
|
||||
getView().updateOptionalAdditionalVote(this);
|
||||
getGame().fireEvent(new GameEventPlayerStatsChanged(this, false));
|
||||
}
|
||||
public void removeAdditionalOptionalVote(long timestamp) {
|
||||
if (additionalOptionalVotes.remove(timestamp) != null) {
|
||||
getView().updateOptionalAdditionalVote(this);
|
||||
getGame().fireEvent(new GameEventPlayerStatsChanged(this, false));
|
||||
}
|
||||
}
|
||||
|
||||
public int getAdditionalOptionalVotesAmount() {
|
||||
int value = 0;
|
||||
for (Integer i : additionalOptionalVotes.values()) {
|
||||
value += i;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public boolean addControlVote(long timestamp) {
|
||||
if (controlVotes.add(timestamp)) {
|
||||
updateControlVote();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public boolean removeControlVote(long timestamp) {
|
||||
if (controlVotes.remove(timestamp)) {
|
||||
updateControlVote();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void updateControlVote() {
|
||||
// need to update all players because it can't know
|
||||
Player control = getGame().getControlVote();
|
||||
for (Player pl : getGame().getPlayers()) {
|
||||
pl.getView().updateControlVote(pl.equals(control));
|
||||
getGame().fireEvent(new GameEventPlayerStatsChanged(pl, false));
|
||||
}
|
||||
}
|
||||
|
||||
public Set<Long> getControlVote() {
|
||||
return controlVotes;
|
||||
}
|
||||
|
||||
public void setControlVote(Set<Long> value) {
|
||||
controlVotes.clear();
|
||||
controlVotes.addAll(value);
|
||||
updateControlVote();
|
||||
}
|
||||
|
||||
public Long getHighestControlVote() {
|
||||
if (controlVotes.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return controlVotes.last();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,7 +166,7 @@ public abstract class PlayerController {
|
||||
return chooseSomeType(kindOfType, sa, validTypes, invalidTypes, false);
|
||||
}
|
||||
|
||||
public abstract Object vote(SpellAbility sa, String prompt, List<Object> options, ListMultimap<Object, Player> votes);
|
||||
public abstract Object vote(SpellAbility sa, String prompt, List<Object> options, ListMultimap<Object, Player> votes, Player forPlayer);
|
||||
public abstract boolean confirmReplacementEffect(ReplacementEffect replacementEffect, SpellAbility effectSA, String question);
|
||||
|
||||
public abstract CardCollectionView getCardsToMulligan(Player firstPlayer);
|
||||
|
||||
@@ -271,6 +271,27 @@ public class PlayerView extends GameEntityView {
|
||||
set(TrackableProperty.NumDrawnThisTurn, p.getNumDrawnThisTurn());
|
||||
}
|
||||
|
||||
public int getAdditionalVote() {
|
||||
return get(TrackableProperty.AdditionalVote);
|
||||
}
|
||||
public void updateAdditionalVote(Player p) {
|
||||
set(TrackableProperty.AdditionalVote, p.getAdditionalVotesAmount());
|
||||
}
|
||||
|
||||
public int getOptionalAdditionalVote() {
|
||||
return get(TrackableProperty.OptionalAdditionalVote);
|
||||
}
|
||||
public void updateOptionalAdditionalVote(Player p) {
|
||||
set(TrackableProperty.OptionalAdditionalVote, p.getAdditionalOptionalVotesAmount());
|
||||
}
|
||||
|
||||
public boolean getControlVote() {
|
||||
return get(TrackableProperty.ControlVotes);
|
||||
}
|
||||
public void updateControlVote(boolean val) {
|
||||
set(TrackableProperty.ControlVotes, val);
|
||||
}
|
||||
|
||||
public ImmutableMultiset<String> getKeywords() {
|
||||
return get(TrackableProperty.Keywords);
|
||||
}
|
||||
@@ -497,6 +518,19 @@ public class PlayerView extends GameEntityView {
|
||||
details.add(Localizer.getInstance().getMessage("lblCardDrawnThisTurnHas", String.valueOf(getNumDrawnThisTurn())));
|
||||
details.add(Localizer.getInstance().getMessage("lblDamagepreventionHas", String.valueOf(getPreventNextDamage())));
|
||||
|
||||
int v = getAdditionalVote();
|
||||
if (v > 0) {
|
||||
details.add(Localizer.getInstance().getMessage("lblAdditionalVotes", String.valueOf(v)));
|
||||
}
|
||||
v = getOptionalAdditionalVote();
|
||||
if (v > 0) {
|
||||
details.add(Localizer.getInstance().getMessage("lblOptionalAdditionalVotes", String.valueOf(v)));
|
||||
}
|
||||
|
||||
if (getControlVote()) {
|
||||
details.add(Localizer.getInstance().getMessage("lblControlsVote"));
|
||||
}
|
||||
|
||||
if (getIsExtraTurn()) {
|
||||
details.add(Localizer.getInstance().getMessage("lblIsExtraTurn"));
|
||||
}
|
||||
|
||||
@@ -181,15 +181,9 @@ public class StaticAbility extends CardTraitBase implements IIdentifiable, Clone
|
||||
layers.add(StaticAbilityLayer.MODIFYPT);
|
||||
}
|
||||
|
||||
if (hasParam("AddHiddenKeyword")) {
|
||||
layers.add(StaticAbilityLayer.RULES);
|
||||
}
|
||||
|
||||
if (hasParam("IgnoreEffectCost") || hasParam("Goad") || hasParam("CanBlockAny") || hasParam("CanBlockAmount")) {
|
||||
layers.add(StaticAbilityLayer.RULES);
|
||||
}
|
||||
|
||||
if (hasParam("AdjustLandPlays")) {
|
||||
if (hasParam("AddHiddenKeyword")
|
||||
|| hasParam("IgnoreEffectCost") || hasParam("Goad") || hasParam("CanBlockAny") || hasParam("CanBlockAmount")
|
||||
|| hasParam("AdjustLandPlays") || hasParam("ControlVote") || hasParam("AdditionalVote") || hasParam("AdditionalOptionalVote")) {
|
||||
layers.add(StaticAbilityLayer.RULES);
|
||||
}
|
||||
|
||||
|
||||
@@ -513,6 +513,20 @@ public final class StaticAbilityContinuous {
|
||||
}
|
||||
}
|
||||
|
||||
if (params.containsKey("ControlVote")) {
|
||||
p.addControlVote(se.getTimestamp());
|
||||
}
|
||||
if (params.containsKey("AdditionalVote")) {
|
||||
String mhs = params.get("AdditionalVote");
|
||||
int add = AbilityUtils.calculateAmount(hostCard, mhs, stAb);
|
||||
p.addAdditionalVote(se.getTimestamp(), add);
|
||||
}
|
||||
if (params.containsKey("AdditionalOptionalVote")) {
|
||||
String mhs = params.get("AdditionalOptionalVote");
|
||||
int add = AbilityUtils.calculateAmount(hostCard, mhs, stAb);
|
||||
p.addAdditionalOptionalVote(se.getTimestamp(), add);
|
||||
}
|
||||
|
||||
if (params.containsKey("RaiseMaxHandSize")) {
|
||||
String rmhs = params.get("RaiseMaxHandSize");
|
||||
int rmax = AbilityUtils.calculateAmount(hostCard, rmhs, stAb);
|
||||
|
||||
@@ -134,6 +134,9 @@ public enum TrackableProperty {
|
||||
HasUnlimitedLandPlay(TrackableTypes.BooleanType),
|
||||
NumLandThisTurn(TrackableTypes.IntegerType),
|
||||
NumDrawnThisTurn(TrackableTypes.IntegerType),
|
||||
AdditionalVote(TrackableTypes.IntegerType),
|
||||
OptionalAdditionalVote(TrackableTypes.IntegerType),
|
||||
ControlVotes(TrackableTypes.BooleanType),
|
||||
Keywords(TrackableTypes.KeywordCollectionViewType, FreezeMode.IgnoresFreeze),
|
||||
Commander(TrackableTypes.CardViewCollectionType, FreezeMode.IgnoresFreeze),
|
||||
CommanderCast(TrackableTypes.IntegerMapType),
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
<parent>
|
||||
<artifactId>forge</artifactId>
|
||||
<groupId>forge</groupId>
|
||||
<version>1.6.33-SNAPSHOT</version>
|
||||
<version>1.6.34-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>forge-gui-android</artifactId>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>forge</artifactId>
|
||||
<groupId>forge</groupId>
|
||||
<version>1.6.33-SNAPSHOT</version>
|
||||
<version>1.6.34-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>forge-gui-desktop</artifactId>
|
||||
@@ -213,7 +213,7 @@
|
||||
<plugin>
|
||||
<groupId>com.akathist.maven.plugins.launch4j</groupId>
|
||||
<artifactId>launch4j-maven-plugin</artifactId>
|
||||
<version>1.5.2</version>
|
||||
<version>1.7.25</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>l4j-gui</id>
|
||||
@@ -235,7 +235,10 @@
|
||||
</classPath>
|
||||
<jre>
|
||||
<minVersion>1.8.0</minVersion>
|
||||
<maxHeapSize>1024</maxHeapSize>
|
||||
<maxHeapSize>4096</maxHeapSize>
|
||||
<opts>
|
||||
<opt>-Dfile.encoding=UTF-8</opt>
|
||||
</opts>
|
||||
</jre>
|
||||
<versionInfo>
|
||||
<fileVersion>
|
||||
@@ -367,7 +370,7 @@
|
||||
<plugin>
|
||||
<groupId>com.akathist.maven.plugins.launch4j</groupId>
|
||||
<artifactId>launch4j-maven-plugin</artifactId>
|
||||
<version>1.5.2</version>
|
||||
<version>1.7.25</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>l4j-gui</id>
|
||||
@@ -389,7 +392,10 @@
|
||||
</classPath>
|
||||
<jre>
|
||||
<minVersion>1.8.0</minVersion>
|
||||
<maxHeapSize>1024</maxHeapSize>
|
||||
<maxHeapSize>4096</maxHeapSize>
|
||||
<opts>
|
||||
<opt>-Dfile.encoding=UTF-8</opt>
|
||||
</opts>
|
||||
</jre>
|
||||
<versionInfo>
|
||||
<fileVersion>
|
||||
@@ -564,7 +570,7 @@
|
||||
<option value="-Dcom.apple.macos.useScreenMenuBar=true" />
|
||||
<option value="-Dcom.apple.mrj.application.apple.menu.about.name=Forge" />
|
||||
<option value="-Dcom.apple.smallTabs=true" />
|
||||
<option value="-Xmx1024M" />
|
||||
<option value="-Xmx4096M" />
|
||||
<option value="-Dapp.dir=$APP_ROOT/Contents/Resources/" />
|
||||
</bundleapp>
|
||||
<copy todir="${project.build.directory}/${project.build.finalName}-osx/Forge.app/Contents/Resources/res">
|
||||
@@ -675,7 +681,7 @@
|
||||
<option value="-Dcom.apple.macos.useScreenMenuBar=true" />
|
||||
<option value="-Dcom.apple.mrj.application.apple.menu.about.name=Forge" />
|
||||
<option value="-Dcom.apple.smallTabs=true" />
|
||||
<option value="-Xmx1024M" />
|
||||
<option value="-Xmx4096M" />
|
||||
<option value="-Dapp.dir=$APP_ROOT/Contents/Resources/" />
|
||||
</bundleapp>
|
||||
<copy todir="${project.build.directory}/${project.build.finalName}-osx/Forge.app/Contents/Resources/res">
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
#!/bin/sh
|
||||
cd "`dirname \"$0\"`"
|
||||
java -Xmx1024m -jar $project.build.finalName$
|
||||
cd $(dirname "${0}")
|
||||
java -Xmx4096m -Dfile.encoding=UTF-8 -jar $project.build.finalName$
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
#!/bin/sh
|
||||
cd "`dirname \"$0\"`"
|
||||
java -Xmx1024m -jar $project.build.finalName$
|
||||
cd $(dirname "${0}")
|
||||
java -Xmx4096m -Dfile.encoding=UTF-8 -jar $project.build.finalName$
|
||||
|
||||
@@ -486,7 +486,7 @@ public class PlayerControllerForTests extends PlayerController {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object vote(SpellAbility sa, String prompt, List<Object> options, ListMultimap<Object, Player> votes) {
|
||||
public Object vote(SpellAbility sa, String prompt, List<Object> options, ListMultimap<Object, Player> votes, Player forPlayer) {
|
||||
return chooseItem(options);
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<parent>
|
||||
<artifactId>forge</artifactId>
|
||||
<groupId>forge</groupId>
|
||||
<version>1.6.33-SNAPSHOT</version>
|
||||
<version>1.6.34-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>forge-gui-ios</artifactId>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>forge</artifactId>
|
||||
<groupId>forge</groupId>
|
||||
<version>1.6.33-SNAPSHOT</version>
|
||||
<version>1.6.34-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>forge-gui-mobile-dev</artifactId>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>forge</artifactId>
|
||||
<groupId>forge</groupId>
|
||||
<version>1.6.33-SNAPSHOT</version>
|
||||
<version>1.6.34-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>forge-gui-mobile</artifactId>
|
||||
|
||||
@@ -164,7 +164,7 @@ public class ImageCache {
|
||||
}
|
||||
return image;
|
||||
}
|
||||
public static void preloadCache(Iterable keys) {
|
||||
public static void preloadCache(Iterable<String> keys) {
|
||||
cache.getAll(keys);
|
||||
}
|
||||
public static TextureRegion croppedBorderImage(Texture image, boolean fullborder) {
|
||||
@@ -173,10 +173,9 @@ public class ImageCache {
|
||||
float rscale = 0.96f;
|
||||
int rw = Math.round(image.getWidth()*rscale);
|
||||
int rh = Math.round(image.getHeight()*rscale);
|
||||
int rx = Math.round((image.getWidth() - rw)/2);
|
||||
int ry = Math.round((image.getHeight() - rh)/2)-2;
|
||||
TextureRegion rimage = new TextureRegion(image, rx, ry, rw, rh);
|
||||
return rimage;
|
||||
int rx = Math.round((image.getWidth() - rw)/2f);
|
||||
int ry = Math.round((image.getHeight() - rh)/2f)-2;
|
||||
return new TextureRegion(image, rx, ry, rw, rh);
|
||||
}
|
||||
public static boolean isWhiteBordered(IPaperCard c) {
|
||||
if (c == null)
|
||||
|
||||
@@ -535,6 +535,9 @@ public class CardRenderer {
|
||||
}
|
||||
|
||||
public static void drawCardWithOverlays(Graphics g, CardView card, float x, float y, float w, float h, CardStackPosition pos) {
|
||||
drawCardWithOverlays(g, card, x, y, w, h, pos, false);
|
||||
}
|
||||
public static void drawCardWithOverlays(Graphics g, CardView card, float x, float y, float w, float h, CardStackPosition pos, boolean stackview) {
|
||||
boolean canShow = MatchController.instance.mayView(card);
|
||||
float oldAlpha = g.getfloatAlphaComposite();
|
||||
boolean unselectable = !MatchController.instance.isSelectable(card) && MatchController.instance.isSelecting();
|
||||
@@ -555,32 +558,10 @@ public class CardRenderer {
|
||||
Color color = FSkinColor.fromRGB(borderColor.r, borderColor.g, borderColor.b);
|
||||
color = FSkinColor.tintColor(Color.WHITE, color, CardRenderer.PT_BOX_TINT);
|
||||
|
||||
//draw name and mana cost overlays if card is small or default card image being used
|
||||
if (h <= NAME_COST_THRESHOLD && canShow) {
|
||||
if (showCardNameOverlay(card)) {
|
||||
g.drawOutlinedText(CardTranslation.getTranslatedName(details.getName()), FSkinFont.forHeight(h * 0.15f), Color.WHITE, Color.BLACK, x + padding -1f, y + padding, w - 2 * padding, h * 0.4f, true, Align.left, false);
|
||||
}
|
||||
if (showCardManaCostOverlay(card)) {
|
||||
float manaSymbolSize = w / 4.5f;
|
||||
if (card.isSplitCard() && card.hasAlternateState()) {
|
||||
if (!card.isFaceDown()) { // no need to draw mana symbols on face down split cards (e.g. manifested)
|
||||
float dy = manaSymbolSize / 2 + Utils.scale(5);
|
||||
|
||||
PaperCard pc = StaticData.instance().getCommonCards().getCard(card.getName());
|
||||
if (Card.getCardForUi(pc).hasKeyword(Keyword.AFTERMATH)){
|
||||
dy *= -1; // flip card costs for Aftermath cards
|
||||
}
|
||||
|
||||
drawManaCost(g, card.getAlternateState().getManaCost(), x - padding, y - dy, w + 2 * padding, h, manaSymbolSize);
|
||||
drawManaCost(g, card.getCurrentState().getManaCost(), x - padding, y + dy, w + 2 * padding, h, manaSymbolSize);
|
||||
}
|
||||
}
|
||||
else {
|
||||
drawManaCost(g, card.getCurrentState().getManaCost(), x - padding, y, w + 2 * padding, h, manaSymbolSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
//card name && manacost original position is here moved at the bottom...
|
||||
|
||||
if (stackview)
|
||||
return; //override
|
||||
if (pos == CardStackPosition.BehindVert) { return; } //remaining rendering not needed if card is behind another card in a vertical stack
|
||||
boolean onTop = (pos == CardStackPosition.Top);
|
||||
|
||||
@@ -656,6 +637,7 @@ public class CardRenderer {
|
||||
float abiSpace = cw / 5.7f;
|
||||
float abiCount = 0;
|
||||
|
||||
if (unselectable){ g.setAlphaComposite(0.6f); }
|
||||
if (onbattlefield && onTop && showAbilityIcons(card)) {
|
||||
if (card.isToken()){
|
||||
CardFaceSymbols.drawSymbol("token", g, abiX, abiY, abiScale, abiScale);
|
||||
@@ -664,85 +646,63 @@ public class CardRenderer {
|
||||
}
|
||||
if (card.getCurrentState().hasFlying()) {
|
||||
CardFaceSymbols.drawSymbol("flying", g, abiX, abiY, abiScale, abiScale);
|
||||
if (unselectable){
|
||||
g.setAlphaComposite(0.6f); g.fillRect(Color.BLACK, abiX, abiY, abiScale, abiScale ); g.setAlphaComposite(oldAlpha);}
|
||||
abiY += abiSpace;
|
||||
abiCount += 1;
|
||||
}
|
||||
if (card.getCurrentState().hasHaste()) {
|
||||
CardFaceSymbols.drawSymbol("haste", g, abiX, abiY, abiScale, abiScale);
|
||||
if (unselectable){
|
||||
g.setAlphaComposite(0.6f); g.fillRect(Color.BLACK, abiX, abiY, abiScale, abiScale ); g.setAlphaComposite(oldAlpha);}
|
||||
abiY += abiSpace;
|
||||
abiCount += 1;
|
||||
}
|
||||
if (card.getCurrentState().hasDoubleStrike()) {
|
||||
CardFaceSymbols.drawSymbol("doublestrike", g, abiX, abiY, abiScale, abiScale);
|
||||
if (unselectable){
|
||||
g.setAlphaComposite(0.6f); g.fillRect(Color.BLACK, abiX, abiY, abiScale, abiScale ); g.setAlphaComposite(oldAlpha);}
|
||||
abiY += abiSpace;
|
||||
abiCount += 1;
|
||||
}
|
||||
else if (card.getCurrentState().hasFirstStrike()) {
|
||||
CardFaceSymbols.drawSymbol("firststrike", g, abiX, abiY, abiScale, abiScale);
|
||||
if (unselectable){
|
||||
g.setAlphaComposite(0.6f); g.fillRect(Color.BLACK, abiX, abiY, abiScale, abiScale ); g.setAlphaComposite(oldAlpha);}
|
||||
abiY += abiSpace;
|
||||
abiCount += 1;
|
||||
}
|
||||
if (card.getCurrentState().hasDeathtouch()) {
|
||||
if (abiCount > 5 ) { abiY = cy + (abiSpace * (abiCount - 6)); abiX = cx + ((cw*2)/1.92f); }
|
||||
CardFaceSymbols.drawSymbol("deathtouch", g, abiX, abiY, abiScale, abiScale);
|
||||
if (unselectable){
|
||||
g.setAlphaComposite(0.6f); g.fillRect(Color.BLACK, abiX, abiY, abiScale, abiScale ); g.setAlphaComposite(oldAlpha);}
|
||||
abiY += abiSpace;
|
||||
abiCount += 1;
|
||||
}
|
||||
if (card.getCurrentState().hasIndestructible()) {
|
||||
if (abiCount > 5 ) { abiY = cy + (abiSpace * (abiCount - 6)); abiX = cx + ((cw*2)/1.92f); }
|
||||
CardFaceSymbols.drawSymbol("indestructible", g, abiX, abiY, abiScale, abiScale);
|
||||
if (unselectable){
|
||||
g.setAlphaComposite(0.6f); g.fillRect(Color.BLACK, abiX, abiY, abiScale, abiScale ); g.setAlphaComposite(oldAlpha);}
|
||||
abiY += abiSpace;
|
||||
abiCount += 1;
|
||||
}
|
||||
if (card.getCurrentState().hasMenace()) {
|
||||
if (abiCount > 5 ) { abiY = cy + (abiSpace * (abiCount - 6)); abiX = cx + ((cw*2)/1.92f); }
|
||||
CardFaceSymbols.drawSymbol("menace", g, abiX, abiY, abiScale, abiScale);
|
||||
if (unselectable){
|
||||
g.setAlphaComposite(0.6f); g.fillRect(Color.BLACK, abiX, abiY, abiScale, abiScale ); g.setAlphaComposite(oldAlpha);}
|
||||
abiY += abiSpace;
|
||||
abiCount += 1;
|
||||
}
|
||||
if (card.getCurrentState().hasFear()) {
|
||||
if (abiCount > 5 ) { abiY = cy + (abiSpace * (abiCount - 6)); abiX = cx + ((cw*2)/1.92f); }
|
||||
CardFaceSymbols.drawSymbol("fear", g, abiX, abiY, abiScale, abiScale);
|
||||
if (unselectable){
|
||||
g.setAlphaComposite(0.6f); g.fillRect(Color.BLACK, abiX, abiY, abiScale, abiScale ); g.setAlphaComposite(oldAlpha);}
|
||||
abiY += abiSpace;
|
||||
abiCount += 1;
|
||||
}
|
||||
if (card.getCurrentState().hasIntimidate()) {
|
||||
if (abiCount > 5 ) { abiY = cy + (abiSpace * (abiCount - 6)); abiX = cx + ((cw*2)/1.92f); }
|
||||
CardFaceSymbols.drawSymbol("intimidate", g, abiX, abiY, abiScale, abiScale);
|
||||
if (unselectable){
|
||||
g.setAlphaComposite(0.6f); g.fillRect(Color.BLACK, abiX, abiY, abiScale, abiScale ); g.setAlphaComposite(oldAlpha);}
|
||||
abiY += abiSpace;
|
||||
abiCount += 1;
|
||||
}
|
||||
if (card.getCurrentState().hasShadow()) {
|
||||
if (abiCount > 5 ) { abiY = cy + (abiSpace * (abiCount - 6)); abiX = cx + ((cw*2)/1.92f); }
|
||||
CardFaceSymbols.drawSymbol("shadow", g, abiX, abiY, abiScale, abiScale);
|
||||
if (unselectable){
|
||||
g.setAlphaComposite(0.6f); g.fillRect(Color.BLACK, abiX, abiY, abiScale, abiScale ); g.setAlphaComposite(oldAlpha);}
|
||||
abiY += abiSpace;
|
||||
abiCount += 1;
|
||||
}
|
||||
if (card.getCurrentState().hasHorsemanship()) {
|
||||
if (abiCount > 5 ) { abiY = cy + (abiSpace * (abiCount - 6)); abiX = cx + ((cw*2)/1.92f); }
|
||||
CardFaceSymbols.drawSymbol("horsemanship", g, abiX, abiY, abiScale, abiScale);
|
||||
if (unselectable){
|
||||
g.setAlphaComposite(0.6f); g.fillRect(Color.BLACK, abiX, abiY, abiScale, abiScale ); g.setAlphaComposite(oldAlpha);}
|
||||
abiY += abiSpace;
|
||||
abiCount += 1;
|
||||
}
|
||||
@@ -753,57 +713,41 @@ public class CardRenderer {
|
||||
List<String> listHK = Arrays.asList(splitK);
|
||||
if (listHK.contains("generic")) {
|
||||
CardFaceSymbols.drawSymbol("hexproof", g, abiX, abiY, abiScale, abiScale);
|
||||
if (unselectable){
|
||||
g.setAlphaComposite(0.6f); g.fillRect(Color.BLACK, abiX, abiY, abiScale, abiScale ); g.setAlphaComposite(oldAlpha);}
|
||||
abiY += abiSpace;
|
||||
abiCount += 1;
|
||||
}
|
||||
if (listHK.contains("R")) {
|
||||
CardFaceSymbols.drawSymbol("hexproofR", g, abiX, abiY, abiScale, abiScale);
|
||||
if (unselectable){
|
||||
g.setAlphaComposite(0.6f); g.fillRect(Color.BLACK, abiX, abiY, abiScale, abiScale ); g.setAlphaComposite(oldAlpha);}
|
||||
abiY += abiSpace;
|
||||
abiCount += 1;
|
||||
}
|
||||
if (listHK.contains("B")) {
|
||||
CardFaceSymbols.drawSymbol("hexproofB", g, abiX, abiY, abiScale, abiScale);
|
||||
if (unselectable){
|
||||
g.setAlphaComposite(0.6f); g.fillRect(Color.BLACK, abiX, abiY, abiScale, abiScale ); g.setAlphaComposite(oldAlpha);}
|
||||
abiY += abiSpace;
|
||||
abiCount += 1;
|
||||
}
|
||||
if (listHK.contains("U")) {
|
||||
CardFaceSymbols.drawSymbol("hexproofU", g, abiX, abiY, abiScale, abiScale);
|
||||
if (unselectable){
|
||||
g.setAlphaComposite(0.6f); g.fillRect(Color.BLACK, abiX, abiY, abiScale, abiScale ); g.setAlphaComposite(oldAlpha);}
|
||||
abiY += abiSpace;
|
||||
abiCount += 1;
|
||||
}
|
||||
if (listHK.contains("G")) {
|
||||
CardFaceSymbols.drawSymbol("hexproofG", g, abiX, abiY, abiScale, abiScale);
|
||||
if (unselectable){
|
||||
g.setAlphaComposite(0.6f); g.fillRect(Color.BLACK, abiX, abiY, abiScale, abiScale ); g.setAlphaComposite(oldAlpha);}
|
||||
abiY += abiSpace;
|
||||
abiCount += 1;
|
||||
}
|
||||
if (listHK.contains("W")) {
|
||||
CardFaceSymbols.drawSymbol("hexproofW", g, abiX, abiY, abiScale, abiScale);
|
||||
if (unselectable){
|
||||
g.setAlphaComposite(0.6f); g.fillRect(Color.BLACK, abiX, abiY, abiScale, abiScale ); g.setAlphaComposite(oldAlpha);}
|
||||
abiY += abiSpace;
|
||||
abiCount += 1;
|
||||
}
|
||||
if (listHK.contains("monocolored")) {
|
||||
CardFaceSymbols.drawSymbol("hexproofC", g, abiX, abiY, abiScale, abiScale);
|
||||
if (unselectable){
|
||||
g.setAlphaComposite(0.6f); g.fillRect(Color.BLACK, abiX, abiY, abiScale, abiScale ); g.setAlphaComposite(oldAlpha);}
|
||||
abiY += abiSpace;
|
||||
abiCount += 1;
|
||||
}
|
||||
} else {
|
||||
CardFaceSymbols.drawSymbol("hexproof", g, abiX, abiY, abiScale, abiScale);
|
||||
if (unselectable){
|
||||
g.setAlphaComposite(0.6f); g.fillRect(Color.BLACK, abiX, abiY, abiScale, abiScale ); g.setAlphaComposite(oldAlpha);}
|
||||
abiY += abiSpace;
|
||||
abiCount += 1;
|
||||
}
|
||||
@@ -811,48 +755,36 @@ public class CardRenderer {
|
||||
else if (card.getCurrentState().hasShroud()) {
|
||||
if (abiCount > 5 ) { abiY = cy + (abiSpace * (abiCount - 6)); abiX = cx + ((cw*2)/1.92f); }
|
||||
CardFaceSymbols.drawSymbol("shroud", g, abiX, abiY, abiScale, abiScale);
|
||||
if (unselectable){
|
||||
g.setAlphaComposite(0.6f); g.fillRect(Color.BLACK, abiX, abiY, abiScale, abiScale ); g.setAlphaComposite(oldAlpha);}
|
||||
abiY += abiSpace;
|
||||
abiCount += 1;
|
||||
}
|
||||
if (card.getCurrentState().hasVigilance()) {
|
||||
if (abiCount > 5 ) { abiY = cy + (abiSpace * (abiCount - 6)); abiX = cx + ((cw*2)/1.92f); }
|
||||
CardFaceSymbols.drawSymbol("vigilance", g, abiX, abiY, abiScale, abiScale);
|
||||
if (unselectable){
|
||||
g.setAlphaComposite(0.6f); g.fillRect(Color.BLACK, abiX, abiY, abiScale, abiScale ); g.setAlphaComposite(oldAlpha);}
|
||||
abiY += abiSpace;
|
||||
abiCount += 1;
|
||||
}
|
||||
if (card.getCurrentState().hasTrample()) {
|
||||
if (abiCount > 5 ) { abiY = cy + (abiSpace * (abiCount - 6)); abiX = cx + ((cw*2)/1.92f); }
|
||||
CardFaceSymbols.drawSymbol("trample", g, abiX, abiY, abiScale, abiScale);
|
||||
if (unselectable){
|
||||
g.setAlphaComposite(0.6f); g.fillRect(Color.BLACK, abiX, abiY, abiScale, abiScale ); g.setAlphaComposite(oldAlpha);}
|
||||
abiY += abiSpace;
|
||||
abiCount += 1;
|
||||
}
|
||||
if (card.getCurrentState().hasReach()) {
|
||||
if (abiCount > 5 ) { abiY = cy + (abiSpace * (abiCount - 6)); abiX = cx + ((cw*2)/1.92f); }
|
||||
CardFaceSymbols.drawSymbol("reach", g, abiX, abiY, abiScale, abiScale);
|
||||
if (unselectable){
|
||||
g.setAlphaComposite(0.6f); g.fillRect(Color.BLACK, abiX, abiY, abiScale, abiScale ); g.setAlphaComposite(oldAlpha);}
|
||||
abiY += abiSpace;
|
||||
abiCount += 1;
|
||||
}
|
||||
if (card.getCurrentState().hasLifelink()) {
|
||||
if (abiCount > 5 ) { abiY = cy + (abiSpace * (abiCount - 6)); abiX = cx + ((cw*2)/1.92f); }
|
||||
CardFaceSymbols.drawSymbol("lifelink", g, abiX, abiY, abiScale, abiScale);
|
||||
if (unselectable){
|
||||
g.setAlphaComposite(0.6f); g.fillRect(Color.BLACK, abiX, abiY, abiScale, abiScale ); g.setAlphaComposite(oldAlpha);}
|
||||
abiY += abiSpace;
|
||||
abiCount += 1;
|
||||
}
|
||||
if (card.getCurrentState().hasDefender()) {
|
||||
if (abiCount > 5 ) { abiY = cy + (abiSpace * (abiCount - 6)); abiX = cx + ((cw*2)/1.92f); }
|
||||
CardFaceSymbols.drawSymbol("defender", g, abiX, abiY, abiScale, abiScale);
|
||||
if (unselectable){
|
||||
g.setAlphaComposite(0.6f); g.fillRect(Color.BLACK, abiX, abiY, abiScale, abiScale ); g.setAlphaComposite(oldAlpha);}
|
||||
abiY += abiSpace;
|
||||
abiCount += 1;
|
||||
}
|
||||
@@ -861,132 +793,138 @@ public class CardRenderer {
|
||||
if (abiCount > 5 ) { abiY = cy + (abiSpace * (abiCount - 6)); abiX = cx + ((cw*2)/1.92f); }
|
||||
if (card.getCurrentState().getProtectionKey().contains("everything") || card.getCurrentState().getProtectionKey().contains("allcolors")) {
|
||||
CardFaceSymbols.drawSymbol("protectAll", g, abiX, abiY, abiScale, abiScale);
|
||||
if (unselectable){
|
||||
g.setAlphaComposite(0.6f); g.fillRect(Color.BLACK, abiX, abiY, abiScale, abiScale ); g.setAlphaComposite(oldAlpha);}
|
||||
abiY += abiSpace;
|
||||
abiCount += 1;
|
||||
}
|
||||
else if (card.getCurrentState().getProtectionKey().contains("coloredspells")) {
|
||||
CardFaceSymbols.drawSymbol("protectColoredSpells", g, abiX, abiY, abiScale, abiScale);
|
||||
if (unselectable){
|
||||
g.setAlphaComposite(0.6f); g.fillRect(Color.BLACK, abiX, abiY, abiScale, abiScale ); g.setAlphaComposite(oldAlpha);}
|
||||
abiY += abiSpace;
|
||||
abiCount += 1;
|
||||
}
|
||||
else if (card.getCurrentState().getProtectionKey().equals("R")) {
|
||||
CardFaceSymbols.drawSymbol("protectR", g, abiX, abiY, abiScale, abiScale);
|
||||
if (unselectable){
|
||||
g.setAlphaComposite(0.6f); g.fillRect(Color.BLACK, abiX, abiY, abiScale, abiScale ); g.setAlphaComposite(oldAlpha);}
|
||||
abiY += abiSpace;
|
||||
abiCount += 1;
|
||||
}
|
||||
else if (card.getCurrentState().getProtectionKey().equals("G")) {
|
||||
CardFaceSymbols.drawSymbol("protectG", g, abiX, abiY, abiScale, abiScale);
|
||||
if (unselectable){
|
||||
g.setAlphaComposite(0.6f); g.fillRect(Color.BLACK, abiX, abiY, abiScale, abiScale ); g.setAlphaComposite(oldAlpha);}
|
||||
abiY += abiSpace;
|
||||
abiCount += 1;
|
||||
}
|
||||
else if (card.getCurrentState().getProtectionKey().equals("B")) {
|
||||
CardFaceSymbols.drawSymbol("protectB", g, abiX, abiY, abiScale, abiScale);
|
||||
if (unselectable){
|
||||
g.setAlphaComposite(0.6f); g.fillRect(Color.BLACK, abiX, abiY, abiScale, abiScale ); g.setAlphaComposite(oldAlpha);}
|
||||
abiY += abiSpace;
|
||||
abiCount += 1;
|
||||
}
|
||||
else if (card.getCurrentState().getProtectionKey().equals("U")) {
|
||||
CardFaceSymbols.drawSymbol("protectU", g, abiX, abiY, abiScale, abiScale);
|
||||
if (unselectable){
|
||||
g.setAlphaComposite(0.6f); g.fillRect(Color.BLACK, abiX, abiY, abiScale, abiScale ); g.setAlphaComposite(oldAlpha);}
|
||||
abiY += abiSpace;
|
||||
abiCount += 1;
|
||||
}
|
||||
else if (card.getCurrentState().getProtectionKey().equals("W")) {
|
||||
CardFaceSymbols.drawSymbol("protectW", g, abiX, abiY, abiScale, abiScale);
|
||||
if (unselectable){
|
||||
g.setAlphaComposite(0.6f); g.fillRect(Color.BLACK, abiX, abiY, abiScale, abiScale ); g.setAlphaComposite(oldAlpha);}
|
||||
abiY += abiSpace;
|
||||
abiCount += 1;
|
||||
}
|
||||
else if (card.getCurrentState().getProtectionKey().equals("RG")||card.getCurrentState().getProtectionKey().equals("GR")) {
|
||||
CardFaceSymbols.drawSymbol("protectRG", g, abiX, abiY, abiScale, abiScale);
|
||||
if (unselectable){
|
||||
g.setAlphaComposite(0.6f); g.fillRect(Color.BLACK, abiX, abiY, abiScale, abiScale ); g.setAlphaComposite(oldAlpha);}
|
||||
abiY += abiSpace;
|
||||
abiCount += 1;
|
||||
}
|
||||
else if (card.getCurrentState().getProtectionKey().equals("RB")||card.getCurrentState().getProtectionKey().equals("BR")) {
|
||||
CardFaceSymbols.drawSymbol("protectRB", g, abiX, abiY, abiScale, abiScale);
|
||||
if (unselectable){
|
||||
g.setAlphaComposite(0.6f); g.fillRect(Color.BLACK, abiX, abiY, abiScale, abiScale ); g.setAlphaComposite(oldAlpha);}
|
||||
abiY += abiSpace;
|
||||
abiCount += 1;
|
||||
}
|
||||
else if (card.getCurrentState().getProtectionKey().equals("RU")||card.getCurrentState().getProtectionKey().equals("UR")) {
|
||||
CardFaceSymbols.drawSymbol("protectRU", g, abiX, abiY, abiScale, abiScale);
|
||||
if (unselectable){
|
||||
g.setAlphaComposite(0.6f); g.fillRect(Color.BLACK, abiX, abiY, abiScale, abiScale ); g.setAlphaComposite(oldAlpha);}
|
||||
abiY += abiSpace;
|
||||
abiCount += 1;
|
||||
}
|
||||
else if (card.getCurrentState().getProtectionKey().equals("RW")||card.getCurrentState().getProtectionKey().equals("WR")) {
|
||||
CardFaceSymbols.drawSymbol("protectRW", g, abiX, abiY, abiScale, abiScale);
|
||||
if (unselectable){
|
||||
g.setAlphaComposite(0.6f); g.fillRect(Color.BLACK, abiX, abiY, abiScale, abiScale ); g.setAlphaComposite(oldAlpha);}
|
||||
abiY += abiSpace;
|
||||
abiCount += 1;
|
||||
}
|
||||
else if (card.getCurrentState().getProtectionKey().equals("GB")||card.getCurrentState().getProtectionKey().equals("BG")) {
|
||||
CardFaceSymbols.drawSymbol("protectGB", g, abiX, abiY, abiScale, abiScale);
|
||||
if (unselectable){
|
||||
g.setAlphaComposite(0.6f); g.fillRect(Color.BLACK, abiX, abiY, abiScale, abiScale ); g.setAlphaComposite(oldAlpha);}
|
||||
abiY += abiSpace;
|
||||
abiCount += 1;
|
||||
}
|
||||
else if (card.getCurrentState().getProtectionKey().equals("GU")||card.getCurrentState().getProtectionKey().equals("UG")) {
|
||||
CardFaceSymbols.drawSymbol("protectGU", g, abiX, abiY, abiScale, abiScale);
|
||||
if (unselectable){
|
||||
g.setAlphaComposite(0.6f); g.fillRect(Color.BLACK, abiX, abiY, abiScale, abiScale ); g.setAlphaComposite(oldAlpha);}
|
||||
abiY += abiSpace;
|
||||
abiCount += 1;
|
||||
}
|
||||
else if (card.getCurrentState().getProtectionKey().equals("GW")||card.getCurrentState().getProtectionKey().equals("WG")) {
|
||||
CardFaceSymbols.drawSymbol("protectGW", g, abiX, abiY, abiScale, abiScale);
|
||||
if (unselectable){
|
||||
g.setAlphaComposite(0.6f); g.fillRect(Color.BLACK, abiX, abiY, abiScale, abiScale ); g.setAlphaComposite(oldAlpha);}
|
||||
abiY += abiSpace;
|
||||
abiCount += 1;
|
||||
}
|
||||
else if (card.getCurrentState().getProtectionKey().equals("BU")||card.getCurrentState().getProtectionKey().equals("UB")) {
|
||||
CardFaceSymbols.drawSymbol("protectBU", g, abiX, abiY, abiScale, abiScale);
|
||||
if (unselectable){
|
||||
g.setAlphaComposite(0.6f); g.fillRect(Color.BLACK, abiX, abiY, abiScale, abiScale ); g.setAlphaComposite(oldAlpha);}
|
||||
abiY += abiSpace;
|
||||
abiCount += 1;
|
||||
}
|
||||
else if (card.getCurrentState().getProtectionKey().equals("BW")||card.getCurrentState().getProtectionKey().equals("WB")) {
|
||||
CardFaceSymbols.drawSymbol("protectBW", g, abiX, abiY, abiScale, abiScale);
|
||||
if (unselectable){
|
||||
g.setAlphaComposite(0.6f); g.fillRect(Color.BLACK, abiX, abiY, abiScale, abiScale ); g.setAlphaComposite(oldAlpha);}
|
||||
abiY += abiSpace;
|
||||
abiCount += 1;
|
||||
}
|
||||
else if (card.getCurrentState().getProtectionKey().equals("UW")||card.getCurrentState().getProtectionKey().equals("WU")) {
|
||||
CardFaceSymbols.drawSymbol("protectUW", g, abiX, abiY, abiScale, abiScale);
|
||||
if (unselectable){
|
||||
g.setAlphaComposite(0.6f); g.fillRect(Color.BLACK, abiX, abiY, abiScale, abiScale ); g.setAlphaComposite(oldAlpha);}
|
||||
abiY += abiSpace;
|
||||
abiCount += 1;
|
||||
}
|
||||
else if (card.getCurrentState().getProtectionKey().contains("generic") || card.getCurrentState().getProtectionKey().length() > 2) {
|
||||
CardFaceSymbols.drawSymbol("protectGeneric", g, abiX, abiY, abiScale, abiScale);
|
||||
if (unselectable){
|
||||
g.setAlphaComposite(0.6f); g.fillRect(Color.BLACK, abiX, abiY, abiScale, abiScale ); g.setAlphaComposite(oldAlpha);}
|
||||
abiY += abiSpace;
|
||||
abiCount += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
//draw name and mana cost overlays if card is small or default card image being used
|
||||
if (h <= NAME_COST_THRESHOLD && canShow) {
|
||||
if (showCardNameOverlay(card)) {
|
||||
float multiplier;
|
||||
switch (Forge.extrawide) {
|
||||
case "default":
|
||||
multiplier = 0.145f; //good for tablets with 16:10 or similar
|
||||
break;
|
||||
case "wide":
|
||||
multiplier = 0.150f;
|
||||
break;
|
||||
case "extrawide":
|
||||
multiplier = 0.155f; //good for tall phones with 21:9 or similar
|
||||
break;
|
||||
default:
|
||||
multiplier = 0.150f;
|
||||
break;
|
||||
}
|
||||
g.drawOutlinedText(CardTranslation.getTranslatedName(details.getName()), FSkinFont.forHeight(h * multiplier), Color.WHITE, Color.BLACK, x + padding -1f, y + padding, w - 2 * padding, h * 0.4f, true, Align.left, false);
|
||||
}
|
||||
if (showCardManaCostOverlay(card)) {
|
||||
float manaSymbolSize = w / 4.5f;
|
||||
if (card.isSplitCard() && card.hasAlternateState()) {
|
||||
if (!card.isFaceDown()) { // no need to draw mana symbols on face down split cards (e.g. manifested)
|
||||
float dy = manaSymbolSize / 2 + Utils.scale(5);
|
||||
|
||||
PaperCard pc = StaticData.instance().getCommonCards().getCard(card.getName());
|
||||
if (Card.getCardForUi(pc).hasKeyword(Keyword.AFTERMATH)){
|
||||
dy *= -1; // flip card costs for Aftermath cards
|
||||
}
|
||||
|
||||
drawManaCost(g, card.getAlternateState().getManaCost(), x - padding, y - dy, w + 2 * padding, h, manaSymbolSize);
|
||||
drawManaCost(g, card.getCurrentState().getManaCost(), x - padding, y + dy, w + 2 * padding, h, manaSymbolSize);
|
||||
}
|
||||
}
|
||||
else {
|
||||
drawManaCost(g, card.getCurrentState().getManaCost(), x - padding, y, w + 2 * padding, h, manaSymbolSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
//reset alpha
|
||||
g.setAlphaComposite(oldAlpha);
|
||||
}
|
||||
|
||||
private static void drawCounterTabs(final CardView card, final Graphics g, final float x, final float y, final float w, final float h) {
|
||||
|
||||
@@ -219,7 +219,7 @@ public class CardZoom extends FOverlay {
|
||||
float w = getWidth();
|
||||
float h = getHeight();
|
||||
float messageHeight = FDialog.MSG_HEIGHT;
|
||||
float AspectRatioMultiplier = 2;
|
||||
float AspectRatioMultiplier;
|
||||
switch (Forge.extrawide) {
|
||||
case "default":
|
||||
AspectRatioMultiplier = 3; //good for tablets with 16:10 or similar
|
||||
|
||||
@@ -40,6 +40,7 @@ import forge.toolbox.FEvent;
|
||||
import forge.toolbox.FEvent.FEventHandler;
|
||||
import forge.toolbox.FLabel;
|
||||
import forge.util.Localizer;
|
||||
import forge.util.TextUtil;
|
||||
import forge.util.collect.FCollectionView;
|
||||
import forge.util.Utils;
|
||||
|
||||
@@ -372,12 +373,35 @@ public class VStack extends FDropDown {
|
||||
|
||||
x += PADDING;
|
||||
y += PADDING;
|
||||
CardRenderer.drawCardWithOverlays(g, stackInstance.getSourceCard(), x, y, CARD_WIDTH, CARD_HEIGHT, CardStackPosition.Top);
|
||||
CardRenderer.drawCardWithOverlays(g, stackInstance.getSourceCard(), x, y, CARD_WIDTH, CARD_HEIGHT, CardStackPosition.Top, true);
|
||||
|
||||
x += CARD_WIDTH + PADDING;
|
||||
w -= x + PADDING - BORDER_THICKNESS;
|
||||
h -= y + PADDING - BORDER_THICKNESS;
|
||||
textRenderer.drawText(g, text, FONT, foreColor, x, y, w, h, y, h, true, Align.left, true);
|
||||
|
||||
String name = stackInstance.getSourceCard().getName();
|
||||
int index = text.indexOf(name);
|
||||
String newtext = "";
|
||||
String cId = "(" + stackInstance.getSourceCard().getId() + ")";
|
||||
|
||||
if (index == -1) {
|
||||
newtext = TextUtil.fastReplace(TextUtil.fastReplace(text.trim(),"--","-"),"- -","-");
|
||||
textRenderer.drawText(g, name + " " + (name.length() > 1 ? cId : "") + "\n" + (newtext.length() > 1 ? newtext : ""),
|
||||
FONT, foreColor, x, y, w, h, y, h, true, Align.left, true);
|
||||
|
||||
} else {
|
||||
String trimFirst = TextUtil.fastReplace("\n" + text.substring(0, index) + text.substring(index + name.length()), "- -", "-");
|
||||
String trimSecond = TextUtil.fastReplace(trimFirst, name+" "+cId, name);
|
||||
newtext = TextUtil.fastReplace(trimSecond, " "+cId, name);
|
||||
|
||||
if(newtext.equals("\n"+name))
|
||||
textRenderer.drawText(g, name + " " + cId, FONT, foreColor, x, y, w, h, y, h, true, Align.left, true);
|
||||
else {
|
||||
newtext = TextUtil.fastReplace(TextUtil.fastReplace(newtext,name+" -","-"), "\n ", "\n");
|
||||
newtext = "\n"+ TextUtil.fastReplace(newtext.trim(),"--","-");
|
||||
textRenderer.drawText(g, name+" "+cId+newtext, FONT, foreColor, x, y, w, h, y, h, true, Align.left, true);
|
||||
}
|
||||
}
|
||||
|
||||
g.endClip();
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>forge</artifactId>
|
||||
<groupId>forge</groupId>
|
||||
<version>1.6.33-SNAPSHOT</version>
|
||||
<version>1.6.34-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>forge-gui</artifactId>
|
||||
|
||||
@@ -2,5 +2,5 @@ Name:Ballot Broker
|
||||
ManaCost:2 W
|
||||
Types:Creature Human Advisor
|
||||
PT:2/3
|
||||
S:Mode$ Continuous | Affected$ You | AddKeyword$ You may vote an additional time. | Description$ While voting, you may vote an additional time. (The votes can be for different choices or for the same choice.)
|
||||
S:Mode$ Continuous | Affected$ You | AdditionalOptionalVote$ 1 | Description$ While voting, you may vote an additional time. (The votes can be for different choices or for the same choice.)
|
||||
Oracle:While voting, you may vote an additional time. (The votes can be for different choices or for the same choice.)
|
||||
@@ -2,6 +2,6 @@ Name:Brago's Representative
|
||||
ManaCost:2 W
|
||||
Types:Creature Human Advisor
|
||||
PT:1/4
|
||||
S:Mode$ Continuous | Affected$ You | AddKeyword$ You get an additional vote. | Description$ While voting, you get an additional vote. (The votes can be for different choices or for the same choice.)
|
||||
S:Mode$ Continuous | Affected$ You | AdditionalVote$ 1 | Description$ While voting, you get an additional vote. (The votes can be for different choices or for the same choice.)
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/bragos_representative.jpg
|
||||
Oracle:While voting, you get an additional vote. (The votes can be for different choices or for the same choice.)
|
||||
|
||||
9
forge-gui/res/cardsfolder/e/expropriate.txt
Normal file
9
forge-gui/res/cardsfolder/e/expropriate.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
Name:Expropriate
|
||||
ManaCost:7 U U
|
||||
Types:Sorcery
|
||||
A:SP$ Vote | Cost$ 7 U U | Defined$ Player | VoteType$ Time,Money | VoteTime$ DBTime | VoteMoney$ DBMoney | EachVote$ True | SubAbility$ DBChange | SpellDescription$ Council’s dilemma — Starting with you, each player votes for time or money. For each time vote, take an extra turn after this one. For each money vote, choose a permanent owned by the voter and gain control of it. Exile Expropriate.
|
||||
SVar:DBTime:DB$ AddTurn | Defined$ You | NumTurns$ 1
|
||||
SVar:DBMoney:DB$ ChooseCard | Defined$ You | Choices$ Permanent.RememberedPlayerOwn | SubAbility$ DBControl
|
||||
SVar:DBControl:DB$ GainControl | Defined$ ChosenCard | NewController$ You
|
||||
SVar:DBChange:DB$ ChangeZone | Origin$ Stack | Destination$ Exile | StackDescription$ None
|
||||
Oracle:Council’s dilemma — Starting with you, each player votes for time or money. For each time vote, take an extra turn after this one. For each money vote, choose a permanent owned by the voter and gain control of it. Exile Expropriate.
|
||||
10
forge-gui/res/cardsfolder/g/glyph_of_reincarnation.txt
Normal file
10
forge-gui/res/cardsfolder/g/glyph_of_reincarnation.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
Name:Glyph of Reincarnation
|
||||
ManaCost:G
|
||||
Types:Instant
|
||||
A:SP$ Pump | Cost$ G | ValidTgts$ Wall | TgtPrompt$ Select target Wall | AILogic$ Pump | ActivationPhases$ Main2->End of Turn | SubAbility$ DBDestroyAll | StackDescription$ SpellDescription | SpellDescription$ Cast this spell only after combat.
|
||||
SVar:DBDestroyAll:DB$ DestroyAll | ValidCards$ Creature.blockedByValidThisTurn ParentTarget | NoRegen$ True | RememberDestroyed$ True | SubAbility$ DBChoose | StackDescription$ SpellDescription | SpellDescription$ Destroy all creatures that were blocked by target Wall this turn. They can’t be regenerated.
|
||||
SVar:DBChoose:DB$ ChooseCard | Defined$ You | Choices$ Creature.OwnedBy Player.Active | ChoiceTitle$ Choose creatures to put on the battlefield | ChoiceZone$ Graveyard | Amount$ X | References$ X | Mandatory$ True | AILogic$ WorstCard | SubAbility$ DBChangeZone | StackDescription$ SpellDescription | SpellDescription$ For each creature that died this way, put a creature card from the graveyard of the player who controlled that creature the last time it became blocked by that Wall onto the battlefield under its owner’s control.
|
||||
SVar:DBChangeZone:DB$ ChangeZone | Defined$ ChosenCard | Origin$ Graveyard | Destination$ Battlefield | SubAbility$ DBCleanup
|
||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||
SVar:X:Count$ValidGraveyard Creature.IsRemembered
|
||||
Oracle:Cast this spell only after combat.\nDestroy all creatures that were blocked by target Wall this turn. They can’t be regenerated. For each creature that died this way, put a creature card from the graveyard of the player who controlled that creature the last time it became blocked by that Wall onto the battlefield under its owner’s control.
|
||||
@@ -3,6 +3,6 @@ ManaCost:U
|
||||
Types:Instant
|
||||
A:SP$ Effect | Cost$ U | Name$ Illusion of Choice Effect | StaticAbilities$ STVoter | SubAbility$ DBDraw | SpellDescription$ You choose how each player votes this turn. Draw a card.
|
||||
SVar:DBDraw:DB$ Draw | NumCards$ 1
|
||||
SVar:STVoter:Mode$ Continuous | EffectZone$ Command | Affected$ You | AddKeyword$ You choose how each player votes this turn. | Description$ You choose how each player votes this turn.
|
||||
SVar:STVoter:Mode$ Continuous | EffectZone$ Command | Affected$ You | ControlVote$ True | Description$ You choose how each player votes this turn.
|
||||
AI:RemoveDeck:All
|
||||
Oracle:You choose how each player votes this turn. Draw a card.
|
||||
17
forge-gui/res/cardsfolder/k/krovikan_vampire.txt
Normal file
17
forge-gui/res/cardsfolder/k/krovikan_vampire.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
Name:Krovikan Vampire
|
||||
ManaCost:3 B B
|
||||
Types:Creature Vampire
|
||||
PT:3/3
|
||||
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Creature.DamagedBy | TriggerZones$ Battlefield | Execute$ TrigPump | Static$ True
|
||||
SVar:TrigPump:DB$ Pump | RememberObjects$ TriggeredCard
|
||||
T:Mode$ ChangesZone | Origin$ Graveyard | Destination$ Any | ValidCard$ Card.IsRemembered | TriggerZones$ Battlefield | Execute$ LoseTrack | Static$ True
|
||||
SVar:LoseTrack:DB$ Pump | ForgetObjects$ TriggeredCard
|
||||
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Any | ValidCard$ Card.Self | Execute$ DBCleanup | Static$ True
|
||||
T:Mode$ TurnBegin | Execute$ DBCleanup | Static$ True
|
||||
T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ Player | TriggerZones$ Battlefield | CheckSVar$ X | SVarCompare$ GE1 | IsPresent$ Card.Self | Execute$ TrigChange | TriggerDescription$ At the beginning of each end step, if a creature dealt damage by CARDNAME this turn died, put that card onto the battlefield under your control. Sacrifice it when you lose control of CARDNAME.
|
||||
SVar:TrigChange:DB$ ChangeZoneAll | ChangeType$ Creature.IsRemembered+ThisTurnEntered_Graveyard_from_Battlefield | Origin$ Graveyard | Destination$ Battlefield | GainControl$ True | RememberChanged$ True | ForgetOtherRemembered$ True | SubAbility$ TrigDelay
|
||||
SVar:TrigDelay:DB$ DelayedTrigger | Mode$ ChangesZone | Origin$ Battlefield | Destination$ Any | ValidCard$ Card.Self | RememberObjects$ Remembered | Execute$ TrigSac | Secondary$ True | SubAbility$ DBCleanup | SpellDescription$ Sacrifice it when you lose control of CARDNAME.
|
||||
SVar:TrigSac:DB$ SacrificeAll | Defined$ DelayTriggerRemembered | SubAbility$ DBCleanup
|
||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||
SVar:X:Remembered$Amount
|
||||
Oracle:At the beginning of each end step, if a creature dealt damage by Krovikan Vampire this turn died, put that card onto the battlefield under your control. Sacrifice it when you lose control of Krovikan Vampire.
|
||||
@@ -6,6 +6,7 @@ S:Mode$ Continuous | Affected$ Card.Self+counters_GE3_P1P1 | AddKeyword$ Trample
|
||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Creature.YouCtrl+powerGTX+Other | References$ X | TriggerZones$ Battlefield | Execute$ TrigPutCounter | TriggerDescription$ Whenever another creature you control enters the battlefield or dies, if that creature's power is greater than CARDNAME's, put a +1/+1 counter on CARDNAME.
|
||||
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Creature.YouCtrl+powerGTX+Other | References$ X | TriggerZones$ Battlefield | Secondary$ True | Execute$ TrigPutCounter | TriggerDescription$ Whenever another creature you control enters the battlefield or dies, if that creature's power is greater than CARDNAME's, put a +1/+1 counter on CARDNAME.
|
||||
SVar:X:Count$CardPower
|
||||
SVar:TrigPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1
|
||||
SVar:Y:TriggeredCard$CardPower
|
||||
SVar:TrigPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1 | ConditionCheckSVar$ X | ConditionSVarCompare$ LTY | References$ X,Y
|
||||
DeckHas:Ability$Counters
|
||||
Oracle:Whenever another creature you control enters the battlefield or dies, if that creature's power is greater than Pelt Collector's, put a +1/+1 counter on Pelt Collector.\nAs long as Pelt Collector has three or more +1/+1 counters on it, it has trample.
|
||||
13
forge-gui/res/cardsfolder/t/timmerian_fiends.txt
Normal file
13
forge-gui/res/cardsfolder/t/timmerian_fiends.txt
Normal file
@@ -0,0 +1,13 @@
|
||||
Name:Timmerian Fiends
|
||||
ManaCost:1 B B
|
||||
Types:Creature Horror
|
||||
PT:1/1
|
||||
K:Remove CARDNAME from your deck before playing if you're not playing for ante.
|
||||
A:AB$ Pump | Cost$ B B B Sac<1/CARDNAME> | ValidTgts$ Artifact | SubAbility$ DBAnte | ImprintCards$ Targeted | RememberObjects$ TargetedController | StackDescription$ SpellDescription | SpellDescription$ The owner of target artifact may ante the top card of their library. If that player doesn’t, exchange ownership of that artifact and CARDNAME. Put the artifact card into your graveyard and CARDNAME from anywhere into that player’s graveyard. This change in ownership is permanent.
|
||||
SVar:DBAnte:DB$ Mill | Defined$ Player.IsRemembered | Destination$ Ante | NumCards$ 1 | RememberMilled$ True | Optional$ True | SubAbility$ ExchangeOwn1 | AILogic$ TimmerianFiends | StackDescription$ None
|
||||
SVar:ExchangeOwn1:DB$ GainOwnership | Defined$ Imprinted | DefinedPlayer$ You | SubAbility$ ToGrave1 | ConditionDefined$ Remembered | ConditionPresent$ Card | ConditionCompare$ EQ0
|
||||
SVar:ToGrave1:DB$ ChangeZone | Defined$ Imprinted | Origin$ Battlefield | Destination$ Graveyard | SubAbility$ ExchangeOwn2 | ConditionDefined$ Remembered | ConditionPresent$ Card | ConditionCompare$ EQ0 | StackDescription$ None
|
||||
SVar:ExchangeOwn2:DB$ GainOwnership | Defined$ Self | DefinedPlayer$ Remembered | SubAbility$ ToGrave | ConditionDefined$ Remembered | ConditionPresent$ Card | ConditionCompare$ EQ0
|
||||
SVar:ToGrave:DB$ ChangeZone | Defined$ Self | Origin$ All | Destination$ Graveyard | SubAbility$ DBCleanup | ConditionDefined$ Remembered | ConditionPresent$ Card | ConditionCompare$ EQ0
|
||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True | ClearImprinted$ True
|
||||
Oracle:Remove Timmerian Fiends from your deck before playing if you’re not playing for ante.\n{B}{B}{B}, Sacrifice Timmerian Fiends: The owner of target artifact may ante the top card of their library. If that player doesn’t, exchange ownership of that artifact and Timmerian Fiends. Put the artifact card into your graveyard and Timmerian Fiends from anywhere into that player’s graveyard. This change in ownership is permanent.
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -2021,6 +2021,9 @@ lblDamagepreventionHas=Damage prevention: {0}
|
||||
lblIsExtraTurn=Extra Turn: Yes
|
||||
lblExtraTurnCountHas=Extra Turn Count: {0}
|
||||
lblAntedHas=Ante''d: {0}
|
||||
lblAdditionalVotes=You get {0} additional votes.
|
||||
lblOptionalAdditionalVotes=You may vote {0} additional times.
|
||||
lblControlsVote=You choose how each player votes.
|
||||
#VStack.java
|
||||
lblAlwaysYes=Always Yes
|
||||
lblAlwaysNo=Always No
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
#!/bin/sh
|
||||
cd "`dirname \"$0\"`"
|
||||
java -Xmx1024m -jar $project.build.finalName$
|
||||
@@ -1,3 +0,0 @@
|
||||
#!/bin/sh
|
||||
cd "`dirname \"$0\"`"
|
||||
java -Xmx1024m -jar $project.build.finalName$
|
||||
@@ -156,6 +156,9 @@ public class DeckgenUtil {
|
||||
//}
|
||||
}
|
||||
|
||||
//remove any cards not valid in format
|
||||
selectedCards = Lists.newArrayList(Iterables.filter(selectedCards, format.getFilterPrinted()));
|
||||
|
||||
List<PaperCard> toRemove = new ArrayList<>();
|
||||
|
||||
//randomly remove cards
|
||||
@@ -252,6 +255,9 @@ public class DeckgenUtil {
|
||||
//}
|
||||
}
|
||||
|
||||
//remove any cards not valid in format
|
||||
selectedCards = Lists.newArrayList(Iterables.filter(selectedCards, format.getFilterPrinted()));
|
||||
|
||||
List<PaperCard> toRemove = new ArrayList<>();
|
||||
|
||||
//randomly remove cards
|
||||
|
||||
@@ -1181,7 +1181,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
||||
|
||||
@Override
|
||||
public Object vote(final SpellAbility sa, final String prompt, final List<Object> options,
|
||||
final ListMultimap<Object, Player> votes) {
|
||||
final ListMultimap<Object, Player> votes, Player forPlayer) {
|
||||
return getGui().one(prompt, options);
|
||||
}
|
||||
|
||||
|
||||
2
pom.xml
2
pom.xml
@@ -5,7 +5,7 @@
|
||||
<artifactId>forge</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<name>Forge Parent</name>
|
||||
<version>1.6.33-SNAPSHOT</version>
|
||||
<version>1.6.34-SNAPSHOT</version>
|
||||
|
||||
<description>
|
||||
Forge lets you play the card game Magic: The Gathering against a computer opponent using all of the rules.
|
||||
|
||||
Reference in New Issue
Block a user