-
Notifications
You must be signed in to change notification settings - Fork 786
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unbound Flourishing's X doubling should be a triggered ability (and related refactors) #12597
Conversation
Spell spell = game.getStack().getSpell(event.getTargetId()); | ||
if (spell != null && spell.isPermanent(game)) { | ||
if (spell.getSpellAbility().getManaCostsToPay().containsX()) { | ||
game.getState().setValue(this.getSourceId() + UnboundFlourishing.needPrefix, spell); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make sure it support multiple triggers/spells. Current code save only one spell per Unbound Flourishing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. I copied it from the copy spell/ability trigger, both of them need to be fixed in that manner.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also don't forget about flourishing ZCC in setValue. So blinked Unbound Flourishing will ignore outdated spell data.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A better solution is to not use the global game state, and instead use target pointers or the effect value map.
…pointer activated ability triggers
Haven't done as much testing with the changes as I'd like so probably best not to merge quite yet, but I think this is all good now. |
@@ -82,6 +83,7 @@ public boolean counter(UUID objectId, Ability source, Game game, PutCards putCar | |||
if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.COUNTER, objectId, source, stackObject.getControllerId()))) { | |||
if (!(stackObject instanceof Spell)) { // spells are removed from stack by the card movement | |||
this.remove(stackObject, game); | |||
game.rememberLKI(Zone.STACK, stackObject); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
interesting
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is required by the test I added - previously it was storing the entire object inside the effect which made it ok to not store it in LKI, but now that I changed it to use a FixedTarget I needed the LKI there.
if (ability.checkEventType(event, game) && ability.checkTrigger(event, game)) { | ||
toRet = true; | ||
} | ||
ability.getEffects().clear(); //Remove afterwards, ensures that they remain synced even with copying |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Though this feels a bit weird, I think I see what this is trying to do and why it can't be done otherwise
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That’s code with effects copy must be removed 100%. Conditional abilities from “or” parts must have all real effects. If something put effects in “or” ability (e.g. abilities container) then that’s wrong logic/design.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any triggered ability that has SetTargetPointer
needs this code to function correctly, as otherwise that inner ability has no access to the effects it's trying to set the target pointers of.
edit: It's also important to note that this isn't copying the effects, it's sharing the effects that are currently inside the OrTriggeredAbility
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It’s weird. Whole OrTriggeredAbility is big workaround with potentially buggy code (example: if something clear/reset data inside triggered ability or init something then it will be broken with that “container”). Must be reworked/removed someday to simple ability with multiple conditionals.
So new part for temporary add/remove is “fine” here — it’s a fix for existing logic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only 53 usages of OrTriggeredAbility. How many of them need target pointers set in order to function? Seems like the sort of thing that could be excluded from scope, with those few usages getting cleaner custom implementations
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ssk97 must be improved, also contains suspected code (see comments).
Mage/src/main/java/mage/abilities/effects/common/CopyStackObjectEffect.java
Show resolved
Hide resolved
if (ability.checkEventType(event, game) && ability.checkTrigger(event, game)) { | ||
toRet = true; | ||
} | ||
ability.getEffects().clear(); //Remove afterwards, ensures that they remain synced even with copying |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That’s code with effects copy must be removed 100%. Conditional abilities from “or” parts must have all real effects. If something put effects in “or” ability (e.g. abilities container) then that’s wrong logic/design.
Mage/src/main/java/mage/filter/predicate/other/AbilitySourceAttachedPredicate.java
Show resolved
Hide resolved
if (!(input instanceof Ability)) { | ||
return false; | ||
} | ||
return !((Ability) input).isManaAbility(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks strange. Mana abilities never goes to stack due mtg rules. So it’s useless to search stack objects for it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Huh, that's a good point. If I understand correctly, that means that FilterActivatedOrTriggeredAbility
just automatically includes the "not a mana ability" clause by its very design?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, before this it was only being used for targeting
The abilities normally will not have any effects, the |
Note the "Whenever" in the rules text, it's a triggered ability and not a replacement effect.
Since Unbound Flourishing was the only card to use the
X_MANA_ANNOUNCE
event and all the associated multiplier code, that should probably all also be removed as well? Leaving this as a draft while I figure out what should be removed there.edit: now also include a rework of "copy that ability" effects to use the stack/LKI instead of a saved object