Page 1 of 6

Mulitstate cards test drive

PostPosted: 20 Oct 2011, 21:53
by Hellfish
EDIT: Screw preservation.

Take 2, this time with Characteristics!
The way it works this time is that a Card can have one OR two CardCharacteristic objects. These objects contain Name, Type, ManaCost and everything else that would change between states of multistate cards. Card.getName(),getType() etc. all delegate to the currently active CardCharacteristic object. No more swapping cards in and out of the game, all that happens now is an Integer changes 1->0 or 0->. :)

I'd like you to keep an especially close eye on Copy/Clone effects on Flip or Doublefaced cards. Also try the Deck Editor. :D

Patch (for r11379,): http://www.mediafire.com/?a1hb6yydhlsa3jg

Awww yeah, full archive incoming! 8)
http://www.mediafire.com/?jjfjj5u6lzli6jb

UPDATE:Fixes unblocked attackers crash.

Obviously, please keep bug reports in this thread. :)

Re: Mulitstate cards test drive

PostPosted: 20 Oct 2011, 21:55
by jeffwadsworth
WOOT!! Never thought I would see anything done on this one.

Re: Mulitstate cards test drive

PostPosted: 20 Oct 2011, 22:04
by Hellfish
It's not out of the woods yet, it's gotta survive THE TWO TRIALS OF USABILITY AND MAINTAINABILITY! (ominous echo)

Re: Mulitstate cards test drive

PostPosted: 20 Oct 2011, 22:45
by jeffwadsworth
Screeching Bats transforms into Stalking Vampire. It has summoning sickness. To my knowledge, it should not.

Playing with Kenzo the Hardhearted that was correctly flipped following it delivering damage to a creature that died on the previous turn. I attacked with it and was blocked by an Ancient Hydra. This error popped up:

| Open
java.lang.NullPointerException
at forge.card.MultiStateHandler.changeState(MultiStateHandler.java:74)
at forge.card.abilityFactory.AbilityFactory_ChangeState.changeStateResolve(AbilityFactory_ChangeState.java:82)
at forge.card.abilityFactory.AbilityFactory_ChangeState.access$0(AbilityFactory_ChangeState.java:66)
at forge.card.abilityFactory.AbilityFactory_ChangeState$1.resolve(AbilityFactory_ChangeState.java:24)
at forge.card.abilityFactory.AbilityFactory.resolve(AbilityFactory.java:2152)
at forge.card.spellability.SpellAbility_Requirements.finishPaying(SpellAbility_Requirements.java:141)
at forge.card.cost.Cost_Payment.payCost(Cost_Payment.java:160)
at forge.card.spellability.SpellAbility_Requirements.startPaying(SpellAbility_Requirements.java:132)
at forge.card.spellability.SpellAbility_Requirements.needPayment(SpellAbility_Requirements.java:121)
at forge.card.spellability.SpellAbility_Requirements.fillRequirements(SpellAbility_Requirements.java:92)
at forge.GameAction.playSpellAbility_NoStack(GameAction.java:2281)
at forge.card.trigger.TriggerHandler$2.resolve(TriggerHandler.java:994)
at forge.card.abilityFactory.AbilityFactory.resolve(AbilityFactory.java:2152)
at forge.MagicStack.resolveStack(MagicStack.java:780)
at forge.Phase.passPriority(Phase.java:686)
at forge.ComputerAI_General.stackResponse(ComputerAI_General.java:473)
at forge.ComputerAI_General.stack_not_empty(ComputerAI_General.java:417)
at forge.gui.input.InputControl.updateInput(InputControl.java:200)
at forge.GuiInput.update(GuiInput.java:30)
at java.util.Observable.notifyObservers(Unknown Source)
at java.util.Observable.notifyObservers(Unknown Source)
at forge.MyObservable.updateObservers(MyObservable.java:17)
at forge.gui.input.InputControl.resetInput(InputControl.java:106)
at forge.Phase.passPriority(Phase.java:677)
at forge.gui.input.Input_PassPriority.selectButtonOK(Input_PassPriority.java:46)
at forge.GuiInput.selectButtonOK(GuiInput.java:57)
at forge.GuiDisplay4.okButtonActionPerformed(GuiDisplay4.java:1405)
at forge.GuiDisplay4.access$25(GuiDisplay4.java:1404)
at forge.GuiDisplay4$33.actionPerformed(GuiDisplay4.java:1142)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$000(Unknown Source)
at java.awt.EventQueue$1.run(Unknown Source)
at java.awt.EventQueue$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue$2.run(Unknown Source)
at java.awt.EventQueue$2.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)

Re: Mulitstate cards test drive

PostPosted: 21 Oct 2011, 08:19
by Hellfish
Thanks,Jeff. Fixed those two, here's a new patch (for r11320)
EDIT: Removed link, newer patch forthcoming which fixes changing state during combat.
EDIT: <see first post>
Includes Cloistered Youth / Unholy Fiend and AF_ChangeStateAll and Moonmist.

EDIT:Will keep patch updates in the first post.

Re: Mulitstate cards test drive

PostPosted: 21 Oct 2011, 12:21
by Hellfish
New patch, see first post.
Added condition parameters for use with ISD Werewolves. Added Gatstaf Shepherd / Gatstaf Howler as an example. Alternate state card images now work.

Re: Mulitstate cards test drive

PostPosted: 21 Oct 2011, 15:10
by jeffwadsworth
I believe Moonmist should be an effect. Right now, it affects cards that were present when it was cast. Anything new to the battlefield is not affected.

My creature Gatstaf Howler. During the opponents upkeep, its transform trigger hit the stack due to my casting 2 spells during my turn. This error occurred.

| Open
This is a Crash Report. An error has occurred. Please save this message to a file.
Please follow the instructions at this address to submit this Crash Report, plus what you were doing at the time:
http://tinyurl.com/3zzrnyb
Reporting bugs in Forge is very important. We thank you for your time.

null


Version:
Forge version SVN, build ID Unknown

OS: Windows 7 Version: 6.1 Architecture: x86

Java Version: 1.6.0_27 Vendor: Sun Microsystems Inc.

Detailed error trace:
java.lang.NullPointerException
at forge.card.MultiStateHandler.changeState(MultiStateHandler.java:90)
at forge.card.abilityFactory.AbilityFactory_ChangeState.changeStateResolve(AbilityFactory_ChangeState.java:107)
at forge.card.abilityFactory.AbilityFactory_ChangeState.access$0(AbilityFactory_ChangeState.java:86)
at forge.card.abilityFactory.AbilityFactory_ChangeState$1.resolve(AbilityFactory_ChangeState.java:31)
at forge.card.abilityFactory.AbilityFactory.resolve(AbilityFactory.java:2170)
at forge.card.spellability.SpellAbility_Requirements.finishPaying(SpellAbility_Requirements.java:141)
at forge.card.cost.Cost_Payment.payCost(Cost_Payment.java:160)
at forge.card.spellability.SpellAbility_Requirements.startPaying(SpellAbility_Requirements.java:132)
at forge.card.spellability.SpellAbility_Requirements.needPayment(SpellAbility_Requirements.java:121)
at forge.card.spellability.SpellAbility_Requirements.fillRequirements(SpellAbility_Requirements.java:92)
at forge.GameAction.playSpellAbility_NoStack(GameAction.java:2281)
at forge.card.trigger.TriggerHandler$2.resolve(TriggerHandler.java:994)
at forge.card.abilityFactory.AbilityFactory.resolve(AbilityFactory.java:2170)
at forge.MagicStack.resolveStack(MagicStack.java:781)
at forge.Phase.passPriority(Phase.java:685)
at forge.ComputerAI_General.stackResponse(ComputerAI_General.java:473)
at forge.ComputerAI_General.stack_not_empty(ComputerAI_General.java:417)
at forge.gui.input.InputControl.updateInput(InputControl.java:200)
at forge.GuiInput.update(GuiInput.java:30)
at java.util.Observable.notifyObservers(Unknown Source)
at java.util.Observable.notifyObservers(Unknown Source)
at forge.MyObservable.updateObservers(MyObservable.java:17)
at forge.gui.input.InputControl.resetInput(InputControl.java:106)
at forge.Phase.passPriority(Phase.java:676)
at forge.gui.input.Input_PassPriority.selectButtonOK(Input_PassPriority.java:46)
at forge.GuiInput.selectButtonOK(GuiInput.java:57)
at forge.GuiDisplay4.okButtonActionPerformed(GuiDisplay4.java:1405)
at forge.GuiDisplay4.access$25(GuiDisplay4.java:1404)
at forge.GuiDisplay4$33.actionPerformed(GuiDisplay4.java:1142)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$000(Unknown Source)
at java.awt.EventQueue$1.run(Unknown Source)
at java.awt.EventQueue$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue$2.run(Unknown Source)
at java.awt.EventQueue$2.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)


Unholy Fiend. You should only lose 1 life during your end step. Right now, you lose it on your opponents end step also.

Test game with Soul Foundry and Gatstaf Shepard. Imprinted Gatstaf Shepard with Soul Foundry. The transform trigger hits the stack and fizzles on resolution. Gatstaf Shepard does not transform.

Re: Mulitstate cards test drive

PostPosted: 21 Oct 2011, 16:38
by Hellfish
Re: The Soul Foundry bit.
Copies of DFC cards only copy the state that was active at the time, and can't transform since they aren't actual double-faced card. This is according to extra rulings made.

I will look into your other points. Thanks!

Re: Mulitstate cards test drive

PostPosted: 21 Oct 2011, 18:17
by Sloth
I've looked at the code Hellfish and I think it would be better to not create a new card object when the card transforms. All the swapping of cards for targets and combat would have to be done for other things like remembered, receivedDamageFromThisTurn, dealtDamageToThisTurn, assignedDamageMap, gainControlTargets, equipping, ... and most importantly for things that we might add in the future.

Isn't it easier to just overwrite the Name, type, P/T and other printed stuff?

Re: Mulitstate cards test drive

PostPosted: 21 Oct 2011, 18:29
by Hellfish
It doesn't create a new card object on transform, it swaps in a preexisting card object. But that's beside the point.

I can modify this method to overwrite characteristics with the alternate's values instead.Occam's Razor and all that. ;)
I'll give it a whirl!

EDIT: One problem I see with it is that keywords handled in postFactoryKeywords wouldn't function correctly if the keyword list is simply swapped in.

Re: Mulitstate cards test drive

PostPosted: 21 Oct 2011, 19:10
by Sloth
Hellfish wrote:EDIT: One problem I see with it is that keywords handled in postFactoryKeywords wouldn't function correctly if the keyword list is simply swapped in.
Well those are only for printed keywords, are there any transforming cards with one of those?

Re: Mulitstate cards test drive

PostPosted: 21 Oct 2011, 19:37
by Hellfish
Hmm, there is not.There could be,though, in Dark Ascension or Roll.

And that's not considering Custom cards.

Re: Mulitstate cards test drive

PostPosted: 21 Oct 2011, 19:54
by Sloth
Hellfish wrote:Hmm, there is not.There could be,though, in Dark Ascension or Roll.

And that's not considering Custom cards.
I'm not so happy about these keywords anyway. If Flashback would be read during runtime Snapcaster Mage and Past in Flames would be scriptable. Fortunately a lot of them are just shortcuts for triggered, activated or static abilities that can always be written out if necessary (Graft, Modular, Provoke, etc.).

Re: Mulitstate cards test drive

PostPosted: 22 Oct 2011, 07:45
by Milod
some1 explain where this .text patch file gos and where wat to copy exacly? i want test it

Re: Mulitstate cards test drive

PostPosted: 22 Oct 2011, 08:57
by Hellfish
Last patch for right now, still using the Card-swapping system. Addresses Multistate planeswalkers, adds Garruk Relentless / Garruk, the Veil-Cursed. I will focus on trying to implement a similar system based on Sloth's suggestion.

Milod: This patch requires access to the source code in Eclipse. I will try to provide a compiled version. I'll post here if I manage it. :)