Card: add CounterKeywordStatic

This commit is contained in:
Hans Mackowiak
2025-04-11 07:13:12 +02:00
parent 41fc4e5041
commit c91d7263d8
3 changed files with 44 additions and 69 deletions

View File

@@ -172,7 +172,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars, ITr
// don't use Enum Set Values or it causes a slow down
private final Multimap<Long, Keyword> cantHaveKeywords = MultimapBuilder.hashKeys().hashSetValues().build();
private final Map<CounterType, Long> counterTypeTimestamps = Maps.newHashMap();
private final Map<CounterType, StaticAbility> counterTypeKeywordStatic = Maps.newHashMap();
private final Map<Long, Integer> canBlockAdditional = Maps.newTreeMap();
private final Set<Long> canBlockAny = Sets.newHashSet();
@@ -1817,9 +1817,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars, ITr
getGame().addCounterAddedThisTurn(source, counterType, this, addAmount);
view.updateCounters(this);
}
if (newValue <= 0) {
removeCounterTimestamp(counterType);
} else if (addCounterTimestamp(counterType, false)) {
if (createCounterStatic(counterType)) {
updateKeywords();
}
if (table != null) {
@@ -1827,57 +1825,31 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars, ITr
}
}
public boolean addCounterTimestamp(CounterType counterType) {
return addCounterTimestamp(counterType, true);
}
public boolean addCounterTimestamp(CounterType counterType, boolean updateView) {
public boolean createCounterStatic(CounterType counterType) {
StaticAbility result;
if (counterType.is(CounterEnumType.MANABOND)) {
removeCounterTimestamp(counterType);
result = counterTypeKeywordStatic.computeIfAbsent(counterType, ct -> {
String s = "Mode$ Continuous | AffectedDefined$ Self | AddType$ Land | RemoveCardTypes$ True | RemoveSubTypes$ True | RemoveAllAbilities$ True | AddAbility$ ManaReflected";
StaticAbility stAb = StaticAbility.create(s, this, currentState, true);
String abStr = "AB$ ManaReflected | Cost$ T | Valid$ Defined.Self | ColorOrType$ Color | ReflectProperty$ Is | SpellDescription$ Add one mana of any of this card's colors.";
stAb.setSVar("ManaReflected", abStr);
return stAb;
});
} else if (counterType.isKeywordCounter()) {
result = counterTypeKeywordStatic.computeIfAbsent(counterType, ct -> {
return StaticAbility.create("Mode$ Continuous | AffectedDefined$ Self | AddKeyword$ " + ct.toString(), this, currentState, true);
});
long timestamp = game.getNextTimestamp();
counterTypeTimestamps.put(counterType, timestamp);
// becomes land in instead of other card types
addChangedCardTypes(new CardType(ImmutableList.of("Land"), false), null, false,
EnumSet.of(RemoveType.CardTypes, RemoveType.SubTypes),
timestamp, 0, updateView, false);
String abStr = "AB$ ManaReflected | Cost$ T | Valid$ Defined.Self | ColorOrType$ Color | ReflectProperty$ Is | SpellDescription$ Add one mana of any of this card's colors.";
SpellAbility sa = AbilityFactory.getAbility(abStr, this);
sa.setIntrinsic(false);
addChangedCardTraits(ImmutableList.of(sa), null, null, null, null, true, false, timestamp, 0);
return true;
}
if (!counterType.isKeywordCounter()) {
if (!Keyword.smartValueOf(counterType.toString().split(":")[0]).isMultipleRedundant()) {
result.putParam("KeywordMultiplier", String.valueOf(getCounters(counterType)));
}
} else {
return false;
}
removeCounterTimestamp(counterType);
long timestamp = game.getNextTimestamp();
counterTypeTimestamps.put(counterType, timestamp);
int num = 1;
if (!Keyword.smartValueOf(counterType.toString().split(":")[0]).isMultipleRedundant()) {
num = getCounters(counterType);
}
addChangedCardKeywords(Collections.nCopies(num, counterType.toString()), null, false, timestamp, null, updateView);
result.putParam("Timestamp", String.valueOf(game.getNextTimestamp()));
return true;
}
public boolean removeCounterTimestamp(CounterType counterType) {
return removeCounterTimestamp(counterType, true);
}
public boolean removeCounterTimestamp(CounterType counterType, boolean updateView) {
Long old = counterTypeTimestamps.remove(counterType);
if (old != null) {
removeChangedCardTypes(old, 0, updateView);
removeChangedCardTraits(old, 0);
removeChangedCardKeywords(old, 0, updateView);
}
return old != null;
}
@Override
public final int subtractCounter(final CounterType counterName, final int n, final Player remover) {
return subtractCounter(counterName, n, remover, false);
@@ -1917,10 +1889,8 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars, ITr
setCounters(counterName, newValue);
view.updateCounters(this);
if (newValue <= 0) {
if (removeCounterTimestamp(counterName, false)) {
updateKeywords();
}
if (newValue <= 0 && (counterName.is(CounterEnumType.MANABOND) || counterName.isKeywordCounter())) {
updateKeywords();
}
//fire card stats changed event if p/t bonuses or loyalty changed from subtracted counters
@@ -1951,18 +1921,15 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars, ITr
@Override
public final void setCounters(final Map<CounterType, Integer> allCounters) {
boolean changed = false;
for (CounterType ct : counters.keySet()) {
if (removeCounterTimestamp(ct, false)) {
changed = true;
}
}
boolean changed = counters.containsKey(CounterEnumType.MANABOND) || counters.keySet().stream().allMatch(CounterType::isKeywordCounter);
counters = allCounters;
view.updateCounters(this);
for (CounterType ct : counters.keySet()) {
if (addCounterTimestamp(ct, false)) {
changed = true;
if (!isLKI()) {
for (CounterType ct : counters.keySet()) {
if (createCounterStatic(ct)) {
changed = true;
}
}
}
if (changed) {
@@ -1973,15 +1940,11 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars, ITr
@Override
public final void clearCounters() {
if (counters.isEmpty()) { return; }
boolean changed = counters.containsKey(CounterEnumType.MANABOND) || counters.keySet().stream().allMatch(CounterType::isKeywordCounter);
counters.clear();
view.updateCounters(this);
boolean changed = false;
for (CounterType ct : Lists.newArrayList(counterTypeTimestamps.keySet())) {
if (removeCounterTimestamp(ct, false)) {
changed = true;
}
}
if (changed) {
updateKeywords();
}
@@ -7291,6 +7254,11 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars, ITr
if (this.isInPlay() && this.isSuspected()) {
result.add(suspectedStatic);
}
for (Map.Entry<CounterType, StaticAbility> e : this.counterTypeKeywordStatic.entrySet()) {
if (this.getCounters(e.getKey()) > 0) {
result.add(e.getValue());
}
}
return result;
}
@@ -8384,5 +8352,9 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars, ITr
setChangedCardTraitsByText(in.getChangedCardTraitsByText());
setChangedCardKeywordsByText(in.getChangedCardKeywordsByText());
for (Map.Entry<CounterType, StaticAbility> e : in.counterTypeKeywordStatic.entrySet()) {
this.counterTypeKeywordStatic.put(e.getKey(), e.getValue().copy(this, true));
}
}
}

View File

@@ -301,6 +301,7 @@ public class CardCopyService {
// extra copy PT boost
newCopy.setPTBoost(copyFrom.getPTBoostTable());
newCopy.copyFrom(copyFrom);
newCopy.setCounters(Maps.newHashMap(copyFrom.getCounters()));
newCopy.setColor(copyFrom.getColor());
@@ -352,8 +353,6 @@ public class CardCopyService {
}
newCopy.setChosenEvenOdd(copyFrom.getChosenEvenOdd());
newCopy.copyFrom(copyFrom);
// for getReplacementList (run after setChangedCardKeywords for caching)
newCopy.setStoredKeywords(copyFrom.getStoredKeywords(), true);
newCopy.setStoredReplacements(copyFrom.getStoredReplacements());

View File

@@ -725,6 +725,10 @@ public final class StaticAbilityContinuous {
}).collect(Collectors.toList());
}
if (newKeywords != null && !newKeywords.isEmpty() && params.containsKey("KeywordMultiplier")) {
newKeywords = newKeywords.stream().flatMap(s -> Collections.nCopies(Integer.valueOf(params.get("KeywordMultiplier")), s).stream()).collect(Collectors.toList());
}
affectedCard.addChangedCardKeywords(newKeywords, removeKeywords,
removeAllAbilities, se.getTimestamp(), stAb, false);
affectedCard.updateKeywordsCache(affectedCard.getCurrentState());