Board index
Programs with AI or Rules Enforcement
Magic: The Gathering - Duels of the Planeswalkers
Programming Talk



DotP2012: Working Leylines
Moderator: CCGHQ Admins
1 post
• Page 1 of 1
DotP2012: Working Leylines
by thefiremind » 15 Nov 2011, 20:34
I finally managed to code the Leylines' ability that allows to put them in play on the first turn ever. I'm sharing it, in case someone needs it. I'll add some explanations, so that everyone can understand what I did.
1) You need nabeshin's storage functions. It could probably work by using an ObjectDataChest's register as well, but since I still haven't understood when those registers are deleted, I prefer to use something more reliable.
2) You need to declare the value of COMPARTMENT_ID_LOST_CHANCE somewhere (for example, I made a PERSONAL_CONSTANTS.LOL in the FUNCTIONS directory of my DLC). If you don't want to do it, just replace the name of the constant with a number of your choice.
3) (Optional but recommended) You should declare the localized text that replaces CARD_QUERY_MC_LEYLINE. Follow the example of kev's GLOSSARY.XML and you'll be fine. No need to make different texts for different Leylines: during the query you can see the card that asks for it.
4) (Optional but recommended) You should complete the localized text according to the Leyline you are coding.
How it works:
The first triggered ability starts when the Leyline is in your hand, and the upkeep starts. I couldn't make it trigger by using BEGINNING_OF_TURN (I don't know why) or by using a previous step like STEP_UNTAP or STEP_DRAW (I suppose it's because those steps don't exist in the first turn ever), but I don't think any player could do many things before the first upkeep anyway, so it's a good approximation of the real rule.
Note that TriggeredForMe() doesn't mean that it will trigger only on the object's owner's upkeep: I just discovered that those step triggers are launched once for every player, so if you try to delete TriggeredForMe(), you'll see that it will trigger twice (by playing 1vs1). It also checks that the value of the register in the storage isn't 1: we want this because we'll set it to 1 when there will be no option to put the Leyline in play anymore. The ability asks the player if he wants to put the leyline in play, and does the job if requested.
The second triggered ability disables the Leyline's power. It starts anywhere at the end of any upkeep if the register in the storage isn't 1, and it sets the register to 1. No Leyline will ever be triggered after the end of the first upkeep, and that's exactly what we want.
If you find a bug or you think you have a more elegant solution, please let me know.
- Code: Select all
<TRIGGERED_ABILITY auto_skip="1" forced_skip="1" active_zone="hand">
<LOCALISED_TEXT LanguageCode="en-US"><![CDATA[If Leyline of ... is in your opening hand, you may begin the game with it on the battlefield.]]></LOCALISED_TEXT>
<LOCALISED_TEXT LanguageCode="de-DE"><![CDATA[]]></LOCALISED_TEXT>
<LOCALISED_TEXT LanguageCode="es-ES"><![CDATA[]]></LOCALISED_TEXT>
<LOCALISED_TEXT LanguageCode="fr-FR"><![CDATA[]]></LOCALISED_TEXT>
<LOCALISED_TEXT LanguageCode="it-IT"><![CDATA[]]></LOCALISED_TEXT>
<LOCALISED_TEXT LanguageCode="jp-JA"><![CDATA[]]></LOCALISED_TEXT>
<TRIGGER value="BEGINNING_OF_STEP">
local store = Storage( Object() )
local nochance = store.get( COMPARTMENT_ID_LOST_CHANCE )
return MTG():GetStep() == STEP_UPKEEP and TriggeredForMe() and ( nochance == nil or nochance ~= 1 )
</TRIGGER>
<RESOLUTION_TIME_ACTION>
local player = Object():GetPlayer()
player:BeginNewMultipleChoice()
player:AddMultipleChoiceAnswer( "CARD_QUERY_OPTION_YES" )
player:AddMultipleChoiceAnswer( "CARD_QUERY_OPTION_NO" )
player:AskMultipleChoiceQuestion( "CARD_QUERY_MC_LEYLINE" )
</RESOLUTION_TIME_ACTION>
<RESOLUTION_TIME_ACTION>
if Object():GetMultipleChoiceResult() == 0 then
MTG():SetProtectedMove(1)
Object():PutIntoPlay( Object():GetOwner() )
MTG():SetProtectedMove(0)
end
local store = Storage( Object() )
store.set( COMPARTMENT_ID_LOST_CHANCE, 1 )
</RESOLUTION_TIME_ACTION>
</TRIGGERED_ABILITY>
<TRIGGERED_ABILITY internal="1" active_zone="any">
<TRIGGER value="END_OF_STEP">
local store = Storage( Object() )
local nochance = store.get( COMPARTMENT_ID_LOST_CHANCE )
return MTG():GetStep() == STEP_UPKEEP and TriggeredForMe() and ( nochance == nil or nochance ~= 1 )
</TRIGGER>
<RESOLUTION_TIME_ACTION>
local store = Storage( Object() )
store.set( COMPARTMENT_ID_LOST_CHANCE, 1 )
</RESOLUTION_TIME_ACTION>
</TRIGGERED_ABILITY>
1) You need nabeshin's storage functions. It could probably work by using an ObjectDataChest's register as well, but since I still haven't understood when those registers are deleted, I prefer to use something more reliable.

2) You need to declare the value of COMPARTMENT_ID_LOST_CHANCE somewhere (for example, I made a PERSONAL_CONSTANTS.LOL in the FUNCTIONS directory of my DLC). If you don't want to do it, just replace the name of the constant with a number of your choice.

3) (Optional but recommended) You should declare the localized text that replaces CARD_QUERY_MC_LEYLINE. Follow the example of kev's GLOSSARY.XML and you'll be fine. No need to make different texts for different Leylines: during the query you can see the card that asks for it.
4) (Optional but recommended) You should complete the localized text according to the Leyline you are coding.

How it works:
The first triggered ability starts when the Leyline is in your hand, and the upkeep starts. I couldn't make it trigger by using BEGINNING_OF_TURN (I don't know why) or by using a previous step like STEP_UNTAP or STEP_DRAW (I suppose it's because those steps don't exist in the first turn ever), but I don't think any player could do many things before the first upkeep anyway, so it's a good approximation of the real rule.

The second triggered ability disables the Leyline's power. It starts anywhere at the end of any upkeep if the register in the storage isn't 1, and it sets the register to 1. No Leyline will ever be triggered after the end of the first upkeep, and that's exactly what we want.

If you find a bug or you think you have a more elegant solution, please let me know.
< Former DotP 2012/2013/2014 modder >
Currently busy with life...
Currently busy with life...
-
thefiremind - Programmer
- Posts: 3515
- Joined: 07 Nov 2011, 10:55
- Has thanked: 118 times
- Been thanked: 722 times
1 post
• Page 1 of 1
Who is online
Users browsing this forum: No registered users and 23 guests