mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 03:38:01 +00:00
Merge branch 'damageTrample' into 'master'
DealDamage: add ExcessDamage See merge request core-developers/forge!2784
This commit is contained in:
@@ -989,7 +989,7 @@ public class GameAction {
|
|||||||
for (final Card c : game.getCardsIn(ZoneType.Battlefield)) {
|
for (final Card c : game.getCardsIn(ZoneType.Battlefield)) {
|
||||||
if (c.isCreature()) {
|
if (c.isCreature()) {
|
||||||
// Rule 704.5f - Put into grave (no regeneration) for toughness <= 0
|
// Rule 704.5f - Put into grave (no regeneration) for toughness <= 0
|
||||||
if (c.getLethal() <= 0) {
|
if (c.getNetToughness() <= 0) {
|
||||||
if (noRegCreats == null) {
|
if (noRegCreats == null) {
|
||||||
noRegCreats = new CardCollection();
|
noRegCreats = new CardCollection();
|
||||||
}
|
}
|
||||||
@@ -1009,7 +1009,7 @@ public class GameAction {
|
|||||||
}
|
}
|
||||||
// Rule 704.5g - Destroy due to lethal damage
|
// Rule 704.5g - Destroy due to lethal damage
|
||||||
// Rule 704.5h - Destroy due to deathtouch
|
// Rule 704.5h - Destroy due to deathtouch
|
||||||
else if (c.getLethal() <= c.getDamage() || c.hasBeenDealtDeathtouchDamage()) {
|
else if (c.getDamage() > 0 && (c.getLethal() <= c.getDamage() || c.hasBeenDealtDeathtouchDamage())) {
|
||||||
if (desCreats == null) {
|
if (desCreats == null) {
|
||||||
desCreats = new CardCollection();
|
desCreats = new CardCollection();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
package forge.game.ability.effects;
|
package forge.game.ability.effects;
|
||||||
|
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
|
import forge.game.GameEntity;
|
||||||
import forge.game.GameEntityCounterTable;
|
import forge.game.GameEntityCounterTable;
|
||||||
import forge.game.GameObject;
|
import forge.game.GameObject;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
@@ -11,6 +13,7 @@ import forge.game.card.Card;
|
|||||||
import forge.game.card.CardCollection;
|
import forge.game.card.CardCollection;
|
||||||
import forge.game.card.CardDamageMap;
|
import forge.game.card.CardDamageMap;
|
||||||
import forge.game.card.CardUtil;
|
import forge.game.card.CardUtil;
|
||||||
|
import forge.game.keyword.Keyword;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.util.Lang;
|
import forge.util.Lang;
|
||||||
@@ -123,6 +126,7 @@ public class DamageDealEffect extends DamageBaseEffect {
|
|||||||
@Override
|
@Override
|
||||||
public void resolve(SpellAbility sa) {
|
public void resolve(SpellAbility sa) {
|
||||||
final Card hostCard = sa.getHostCard();
|
final Card hostCard = sa.getHostCard();
|
||||||
|
final Player activationPlayer = sa.getActivatingPlayer();
|
||||||
final Game game = hostCard.getGame();
|
final Game game = hostCard.getGame();
|
||||||
|
|
||||||
final String damage = sa.getParam("NumDmg");
|
final String damage = sa.getParam("NumDmg");
|
||||||
@@ -234,6 +238,9 @@ public class DamageDealEffect extends DamageBaseEffect {
|
|||||||
|
|
||||||
for (final Object o : tgts) {
|
for (final Object o : tgts) {
|
||||||
dmg = (sa.usesTargeting() && sa.hasParam("DividedAsYouChoose")) ? sa.getTargetRestrictions().getDividedValue(o) : dmg;
|
dmg = (sa.usesTargeting() && sa.hasParam("DividedAsYouChoose")) ? sa.getTargetRestrictions().getDividedValue(o) : dmg;
|
||||||
|
if (dmg <= 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (o instanceof Card) {
|
if (o instanceof Card) {
|
||||||
final Card c = (Card) o;
|
final Card c = (Card) o;
|
||||||
final Card gc = game.getCardState(c, null);
|
final Card gc = game.getCardState(c, null);
|
||||||
@@ -247,7 +254,27 @@ public class DamageDealEffect extends DamageBaseEffect {
|
|||||||
c.setHasBeenDealtDeathtouchDamage(false);
|
c.setHasBeenDealtDeathtouchDamage(false);
|
||||||
c.clearAssignedDamage();
|
c.clearAssignedDamage();
|
||||||
} else {
|
} else {
|
||||||
c.addDamage(dmg, sourceLKI, false, noPrevention, damageMap, preventMap, counterTable, sa);
|
if (sa.hasParam("ExcessDamage") && (!sa.hasParam("ExcessDamageCondition") ||
|
||||||
|
sourceLKI.isValid(sa.getParam("ExcessDamageCondition").split(","), activationPlayer, hostCard, sa))) {
|
||||||
|
// excess damage explicit says toughness, not lethal damage in the rules
|
||||||
|
int lethal = c.getNetToughness() - c.getDamage();
|
||||||
|
if (sourceLKI.hasKeyword(Keyword.DEATHTOUCH)) {
|
||||||
|
lethal = Math.min(lethal, 1);
|
||||||
|
}
|
||||||
|
int dmgToTarget = Math.min(lethal, dmg);
|
||||||
|
|
||||||
|
c.addDamage(dmgToTarget, sourceLKI, false, noPrevention, damageMap, preventMap, counterTable, sa);
|
||||||
|
|
||||||
|
List<GameEntity> list = Lists.newArrayList();
|
||||||
|
list.addAll(AbilityUtils.getDefinedCards(hostCard, sa.getParam("ExcessDamage"), sa));
|
||||||
|
list.addAll(AbilityUtils.getDefinedPlayers(hostCard, sa.getParam("ExcessDamage"), sa));
|
||||||
|
|
||||||
|
if (!list.isEmpty()) {
|
||||||
|
list.get(0).addDamage(dmg - dmgToTarget, sourceLKI, false, noPrevention, damageMap, preventMap, counterTable, sa);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
c.addDamage(dmg, sourceLKI, false, noPrevention, damageMap, preventMap, counterTable, sa);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (o instanceof Player) {
|
} else if (o instanceof Player) {
|
||||||
|
|||||||
@@ -4793,7 +4793,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
|
|
||||||
// this is the amount of damage a creature needs to receive before it dies
|
// this is the amount of damage a creature needs to receive before it dies
|
||||||
public final int getLethal() {
|
public final int getLethal() {
|
||||||
if (getAmountOfKeyword("Lethal damage dealt to CARDNAME is determined by its power rather than its toughness.") % 2 !=0) {
|
if (hasKeyword("Lethal damage dealt to CARDNAME is determined by its power rather than its toughness.")) {
|
||||||
return getNetPower(); }
|
return getNetPower(); }
|
||||||
else {
|
else {
|
||||||
return getNetToughness(); }
|
return getNetToughness(); }
|
||||||
@@ -4801,11 +4801,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
|
|
||||||
// this is the minimal damage a trampling creature has to assign to a blocker
|
// this is the minimal damage a trampling creature has to assign to a blocker
|
||||||
public final int getLethalDamage() {
|
public final int getLethalDamage() {
|
||||||
if (getAmountOfKeyword("Lethal damage dealt to CARDNAME is determined by its power rather than its toughness.") % 2 !=0) {
|
return getLethal() - getDamage() - getTotalAssignedDamage();
|
||||||
return getNetPower() - getDamage() - getTotalAssignedDamage();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return getNetToughness() - getDamage() - getTotalAssignedDamage();}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final int getDamage() {
|
public final int getDamage() {
|
||||||
|
|||||||
@@ -254,6 +254,7 @@ public class CardView extends GameEntityView {
|
|||||||
}
|
}
|
||||||
void updateDamage(Card c) {
|
void updateDamage(Card c) {
|
||||||
set(TrackableProperty.Damage, c.getDamage());
|
set(TrackableProperty.Damage, c.getDamage());
|
||||||
|
set(TrackableProperty.LethalDamage, c.getLethalDamage());
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getAssignedDamage() {
|
public int getAssignedDamage() {
|
||||||
@@ -261,10 +262,11 @@ public class CardView extends GameEntityView {
|
|||||||
}
|
}
|
||||||
void updateAssignedDamage(Card c) {
|
void updateAssignedDamage(Card c) {
|
||||||
set(TrackableProperty.AssignedDamage, c.getTotalAssignedDamage());
|
set(TrackableProperty.AssignedDamage, c.getTotalAssignedDamage());
|
||||||
|
set(TrackableProperty.LethalDamage, c.getLethalDamage());
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getLethalDamage() {
|
public int getLethalDamage() {
|
||||||
return getCurrentState().getToughness() - getDamage() - getAssignedDamage();
|
return get(TrackableProperty.LethalDamage);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getShieldCount() {
|
public int getShieldCount() {
|
||||||
@@ -701,6 +703,7 @@ public class CardView extends GameEntityView {
|
|||||||
}
|
}
|
||||||
void updateState(Card c) {
|
void updateState(Card c) {
|
||||||
updateName(c);
|
updateName(c);
|
||||||
|
updateDamage(c);
|
||||||
|
|
||||||
boolean isSplitCard = c.isSplitCard();
|
boolean isSplitCard = c.isSplitCard();
|
||||||
set(TrackableProperty.Cloned, c.isCloned());
|
set(TrackableProperty.Cloned, c.isCloned());
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ public enum TrackableProperty {
|
|||||||
CommanderAltType(TrackableTypes.StringType),
|
CommanderAltType(TrackableTypes.StringType),
|
||||||
Damage(TrackableTypes.IntegerType),
|
Damage(TrackableTypes.IntegerType),
|
||||||
AssignedDamage(TrackableTypes.IntegerType),
|
AssignedDamage(TrackableTypes.IntegerType),
|
||||||
|
LethalDamage(TrackableTypes.IntegerType),
|
||||||
ShieldCount(TrackableTypes.IntegerType),
|
ShieldCount(TrackableTypes.IntegerType),
|
||||||
ChosenType(TrackableTypes.StringType),
|
ChosenType(TrackableTypes.StringType),
|
||||||
ChosenColors(TrackableTypes.StringListType),
|
ChosenColors(TrackableTypes.StringListType),
|
||||||
|
|||||||
@@ -932,7 +932,7 @@ public final class CMatchUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<CardView, Integer> assignDamage(final CardView attacker,
|
public Map<CardView, Integer> assignCombatDamage(final CardView attacker,
|
||||||
final List<CardView> blockers, final int damage,
|
final List<CardView> blockers, final int damage,
|
||||||
final GameEntityView defender, final boolean overrideOrder) {
|
final GameEntityView defender, final boolean overrideOrder) {
|
||||||
if (damage <= 0) {
|
if (damage <= 0) {
|
||||||
@@ -949,7 +949,7 @@ public final class CMatchUI
|
|||||||
FThreads.invokeInEdtAndWait(new Runnable() {
|
FThreads.invokeInEdtAndWait(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
final VAssignDamage v = new VAssignDamage(CMatchUI.this, attacker, blockers, damage, defender, overrideOrder);
|
final VAssignCombatDamage v = new VAssignCombatDamage(CMatchUI.this, attacker, blockers, damage, defender, overrideOrder);
|
||||||
result.set(v.getDamageMap());
|
result.set(v.getDamageMap());
|
||||||
}});
|
}});
|
||||||
return result.get();
|
return result.get();
|
||||||
|
|||||||
@@ -6,12 +6,12 @@
|
|||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
@@ -54,14 +54,14 @@ import forge.util.Localizer;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Assembles Swing components of assign damage dialog.
|
* Assembles Swing components of assign damage dialog.
|
||||||
*
|
*
|
||||||
* This needs a JDialog to maintain a modal state.
|
* This needs a JDialog to maintain a modal state.
|
||||||
* Without the modal state, the PhaseHandler automatically
|
* Without the modal state, the PhaseHandler automatically
|
||||||
* moves forward to phase Main2 without assigning damage.
|
* moves forward to phase Main2 without assigning damage.
|
||||||
*
|
*
|
||||||
* <br><br><i>(V at beginning of class name denotes a view class.)</i>
|
* <br><br><i>(V at beginning of class name denotes a view class.)</i>
|
||||||
*/
|
*/
|
||||||
public class VAssignDamage {
|
public class VAssignCombatDamage {
|
||||||
final Localizer localizer = Localizer.getInstance();
|
final Localizer localizer = Localizer.getInstance();
|
||||||
private final CMatchUI matchUI;
|
private final CMatchUI matchUI;
|
||||||
|
|
||||||
@@ -119,7 +119,7 @@ public class VAssignDamage {
|
|||||||
CardView source = ((CardPanel) evt.getSource()).getCard();
|
CardView source = ((CardPanel) evt.getSource()).getCard();
|
||||||
if (!damage.containsKey(source)) source = null; // to get player instead of fake card
|
if (!damage.containsKey(source)) source = null; // to get player instead of fake card
|
||||||
|
|
||||||
final FSkin.Colors brdrColor = VAssignDamage.this.canAssignTo(source) ? FSkin.Colors.CLR_ACTIVE : FSkin.Colors.CLR_INACTIVE;
|
final FSkin.Colors brdrColor = VAssignCombatDamage.this.canAssignTo(source) ? FSkin.Colors.CLR_ACTIVE : FSkin.Colors.CLR_INACTIVE;
|
||||||
((CardPanel) evt.getSource()).setBorder(new FSkin.LineSkinBorder(FSkin.getColor(brdrColor), 2));
|
((CardPanel) evt.getSource()).setBorder(new FSkin.LineSkinBorder(FSkin.getColor(brdrColor), 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,13 +135,13 @@ public class VAssignDamage {
|
|||||||
boolean meta = evt.isControlDown();
|
boolean meta = evt.isControlDown();
|
||||||
boolean isLMB = SwingUtilities.isLeftMouseButton(evt);
|
boolean isLMB = SwingUtilities.isLeftMouseButton(evt);
|
||||||
boolean isRMB = SwingUtilities.isRightMouseButton(evt);
|
boolean isRMB = SwingUtilities.isRightMouseButton(evt);
|
||||||
|
|
||||||
if ( isLMB || isRMB)
|
if ( isLMB || isRMB)
|
||||||
assignDamageTo(source, meta, isLMB);
|
assignDamageTo(source, meta, isLMB);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public VAssignDamage(final CMatchUI matchUI, final CardView attacker, final List<CardView> blockers, final int damage0, final GameEntityView defender0, boolean overrideOrder) {
|
public VAssignCombatDamage(final CMatchUI matchUI, final CardView attacker, final List<CardView> blockers, final int damage0, final GameEntityView defender0, boolean overrideOrder) {
|
||||||
this.matchUI = matchUI;
|
this.matchUI = matchUI;
|
||||||
String s = localizer.getMessage("lbLAssignDamageDealtBy");
|
String s = localizer.getMessage("lbLAssignDamageDealtBy");
|
||||||
dlg.setTitle(s.replace("%s",attacker.toString()));
|
dlg.setTitle(s.replace("%s",attacker.toString()));
|
||||||
@@ -194,12 +194,12 @@ public class VAssignDamage {
|
|||||||
CardView fakeCard = null;
|
CardView fakeCard = null;
|
||||||
if (defender instanceof CardView) {
|
if (defender instanceof CardView) {
|
||||||
fakeCard = (CardView)defender;
|
fakeCard = (CardView)defender;
|
||||||
} else if (defender instanceof PlayerView) {
|
} else if (defender instanceof PlayerView) {
|
||||||
final PlayerView p = (PlayerView)defender;
|
final PlayerView p = (PlayerView)defender;
|
||||||
fakeCard = new CardView(-1, null, defender.toString(), p, matchUI.getAvatarImage(p.getLobbyPlayerName()));
|
fakeCard = new CardView(-1, null, defender.toString(), p, matchUI.getAvatarImage(p.getLobbyPlayerName()));
|
||||||
}
|
}
|
||||||
addPanelForDefender(pnlDefenders, fakeCard);
|
addPanelForDefender(pnlDefenders, fakeCard);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add "opponent placeholder" card if trample allowed
|
// Add "opponent placeholder" card if trample allowed
|
||||||
// If trample allowed, make card placeholder
|
// If trample allowed, make card placeholder
|
||||||
@@ -231,7 +231,7 @@ public class VAssignDamage {
|
|||||||
|
|
||||||
pnlMain.add(pnlButtons, "ax center, w 350px!, gap 10px 10px 10px 10px, span 2");
|
pnlMain.add(pnlButtons, "ax center, w 350px!, gap 10px 10px 10px 10px, span 2");
|
||||||
overlay.add(pnlMain);
|
overlay.add(pnlMain);
|
||||||
|
|
||||||
pnlMain.getRootPane().setDefaultButton(btnOK);
|
pnlMain.getRootPane().setDefaultButton(btnOK);
|
||||||
SwingUtilities.invokeLater(new Runnable() {
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
@@ -271,13 +271,13 @@ public class VAssignDamage {
|
|||||||
* @param isLMB
|
* @param isLMB
|
||||||
*/
|
*/
|
||||||
private void assignDamageTo(CardView source, final boolean meta, final boolean isAdding) {
|
private void assignDamageTo(CardView source, final boolean meta, final boolean isAdding) {
|
||||||
if ( !damage.containsKey(source) )
|
if ( !damage.containsKey(source) )
|
||||||
source = null;
|
source = null;
|
||||||
|
|
||||||
// If trying to assign to the defender, follow the normal assignment rules
|
// If trying to assign to the defender, follow the normal assignment rules
|
||||||
// No need to check for "active" creature assignee when overiding combatant order
|
// No need to check for "active" creature assignee when overiding combatant order
|
||||||
if ((source == null || source == defender || !overrideCombatantOrder) && isAdding &&
|
if ((source == null || source == defender || !overrideCombatantOrder) && isAdding &&
|
||||||
!VAssignDamage.this.canAssignTo(source)) {
|
!VAssignCombatDamage.this.canAssignTo(source)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -285,9 +285,9 @@ public class VAssignDamage {
|
|||||||
int lethalDamage = getDamageToKill(source);
|
int lethalDamage = getDamageToKill(source);
|
||||||
int damageItHad = damage.get(source).damage;
|
int damageItHad = damage.get(source).damage;
|
||||||
int leftToKill = Math.max(0, lethalDamage - damageItHad);
|
int leftToKill = Math.max(0, lethalDamage - damageItHad);
|
||||||
|
|
||||||
int damageToAdd = isAdding ? 1 : -1;
|
int damageToAdd = isAdding ? 1 : -1;
|
||||||
|
|
||||||
int leftToAssign = getRemainingDamage();
|
int leftToAssign = getRemainingDamage();
|
||||||
// Left click adds damage, right click substracts damage.
|
// Left click adds damage, right click substracts damage.
|
||||||
// Hold Ctrl to assign lethal damage, Ctrl-click again on a creature with lethal damage to assign all available damage to it
|
// Hold Ctrl to assign lethal damage, Ctrl-click again on a creature with lethal damage to assign all available damage to it
|
||||||
@@ -298,18 +298,18 @@ public class VAssignDamage {
|
|||||||
damageToAdd = damageItHad > lethalDamage ? lethalDamage - damageItHad : -damageItHad;
|
damageToAdd = damageItHad > lethalDamage ? lethalDamage - damageItHad : -damageItHad;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( damageToAdd > leftToAssign )
|
if ( damageToAdd > leftToAssign )
|
||||||
damageToAdd = leftToAssign;
|
damageToAdd = leftToAssign;
|
||||||
|
|
||||||
// cannot assign first blocker less than lethal damage except when overriding order
|
// cannot assign first blocker less than lethal damage except when overriding order
|
||||||
boolean isFirstBlocker = defenders.get(0).card == source;
|
boolean isFirstBlocker = defenders.get(0).card == source;
|
||||||
if (!overrideCombatantOrder && isFirstBlocker && damageToAdd + damageItHad < lethalDamage )
|
if (!overrideCombatantOrder && isFirstBlocker && damageToAdd + damageItHad < lethalDamage )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ( 0 == damageToAdd || damageToAdd + damageItHad < 0)
|
if ( 0 == damageToAdd || damageToAdd + damageItHad < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
addDamage(source, damageToAdd);
|
addDamage(source, damageToAdd);
|
||||||
checkDamageQueue();
|
checkDamageQueue();
|
||||||
updateLabels();
|
updateLabels();
|
||||||
@@ -350,7 +350,7 @@ public class VAssignDamage {
|
|||||||
}
|
}
|
||||||
if ( dmgLeft < 0 )
|
if ( dmgLeft < 0 )
|
||||||
throw new RuntimeException("initialAssignDamage managed to assign more damage than it could");
|
throw new RuntimeException("initialAssignDamage managed to assign more damage than it could");
|
||||||
if (toAllBlockers && dmgLeft > 0) {
|
if (toAllBlockers && dmgLeft > 0) {
|
||||||
// flush the remaining damage into last defender if assigning all damage
|
// flush the remaining damage into last defender if assigning all damage
|
||||||
addDamage(dtLast.card, dmgLeft );
|
addDamage(dtLast.card, dmgLeft );
|
||||||
}
|
}
|
||||||
@@ -362,7 +362,7 @@ public class VAssignDamage {
|
|||||||
for(DamageTarget dt : defenders)
|
for(DamageTarget dt : defenders)
|
||||||
dt.damage = 0;
|
dt.damage = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addDamage(final CardView card, int addedDamage) {
|
private void addDamage(final CardView card, int addedDamage) {
|
||||||
// If we don't have enough left or we're trying to unassign too much return
|
// If we don't have enough left or we're trying to unassign too much return
|
||||||
final int canAssign = getRemainingDamage();
|
final int canAssign = getRemainingDamage();
|
||||||
@@ -371,7 +371,7 @@ public class VAssignDamage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final DamageTarget dt = damage.get(card);
|
final DamageTarget dt = damage.get(card);
|
||||||
dt.damage = Math.max(0, addedDamage + dt.damage);
|
dt.damage = Math.max(0, addedDamage + dt.damage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -393,7 +393,7 @@ public class VAssignDamage {
|
|||||||
|
|
||||||
int damageLeft = totalDamageToAssign;
|
int damageLeft = totalDamageToAssign;
|
||||||
boolean allHaveLethal = true;
|
boolean allHaveLethal = true;
|
||||||
|
|
||||||
for ( DamageTarget dt : defenders )
|
for ( DamageTarget dt : defenders )
|
||||||
{
|
{
|
||||||
int dmg = dt.damage;
|
int dmg = dt.damage;
|
||||||
@@ -402,9 +402,9 @@ public class VAssignDamage {
|
|||||||
int overkill = dmg - lethal;
|
int overkill = dmg - lethal;
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.append(dmg);
|
sb.append(dmg);
|
||||||
if( overkill >= 0 ) {
|
if( overkill >= 0 ) {
|
||||||
sb.append(" (").append(localizer.getMessage("lblLethal"));
|
sb.append(" (").append(localizer.getMessage("lblLethal"));
|
||||||
if( overkill > 0 )
|
if( overkill > 0 )
|
||||||
sb.append(" +").append(overkill);
|
sb.append(" +").append(overkill);
|
||||||
sb.append(")");
|
sb.append(")");
|
||||||
}
|
}
|
||||||
@@ -421,9 +421,9 @@ public class VAssignDamage {
|
|||||||
// assigned dynamically, the cards die off and further damage to them can't
|
// assigned dynamically, the cards die off and further damage to them can't
|
||||||
// be modified.
|
// be modified.
|
||||||
private void finish() {
|
private void finish() {
|
||||||
if ( getRemainingDamage() > 0 )
|
if ( getRemainingDamage() > 0 )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
dlg.dispose();
|
dlg.dispose();
|
||||||
SOverlayUtils.hideOverlay();
|
SOverlayUtils.hideOverlay();
|
||||||
}
|
}
|
||||||
@@ -441,7 +441,10 @@ public class VAssignDamage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
lethalDamage = VAssignDamage.this.attackerHasDeathtouch ? 1 : Math.max(0, card.getLethalDamage());
|
lethalDamage = Math.max(0, card.getLethalDamage());
|
||||||
|
if (attackerHasDeathtouch) {
|
||||||
|
lethalDamage = Math.min(lethalDamage, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return lethalDamage;
|
return lethalDamage;
|
||||||
}
|
}
|
||||||
@@ -45,7 +45,7 @@ import forge.player.PlayerZoneUpdate;
|
|||||||
import forge.player.PlayerZoneUpdates;
|
import forge.player.PlayerZoneUpdates;
|
||||||
import forge.properties.ForgePreferences;
|
import forge.properties.ForgePreferences;
|
||||||
import forge.properties.ForgePreferences.FPref;
|
import forge.properties.ForgePreferences.FPref;
|
||||||
import forge.screens.match.views.VAssignDamage;
|
import forge.screens.match.views.VAssignCombatDamage;
|
||||||
import forge.screens.match.views.VPhaseIndicator;
|
import forge.screens.match.views.VPhaseIndicator;
|
||||||
import forge.screens.match.views.VPhaseIndicator.PhaseLabel;
|
import forge.screens.match.views.VPhaseIndicator.PhaseLabel;
|
||||||
import forge.screens.match.views.VPlayerPanel;
|
import forge.screens.match.views.VPlayerPanel;
|
||||||
@@ -172,7 +172,7 @@ public class MatchController extends AbstractGuiGame {
|
|||||||
public void showPromptMessage(final PlayerView player, final String message) {
|
public void showPromptMessage(final PlayerView player, final String message) {
|
||||||
view.getPrompt(player).setMessage(message);
|
view.getPrompt(player).setMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void showPromptMessage(final PlayerView player, final String message, final CardView card) {
|
public void showPromptMessage(final PlayerView player, final String message, final CardView card) {
|
||||||
view.getPrompt(player).setMessage(message, card);
|
view.getPrompt(player).setMessage(message, card);
|
||||||
@@ -360,11 +360,11 @@ public class MatchController extends AbstractGuiGame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<CardView, Integer> assignDamage(final CardView attacker, final List<CardView> blockers, final int damage, final GameEntityView defender, final boolean overrideOrder) {
|
public Map<CardView, Integer> assignCombatDamage(final CardView attacker, final List<CardView> blockers, final int damage, final GameEntityView defender, final boolean overrideOrder) {
|
||||||
return new WaitCallback<Map<CardView, Integer>>() {
|
return new WaitCallback<Map<CardView, Integer>>() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
final VAssignDamage v = new VAssignDamage(attacker, blockers, damage, defender, overrideOrder, this);
|
final VAssignCombatDamage v = new VAssignCombatDamage(attacker, blockers, damage, defender, overrideOrder, this);
|
||||||
v.show();
|
v.show();
|
||||||
}
|
}
|
||||||
}.invokeAndWait();
|
}.invokeAndWait();
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ import java.util.Map;
|
|||||||
|
|
||||||
import com.badlogic.gdx.utils.Align;
|
import com.badlogic.gdx.utils.Align;
|
||||||
|
|
||||||
public class VAssignDamage extends FDialog {
|
public class VAssignCombatDamage extends FDialog {
|
||||||
private static final float CARD_GAP_X = Utils.scale(10);
|
private static final float CARD_GAP_X = Utils.scale(10);
|
||||||
private static final float ADD_BTN_HEIGHT = Utils.AVG_FINGER_HEIGHT * 0.75f;
|
private static final float ADD_BTN_HEIGHT = Utils.AVG_FINGER_HEIGHT * 0.75f;
|
||||||
|
|
||||||
@@ -95,7 +95,7 @@ public class VAssignDamage extends FDialog {
|
|||||||
* @param defender GameEntity that's bein attacked
|
* @param defender GameEntity that's bein attacked
|
||||||
* @param overrideOrder override combatant order
|
* @param overrideOrder override combatant order
|
||||||
*/
|
*/
|
||||||
public VAssignDamage(final CardView attacker, final List<CardView> blockers, final int damage0, final GameEntityView defender0, boolean overrideOrder, final WaitCallback<Map<CardView, Integer>> waitCallback) {
|
public VAssignCombatDamage(final CardView attacker, final List<CardView> blockers, final int damage0, final GameEntityView defender0, boolean overrideOrder, final WaitCallback<Map<CardView, Integer>> waitCallback) {
|
||||||
super(Localizer.getInstance().getMessage("lbLAssignDamageDealtBy").replace("%s",CardTranslation.getTranslatedName(attacker.getName())) , 3);
|
super(Localizer.getInstance().getMessage("lbLAssignDamageDealtBy").replace("%s",CardTranslation.getTranslatedName(attacker.getName())) , 3);
|
||||||
|
|
||||||
callback = waitCallback;
|
callback = waitCallback;
|
||||||
@@ -453,7 +453,10 @@ public class VAssignDamage extends FDialog {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
lethalDamage = attackerHasDeathtouch ? 1 : Math.max(0, source.getLethalDamage());
|
lethalDamage = Math.max(0, source.getLethalDamage());
|
||||||
|
if (attackerHasDeathtouch) {
|
||||||
|
lethalDamage = Math.min(lethalDamage, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return lethalDamage;
|
return lethalDamage;
|
||||||
}
|
}
|
||||||
5
forge-gui/res/cardsfolder/f/flame_spill.txt
Normal file
5
forge-gui/res/cardsfolder/f/flame_spill.txt
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
Name:Flame Spill
|
||||||
|
ManaCost:2 R
|
||||||
|
Types:Instant
|
||||||
|
A:SP$ DealDamage | Cost$ 2 R | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumDmg$ 4 | ExcessDamage$ TargetedController | SpellDescription$ CARDNAME deals 4 damage to target creature. Excess damage is dealt to that creature’s controller instead.
|
||||||
|
Oracle:Flame Spill deals 4 damage to target creature. Excess damage is dealt to that creature’s controller instead.
|
||||||
7
forge-gui/res/cardsfolder/r/ram_through.txt
Normal file
7
forge-gui/res/cardsfolder/r/ram_through.txt
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
Name:Ram Through
|
||||||
|
ManaCost:1 G
|
||||||
|
Types:Instant
|
||||||
|
A:SP$ Pump | Cost$ 1 G | ValidTgts$ Creature.YouCtrl | AILogic$ PowerDmg | TgtPrompt$ Select target creature you control | SubAbility$ SoulsDamage | StackDescription$ SpellDescription | SpellDescription$ Target creature you control deals damage equal to its power to target creature you don’t control. If the creature you control has trample, excess damage is dealt to that creature’s controller instead.
|
||||||
|
SVar:SoulsDamage:DB$ DealDamage | ValidTgts$ Creature.YouDontCtrl | AILogic$ PowerDmg | TgtPrompt$ Select target creature you don't control | NumDmg$ X | References$ X | ConditionDefined$ Targeted | ConditionPresent$ Creature | ConditionCompare$ EQ1 | DamageSource$ ParentTarget | ExcessDamage$ TargetedController | ExcessDamageCondition$ Card.withTrample | StackDescription$ None
|
||||||
|
SVar:X:ParentTargeted$CardPower
|
||||||
|
Oracle:Target creature you control deals damage equal to its power to target creature you don’t control. If the creature you control has trample, excess damage is dealt to that creature’s controller instead.
|
||||||
@@ -62,7 +62,7 @@ public interface IGuiGame {
|
|||||||
void updateLives(Iterable<PlayerView> livesUpdate);
|
void updateLives(Iterable<PlayerView> livesUpdate);
|
||||||
void setPanelSelection(CardView hostCard);
|
void setPanelSelection(CardView hostCard);
|
||||||
SpellAbilityView getAbilityToPlay(CardView hostCard, List<SpellAbilityView> abilities, ITriggerEvent triggerEvent);
|
SpellAbilityView getAbilityToPlay(CardView hostCard, List<SpellAbilityView> abilities, ITriggerEvent triggerEvent);
|
||||||
Map<CardView, Integer> assignDamage(CardView attacker, List<CardView> blockers, int damage, GameEntityView defender, boolean overrideOrder);
|
Map<CardView, Integer> assignCombatDamage(CardView attacker, List<CardView> blockers, int damage, GameEntityView defender, boolean overrideOrder);
|
||||||
|
|
||||||
void message(String message);
|
void message(String message);
|
||||||
void message(String message, String title);
|
void message(String message, String title);
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ public enum ProtocolMethod {
|
|||||||
updateLives (Mode.SERVER, Void.TYPE, Iterable/*PlayerView*/.class),
|
updateLives (Mode.SERVER, Void.TYPE, Iterable/*PlayerView*/.class),
|
||||||
setPanelSelection (Mode.SERVER, Void.TYPE, CardView.class),
|
setPanelSelection (Mode.SERVER, Void.TYPE, CardView.class),
|
||||||
getAbilityToPlay (Mode.SERVER, SpellAbilityView.class, CardView.class, List/*SpellAbilityView*/.class, ITriggerEvent.class),
|
getAbilityToPlay (Mode.SERVER, SpellAbilityView.class, CardView.class, List/*SpellAbilityView*/.class, ITriggerEvent.class),
|
||||||
assignDamage (Mode.SERVER, Map.class, CardView.class, List/*CardView*/.class, Integer.TYPE, GameEntityView.class, Boolean.TYPE),
|
assignCombatDamage (Mode.SERVER, Map.class, CardView.class, List/*CardView*/.class, Integer.TYPE, GameEntityView.class, Boolean.TYPE),
|
||||||
message (Mode.SERVER, Void.TYPE, String.class, String.class),
|
message (Mode.SERVER, Void.TYPE, String.class, String.class),
|
||||||
showErrorDialog (Mode.SERVER, Void.TYPE, String.class, String.class),
|
showErrorDialog (Mode.SERVER, Void.TYPE, String.class, String.class),
|
||||||
showConfirmDialog (Mode.SERVER, Boolean.TYPE, String.class, String.class, String.class, String.class, Boolean.TYPE),
|
showConfirmDialog (Mode.SERVER, Boolean.TYPE, String.class, String.class, String.class, String.class, Boolean.TYPE),
|
||||||
|
|||||||
@@ -195,8 +195,8 @@ public class NetGuiGame extends AbstractGuiGame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<CardView, Integer> assignDamage(final CardView attacker, final List<CardView> blockers, final int damage, final GameEntityView defender, final boolean overrideOrder) {
|
public Map<CardView, Integer> assignCombatDamage(final CardView attacker, final List<CardView> blockers, final int damage, final GameEntityView defender, final boolean overrideOrder) {
|
||||||
return sendAndWait(ProtocolMethod.assignDamage, attacker, blockers, damage, defender, overrideOrder);
|
return sendAndWait(ProtocolMethod.assignCombatDamage, attacker, blockers, damage, defender, overrideOrder);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -291,7 +291,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
if ((attacker.hasKeyword(Keyword.TRAMPLE) && defender != null) || (blockers.size() > 1)) {
|
if ((attacker.hasKeyword(Keyword.TRAMPLE) && defender != null) || (blockers.size() > 1)) {
|
||||||
final CardView vAttacker = CardView.get(attacker);
|
final CardView vAttacker = CardView.get(attacker);
|
||||||
final GameEntityView vDefender = GameEntityView.get(defender);
|
final GameEntityView vDefender = GameEntityView.get(defender);
|
||||||
final Map<CardView, Integer> result = getGui().assignDamage(vAttacker, vBlockers, damageDealt,
|
final Map<CardView, Integer> result = getGui().assignCombatDamage(vAttacker, vBlockers, damageDealt,
|
||||||
vDefender, overrideOrder);
|
vDefender, overrideOrder);
|
||||||
for (final Entry<CardView, Integer> e : result.entrySet()) {
|
for (final Entry<CardView, Integer> e : result.entrySet()) {
|
||||||
map.put(game.getCard(e.getKey()), e.getValue());
|
map.put(game.getCard(e.getKey()), e.getValue());
|
||||||
|
|||||||
Reference in New Issue
Block a user