I've spent the last day or so working on trying to get split cards to work. To begin with, I'm focusing on the new ones from Amonkhet, where the first half is castable normally, but the second half is only castable from the graveyard. Thanks to the rules changes regarding split cards, they should be fully codable, since they always have the combined characteristics except when they're on the stack. They never return two answers to a question like "What's your CMC?" Now, they just return the combined value.
In order to manage this, I've set it up so they have the full combined characteristics on the card. The card then gets a static which reduces the cost by the Aftermath's cost, which will leave it at the normal cost (I don't know the rules regarding increasing the cost of split cards, but I'm not worried about that fringe case for the moment...). At the beginning of the game, it creates a copy of each of the two separate cards, storing their copiable values. Then, when it goes to the stack, it'll use the copiable values of one or the other. When to use each (for aftermath cards) is pretty simple, so choosing which to use is working fine. What's not is actually using the second one.
The card I'm testing with is Onward to Victory (
Onward//Victory).
Onward
Instant
Target creature gets +
X/+0 until end of turn, where
X is its power.
Victory
Sorcery
Aftermath (only castable from graveyard; exile it when it resolves.)
Target creature gets double strike until end of turn.
See, I've set it up so it creates each in turn using a function "CW_Flip_StoreA("_ONWARD", "ONWARD", 1, 1)" and "CW_Flip_StoreA("_VICTORY", "VICTORY", 2, 1)". Then, in a delayed triggered ability created inside that function, it calls "CW_Flip_StoreB("_ONWARD", "ONWARD", 1, 1)" and "CW_Flip_StoreB("_VICTORY", "VICTORY", 2, 1)". The functions have the same parameters for clarity at the moment, but that'll all be cleaned up once it's fully working. Anyway, here are the functions and the card.
- functions | Open
- Code: Select all
CW_Flip_StoreA = function(sFileName, sCardName, iChestIndex, iDelayedTriggerIndex)
if sFileName ~= nil and sCardName ~= nil and iChestIndex ~= nil then
if iDelayedTriggerIndex == nil then
iDelayedTriggerIndex = 0
end
MTG():CreateDelayedTrigger(iDelayedTriggerIndex)
MTG():PutTokensOntoBattlefield(sFileName, 1, EffectController(), CW_DC_ObjectDC(iChestIndex))
end
end
CW_Flip_StoreB = function(sFileName, sCardName, iChestIndex, iDelayedTriggerIndex)
local oTokenChest = CW_DC_ObjectDC(iChestIndex)
if oTokenChest ~= nil then
local oToken = oTokenChest:Get_NthCardPtr(0)
if oToken ~= nil and oToken:GetCardName() == sCardName then
oTokenChest:Clear()
oToken:StoreCopiableValues(oTokenChest)
Debug(sCardName, iChestIndex)
end
end
end
- Onward to Victory | Open
- Code: Select all
<?xml version="1.0"?>
<CARD_V2 ExportVersion="1">
<FILENAME text="ONWARD_TO_VICTORY" />
<CARDNAME text="ONWARD_TO_VICTORY" />
<TITLE>
<LOCALISED_TEXT LanguageCode="en-US"><![CDATA[Onward to Victory]]></LOCALISED_TEXT>
</TITLE>
<MULTIVERSEID value="30170" />
<ARTID value="ONWARD_TO_VICTORY" />
<ARTIST name="Unknown" />
<CASTING_COST cost="{4}{R}{W}" />
<TYPE metaname="Instant" />
<TYPE metaname="Sorcery" />
<EXPANSION value="AKH" />
<RARITY metaname="R" />
<TRIGGERED_ABILITY replacement_effect="1" active_zone="ZONE_ANY">
<TRIGGER value="BEGINNING_OF_STEP">
return MTG():GetStep() == STEP_UPKEEP and MTG():GetTurnNumber() == 0
</TRIGGER>
<RESOLUTION_TIME_ACTION>
CW_Flip_StoreA("_ONWARD", "ONWARD", 0, 1)
CW_Flip_StoreA("_VICTORY", "VICTORY", 1, 1)
</RESOLUTION_TIME_ACTION>
</TRIGGERED_ABILITY>
<TRIGGERED_ABILITY replacement_effect="1" active_zone="ZONE_ANY" resource_id="1" priority="-1">
<TRIGGER value="ZONECHANGE_CONSIDERED" to_zone="ZONE_BATTLEFIELD" from_zone="ZONE_ANY" pre_trigger="1" simple_qualifier="objectyoucontrol">
if TriggerObject() ~= nil then
MTG():OverrideEvent()
return true
end
return false
</TRIGGER>
<RESOLUTION_TIME_ACTION>
CW_Flip_StoreB("_ONWARD", "ONWARD", 0, 1)
CW_Flip_StoreB("_VICTORY", "VICTORY", 1, 1)
</RESOLUTION_TIME_ACTION>
<CLEANUP fire_once="1" />
</TRIGGERED_ABILITY>
<TRIGGERED_ABILITY replacement_effect="1" active_zone="ZONE_ANY">
<TRIGGER value="CONSIDERED_FOR_CAST" simple_qualifier="self" pre_trigger="1" />
<RESOLUTION_TIME_ACTION>
if TriggerObject() ~= nil then
TriggerObject():DecreaseColouredCost(COLOUR_WHITE, 1)
TriggerObject():DecreaseCost(2)
end
</RESOLUTION_TIME_ACTION>
</TRIGGERED_ABILITY>
<STATIC_ABILITY linked_ability_group="1" active_zone="ZONE_ANY">
<CONTINUOUS_ACTION layer="0">
local oOwner = EffectSource():GetPlayer()
local iRefID = EffectSource():GetRef()
local oRefChest = oOwner:PlayerDataChest():Get_Chest(iRefID)
if oRefChest ~= nil then
if oRefChest:Get_Int(0) ~= 1 and LinkedDC():Get_Int(0) ~= 1 then
EffectSource():GetCurrentCharacteristics():GrantAbility(10)
else
EffectSource():GetCurrentCharacteristics():GrantAbility(20)
end
else
oRefChest = oOwner:PlayerDataChest():Make_Chest(iRefID)
oRefChest:Set_Int(0, 0)
end
</CONTINUOUS_ACTION>
</STATIC_ABILITY>
<TRIGGERED_ABILITY active_zone="ZONE_ANY" linked_ability_group="1" replacement_effect="1">
<TRIGGER value="ZONECHANGE_END" to_zone="ZONE_STACK" from_zone="ZONE_ANY">
local oOwner = Object():GetPlayer()
local iRefID = Object():GetRef()
local oRefChest = oOwner:PlayerDataChest():Get_Chest(iRefID)
if oRefChest ~= nil then
if oRefChest:Get_Int(0) ~= 1 and LinkedDC():Get_Int(0) ~= 1 then
EffectDC():Set_Int(0, 0)
else
EffectDC():Set_Int(0, 1)
end
return true
end
return false
</TRIGGER>
<CONTINUOUS_ACTION layer="1">
Debug(EffectDC():Get_Int(0))
Object():UseCopiableValues(CW_DC_ObjectDC(EffectDC():Get_Int(0)))
</CONTINUOUS_ACTION>
<DURATION>
if EffectSource() == nil or EffectSource():GetZone() ~= ZONE_STACK then
Debug("End")
end
return EffectSource() == nil or EffectSource():GetZone() ~= ZONE_STACK
</DURATION>
</TRIGGERED_ABILITY>
<TRIGGERED_ABILITY replacement_effect="1" active_zone="ZONE_ANY"> -- Permanently protect ObjectDC
<TRIGGER value="ZONECHANGE_CONSIDERED" pre_trigger="1" simple_qualifier="self" />
<RESOLUTION_TIME_ACTION>
RSN_ProtectObjectDC()
</RESOLUTION_TIME_ACTION>
</TRIGGERED_ABILITY>
<STATIC_ABILITY linked_ability_group="1" active_zone="ZONE_GRAVEYARD">
<CONTINUOUS_ACTION layer="1">
local oOwner = EffectSource():GetPlayer()
local iRefID = EffectSource():GetRef()
local oRefChest = oOwner:PlayerDataChest():Get_Chest(iRefID)
if oRefChest ~= nil then
local iState = LinkedDC():Get_Int(0)
LinkedDC():Set_Int(0, 1)
if EffectController():CanCastSpellUsingResourceCost(EffectSource(), 0) then
oRefChest:Set_Int(1,1)
else
oRefChest:Set_Int(1,0)
end
LinkedDC():Set_Int(0, iState)
else
oRefChest = oOwner:PlayerDataChest():Make_Chest(iRefID)
oRefChest:Set_Int(1,0)
end
</CONTINUOUS_ACTION>
</STATIC_ABILITY>
<SPELL_ABILITY>
<LOCALISED_TEXT LanguageCode="en-US"><![CDATA[Target creature gets +X/+0 until end of turn, where X is its power.]]></LOCALISED_TEXT>
</SPELL_ABILITY>
<ACTIVATED_ABILITY forced_skip="1" qualifier="Alternate" active_zone="ZONE_GRAVEYARD" linked_ability_group="1">
<LOCALISED_TEXT LanguageCode="en-US"><![CDATA[Aftermath {2}{W}: Target creature gains double strike until end of turn.]]></LOCALISED_TEXT>
<COST type="Generic">
<PREREQUISITE>
local oRefChest = EffectSource():GetPlayer():PlayerDataChest():Get_Chest(EffectSource():GetRef())
return oRefChest ~= nil and oRefChest:Get_Int(1) == 1 and EffectController():IsSorceryTime()
</PREREQUISITE>
<PLAY_TIME_ACTION>
RSN_MarkManaAbilityStart()
</PLAY_TIME_ACTION>
<PLAY_TIME_ACTION>
EffectSource():GetPlayer():PlayerDataChest():Make_Chest(EffectSource():GetRef()):Set_Int(0, 1)
</PLAY_TIME_ACTION>
</COST>
<RESOLUTION_TIME_ACTION>
MTG():CreateDelayedTrigger(2, nil)
</RESOLUTION_TIME_ACTION>
<RESOLUTION_TIME_ACTION>
EffectController():CastSpellUsingResourceCost(EffectSource(), 0)
</RESOLUTION_TIME_ACTION>
<RESOLUTION_TIME_ACTION>
RSN_MarkManaAbilityEnd()
</RESOLUTION_TIME_ACTION>
</ACTIVATED_ABILITY>
<TRIGGERED_ABILITY resource_id="2" replacement_effect="1" linked_ability_group="1">
<TRIGGER value="SPELL_RESOLVED" simple_qualifier="self" />
<PLAY_TIME_ACTION>
Object():GetPlayer():PlayerDataChest():Make_Chest(Object():GetRef()):Set_Int(0, 0)
LinkedDC():Set_Int(0, 1)
</PLAY_TIME_ACTION>
<RESOLUTION_TIME_ACTION>
Object():Exile()
</RESOLUTION_TIME_ACTION>
</TRIGGERED_ABILITY>
<SPELL_ABILITY resource_id="10">
<TARGET tag="CARD_QUERY_CHOOSE_CREATURE_TO_GET_X_0" definition="0" compartment="0" count="1" />
<TARGET_DEFINITION id="0">
local oFilter = ClearFilter()
oFilter:Add(FE_TYPE, OP_IS, CARD_TYPE_CREATURE)
</TARGET_DEFINITION>
<RESOLUTION_TIME_ACTION>
local oTarget = EffectDC():Get_Targets(0) and EffectDC():Get_Targets(0):Get_CardPtr(0)
if oTarget ~= nil then
EffectDC():Set_Int(1, oTarget:GetCurrentCharacteristics():Power_Get())
end
</RESOLUTION_TIME_ACTION>
<CONTINUOUS_ACTION layer="7C">
local oTarget = EffectDC():Get_Targets(0) and EffectDC():Get_Targets(0):Get_CardPtr(0)
if oTarget ~= nil then
oTarget:GetCurrentCharacteristics():Power_Add(EffectDC():Get_Int(1))
end
</CONTINUOUS_ACTION>
<DURATION simple_duration="UntilEOT" />
<AI_SIMPLIFIED_TARGETING compartment="0" hint="HINT_ALLIED_ONLY" />
</SPELL_ABILITY>
<SPELL_ABILITY resource_id="20" linked_ability_group="1">
<TARGET tag="CARD_QUERY_CHOOSE_CREATURE" definition="0" compartment="0" count="1" />
<TARGET_DEFINITION id="0">
local oFilter = ClearFilter()
oFilter:Add(FE_TYPE, OP_IS, CARD_TYPE_CREATURE)
</TARGET_DEFINITION>
<CONTINUOUS_ACTION layer="7C">
local oTarget = EffectDC():Get_Targets(0) and EffectDC():Get_Targets(0):Get_CardPtr(0)
if oTarget ~= nil then
oTarget:GetCurrentCharacteristics():Bool_Set(CHARACTERISTIC_DOUBLE_STRIKE, 1)
end
</CONTINUOUS_ACTION>
<DURATION simple_duration="UntilEOT" />
<AI_SIMPLIFIED_TARGETING compartment="0" hint="HINT_ALLIED_ONLY" />
</SPELL_ABILITY>
<TRIGGERED_ABILITY linked_ability_group="1" replacement_effect="1" active_zone="ZONE_ANY">
<TRIGGER value="SPELL_RESOLVED">
return TriggerObject() == Object()
</TRIGGER>
<RESOLUTION_TIME_ACTION>
EffectSource():GetPlayer():PlayerDataChest():Make_Chest(EffectSource():GetRef()):Clear()
LinkedDC():Clear()
</RESOLUTION_TIME_ACTION>
</TRIGGERED_ABILITY>
<UTILITY_ABILITY resource_id="0">
<COST mana_cost="{4}{W}{W}" type="Mana" />
</UTILITY_ABILITY>
<AUTHOR><![CDATA[Xander9009]]></AUTHOR>
<EDITORS><![CDATA[Xander9009]]></EDITORS>
<DATE><![CDATA[09-04-17]]></DATE>
</CARD_V2>
- Onward | Open
- Code: Select all
<?xml version="1.0"?>
<CARD_V2 ExportVersion="1">
<FILENAME text="_ONWARD" />
<CARDNAME text="ONWARD" />
<TITLE>
<LOCALISED_TEXT LanguageCode="en-US"><![CDATA[Onward]]></LOCALISED_TEXT>
</TITLE>
<MULTIVERSEID value="90090001" />
<ARTID value="ONWARD_TO_VICTORY" />
<ARTIST name="Unknown" />
<CASTING_COST cost="{2}{R}" />
<TYPE metaname="Instant" />
<EXPANSION value="AKH" />
<RARITY metaname="R" />
<SPELL_ABILITY>
<LOCALISED_TEXT LanguageCode="en-US"><![CDATA[Target creature gets +X/+0 until end of turn, where X is its power.]]></LOCALISED_TEXT>
<TARGET tag="CARD_QUERY_CHOOSE_CREATURE_TO_GET_X_0" definition="0" compartment="0" count="1" />
<TARGET_DEFINITION id="0">
local oFilter = ClearFilter()
oFilter:Add(FE_TYPE, OP_IS, CARD_TYPE_CREATURE)
</TARGET_DEFINITION>
<RESOLUTION_TIME_ACTION>
local oTarget = EffectDC():Get_Targets(0) and EffectDC():Get_Targets(0):Get_CardPtr(0)
if oTarget ~= nil then
EffectDC():Set_Int(1, oTarget:GetCurrentCharacteristics():Power_Get())
end
</RESOLUTION_TIME_ACTION>
<CONTINUOUS_ACTION layer="7C">
local oTarget = EffectDC():Get_Targets(0) and EffectDC():Get_Targets(0):Get_CardPtr(0)
if oTarget ~= nil then
oTarget:GetCurrentCharacteristics():Power_Add(EffectDC():Get_Int(1))
end
</CONTINUOUS_ACTION>
<DURATION simple_duration="UntilEOT" />
<AI_SIMPLIFIED_TARGETING compartment="0" hint="HINT_ALLIED_ONLY" />
</SPELL_ABILITY>
<AUTHOR><![CDATA[Xander9009]]></AUTHOR>
<EDITORS><![CDATA[Xander9009]]></EDITORS>
<DATE><![CDATA[09-04-17]]></DATE>
</CARD_V2>
- Victory | Open
- Code: Select all
<?xml version="1.0"?>
<CARD_V2 ExportVersion="1">
<FILENAME text="_VICTORY" />
<CARDNAME text="VICTORY" />
<TITLE>
<LOCALISED_TEXT LanguageCode="en-US"><![CDATA[Victory]]></LOCALISED_TEXT>
</TITLE>
<MULTIVERSEID value="90090002" />
<ARTID value="ONWARD_TO_VICTORY" />
<ARTIST name="Unknown" />
<CASTING_COST cost="{2}{W}" />
<TYPE metaname="Sorcery" />
<EXPANSION value="AKH" />
<RARITY metaname="R" />
<SPELL_ABILITY>
<LOCALISED_TEXT LanguageCode="en-US"><![CDATA[Target creature gains double strike until end of turn.]]></LOCALISED_TEXT>
<TARGET tag="CARD_QUERY_CHOOSE_CREATURE" definition="0" compartment="0" count="1" />
<TARGET_DEFINITION id="0">
local oFilter = ClearFilter()
oFilter:Add(FE_TYPE, OP_IS, CARD_TYPE_CREATURE)
</TARGET_DEFINITION>
<CONTINUOUS_ACTION layer="7C">
local oTarget = EffectDC():Get_Targets(0) and EffectDC():Get_Targets(0):Get_CardPtr(0)
if oTarget ~= nil then
oTarget:GetCurrentCharacteristics():Bool_Set(CHARACTERISTIC_DOUBLE_STRIKE, 1)
end
</CONTINUOUS_ACTION>
<DURATION simple_duration="UntilEOT" />
<AI_SIMPLIFIED_TARGETING compartment="0" hint="HINT_ALLIED_ONLY" />
</SPELL_ABILITY>
<AUTHOR><![CDATA[Xander9009]]></AUTHOR>
<EDITORS><![CDATA[Xander9009]]></EDITORS>
<DATE><![CDATA[09-04-17]]></DATE>
</CARD_V2>
So, the thing to really notice is in the fifth ability on line 65. In this ability, it figures out whether it should use the copiable values stored in chest 0 or chest 1 and stores that value to be used for the duration of the ability. Then, the CA uses the copiable values found in the chest indicated. When it's cast from your hand, it shows 0 and then when it goes to the graveyard it shows end, and it actually uses the copiable values (it doesn't display the mana cost correctly, but it does
work correctly, despite displaying wrong). That's exactly what it should do.
When you cast it from your graveyard with its Aftermath ability, it shows the debug message "1" to show it's using the right chest, and then it shows "end" when it leaves the stack, which is all correct. But it never actually uses the copiable values, tested by seeing if
Thoughtbind can counter it, which it can't.
Now, I thought maybe it's an issue with the values being stored improperly and thus retrieving them is failing. The method of storing them is a bit unorthodox, so it made sense. But swapping the values on lines 72 and 74 made it properly use the values from Victory, showing the values are retrievable. The only problem is that when it's cast from the graveyard via the Aftermath ability, it doesn't properly use the copiable values.
If the spell is copied, it copies the spell that was actually chosen for casting, which is correct. I'm not sure how it would react to a few other situations, but at the very least, it mostly works normally. But I can't seem to make this particular bit work, and I've run out of ideas for how I might fix it. (I've tried several things, but nothing works.)