Xander9009 wrote:I've made a custom card (for a custom mechanic-based deck) and while it's 99% working, I can't seem to manage the last 1%. It's got three abilities:
Artifact, costs

- Enters the battlefield with a Charge counter, plus has Sunburst (for a total of 1 counter if paid for with colorless and 2 if paid for with colored mana).
- Other creatures with the new mechanic (as of now, they're listed by name) enter the battlefield with Sunburst.
- Permanents you control with the new mechanic (for now, it's those with charge counters) can have a counter removed in exchange for 1 mana of a color based on that card's color(s).
The problem is with the third ability. What it's supposed to do: If it's a colorless card, it's colorless mana, blue cards give blue mana, blue and black cards make you choose blue or black. What it
is doing: makes you choose between the card's color(s) (even if only one) and colorless. The thing is, I know more or less
how I should remove that prompt if it's only one color or none, but every time I try, the card either starts producing only colorless mana (and always without a prompt) or the game freezes. I've run out of ideas for this annoying should-be-easy-too-fix problem. Anyone feel like helping me out a bit?
Try this:
- Mana Ability | Open
- Code: Select all
<ACTIVATED_ABILITY forced_skip="1" resource_id="0">
<LOCALISED_TEXT LanguageCode="en-US"><![CDATA[Remove a charge counter from this permanent: Add to your mana pool 1 mana of any color that shares a color with this permanent.]]></LOCALISED_TEXT>
<COST type="RemoveCountersSelf" amount="1" counter_type="Charge" />
<PLAY_TIME_ACTION>
local nColours = EffectSource():GetColour():GetNumColours()
EffectDC():Int_Set( 0, nColours )
if (nColours <= 1) then
EffectDC():Int_Set( 1, RSN_GetFirstProducibleColour( EffectSource() ) )
end
</PLAY_TIME_ACTION>
<PLAY_TIME_ACTION>
if (EffectDC():Int_Get( 0 ) > 1) then
local oPlayer = EffectController()
local oCard = EffectSource()
if (oPlayer ~= nil) then
oPlayer:BeginNewMultipleChoice()
oPlayer:AddMultipleChoiceAnswer( "RSN_MODE_PRODUCE_W", EffectSource():GetColour():Test( COLOUR_WHITE ) == true )
oPlayer:AddMultipleChoiceAnswer( "RSN_MODE_PRODUCE_U", EffectSource():GetColour():Test( COLOUR_BLUE ) == true )
oPlayer:AddMultipleChoiceAnswer( "RSN_MODE_PRODUCE_B", EffectSource():GetColour():Test( COLOUR_BLACK ) == true )
oPlayer:AddMultipleChoiceAnswer( "RSN_MODE_PRODUCE_R", EffectSource():GetColour():Test( COLOUR_RED ) == true )
oPlayer:AddMultipleChoiceAnswer( "RSN_MODE_PRODUCE_G", EffectSource():GetColour():Test( COLOUR_GREEN ) == true )
oPlayer:AskMultipleChoiceQuestion( "MODE_CHOOSE_ONE", oCard )
end
end
</PLAY_TIME_ACTION>
<RESOLUTION_TIME_ACTION>
local nColour = 0
if (EffectDC():Int_Get( 0 ) > 1) then
nColour = EffectController():GetMultipleChoiceResult() + 1
else
nColour = EffectDC():Int_Get( 1 )
end
if (nColour == COLOUR_COLOURLESS) then
RSN_Produce( "{1}", 1 )
elseif (nColour == COLOUR_WHITE) then
RSN_Produce( "{W}", 1 )
elseif (nColour == COLOUR_BLUE) then
RSN_Produce( "{U}", 1 )
elseif (nColour == COLOUR_BLACK) then
RSN_Produce( "{B}", 1 )
elseif (nColour == COLOUR_RED) then
RSN_Produce( "{R}", 1 )
elseif (nColour == COLOUR_GREEN) then
RSN_Produce( "{G}", 1 )
end
</RESOLUTION_TIME_ACTION>
<RESOLUTION_TIME_ACTION>
RSN_EliminateExtraManaTokens()
</RESOLUTION_TIME_ACTION>
<RESOLUTION_TIME_ACTION>
S_DisplayManaPool(EffectController())
RSN_MarkManaAbilityEnd()
</RESOLUTION_TIME_ACTION>
<AI_AVAILABILITY window_step="upkeep" type="window" />
<AI_AVAILABILITY window_step="main_1" window_turn="my_turn" type="window" />
<AI_AVAILABILITY window_step="begin_combat" window_turn="their_turn" type="window" />
<AI_AVAILABILITY window_step="declare_attackers" window_turn="their_turn" type="window" />
<AI_AVAILABILITY window_step="declare_blockers" type="window" />
<AI_AVAILABILITY window_step="main_2" window_turn="my_turn" type="window" />
<AI_AVAILABILITY window_step="end_of_turn" type="window" />
<AI_AVAILABILITY window_step="end_of_turn" window_turn="their_turn" type="window" />
<AI_AVAILABILITY type="in_response" response_source="1" response_target="1" />
<AI_AVAILABILITY type="in_response" response_source="1" />
<AI_AVAILABILITY type="in_response" response_target="1" />
</ACTIVATED_ABILITY>
It first checks how many colours the card has and stores that in a DC register; then if it has 1 or less it stores the first producible colour in another DC register (the function RSN_GetFirstProducibleColour() works because in the next ability you mark what can be produced based on the card's colours). Then in the next action if the stored colours (EffectDC() register) are greater than 1 we ask the question (without the colourless option). In the mana producing action we first check how many colours (our stored EffectDC() register) and if greater than 1 we ask for the result of the question otherwise we look to see what colour was stored in the other EffectDC() register.
Xander9009 wrote:While I'm at it, I'll save space and just ask here, does anyone know how to add a custom ability?
You've already added custom abilities and there is no trick to it.
Xander9009 wrote:I know it can't be coded in like the vanilla abilities, but are there any tricks that I can use to easily have certain cards have an ability and other cards be able to know they have the ability? Would the Scry trick made by Sumo work (the one to trigger the new card's "Player scried" condition)? Should I use the original Scry trick by TFM and use an unused ability? Something else entirely?
What you are describing here is not custom abilities, but custom characteristics and is very different. The scry tricks used won't work because they just signal when scry has been used, not which cards have scry.
A while back in working with Undying and Persist, I developed a system that I designed to allow for custom characteristics,
Characteristic Functions (requires my ObjectDC functions as well). Currently, the system is unused as no one has really needed it. There are 2 ways to use these functions:
- Use the functions to assign both a fake characteristic and create the ability on each card that you want to have the fake characteristic (GrantAbility() does work if the card is designed to give the fake characteristic to something else).
- Use the functions to assign a fake characteristic to a card and have the ability portion of the fake characteristic managed by an invisible manager token.
Regardless of which option you choose the default Characteristic Manager token must be created (this manages the fake characteristics so they get properly removed when they are supposed to be). The Persist and Undying fake characteristics can be ignored since they aren't needed (we found a way to code them without needing extra abilities).
To use it you need to create a LOL file to contain the constants for your fake characteristics each with unique values (to prevent conflicts) like so:
- MY_CUSTOM_CHARACTERISTICS.LOL | Open
- Code: Select all
MY_CHARACTERISTIC_SOMETHING = 1234001
Then if you are doing the manager route (if not then skip this) you need to create a manager token (a single manager can easily manage multiple custom characteristics):
- MY_CUSTOM_MANAGER | Open
- Code: Select all
<?xml version="1.0"?>
<CARD_V2 ExportVersion="1">
<FILENAME text="MY_CUSTOM_CHARACTERISTIC_MANAGER" />
<CARDNAME text="MY_CUSTOM_CHARACTERISTIC_MANAGER" />
<TITLE>
<LOCALISED_TEXT LanguageCode="en-US"><![CDATA[MY CHARACTERISTIC MANAGER]]></LOCALISED_TEXT>
<LOCALISED_TEXT LanguageCode="fr-FR"><![CDATA[MY CHARACTERISTIC MANAGER]]></LOCALISED_TEXT>
<LOCALISED_TEXT LanguageCode="es-ES"><![CDATA[MY CHARACTERISTIC MANAGER]]></LOCALISED_TEXT>
<LOCALISED_TEXT LanguageCode="de-DE"><![CDATA[MY CHARACTERISTIC MANAGER]]></LOCALISED_TEXT>
<LOCALISED_TEXT LanguageCode="it-IT"><![CDATA[MY CHARACTERISTIC MANAGER]]></LOCALISED_TEXT>
<LOCALISED_TEXT LanguageCode="jp-JA"><![CDATA[MY CHARACTERISTIC MANAGER]]></LOCALISED_TEXT>
<LOCALISED_TEXT LanguageCode="ko-KR"><![CDATA[MY CHARACTERISTIC MANAGER]]></LOCALISED_TEXT>
<LOCALISED_TEXT LanguageCode="ru-RU"><![CDATA[MY CHARACTERISTIC MANAGER]]></LOCALISED_TEXT>
<LOCALISED_TEXT LanguageCode="pt-BR"><![CDATA[MY CHARACTERISTIC MANAGER]]></LOCALISED_TEXT>
</TITLE>
<ARTID value="0" />
<ARTIST name="None" />
<CASTING_COST cost="" />
<EXPANSION value="MANAGER_TOKENS" />
<RARITY metaname="T" />
<!-- Shroud so it can't be targeted. -->
<STATIC_ABILITY>
<INTRINSIC characteristic="CHARACTERISTIC_SHROUD" />
</STATIC_ABILITY>
<!-- Indestructible so it can't be destroyed. -->
<STATIC_ABILITY>
<INTRINSIC characteristic="CHARACTERISTIC_INDESTRUCTIBLE" />
</STATIC_ABILITY>
<!-- Protection from everything to prevent unwanted removal. -->
<STATIC_ABILITY>
<CONTINUOUS_ACTION layer="0">
if (EffectSource() ~= nil) then
local oFilter = ClearFilter()
local oSubfilter = oFilter:AddSubFilter_Or()
oSubfilter:Add( FE_TYPE, OP_IS, CARD_TYPE_ARTIFACT )
oSubfilter:Add( FE_TYPE, OP_IS, CARD_TYPE_CREATURE )
oSubfilter:Add( FE_TYPE, OP_IS, CARD_TYPE_ENCHANTMENT )
oSubfilter:Add( FE_TYPE, OP_IS, CARD_TYPE_INSTANT )
oSubfilter:Add( FE_TYPE, OP_IS, CARD_TYPE_LAND )
oSubfilter:Add( FE_TYPE, OP_IS, CARD_TYPE_PHENOMENON )
oSubfilter:Add( FE_TYPE, OP_IS, CARD_TYPE_PLANE )
oSubfilter:Add( FE_TYPE, OP_IS, CARD_TYPE_PLANESWALKER )
oSubfilter:Add( FE_TYPE, OP_IS, CARD_TYPE_SCHEME )
oSubfilter:Add( FE_TYPE, OP_IS, CARD_TYPE_SORCERY )
EffectSource():Protection()
end
</CONTINUOUS_ACTION>
</STATIC_ABILITY>
<!-- Now we have extra abilities for those characteristics which are built into this manager. -->
<!-- In other words these are the functions that make the custom characteristics actually do something. -->
</CARD_V2>
On the card that is going to either have or give the custom characteristic you need to add a couple of abilities. This is required so that the manager(s) get created to handle the custom characteristics (does not matter if RSN_Characteristics_CreateManagers() is called multiple times as it will only ever create the manager(s) once).
- This creates the manager(s) | Open
- Code: Select all
<TRIGGERED_ABILITY replacement_effect="1" active_zone="ZONE_HAND">
<TRIGGER value="BEGINNING_OF_STEP">
return ((MTG():GetStep() == STEP_UPKEEP) and (MTG():GetTurnNumber() == 0))
</TRIGGER>
<RESOLUTION_TIME_ACTION>
-- If you have created your own manager(s) then you need to add them as parameters to the function call below. Like this: RSN_Characteristics_CreateManagers("MY_CUSTOM_CHARACTERISTIC_MANAGER", "ANOTHER_MANAGER", "AND_ANOTHER")
RSN_Characteristics_CreateManagers()
</RESOLUTION_TIME_ACTION>
</TRIGGERED_ABILITY>
<TRIGGERED_ABILITY replacement_effect="1" active_zone="ZONE_LIBRARY">
<TRIGGER value="BEGINNING_OF_STEP">
return ((MTG():GetStep() == STEP_UPKEEP) and (MTG():GetTurnNumber() == 0))
</TRIGGER>
<RESOLUTION_TIME_ACTION>
-- If you have created your own manager(s) then you need to add them as parameters to the function call below. Like this: RSN_Characteristics_CreateManagers("MY_CUSTOM_CHARACTERISTIC_MANAGER", "ANOTHER_MANAGER", "AND_ANOTHER")
RSN_Characteristics_CreateManagers()
</RESOLUTION_TIME_ACTION>
</TRIGGERED_ABILITY>
If you are using the non-manager route then you need to create the ability to actually do what the characteristic is supposed to do on the card(s).
Finally, you need to assign the custom characteristic to the card(s). This could be a static ability on the card (like regular characteristics, except use layer 6 or RemoveAllAbilities() may not work right) or granted using GrantAbility() (layer 6 as standard). For example to use the static ability example:
- Assign Custom Characteristic | Open
- Code: Select all
<STATIC_ABILITY active_zone="ZONE_ANY">
<LOCALISED_TEXT LanguageCode="en-US"><![CDATA[My Custom Characteristic]]></LOCALISED_TEXT>
<CONTINUOUS_ACTION layer="6">
RSN_Characteristics_Set( EffectSource(), MY_CHARACTERISTIC_SOMETHING, 1 )
</CONTINUOUS_ACTION>
</STATIC_ABILITY>
The active_zone is there to try and ensure it will work in any zone except
Exile. If you need to be able to detect it in
Exile then you need to add another copy of the ability with active_zone="ZONE_EXILE" as ZONE_ANY does not cover exile for whatever reason.