Skip to content

CardState: move IntrinsicSpell into LandTraitChanges - #11631

Draft
Hanmac wants to merge 2 commits into
masterfrom
LandTraitChangesCacheV2
Draft

CardState: move IntrinsicSpell into LandTraitChanges#11631
Hanmac wants to merge 2 commits into
masterfrom
LandTraitChangesCacheV2

Conversation

@Hanmac

@Hanmac Hanmac commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Part of #11409

kinda cleanup before Cache are added

i try to make each of them "before changes" - "changes" - "after rules" more uniform
See this comment: #11409 (comment)

Comment thread forge-game/src/main/java/forge/game/card/CardState.java Outdated

@tool4ever tool4ever left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

feels like the logic flow gets a bit harder to follow now 🤔

can't we do something a bit more radical and try to avoid all rulesHost stuff:
just have getReplacementList() add them on demand?

a bit like getHiddenStaticAbilities() but the big bonus is we might be able to reuse a single instance of adventureRep/omen... for the whole game 🏎️
(because all of them can just use ReplacedCard instead of Self)

@Hanmac

Hanmac commented Aug 17, 2026

Copy link
Copy Markdown
Contributor Author

feels like the logic flow gets a bit harder to follow now 🤔

can't we do something a bit more radical and try to avoid all rulesHost stuff: just have getReplacementList() add them on demand?

a bit like getHiddenStaticAbilities() but the big bonus is we might be able to reuse a single instance of adventureRep/omen... for the whole game 🏎️ (because all of them can just use ReplacedCard instead of Self)

Maybe for later MRs.

The Counter Based ones are still excluded by the rulesHost check:

public void updateReplacementEffects(List<ReplacementEffect> list, CardState state, boolean rulesHost) {
for (final ICardTraitChanges ck : getChangedCardTraitsList(state)) {
ck.applyReplacementEffect(list);
}
// Keywords are already sorted by Layer
getUnhiddenKeywords(state).applyReplacementEffect(list);
if (!rulesHost) {
return;
}

i also wanted to move these special ones:

if (isInPlay()) {
if (isFaceDown() && state.getStateName() == CardStateName.FaceDown) {
for (SpellAbility sa : getState(CardStateName.Original).getNonManaAbilities()) {
if (sa.isTurnFaceUp()) {
list.add(sa);
}
}
}
} else if (hasState(CardStateName.Secondary) && state.getStateName() == CardStateName.Original) {
// Adventure and Omen may only be cast not from Battlefield
list.addAll(getState(CardStateName.Secondary).getSpellAbilities());
}

into getAllPossibleAbilities, there:

if (isInPlay() && isFaceDown() && oState.getType().isCreature() && oState.getManaCost() != null && !oState.getManaCost().isNoCost())
{
if (isManifested()) {
abilities.add(oState.getManifestUp());
}
if (isCloaked()) {
abilities.add(oState.getCloakUp());
}
}

so we don't need to exclude them anymore when checking for hasNoAbilities:

if (sa.isMorphUp() || sa.isDisguiseUp()) {
continue;
}
// while Adventure and Omen are part of Secondary
if ((sa.isAdventure() || sa.isOmen()) && !getCurrentStateName().equals(sa.getCardStateName())) {
continue;
}

but then the Tests does fail, because it can't find them anymore:

SpellAbility unmorphSA = findSAWithPrefix(ripper, "Morph — Reveal a black card");
AssertJUnit.assertNotNull(unmorphSA);
sim.simulateSpellAbility(unmorphSA);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants