diff --git a/gemp-lotr/db/2024-12-06_renumber_V1_promos.sql b/gemp-lotr/db/2024-12-06_renumber_V1_promos.sql index e4f17e0a4..e70efbc79 100644 --- a/gemp-lotr/db/2024-12-06_renumber_V1_promos.sql +++ b/gemp-lotr/db/2024-12-06_renumber_V1_promos.sql @@ -1,7 +1,7 @@ SELECT * FROM transfer t -# WHERE collection RLIKE('(101_65|101_66|101_67)') +WHERE contents RLIKE('(101_65|101_66|101_67)') ORDER BY id DESC; SELECT * @@ -20,16 +20,16 @@ WHERE contents RLIKE('(101_65|101_66|101_67)'); -- WHERE c.id IN (59510, 64642, 64643) UPDATE transfer -SET collection = REGEXP_REPLACE(collection, '101_65', '101_101') -WHERE collection RLIKE('101_65'); +SET contents = REGEXP_REPLACE(contents, '101_65', '101_101') +WHERE contents RLIKE('101_65'); UPDATE transfer -SET collection = REGEXP_REPLACE(collection, '101_66', '101_102') -WHERE collection RLIKE('101_66'); +SET contents = REGEXP_REPLACE(contents, '101_66', '101_102') +WHERE contents RLIKE('101_66'); UPDATE transfer -SET collection = REGEXP_REPLACE(collection, '101_67', '101_103') -WHERE collection RLIKE('101_67'); +SET contents = REGEXP_REPLACE(contents, '101_67', '101_103') +WHERE contents RLIKE('101_67'); UPDATE collection_entries @@ -62,7 +62,7 @@ WHERE contents RLIKE('101_67'); SELECT * FROM transfer t -WHERE collection RLIKE('(101_101|101_102|101_103)') +WHERE contents RLIKE('(101_101|101_102|101_103)') ORDER BY id DESC; SELECT * diff --git a/gemp-lotr/db/2024-12-06_rework_transfer_table_and_announcements.sql b/gemp-lotr/db/2024-12-06_rework_transfer_table_and_announcements.sql index b3be87ccd..a8c0480a0 100644 --- a/gemp-lotr/db/2024-12-06_rework_transfer_table_and_announcements.sql +++ b/gemp-lotr/db/2024-12-06_rework_transfer_table_and_announcements.sql @@ -9,15 +9,15 @@ WHERE player = 'wert' SELECT * FROM gemp_db.transfer t -# WHERE collection RLIKE('(101_65|101_66|101_67)') +WHERE collection RLIKE('(101_65|101_66|101_67)') ORDER BY id DESC; -UPDATE transfer -SET notify = TRUE -WHERE id = 5031 +-- UPDATE transfer +-- SET notify = TRUE +-- WHERE id = 5031 -SELECT NOW(), NOW() + INTERVAL 24 HOUR +-- SELECT NOW(), NOW() + INTERVAL 24 HOUR diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/css/gemp-001/game.css b/gemp-lotr/gemp-lotr-async/src/main/web/css/gemp-001/game.css index 8d1155b12..17de559c3 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/css/gemp-001/game.css +++ b/gemp-lotr/gemp-lotr-async/src/main/web/css/gemp-001/game.css @@ -13,6 +13,11 @@ body { color: #A63F03; } +.ui-widget-content a:link, +.msg-content p a:link { + color: #BF6B04; +} + .deckSize { display: table-cell; text-align: center; diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/css/gemp-001/hall.css b/gemp-lotr/gemp-lotr-async/src/main/web/css/gemp-001/hall.css index 3d2512a6e..2374d33f6 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/css/gemp-001/hall.css +++ b/gemp-lotr/gemp-lotr-async/src/main/web/css/gemp-001/hall.css @@ -26,7 +26,7 @@ html, body { a:visited { - color: #A63F03; + color: #BF6B04; } .custom-icon { @@ -215,8 +215,9 @@ button { #buttonsDiv a, #motd a, #infoButtons a, -.msg-content p a { - color: #BF6B04; +.msg-content p a, +#announcement-dialog a { + color: #E88104; } #infoButtons { @@ -827,4 +828,12 @@ table.standings { margin-left: auto; margin-right: auto; padding-bottom: 50px; -} \ No newline at end of file +} + +#announcement-dialog img{ + width:90%; + max-width:600px; + display: block; + margin-left: auto; + margin-right: auto; +} diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/announcementDeliveryService.js b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/announcementDeliveryService.js index f6265528e..e9fe2583f 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/announcementDeliveryService.js +++ b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/announcementDeliveryService.js @@ -31,7 +31,7 @@ function announcementDeliveryService(comm, json) { closeOnEscape:true, close: closeCleanup, resizable:false, - width:$(window).width() * 0.9, + width:800, height:$(window).height() * 0.9, closeText: '' }); diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/setV01/V1_moria.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/setV01/V1_moria.hjson index 83ed58d15..2ff71a217 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/setV01/V1_moria.hjson +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/setV01/V1_moria.hjson @@ -376,18 +376,27 @@ filter: tentacle memorize: woundedTentacle } + + ] + effect: [ { - type: Killed - filter: tentacle - cause: wounds - memorize: woundedTentacle + type: If + check: { + type: HasCardInDiscard + filter: memory(woundedTentacle) + } + true: { + type: StackCardsFromDiscard + select: memory(woundedTentacle) + where: self + } + false: { + type: StackCardsFromPlay + select: memory(woundedTentacle) + where: self + } } ] - effect: { - type: StackCardsFromPlay - select: memory(woundedTentacle) - where: self - } } { type: activated diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/setV02/V2-Isengard.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/setV02/V2-Isengard.hjson index 40aea8e47..af48dfb7c 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/setV02/V2-Isengard.hjson +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/setV02/V2-Isengard.hjson @@ -139,9 +139,10 @@ { type: KilledTrigger optional: true + player: owner requires: { type: CanSpot - filter: self,InSkirmish + filter: RecentlyInSkirmishAgainst(self) } cost: { type: RemoveCultureTokens @@ -151,7 +152,7 @@ } effect: { type: wound - select: choose(companion,inSkirmishAgainst(self)) + select: choose(companion,RecentlyInSkirmishAgainst(self)) } } ] diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/KilledTriggerEffectProcessor.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/KilledTriggerEffectProcessor.java index 3271e51bf..4fdbe24ba 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/KilledTriggerEffectProcessor.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/KilledTriggerEffectProcessor.java @@ -3,18 +3,27 @@ package com.gempukku.lotro.cards.build.field.effect; import com.gempukku.lotro.cards.build.BuiltLotroCardBlueprint; import com.gempukku.lotro.cards.build.CardGenerationEnvironment; import com.gempukku.lotro.cards.build.InvalidCardDefinitionException; +import com.gempukku.lotro.cards.build.PlayerSource; import com.gempukku.lotro.cards.build.field.EffectProcessor; import com.gempukku.lotro.cards.build.field.FieldUtils; +import com.gempukku.lotro.cards.build.field.effect.appender.resolver.PlayerResolver; import org.json.simple.JSONObject; public class KilledTriggerEffectProcessor implements EffectProcessor { @Override public void processEffect(JSONObject value, BuiltLotroCardBlueprint blueprint, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { - FieldUtils.validateAllowedFields(value, "optional", "requires", "cost", "effect"); + FieldUtils.validateAllowedFields(value, "optional", "player", "requires", "cost", "effect"); final boolean optional = FieldUtils.getBoolean(value.get("optional"), "optional", false); + final String player = FieldUtils.getString(value.get("player"), "player"); + PlayerSource playerSource = (player != null) ? PlayerResolver.resolvePlayer(player) : null; + DefaultActionSource triggerActionSource = new DefaultActionSource(); + if (playerSource != null) { + triggerActionSource.setPlayingPlayer(playerSource); + } + EffectUtils.processRequirementsCostsAndEffects(value, environment, triggerActionSource); if (optional) blueprint.setKilledOptionalTriggerAction(triggerActionSource); diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/filter/FilterFactory.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/filter/FilterFactory.java index 8f87d1e2e..24d8b551f 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/filter/FilterFactory.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/filter/FilterFactory.java @@ -414,6 +414,11 @@ public class FilterFactory { final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(parameter, environment); return (actionContext) -> Filters.inSkirmishAgainst(filterableSource.getFilterable(actionContext)); }); + parameterFilters.put("recentlyinskirmishagainst", + (parameter, environment) -> { + final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(parameter, environment); + return (actionContext) -> Filters.recentlyInSkirmishAgainst(filterableSource.getFilterable(actionContext)); + }); parameterFilters.put("inskirmishagainstatleast", (parameter, environment) -> { String[] split = parameter.split(",", 2); diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/filters/Filters.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/filters/Filters.java index 3d3d9d6fc..6ffc0f5bc 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/filters/Filters.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/filters/Filters.java @@ -317,6 +317,18 @@ public class Filters { }; } + public static Filter recentlyInSkirmishAgainst(final Filterable... againstFilter) { + return (game, physicalCard) -> { + Skirmish skirmish = game.getGameState().getSkirmish(); + if (skirmish != null && skirmish.getFellowshipCharacter() != null) { + return (skirmish.getFellowshipCharacter() == physicalCard && (Filters.acceptsAny(game, skirmish.getShadowCharacters(), Filters.and(againstFilter)) || Filters.acceptsAny(game, skirmish.getRemovedFromSkirmish(), Filters.and(againstFilter)))) + || (skirmish.getShadowCharacters().contains(physicalCard) && Filters.and(againstFilter).accepts(game, skirmish.getFellowshipCharacter())); + + } + return false; + }; + } + public static Filter canBeReturnedToHand(final PhysicalCard source) { return (game, physicalCard) -> game.getModifiersQuerying().canBeReturnedToHand(game, physicalCard, source); } diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/collection/CachedTransferDAO.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/collection/CachedTransferDAO.java index 926704eb9..264aec2e9 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/collection/CachedTransferDAO.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/collection/CachedTransferDAO.java @@ -97,7 +97,12 @@ public class CachedTransferDAO implements TransferDAO, Cached { @Override public DBDefs.Announcement getUndeliveredAnnouncement(Player player) { - return _delegate.getUndeliveredAnnouncement(player); + return this.getUndeliveredAnnouncement(player, getCurrentAnnouncement()); + } + + @Override + public DBDefs.Announcement getUndeliveredAnnouncement(Player player, DBDefs.Announcement announcement) { + return _delegate.getUndeliveredAnnouncement(player, announcement); } @Override diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/collection/TransferDAO.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/collection/TransferDAO.java index c7d3eba13..1a493a224 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/collection/TransferDAO.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/collection/TransferDAO.java @@ -18,6 +18,7 @@ public interface TransferDAO { int addTransferFrom(String player, String reason, String collectionName, int currency, CardCollection items); DBDefs.Announcement getUndeliveredAnnouncement(Player player); + DBDefs.Announcement getUndeliveredAnnouncement(Player player, DBDefs.Announcement announcement); DBDefs.Transfer addAnnouncementEntryForPlayer(DBDefs.Announcement announcement, Player player); void dismissAnnouncement(DBDefs.Announcement announcement, Player player); void snoozeAnnouncement(DBDefs.Announcement announcement, Player player); diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/DbTransferDAO.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/DbTransferDAO.java index f3a65db3f..46784b25b 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/DbTransferDAO.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/DbTransferDAO.java @@ -226,8 +226,24 @@ public class DbTransferDAO implements TransferDAO { } catch (Exception ex) { throw new RuntimeException("Unable to get undelivered announcement for player", ex); } + } + @Override + public DBDefs.Announcement getUndeliveredAnnouncement(Player player, DBDefs.Announcement currentAnnouncement) { + try { + if(currentAnnouncement == null) { + currentAnnouncement = getCurrentAnnouncement(); + } + var transferEntry = addAnnouncementEntryForPlayer(currentAnnouncement, player); + if(transferEntry == null || !transferEntry.notify || DateUtils.Now().isBefore(transferEntry.GetUTCDateRecorded())) + return null; + + return currentAnnouncement; + + } catch (Exception ex) { + throw new RuntimeException("Unable to get undelivered announcement for player", ex); + } } @Override diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vsets/set_v01/Card_V1_034_Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vsets/set_v01/Card_V1_034_Tests.java index 3d6ecec30..cd5c7c1ed 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vsets/set_v01/Card_V1_034_Tests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vsets/set_v01/Card_V1_034_Tests.java @@ -2,9 +2,10 @@ package com.gempukku.lotro.cards.unofficial.pc.vsets.set_v01; import com.gempukku.lotro.cards.GenericCardTestHelper; import com.gempukku.lotro.common.*; +import com.gempukku.lotro.filters.Filters; import com.gempukku.lotro.game.CardNotFoundException; -import com.gempukku.lotro.game.PhysicalCardImpl; import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; +import com.gempukku.lotro.logic.modifiers.AddKeywordModifier; import org.junit.Test; import java.util.HashMap; @@ -16,10 +17,12 @@ public class Card_V1_034_Tests protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException { return new GenericCardTestHelper( - new HashMap<>() - {{ - put("card", "101_34"); - // put other cards in here as needed for the test case + new HashMap<>() {{ + put("darkwaters", "101_34"); + put("tentacle1", "2_58"); + put("tentacle2", "2_66"); + put("song", "3_5"); + put("greenleaf", "1_50"); }}, GenericCardTestHelper.FellowshipSites, GenericCardTestHelper.FOTRFrodo, @@ -46,7 +49,7 @@ public class Card_V1_034_Tests var scn = GetScenario(); - var card = scn.GetFreepsCard("card"); + var card = scn.GetFreepsCard("darkwaters"); assertEquals("Out of Dark Waters", card.getBlueprint().getTitle()); assertNull(card.getBlueprint().getSubtitle()); @@ -58,18 +61,95 @@ public class Card_V1_034_Tests assertEquals(1, card.getBlueprint().getTwilightCost()); } - // Uncomment any @Test markers below once this is ready to be used - //@Test - public void OutofDarkWatersTest1() throws DecisionResultInvalidException, CardNotFoundException { + @Test + public void DarkWatersStacksWoundedTentacles() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - var scn = GetScenario(); + GenericCardTestHelper scn = GetScenario(); - var card = scn.GetFreepsCard("card"); - scn.FreepsMoveCardToHand(card); + var darkwaters = scn.GetShadowCard("darkwaters"); + var tentacle2 = scn.GetShadowCard("tentacle2"); + scn.ShadowMoveCardToSupportArea(darkwaters); + scn.ShadowMoveCardToHand(tentacle2); + + scn.FreepsMoveCharToTable("greenleaf"); scn.StartGame(); - scn.FreepsPlayCard(card); + scn.SetTwilight(4); + scn.ApplyAdHocModifier(new AddKeywordModifier(null, Filters.siteNumber(2), null, Keyword.MARSH)); + scn.FreepsPassCurrentPhaseAction(); + + scn.ShadowPlayCard(tentacle2); + + assertEquals(0, scn.getWounds(tentacle2)); + assertEquals(Zone.SHADOW_CHARACTERS, tentacle2.getZone()); + + scn.SkipToPhase(Phase.ARCHERY); + scn.PassCurrentPhaseActions(); + + assertEquals(1, scn.getWounds(tentacle2)); + assertTrue(scn.ShadowHasOptionalTriggerAvailable()); + scn.ShadowAcceptOptionalTrigger(); + + assertEquals(Zone.STACKED, tentacle2.getZone()); + assertEquals(darkwaters, tentacle2.getStackedOn()); + } + + @Test + public void DarkWatersStacksTentaclesKilledByWound() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + var darkwaters = scn.GetShadowCard("darkwaters"); + var tentacle1 = scn.GetShadowCard("tentacle1"); + scn.ShadowMoveCardToSupportArea(darkwaters); + scn.ShadowMoveCardToHand(tentacle1); + + scn.FreepsMoveCharToTable("greenleaf"); + + scn.StartGame(); + scn.SetTwilight(4); + scn.ApplyAdHocModifier(new AddKeywordModifier(null, Filters.siteNumber(2), null, Keyword.MARSH)); + scn.FreepsPassCurrentPhaseAction(); + + scn.ShadowPlayCard(tentacle1); + + assertEquals(Zone.SHADOW_CHARACTERS, tentacle1.getZone()); + + scn.SkipToPhase(Phase.ARCHERY); + scn.PassCurrentPhaseActions(); + + assertTrue(scn.ShadowHasOptionalTriggerAvailable()); + scn.ShadowAcceptOptionalTrigger(); + + assertEquals(Zone.STACKED, tentacle1.getZone()); + assertEquals(darkwaters, tentacle1.getStackedOn()); + } + + + @Test + public void DarkWatersCanBurn2AStackedTentaclesToPreventSelfDiscard() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + var song = scn.GetFreepsCard("song"); + scn.FreepsMoveCardToSupportArea(song); + + var darkwaters = scn.GetShadowCard("darkwaters"); + var tentacle1 = scn.GetShadowCard("tentacle1"); + var tentacle2 = scn.GetShadowCard("tentacle2"); + scn.ShadowMoveCardToSupportArea(darkwaters); + //scn.ShadowMoveCardToHand(tentacle1, tentacle2); + + scn.StartGame(); + scn.StackCardsOn(darkwaters, tentacle1, tentacle2); + + scn.FreepsUseCardAction(song); + scn.FreepsChooseCard(darkwaters); + assertTrue(scn.ShadowHasOptionalTriggerAvailable()); + scn.ShadowAcceptOptionalTrigger(); + assertEquals(Zone.DISCARD, tentacle1.getZone()); + assertEquals(Zone.DISCARD, tentacle2.getZone()); + assertEquals(Zone.SUPPORT, darkwaters.getZone()); - assertEquals(1, scn.GetTwilight()); } } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vsets/set_v02/Card_V2_020_Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vsets/set_v02/Card_V2_020_Tests.java index f13918ddf..19852fba5 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vsets/set_v02/Card_V2_020_Tests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vsets/set_v02/Card_V2_020_Tests.java @@ -3,7 +3,6 @@ package com.gempukku.lotro.cards.unofficial.pc.vsets.set_v02; import com.gempukku.lotro.cards.GenericCardTestHelper; import com.gempukku.lotro.common.*; import com.gempukku.lotro.game.CardNotFoundException; -import com.gempukku.lotro.game.PhysicalCardImpl; import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; import org.junit.Test; @@ -18,8 +17,11 @@ public class Card_V2_020_Tests return new GenericCardTestHelper( new HashMap<>() {{ - put("card", "102_20"); - // put other cards in here as needed for the test case + put("fanatic", "102_20"); + put("savage", "1_151"); + put("machine", "5_60"); + + put("treebeard", "10_18"); }}, GenericCardTestHelper.FellowshipSites, GenericCardTestHelper.FOTRFrodo, @@ -49,7 +51,7 @@ public class Card_V2_020_Tests var scn = GetScenario(); - var card = scn.GetFreepsCard("card"); + var card = scn.GetFreepsCard("fanatic"); assertEquals("Berserk Fanatic", card.getBlueprint().getTitle()); assertNull(card.getBlueprint().getSubtitle()); @@ -66,18 +68,71 @@ public class Card_V2_020_Tests assertEquals(5, card.getBlueprint().getSiteNumber()); } - // Uncomment any @Test markers below once this is ready to be used - //@Test - public void BerserkFanaticTest1() throws DecisionResultInvalidException, CardNotFoundException { + @Test + public void BerserkFanaticIsStrenghtPlus1ForEachWoundOnEachCharacterInSkirmish() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup var scn = GetScenario(); - var card = scn.GetFreepsCard("card"); - scn.FreepsMoveCardToHand(card); + var fanatic = scn.GetShadowCard("fanatic"); + var savage = scn.GetShadowCard("savage"); + var machine = scn.GetShadowCard("machine"); + scn.ShadowMoveCharToTable(fanatic, savage); + scn.ShadowMoveCardToSupportArea(machine); + + var frodo = scn.GetRingBearer(); scn.StartGame(); - scn.FreepsPlayCard(card); - assertEquals(3, scn.GetTwilight()); + scn.addWounds(frodo, 1); + scn.addWounds(fanatic, 1); + scn.addWounds(savage, 1); + + //not in skirmish, should be base + assertEquals(8, scn.getStrength(fanatic)); + + scn.SkipToAssignments(); + scn.FreepsDeclineAssignments(); + scn.ShadowAssignToMinions(frodo, fanatic, savage); + scn.FreepsResolveSkirmish(frodo); + + //Base strength of 8, +1 strength for the single wound on each of itself, the savage, and frodo + assertEquals(11, scn.getStrength(fanatic)); + } + + @Test + public void BerserkFanaticDyingInSkirmishCanRemove2TokensFromMachineToWoundSkirmisher() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + var scn = GetScenario(); + + var fanatic = scn.GetShadowCard("fanatic"); + var machine = scn.GetShadowCard("machine"); + scn.ShadowMoveCharToTable(fanatic); + scn.ShadowMoveCardToSupportArea(machine); + + var treebeard = scn.GetFreepsCard("treebeard"); + scn.FreepsMoveCharToTable(treebeard); + + scn.StartGame(); + + scn.addWounds(fanatic, 2); + scn.AddTokensToCard(machine, 2); + + scn.SkipToAssignments(); + scn.FreepsAssignToMinions(treebeard, fanatic); + scn.FreepsResolveSkirmish(treebeard); + + assertEquals(1, scn.GetVitality(fanatic)); + assertEquals(0, scn.GetWoundsOn(treebeard)); + assertEquals(2, scn.GetCultureTokensOn(machine)); + assertEquals(Zone.SHADOW_CHARACTERS, fanatic.getZone()); + + scn.PassCurrentPhaseActions(); + + assertTrue(scn.ShadowHasOptionalTriggerAvailable()); + scn.ShadowAcceptOptionalTrigger(); + + assertEquals(1, scn.GetWoundsOn(treebeard)); + assertEquals(0, scn.GetCultureTokensOn(machine)); + assertEquals(Zone.DISCARD, fanatic.getZone()); } } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vsets/set_v02/Card_V2_048_Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vsets/set_v02/Card_V2_048_Tests.java index 50a5c8b8c..8e985e975 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vsets/set_v02/Card_V2_048_Tests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vsets/set_v02/Card_V2_048_Tests.java @@ -1,9 +1,11 @@ package com.gempukku.lotro.cards.unofficial.pc.vsets.set_v02; import com.gempukku.lotro.cards.GenericCardTestHelper; -import com.gempukku.lotro.common.*; +import com.gempukku.lotro.common.CardType; +import com.gempukku.lotro.common.Culture; +import com.gempukku.lotro.common.Keyword; +import com.gempukku.lotro.common.Side; import com.gempukku.lotro.game.CardNotFoundException; -import com.gempukku.lotro.game.PhysicalCardImpl; import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; import org.junit.Test; @@ -49,7 +51,7 @@ public class Card_V2_048_Tests assertEquals("Stronghold of My Fathers", card.getBlueprint().getTitle()); assertNull(card.getBlueprint().getSubtitle()); - assertFalse(card.getBlueprint().isUnique()); + assertTrue(card.getBlueprint().isUnique()); assertEquals(Side.FREE_PEOPLE, card.getBlueprint().getSide()); assertEquals(Culture.ROHAN, card.getBlueprint().getCulture()); assertEquals(CardType.POSSESSION, card.getBlueprint().getCardType());