Merge branch 'master' of https://github.com/Card-Forge/forge into adventure

This commit is contained in:
Grimm
2022-08-22 14:46:49 +02:00
469 changed files with 960 additions and 225 deletions

View File

@@ -2809,7 +2809,7 @@ public class ComputerUtil {
|| type.is(CounterEnumType.GOLD) || type.is(CounterEnumType.MUSIC) || type.is(CounterEnumType.PUPA)
|| type.is(CounterEnumType.PARALYZATION) || type.is(CounterEnumType.SHELL) || type.is(CounterEnumType.SLEEP)
|| type.is(CounterEnumType.SLUMBER) || type.is(CounterEnumType.SLEIGHT) || type.is(CounterEnumType.WAGE)
|| type.is(CounterEnumType.INCARNATION) || type.is(CounterEnumType.RUST);
|| type.is(CounterEnumType.INCARNATION) || type.is(CounterEnumType.RUST) || type.is(CounterEnumType.STUN);
}
// this countertypes has no effect

View File

@@ -190,6 +190,15 @@ public final class ColorSet implements Comparable<ColorSet>, Iterable<Byte>, Ser
return this.countColors() > 1;
}
/**
* Checks if is all colors.
*
* @return true, if is all colors
*/
public boolean isAllColors() {
return this == ALL_COLORS;
}
/**
* Checks if is mono color.
*

View File

@@ -59,6 +59,11 @@ public class ForgeScript {
return false;
return property.startsWith("non") != colors.isMulticolor();
} else if (property.contains("AllColors")) {
if (property.endsWith("Source") && isColorlessSource)
return false;
return property.startsWith("non") != colors.isAllColors();
} else if (property.contains("MonoColor")) { // ... Card is monocolored
if (property.endsWith("Source") && isColorlessSource)
return false;

View File

@@ -366,7 +366,9 @@ public class GameAction {
}
}
if (zoneFrom == null) {
// in addition to actual tokens, cards "made" by digital-only mechanics
// are also added to inbound tokens so their etb replacements will work
if (zoneFrom == null || zoneFrom.is(ZoneType.None)) {
copied.getOwner().addInboundToken(copied);
}

View File

@@ -3478,8 +3478,8 @@ public class AbilityUtils {
}
if (value.equals("OpponentsAttackedThisTurn")) {
final List<Player> opps = player.getAttackedPlayersMyTurn();
return doXMath(opps == null ? 0 : opps.size(), m, source, ctb);
final Iterable<Player> opps = player.getAttackedPlayersMyTurn();
return doXMath(opps == null ? 0 : Iterables.size(opps), m, source, ctb);
}
if (value.equals("OpponentsAttackedThisCombat")) {

View File

@@ -596,7 +596,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
}
if (sa.hasParam("GainControl")) {
final String g = sa.getParam("GainControl");
Player newController = g.equals("True") ? sa.getActivatingPlayer() :
Player newController = g.equals("True") ? player :
AbilityUtils.getDefinedPlayers(sa.getHostCard(), g, sa).get(0);
if (newController != null) {
if (newController != gameCard.getController()) {
@@ -764,7 +764,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
movedCard.setForetoldThisTurn(true);
movedCard.setForetoldByEffect(true);
// look at the exiled card
movedCard.addMayLookTemp(sa.getActivatingPlayer());
movedCard.addMayLookTemp(player);
}
if (sa.hasParam("TrackDiscarded")) {

View File

@@ -439,6 +439,9 @@ public class CountersPutEffect extends SpellAbilityEffect {
}
if (obj instanceof Card) {
if (sa.hasParam("CounterNumPerDefined")) {
counterAmount = AbilityUtils.calculateAmount(gameCard, sa.getParam("CounterNumPerDefined"), sa);
}
counterAmount = sa.usesTargeting() && sa.isDividedAsYouChoose() ? sa.getDividedValue(gameCard)
: counterAmount;
if (!sa.usesTargeting() || gameCard.canBeTargetedBy(sa)) {

View File

@@ -1,8 +1,12 @@
package forge.game.ability.effects;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import forge.StaticData;
import forge.card.ICardFace;
import forge.game.Game;
import forge.game.ability.AbilityKey;
import forge.game.ability.AbilityUtils;
@@ -14,6 +18,9 @@ import forge.game.player.Player;
import forge.game.player.PlayerCollection;
import forge.game.spellability.SpellAbility;
import forge.game.zone.ZoneType;
import forge.util.Aggregates;
import forge.util.CardTranslation;
import forge.util.Localizer;
public class MakeCardEffect extends SpellAbilityEffect {
@Override
@@ -40,6 +47,20 @@ public class MakeCardEffect extends SpellAbilityEffect {
if (def.size() > 0) {
name = def.getFirst().getName();
}
} else if (sa.hasParam("Spellbook")) {
List<String> spellbook = Arrays.asList(sa.getParam("Spellbook").split(","));
List<ICardFace> faces = new ArrayList<>();
for (String s : spellbook) {
// Cardnames that include "," must use ";" instead in Spellbook$ (i.e. Tovolar; Dire Overlord)
s = s.replace(";", ",");
faces.add(StaticData.instance().getCommonCards().getFaceByName(s));
}
if (sa.hasParam("AtRandom")) {
name = Aggregates.random(faces).getName();
} else {
name = player.getController().chooseCardName(sa, faces,
Localizer.getInstance().getMessage("lblChooseFromSpellbook", CardTranslation.getTranslatedName(source.getName())));
}
}
final ZoneType zone = ZoneType.smartValueOf(sa.getParamOrDefault("Zone", "Library"));
int amount = sa.hasParam("Amount") ?
@@ -50,12 +71,7 @@ public class MakeCardEffect extends SpellAbilityEffect {
if (!name.equals("")) {
while (amount > 0) {
Card card = Card.fromPaperCard(StaticData.instance().getCommonCards().getUniqueByName(name), player);
if (sa.hasParam("IsToken")) {
card.setToken(true);
}
if (!sa.hasParam("NotToken")) {
card.setTokenCard(true);
}
game.getAction().moveTo(ZoneType.None, card, sa, moveParams);
cards.add(card);
amount--;

View File

@@ -334,6 +334,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
private ReplacementEffect shieldCounterReplaceDamage = null;
private ReplacementEffect shieldCounterReplaceDestroy = null;
private ReplacementEffect stunCounterReplaceUntap = null;
// Enumeration for CMC request types
public enum SplitCMCMode {
@@ -6100,16 +6101,16 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
}
// Shield Counter aren't affected by Changed Card Traits
if (this.getCounters(CounterEnumType.SHIELD) > 0) {
if (getCounters(CounterEnumType.SHIELD) > 0) {
String sa = "DB$ RemoveCounter | Defined$ Self | CounterType$ Shield | CounterNum$ 1";
if (shieldCounterReplaceDamage == null) {
String reStr = "Event$ DamageDone | ActiveZones$ Battlefield | ValidTarget$ Card.Self | PreventionEffect$ True | AlwaysReplace$ True "
String reStr = "Event$ DamageDone | ActiveZones$ Battlefield | ValidTarget$ Card.Self | PreventionEffect$ True | AlwaysReplace$ True | Secondary$ True "
+ "| Description$ If damage would be dealt to this permanent, prevent that damage and remove a shield counter from it.";
shieldCounterReplaceDamage = ReplacementHandler.parseReplacement(reStr, this, false, null);
shieldCounterReplaceDamage.setOverridingAbility(AbilityFactory.getAbility(sa, this));
}
if (shieldCounterReplaceDestroy == null) {
String reStr = "Event$ Destroy | ActiveZones$ Battlefield | ValidCard$ Card.Self | ValidSource$ SpellAbility "
String reStr = "Event$ Destroy | ActiveZones$ Battlefield | ValidCard$ Card.Self | ValidSource$ SpellAbility | Secondary$ True "
+ "| Description$ If this permanent would be destroyed as the result of an effect, instead remove a shield counter from it.";
shieldCounterReplaceDestroy = ReplacementHandler.parseReplacement(reStr, this, false, null);
shieldCounterReplaceDestroy.setOverridingAbility(AbilityFactory.getAbility(sa, this));
@@ -6118,6 +6119,17 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
list.add(shieldCounterReplaceDamage);
list.add(shieldCounterReplaceDestroy);
}
if (getCounters(CounterEnumType.STUN) > 0) {
String sa = "DB$ RemoveCounter | Defined$ Self | CounterType$ Stun | CounterNum$ 1";
if (stunCounterReplaceUntap == null) {
String reStr = "Event$ Untap | ActiveZones$ Battlefield | ValidCard$ Card.Self | Secondary$ True "
+ "| Description$ If this permanent would become untapped, instead remove a stun counter from it.";
stunCounterReplaceUntap = ReplacementHandler.parseReplacement(reStr, this, false, null);
stunCounterReplaceUntap.setOverridingAbility(AbilityFactory.getAbility(sa, this));
}
list.add(stunCounterReplaceUntap);
}
}
public boolean hasReplacementEffect(final ReplacementEffect re) {

View File

@@ -1391,6 +1391,10 @@ public class CardProperty {
if (card.getNetPower() <= card.getNetToughness()) {
return false;
}
} else if (property.equals("powerGTbasePower")) {
if (card.getNetPower() <= card.getCurrentPower()) {
return false;
}
} else if (property.equals("powerLTtoughness")) {
if (card.getNetPower() >= card.getNetToughness()) {
return false;

View File

@@ -329,6 +329,8 @@ public enum CounterEnumType {
STUDY("STUDY", 226, 192, 165),
STUN("STUN", 226, 192, 165),
TASK("TASK", 191, 63, 49),
THEFT("THEFT", 255, 176, 125),

View File

@@ -407,10 +407,7 @@ public class CombatUtil {
c.getDamageHistory().setCreatureAttackedThisCombat(defender);
c.getDamageHistory().clearNotAttackedSinceLastUpkeepOf();
c.getController().addCreaturesAttackedThisTurn(CardUtil.getLKICopy(c));
if (defender instanceof Player) {
c.getController().addAttackedPlayersMyTurn(combat.getDefenderPlayerByAttacker(c));
}
c.getController().addCreaturesAttackedThisTurn(CardUtil.getLKICopy(c), defender);
}
/**

View File

@@ -24,6 +24,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Deque;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -202,8 +203,7 @@ public class Player extends GameEntity implements Comparable<Player> {
private Table<Long, Long, KeywordsChange> changedKeywords = TreeBasedTable.create();
private ManaPool manaPool = new ManaPool(this);
private List<Card> creatureAttackedThisTurn = new ArrayList<>();
private List<Player> attackedPlayersThisTurn = new ArrayList<>();
private Map<GameEntity, List<Card>> attackedThisTurn = new HashMap<>();
private List<Player> attackedPlayersLastTurn = new ArrayList<>();
private List<Player> attackedPlayersThisCombat = new ArrayList<>();
@@ -1826,37 +1826,37 @@ public class Player extends GameEntity implements Comparable<Player> {
}
public final List<Card> getCreaturesAttackedThisTurn() {
return creatureAttackedThisTurn;
List<Card> result = Lists.newArrayList(Iterables.concat(attackedThisTurn.values()));
return result;
}
public final void addCreaturesAttackedThisTurn(final Card c) {
creatureAttackedThisTurn.add(c);
public final List<Card> getCreaturesAttackedThisTurn(final GameEntity e) {
return attackedThisTurn.getOrDefault(e, Lists.newArrayList());
}
public final void addCreaturesAttackedThisTurn(final Card c, final GameEntity e) {
final List<Card> creatures = attackedThisTurn.getOrDefault(e, Lists.newArrayList());
creatures.add(c);
attackedThisTurn.putIfAbsent(e, creatures);
if (e instanceof Player && !attackedPlayersThisCombat.contains(e)) {
attackedPlayersThisCombat.add((Player) e);
}
public final void clearCreaturesAttackedThisTurn() {
creatureAttackedThisTurn.clear();
}
public final void addAttackedPlayersMyTurn(final Player p) {
if (!attackedPlayersThisTurn.contains(p)) {
attackedPlayersThisCombat.add(p);
attackedPlayersThisTurn.add(p);
}
}
public final List<Player> getAttackedPlayersMyTurn() {
return attackedPlayersThisTurn;
public final Iterable<Player> getAttackedPlayersMyTurn() {
return Iterables.filter(attackedThisTurn.keySet(), Player.class);
}
public final List<Player> getAttackedPlayersMyLastTurn() {
return attackedPlayersLastTurn;
}
public final void clearAttackedPlayersMyTurn() {
attackedPlayersThisTurn.clear();
public final void clearAttackedMyTurn() {
attackedThisTurn.clear();
}
public final void setAttackedPlayersMyLastTurn(List<Player> players) {
public final void setAttackedPlayersMyLastTurn(Iterable<Player> players) {
attackedPlayersLastTurn.clear();
attackedPlayersLastTurn.addAll(players);
Iterables.addAll(attackedPlayersLastTurn, players);
}
public final List<Player> getAttackedPlayersMyCombat() {
return attackedPlayersThisTurn;
return attackedPlayersThisCombat;
}
public final void clearAttackedPlayersMyCombat() {
attackedPlayersThisCombat.clear();
@@ -2390,7 +2390,6 @@ public class Player extends GameEntity implements Comparable<Player> {
resetNumForetoldThisTurn();
resetNumTokenCreatedThisTurn();
setNumCardsInHandStartedThisTurnWith(getCardsIn(ZoneType.Hand).size());
clearCreaturesAttackedThisTurn();
setActivateLoyaltyAbilityThisTurn(false);
setTappedLandForManaThisTurn(false);
setLandsPlayedLastTurn(getLandsPlayedThisTurn());
@@ -2417,8 +2416,8 @@ public class Player extends GameEntity implements Comparable<Player> {
// set last turn nr
if (game.getPhaseHandler().isPlayerTurn(this)) {
setAttackedPlayersMyLastTurn(attackedPlayersThisTurn);
clearAttackedPlayersMyTurn();
setAttackedPlayersMyLastTurn(getAttackedPlayersMyTurn());
clearAttackedMyTurn();
this.lastTurnNr = game.getPhaseHandler().getTurn();
}
}

View File

@@ -381,6 +381,14 @@ public class PlayerProperty {
if (player.getCreaturesAttackedThisTurn().isEmpty()) {
return false;
}
} else if (property.startsWith("wasAttackedThisTurnBy")) {
String restriction = property.split(" ")[1];
for (Card c : sourceController.getCreaturesAttackedThisTurn(player)) {
if (c.isValid(restriction, sourceController, source, spellAbility)) {
return true;
}
}
return false;
} else if (property.equals("attackedYouTheirLastTurn")) {
if (!player.getAttackedPlayersMyLastTurn().contains(sourceController)) {
return false;

View File

@@ -361,6 +361,10 @@ public class AbilityManaPart implements java.io.Serializable {
}
}
if (restriction.equals("CantCastNonArtifactSpells")) {
return !sa.isSpell() || sa.getHostCard().isArtifact();
}
// the payment is for a resolving SA, currently no other restrictions would allow that
if (getSourceCard().getGame().getStack().getInstanceFromSpellAbility(sa.getRootAbility()) != null) {
return false;

View File

@@ -41,7 +41,7 @@ public class CardEditionCollectionCardMockTestCase extends CardMockTestCase {
CardDb cardDb = FModel.getMagicDb().getCommonCards();
String[] cardNames = { "Shivan Dragon", "Animate Wall", "Balance", "Blessing", "Force of Will" };
String[] expectedSets = { "M20", "MED", "SLD", "M14", "2XM" };
String[] expectedSets = { "M20", "MED", "SLD", "M14", "DMR" };
List<PaperCard> cards = new ArrayList<>();
for (int i = 0; i < 5; i++) {
String cardName = cardNames[i];

View File

@@ -60,6 +60,8 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
// Fantasy/Chaos mode settings.
private boolean fantasyMode = false;
private boolean announceFantasy = false;
private boolean usingCustomDeck = false;
private boolean announceCustom = false;
// Signals
SignalList onLifeTotalChangeList = new SignalList();
@@ -83,6 +85,7 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
//Reset all properties HERE.
fantasyMode = false;
announceFantasy = false;
usingCustomDeck = false;
blessing = null;
gold = 0;
maxLife = 20;
@@ -104,9 +107,10 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
private final CardPool cards=new CardPool();
private final ItemPool<InventoryItem> newCards=new ItemPool<>(InventoryItem.class);
public void create(String n, Deck startingDeck, boolean male, int race, int avatar, boolean isFantasy, DifficultyData difficultyData) {
public void create(String n, Deck startingDeck, boolean male, int race, int avatar, boolean isFantasy, boolean isUsingCustomDeck, DifficultyData difficultyData) {
clear();
announceFantasy = fantasyMode = isFantasy; //Set Chaos mode first.
announceCustom = usingCustomDeck = isUsingCustomDeck;
deck = startingDeck;
decks[0] = deck;
@@ -289,6 +293,8 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
fantasyMode = data.containsKey("fantasyMode") ? data.readBool("fantasyMode") : false;
announceFantasy = data.containsKey("announceFantasy") ? data.readBool("announceFantasy") : false;
usingCustomDeck = data.containsKey("usingCustomDeck") ? data.readBool("usingCustomDeck") : false;
announceCustom = data.containsKey("announceCustom") ? data.readBool("announceCustom") : false;
onLifeTotalChangeList.emit();
onGoldChangeList.emit();
@@ -315,6 +321,8 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
data.store("fantasyMode",fantasyMode);
data.store("announceFantasy",announceFantasy);
data.store("usingCustomDeck", usingCustomDeck);
data.store("announceCustom", announceCustom);
data.store("worldPosX",worldPosX);
data.store("worldPosY",worldPosY);
@@ -493,6 +501,9 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
public boolean isFantasyMode(){
return fantasyMode;
}
public boolean isUsingCustomDeck(){
return usingCustomDeck;
}
public boolean hasAnnounceFantasy(){
return announceFantasy;
@@ -501,6 +512,12 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
public void clearAnnounceFantasy(){
announceFantasy = false;
}
public boolean hasAnnounceCustom(){
return announceCustom;
}
public void clearAnnounceCustom(){
announceCustom = false;
}
public boolean hasColorView() {
for(String name:equippedItems.values()) {

View File

@@ -73,8 +73,9 @@ public class DuelScene extends ForgeScene {
public void GameEnd() {
boolean winner = humanPlayer == hostedMatch.getGame().getMatch().getWinner();
String enemyName = (enemy.nameOverride.isEmpty() ? enemy.getData().name : enemy.nameOverride);
boolean showMessages = enemy.getData().copyPlayerDeck && Current.player().isUsingCustomDeck();
Current.player().clearBlessing();
if (chaosBattle && !winner) {
if ((chaosBattle||showMessages) && !winner) {
callbackExit = true;
List<String> insult = Lists.newArrayList("I'm sorry...", "... ....", "Learn from your defeat.",
"I haven't begun to use my full power.", "No matter how much you try, you still won't beat me.",
@@ -233,7 +234,7 @@ public class DuelScene extends ForgeScene {
this.AIExtras = aiCards;
deck = deckProxy.getDeck();
} else {
deck = currentEnemy.copyPlayerDeck ? this.playerDeck : currentEnemy.generateDeck(Current.player().isFantasyMode(), Current.player().getDifficulty().name.equalsIgnoreCase("Hard"));
deck = currentEnemy.copyPlayerDeck ? this.playerDeck : currentEnemy.generateDeck(Current.player().isFantasyMode(), Current.player().isUsingCustomDeck()||Current.player().getDifficulty().name.equalsIgnoreCase("Hard"));
}
RegisteredPlayer aiPlayer = RegisteredPlayer.forVariants(playerCount, appliedVariants, deck, null, false, null, null);
@@ -285,7 +286,8 @@ public class DuelScene extends ForgeScene {
hostedMatch.setEndGameHook(() -> DuelScene.this.GameEnd());
hostedMatch.startMatch(rules, appliedVariants, players, guiMap);
MatchController.instance.setGameView(hostedMatch.getGameView());
if (chaosBattle) {
boolean showMessages = enemy.getData().copyPlayerDeck && Current.player().isUsingCustomDeck();
if (chaosBattle||showMessages) {
List<String> list = Lists.newArrayList("It all depends on your skill!", "It's showtime!", "Let's party!",
"You've proved yourself!", "Are you ready? Go!", "Prepare to strike, now!", "Let's go!", "What's next?",
"Yeah, I've been waitin' for this!", "The stage of battle is set!", "And the battle begins!", "Let's get started!",

View File

@@ -15,6 +15,7 @@ import forge.adventure.util.Selector;
import forge.adventure.util.UIActor;
import forge.adventure.world.WorldSave;
import forge.card.ColorSet;
import forge.deck.DeckProxy;
import forge.localinstance.properties.ForgePreferences;
import forge.model.FModel;
import forge.player.GamePlayerUtil;
@@ -36,7 +37,8 @@ public class NewGameScene extends UIScene {
private Selector gender;
private Selector mode;
private Selector difficulty;
private Array<String> stringList, random;
private Array<String> stringList, random, custom;
private Label colorLabel;
public NewGameScene() {
super(Forge.isLandscapeMode() ? "ui/new_game.json" : "ui/new_game_portrait.json");
@@ -54,7 +56,7 @@ public class NewGameScene extends UIScene {
avatarIndex,
colorIds[colorId.getCurrentIndex()],
Config.instance().getConfigData().difficulties[difficulty.getCurrentIndex()],
mode.getCurrentIndex()==2, mode.getCurrentIndex()==1, 0);//maybe replace with enum
mode.getCurrentIndex() == 2, mode.getCurrentIndex() == 1, mode.getCurrentIndex() == 3, colorId.getCurrentIndex(), 0);//maybe replace with enum
GamePlayerUtil.getGuiPlayer().setName(selectedName.getText());
Forge.switchScene(SceneType.GameScene.instance);
};
@@ -75,7 +77,12 @@ public class NewGameScene extends UIScene {
avatarImage = ui.findActor("avatarPreview");
gender = ui.findActor("gender");
mode = ui.findActor("mode");
mode.setTextList(new String[]{"Standard", "Constructed","Chaos"});
colorLabel = ui.findActor("colorIdL");
String colorIdLabel = colorLabel.getText().toString();
custom = new Array<>();
for (DeckProxy deckProxy : DeckProxy.getAllCustomStarterDecks())
custom.add(deckProxy.getName());
mode.setTextList(custom.isEmpty() ? new String[]{"Standard", "Constructed", "Chaos"} : new String[]{"Standard", "Constructed", "Chaos", "Custom"});
gender.setTextList(new String[]{"Male", "Female"});
gender.addListener(event -> NewGameScene.this.updateAvatar());
Random rand = new Random();
@@ -94,9 +101,12 @@ public class NewGameScene extends UIScene {
mode.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent changeEvent, Actor actor) {
colorLabel.setText(mode.getCurrentIndex() < 2 ? colorIdLabel : Forge.getLocalizer().getMessage("lblDeck")+":");
if (mode.getCurrentIndex() == 3)
colorId.setTextList(custom);
if (mode.getCurrentIndex() == 2)
colorId.setTextList(random);
else
if (mode.getCurrentIndex() < 2)
colorId.setTextList(stringList);
}
});
@@ -125,9 +135,6 @@ public class NewGameScene extends UIScene {
ui.onButtonPress("start", () -> NewGameScene.this.start());
ui.onButtonPress("leftAvatar", () -> NewGameScene.this.leftAvatar());
ui.onButtonPress("rightAvatar", () -> NewGameScene.this.rightAvatar());
}
private void rightAvatar() {
@@ -156,8 +163,7 @@ public class NewGameScene extends UIScene {
updateAvatar();
Gdx.input.setInputProcessor(stage); //Start taking input from the ui
if(Forge.createNewAdventureMap)
{
if (Forge.createNewAdventureMap) {
FModel.getPreferences().setPref(ForgePreferences.FPref.UI_ENABLE_MUSIC, false);
WorldSave.generateNewWorld(selectedName.getText(),
gender.getCurrentIndex() == 0,
@@ -165,7 +171,7 @@ public class NewGameScene extends UIScene {
avatarIndex,
colorIds[colorId.getCurrentIndex()],
Config.instance().getConfigData().difficulties[difficulty.getCurrentIndex()],
mode.getCurrentIndex()==2, mode.getCurrentIndex()==1, 0);//maybe replace with enum
mode.getCurrentIndex() == 2, mode.getCurrentIndex() == 1, mode.getCurrentIndex() == 3, colorId.getCurrentIndex(), 0);//maybe replace with enum
GamePlayerUtil.getGuiPlayer().setName(selectedName.getText());
Forge.switchScene(SceneType.GameScene.instance);
}

View File

@@ -195,7 +195,7 @@ public static ConsoleCommandInterpreter getInstance()
});
registerCommand(new String[]{"dumpEnemyDeckColors"}, s -> {
for(EnemyData E : new Array.ArrayIterator<>(WorldData.getAllEnemies())){
Deck D = E.generateDeck(Current.player().isFantasyMode(), Current.player().getDifficulty().name.equalsIgnoreCase("Hard"));
Deck D = E.generateDeck(Current.player().isFantasyMode(), Current.player().isUsingCustomDeck()||Current.player().getDifficulty().name.equalsIgnoreCase("Hard"));
DeckProxy DP = new DeckProxy(D, "Constructed", GameType.Constructed, null);
ColorSet colorSet = DP.getColor();
System.out.printf("%s: Colors: %s (%s%s%s%s%s%s)\n", D.getName(), DP.getColor(),
@@ -211,7 +211,7 @@ public static ConsoleCommandInterpreter getInstance()
});
registerCommand(new String[]{"dumpEnemyDeckList"}, s -> {
for(EnemyData E : new Array.ArrayIterator<>(WorldData.getAllEnemies())){
Deck D = E.generateDeck(Current.player().isFantasyMode(), Current.player().getDifficulty().name.equalsIgnoreCase("Hard"));
Deck D = E.generateDeck(Current.player().isFantasyMode(), Current.player().isUsingCustomDeck()||Current.player().getDifficulty().name.equalsIgnoreCase("Hard"));
DeckProxy DP = new DeckProxy(D, "Constructed", GameType.Constructed, null);
ColorSet colorSet = DP.getColor();
System.out.printf("Deck: %s\n%s\n\n", D.getName(), DP.getDeck().getMain().toCardList("\n")
@@ -221,7 +221,7 @@ public static ConsoleCommandInterpreter getInstance()
});
registerCommand(new String[]{"dumpEnemyColorIdentity"}, s -> {
for(EnemyData E : new Array.ArrayIterator<>(WorldData.getAllEnemies())){
Deck D = E.generateDeck(Current.player().isFantasyMode(), Current.player().getDifficulty().name.equalsIgnoreCase("Hard"));
Deck D = E.generateDeck(Current.player().isFantasyMode(), Current.player().isUsingCustomDeck()||Current.player().getDifficulty().name.equalsIgnoreCase("Hard"));
DeckProxy DP = new DeckProxy(D, "Constructed", GameType.Constructed, null);
ColorSet colorSet = DP.getColor();
System.out.printf("%s Colors: %s | Deck Colors: %s (%s)\n", E.name, E.colors, DP.getColorIdentity().toEnumSet().toString(), DP.getName()

View File

@@ -153,25 +153,19 @@ public class WorldStage extends GameStage implements SaveFileContent {
if (playerIsWinner) {
player.setAnimation(CharacterSprite.AnimationTypes.Attack);
currentMob.setAnimation(CharacterSprite.AnimationTypes.Death);
startPause(0.5f, new Runnable() {
@Override
public void run() {
startPause(0.5f, () -> {
((RewardScene) SceneType.RewardScene.instance).loadRewards(currentMob.getRewards(), RewardScene.Type.Loot, null);
WorldStage.this.removeEnemy(currentMob);
currentMob = null;
Forge.switchScene(SceneType.RewardScene.instance);
}
});
} else {
player.setAnimation(CharacterSprite.AnimationTypes.Hit);
currentMob.setAnimation(CharacterSprite.AnimationTypes.Attack);
startPause(0.5f, new Runnable() {
@Override
public void run() {
startPause(0.5f, () -> {
Current.player().defeated();
WorldStage.this.removeEnemy(currentMob);
currentMob = null;
}
});
}
@@ -269,6 +263,11 @@ public class WorldStage extends GameStage implements SaveFileContent {
WorldSave.getCurrentSave().getPlayer().getSelectedDeck().getName()+
"\nEnemy will use Preconstructed or Random Generated Decks. Genetic AI Decks will be available to some enemies on Hard difficulty.", WorldSave.getCurrentSave().getPlayer().getSelectedDeck());
WorldSave.getCurrentSave().getPlayer().clearAnnounceFantasy();
} else if (WorldSave.getCurrentSave().getPlayer().hasAnnounceCustom()) {
MapStage.getInstance().showDeckAwardDialog("{GRADIENT}Custom Deck Mode!{ENDGRADIENT}\n"+ WorldSave.getCurrentSave().getPlayer().getName()+ "'s Deck: "+
WorldSave.getCurrentSave().getPlayer().getSelectedDeck().getName()+
"\nSome enemies will use Genetic AI Decks randomly.", WorldSave.getCurrentSave().getPlayer().getSelectedDeck());
WorldSave.getCurrentSave().getPlayer().clearAnnounceCustom();
}
}

View File

@@ -535,7 +535,7 @@ public class CardUtil {
if(path.endsWith(".dck"))
return DeckSerializer.fromFile(new File(Config.instance().getFilePath(path)));
if(forAI && isFantasyMode) {
if(forAI && (isFantasyMode||useGeneticAI)) {
Deck deck = DeckgenUtil.getRandomOrPreconOrThemeDeck(colors, forAI, isTheme, useGeneticAI);
if (deck != null)
return deck;

View File

@@ -9,6 +9,7 @@ import forge.adventure.util.SaveFileData;
import forge.adventure.util.SignalList;
import forge.card.ColorSet;
import forge.deck.Deck;
import forge.deck.DeckProxy;
import forge.deck.DeckgenUtil;
import forge.localinstance.properties.ForgeConstants;
import forge.player.GamePlayerUtil;
@@ -122,20 +123,15 @@ public class WorldSave {
return currentSave;
}
public static WorldSave generateNewWorld(String name, boolean male, int race, int avatarIndex, ColorSet startingColorIdentity, DifficultyData diff, boolean chaos, boolean constructed, long seed) {
public static WorldSave generateNewWorld(String name, boolean male, int race, int avatarIndex, ColorSet startingColorIdentity, DifficultyData diff, boolean chaos, boolean constructed, boolean custom, int customDeckIndex, long seed) {
currentSave.world.generateNew(seed);
currentSave.pointOfInterestChanges.clear();
Deck starterDeck = chaos ? DeckgenUtil.getRandomOrPreconOrThemeDeck("", false, false, false) : Config.instance().starterDeck(startingColorIdentity,diff,constructed);
currentSave.player.create(name, starterDeck, male, race, avatarIndex, chaos, diff);
Deck starterDeck = chaos ? DeckgenUtil.getRandomOrPreconOrThemeDeck("", false, false, false) : custom ? DeckProxy.getAllCustomStarterDecks().get(customDeckIndex).getDeck() : Config.instance().starterDeck(startingColorIdentity,diff,constructed);
currentSave.player.create(name, starterDeck, male, race, avatarIndex, chaos, custom, diff);
currentSave.player.setWorldPosY((int) (currentSave.world.getData().playerStartPosY * currentSave.world.getData().height * currentSave.world.getTileSize()));
currentSave.player.setWorldPosX((int) (currentSave.world.getData().playerStartPosX * currentSave.world.getData().width * currentSave.world.getTileSize()));
//after getting deck override starting color identity to match
//if (identity != startingColorIdentity)
// currentSave.player.setColorIdentity(identity);
currentSave.onLoadList.emit();
return currentSave;
//return currentSave = ret;
}
public boolean autoSave() {

View File

@@ -43,7 +43,7 @@
<dependency>
<groupId>com.github.tommyettinger</groupId>
<artifactId>textratypist</artifactId>
<version>2f773002a8</version>
<version>0.7.1</version>
</dependency>
<dependency>
<groupId>com.github.tommyettinger</groupId>

View File

@@ -3,8 +3,8 @@ ManaCost:4 U U
Types:Creature Shapeshifter
PT:4/5
A:AB$ ChangeZone | Cost$ U | Defined$ Self | Origin$ Battlefield | Destination$ Exile | SubAbility$ DelTrig | RememberChanged$ True | SpellDescription$ Exile CARDNAME. Return it to the battlefield under its owner's control at the beginning of the next end step.
SVar:DelTrig:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | Execute$ TrigReturn | ConditionDefined$ Remembered | ConditionPresent$ Card | TriggerDescription$ Return CARDNAME to the battlefield.
SVar:TrigReturn:DB$ ChangeZone | Defined$ Self | Origin$ Exile | Destination$ Battlefield
SVar:DelTrig:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | Execute$ TrigReturn | ConditionDefined$ Remembered | ConditionPresent$ Card | RememberObjects$ Remembered | TriggerDescription$ Return CARDNAME to the battlefield.
SVar:TrigReturn:DB$ ChangeZone | Defined$ DelayTriggerRememberedLKI | Origin$ Exile | Destination$ Battlefield
A:AB$ Pump | Cost$ U | Defined$ Self | KW$ HIDDEN Unblockable | SpellDescription$ CARDNAME can't be blocked this turn.
A:AB$ Pump | Cost$ 1 | Defined$ Self | NumAtt$ +1 | NumDef$ -1 | SpellDescription$ CARDNAME gets +1/-1 until end of turn.
A:AB$ Pump | Cost$ 1 | Defined$ Self | NumAtt$ -1 | NumDef$ +1 | SpellDescription$ CARDNAME gets -1/+1 until end of turn.

View File

@@ -3,7 +3,7 @@ ManaCost:1 G W
Types:Creature Frog Beast
PT:3/4
A:AB$ ChangeZone | Cost$ Discard<2/Card> | Defined$ Self | Origin$ Battlefield | Destination$ Exile | SubAbility$ DelTrig | RememberChanged$ True | SpellDescription$ Exile CARDNAME. Return it to the battlefield under its owner's control at the beginning of the next end step.
SVar:DelTrig:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | Execute$ TrigReturn | ConditionDefined$ Remembered | ConditionPresent$ Card | TriggerDescription$ Return CARDNAME to the battlefield.
SVar:TrigReturn:DB$ ChangeZone | Origin$ Exile | Destination$ Battlefield | Defined$ Self
SVar:DelTrig:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | Execute$ TrigReturn | ConditionDefined$ Remembered | ConditionPresent$ Card | RememberObjects$ Remembered | TriggerDescription$ Return CARDNAME to the battlefield.
SVar:TrigReturn:DB$ ChangeZone | Origin$ Exile | Destination$ Battlefield | Defined$ DelayTriggerRememberedLKI
AI:RemoveDeck:All
Oracle:Discard two cards: Exile Anurid Brushhopper. Return it to the battlefield under its owner's control at the beginning of the next end step.

View File

@@ -0,0 +1,9 @@
Name:Baird, Argivian Recruiter
ManaCost:R W
Types:Legendary Creature Human Soldier
PT:2/2
T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigToken | IsPresent$ Creature.YouCtrl+powerGTbasePower | TriggerDescription$ At the beginning of your end step, if you control a creature with power greater than its base power, create a 1/1 white Soldier creature token.
SVar:TrigToken:DB$ Token | TokenScript$ w_1_1_soldier
DeckHas:Ability$Token
AI:RemoveDeck:Random
Oracle:At the beginning of your end step, if you control a creature with power greater than its base power, create a 1/1 white Soldier creature token.

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