It is currently 18 Apr 2024, 02:34
   
Text Size

General DotP 2014 Coding Questions

Moderator: CCGHQ Admins

General DotP 2014 Coding Questions

Postby MC Brodie » 07 Aug 2013, 13:15

I've started this thread so can keep from cluttering up the Formal Request Thread. This thread may also be helpful for other beginner modders with questions. Feel free to post any general questions you may have.

So...

One problem that I'm having is the AI takes a long time when playing with or maybe against my cards. On multeyemeteor's YouTube channel I saw TFM state that this could be due to the lack of defining AI Availability on instants and sorceries. I know I'll need to go back through my cards to make sure I've done that. I've also seen an AI Base Score tag defined on some cards, but not all. Do we know how this affects the AI and could the lack of defining this value slow down the AI? Also, does anyone have any suggestions for coding cards that will be more compatible with the AI?

Thank you to all of the experienced modders who have taken their time and effort to figure these things out in the first place.
-----------------------------------------------------------------------
Song of the Day: 46 and 2 (cover)
MC Brodie
 
Posts: 310
Joined: 01 Jun 2013, 00:10
Has thanked: 44 times
Been thanked: 34 times

Re: General DotP 2014 Coding Questions

Postby thefiremind » 07 Aug 2013, 13:25

MC Brodie wrote:One problem that I'm having is the AI takes a long time when playing with or maybe against my cards. On multeyemeteor's YouTube channel I saw TFM state that this could be due to the lack of defining AI Availability on instants and sorceries. I know I'll need to go back through my cards to make sure I've done that.
I can guarantee that most of the times the lack of AI_AVAILABILITY blocks is the culprit for the slowdowns. You can tell that it's not a normal slowdown (where the AI takes time because it really needs to) when you have unnatural pauses after your main phases, exactly as you have seen in the video.

MC Brodie wrote:I've also seen an AI Base Score tag defined on some cards, but not all. Do we know how this affects the AI and could the lack of defining this value slow down the AI? Also, does anyone have any suggestions for coding cards that will be more compatible with the AI?
The AI_BASE_SCORE is used by the AI in order to decide whether to trade or not during combat, or which thing should have high priority getting rid of, or which card is better to discard with Distress, and so on. 150 is usually chosen as "unit", and the scores are multiples of that. Some characteristics of the cards are automatically taken into account, as you can see if you open DATA_CORE\DATA_ALL_PLATFORMS\CONFIGS\DEFAULT_AI_SETTINGS.XML. For particular abilities you should try to decide how much they are worth, maybe by looking at similar cards that already exist. You can also give a negative score if a card has a bad ability (can't block, deals damage to you, etc.) or if you can care less about it because you can easily get it back (Gravecrawler). Anyway the lack of AI_BASE_SCORE doesn't cause any slowdown, it just makes the AI take some wrong decisions.
< Former DotP 2012/2013/2014 modder >
Currently busy with life...
User avatar
thefiremind
Programmer
 
Posts: 3515
Joined: 07 Nov 2011, 10:55
Has thanked: 118 times
Been thanked: 721 times

Re: General DotP 2014 Coding Questions

Postby gorem2k » 08 Aug 2013, 14:22

How do I grant an activated ability, inside an activated ability, that need to stay active forever, if I have already a continuous_action duration that last until end of turn?

example | Open
Code: Select all
  <ACTIVATED_ABILITY>
    <LOCALISED_TEXT LanguageCode="en-US"><![CDATA[“Swamps you control have ‘{T}: Add {B}{B}{B}{B} to your mana pool.’”]]>
    <AVAILABILITY per_turn_limit="1" sorcery_time="1" />
    <FILTER filter_id="0">
    local filter = ClearFilter()
    filter:Add( FE_TYPE, OP_IS, CARD_TYPE_LAND )
    filter:Add( FE_SUBTYPE, OP_IS, LAND_TYPE_SWAMP )
    filter:Add( FE_CONTROLLER, OP_IS, EffectController() )
    </FILTER>
    <CONTINUOUS_ACTION layer="6" filter_id="0">
    if FilteredCard() ~= nil then
      FilteredCard():GetCurrentCharacteristics():GrantAbility(1)
    end
    </CONTINUOUS_ACTION>
    <CONTINUOUS_ACTION layer="8">
    if EffectSource() ~= nil then
       EffectSource():GetCurrentCharacteristics():Bool_Set( CHARACTERISTIC_CANT_USE_ACTIVATED_ABILITIES, 1 )
    end
    </CONTINUOUS_ACTION>
    <DURATION simple_duration="UntilEOT" />
  </ACTIVATED_ABILITY>

  <ACTIVATED_ABILITY resource_id="1">
    <LOCALISED_TEXT LanguageCode="en-US"><![CDATA[{T}: Add {B}{B}{B}{B} to your mana pool.]]></LOCALISED_TEXT>

... ... ...

this will make swamp have ability only until end of turn, but I have to keep CANT_USE_ACTIVATED_ABILITIES !
gorem2k
 
Posts: 464
Joined: 01 Apr 2013, 04:21
Has thanked: 48 times
Been thanked: 33 times

Re: General DotP 2014 Coding Questions

Postby thefiremind » 08 Aug 2013, 14:55

gorem2k wrote:How do I grant an activated ability, inside an activated ability, that need to stay active forever, if I have already a continuous_action duration that last until end of turn?
I don't like to do that, but when it's the only way... you'll need to use the trick that I was using in DotP2012 for Umezawa's Jitte: move one of the CONTINUOUS_ACTIONs to a delayed ABILITY_RESOLVED trigger, then add the creation of that trigger to the original ability.

example | Open
Code: Select all
  <ACTIVATED_ABILITY>
    <LOCALISED_TEXT LanguageCode="en-US"><![CDATA[“Swamps you control have ‘{T}: Add {B}{B}{B}{B} to your mana pool.’”]]>
    <AVAILABILITY per_turn_limit="1" sorcery_time="1" />
    <FILTER filter_id="0">
    local filter = ClearFilter()
    filter:Add( FE_TYPE, OP_IS, CARD_TYPE_LAND )
    filter:Add( FE_SUBTYPE, OP_IS, LAND_TYPE_SWAMP )
    filter:Add( FE_CONTROLLER, OP_IS, EffectController() )
    </FILTER>
    <RESOLUTION_TIME_ACTION>
    local delayDC = EffectDC():Make_Chest(1)
    delayDC:Set_CardPtr( 0, EffectSource() )
    MTG():CreateDelayedTrigger(0, delayDC)
    </RESOLUTION_TIME_ACTION>
    <CONTINUOUS_ACTION layer="6" filter_id="0">
    if FilteredCard() ~= nil then
      FilteredCard():GetCurrentCharacteristics():GrantAbility(1)
    end
    </CONTINUOUS_ACTION>
    <DURATION>
    return FilteredCard() == nil
    </DURATION>
  </ACTIVATED_ABILITY>

  <TRIGGERED_ABILITY replacement_effect="1" resource_id="0">
    <TRIGGER value="ABILITY_RESOLVED" />
    <CONTINUOUS_ACTION layer="8">
    local source = EffectDC():Get_CardPtr(0)
    if source ~= nil then
       source:GetCurrentCharacteristics():Bool_Set( CHARACTERISTIC_CANT_USE_ACTIVATED_ABILITIES, 1 )
    end
    </CONTINUOUS_ACTION>
    <DURATION simple_duration="UntilEOT" />
  </TRIGGERED_ABILITY>

  <ACTIVATED_ABILITY resource_id="1">
    <LOCALISED_TEXT LanguageCode="en-US"><![CDATA[{T}: Add {B}{B}{B}{B} to your mana pool.]]></LOCALISED_TEXT>

... ... ...

Last edited by thefiremind on 10 Aug 2013, 09:23, edited 1 time in total.
< Former DotP 2012/2013/2014 modder >
Currently busy with life...
User avatar
thefiremind
Programmer
 
Posts: 3515
Joined: 07 Nov 2011, 10:55
Has thanked: 118 times
Been thanked: 721 times

Re: General DotP 2014 Coding Questions

Postby gorem2k » 09 Aug 2013, 06:31

that didn't work...

However, the delaydc triggered because I could activate abilities next turn.

the card says you got an Emblem. I thought about substitute Emblem with a "special" counter to verify if I have the 'Emblem'. but when the card dies, it's over!

I'm now doing damage redirections for instant and sorcery but I can't figure out to make Slagstorm deal 3 damage to a fake planeswalker, (prevent that damage to its controller) and let it deal the 3 damage to me. All I can do is prevent ALL damage when I target a planeswalker. this is quite complicated. I may leave it alone and live with that. unless someone works on that along with me, or have a better alternative.

this is my last attempt:

code | Open
Code: Select all
  <TRIGGERED_ABILITY replacement_query="1">
    <TRIGGER value="SOURCE_DEALS_DAMAGE_TO_PLAYER" pre_trigger="1">
    if SecondaryPlayer() == EffectController() and
       TriggerObject():GetOwner() ~= EffectController() and
       (TriggerObject():GetCardType():Test (CARD_TYPE_INSTANT) or
       TriggerObject():GetCardType():Test (CARD_TYPE_SORCERY) ) then
       EffectDC():Int_Set(0, Damage():GetAmount() )
       Damage():PreventAll() -- I don't know for cards like Slagstorm...
       return true
    end
    return false
    </TRIGGER>
    <RESOLUTION_TIME_ACTION>
    if TriggerObject() ~= nil then
        local player = TriggerObject():GetOwner()
        local filter = ClearFilter()
        filter:Add( FE_TYPE, OP_IS, CARD_TYPE_ENCHANTMENT )
        filter:Add( FE_CONTROLLER, OP_IS, EffectController() )
        filter:SetZone( ZONE_BATTLEFIELD )
        player:ChooseItem("CARD_QUERY_CHOOSE_PLANESWALKER", EffectDC():Make_Targets(1), QUERY_FLAG_MAY )
    end
    </RESOLUTION_TIME_ACTION>
    <RESOLUTION_TIME_ACTION>
    if TriggerObject() ~= nil then
      local planeswalker = EffectDC():Get_Targets(1):Get_CardPtr(0)
      local damage = EffectDC():Int_Get(0)
      if planeswalker ~= nil then
         planeswalker:RemoveCounters( MTG():GetCountersType("Loyalty"), damage )
        elseif damage &gt; 0 then
         EffectController():LoseLife( damage ) -- can't find a solution with DealDamageTo( damage, EffectController() )
      end
    end
    </RESOLUTION_TIME_ACTION>
  </TRIGGERED_ABILITY>
gorem2k
 
Posts: 464
Joined: 01 Apr 2013, 04:21
Has thanked: 48 times
Been thanked: 33 times

Re: General DotP 2014 Coding Questions

Postby MC Brodie » 13 Aug 2013, 12:03

Thanks for the response thefiremind.

I have question on Data Chests. From what I can tell Data Chests are used to store global variables that are used in different xml blocks (and are also required for saving card information when the card changes zones). It looks like EffectDC is applicable when passing information in the same ability block (eg, between resolution time actions in the same triggered ability) and LinkedDC is applicable for passing information between abilities (eg from a triggered ability to a static ability). Is this correct?

Also I've seen people mention ObjectDC (which isn't supported in the vanilla version) and player data chests. How are these used compared to the other data chests?

Thank you.
-----------------------------------------------------------------------
Song of the Day: 46 and 2 (cover)
MC Brodie
 
Posts: 310
Joined: 01 Jun 2013, 00:10
Has thanked: 44 times
Been thanked: 34 times

Re: General DotP 2014 Coding Questions

Postby thefiremind » 13 Aug 2013, 12:21

MC Brodie wrote:I have question on Data Chests. From what I can tell Data Chests are used to store global variables that are used in different xml blocks (and are also required for saving card information when the card changes zones). It looks like EffectDC is applicable when passing information in the same ability block (eg, between resolution time actions in the same triggered ability) and LinkedDC is applicable for passing information between abilities (eg from a triggered ability to a static ability). Is this correct?
In most cases, this is correct. There's an exception: EffectDC can pass from a UTILITY_ABILITY to a SPELL_ABILITY and this is useful for cards like Fling where you need to remember what you used as additional cost.
LinkedDC can't be used everywhere, though: for example it cannot be read inside AVAILABILITY blocks.
There's another difference: LinkedDC persists as long as the card using it doesn't change zone, while EffectDC persists as long as the ability using it keeps doing something (Lua uses "garbage collection" like Java, so the data is saved until all reference to it gets lost, unless specified otherwise).

MC Brodie wrote:Also I've seen people mention ObjectDC (which isn't supported in the vanilla version) and player data chests. How are these used compared to the other data chests?
ObjectDC was the "precursor" of LinkedDC in previous games, and RiiakShiNal made his own version in order to make it available for DotP2014, this overcomes LinkedDC's limitations. For additional info on RiiakShiNal's ObjectDC you had better ask him, though. :wink:
Player data chests are linked to each player, so they persist as long as the player is in game, this is useful when you need to save information pertaining to a player that doesn't depend on a card staying in a particular zone. For example, Angelic Accord needs to know how much life a player gained during a turn and the game doesn't keep that count automatically, so it's up to us to keep it, but the player could gain life before Angelic Accord is on the battlefield, so it's safer to save the life gain on a player basis rather than on a card basis.

There's also a duel data chest that persists for the whole match.
< Former DotP 2012/2013/2014 modder >
Currently busy with life...
User avatar
thefiremind
Programmer
 
Posts: 3515
Joined: 07 Nov 2011, 10:55
Has thanked: 118 times
Been thanked: 721 times

Re: General DotP 2014 Coding Questions

Postby RiiakShiNal » 13 Aug 2013, 14:11

My ObjectDC functions are meant to be used in places where having information linked to a card is useful, but either needs to be accessed by other cards or needs to be used in places where other data chests either can't be used or are not feasible to use. Note that my fake ObjectDCs should be cleared when the card changes zones much like in DotP 2013.

For example my manual mana functions need to store information linked to the card using them such as what type of mana and how much was produced, also was an activated ability used as a mana ability, and what types of mana can be produced. However, the information stored using the manual mana functions also needs to be accessed by other cards (like Mana Flare, Exotic Orchard, Reflecting Pool, Burning-Tree Shaman, etc...) for their abilities to work properly as well. EffectDC() doesn't work because multiple abilities need access to it, LinkedDC() doesn't work because other cards need access to it, PlayerDataChest() doesn't make sense because the information needs to be linked to the card, and DuelDataChest() also doesn't really make sense because again the data needs to be linked to the card. So I had to fake creating an ObjectDC (actually uses DuelDataChest(), but uses a register modders are not likely to use and links the data chests with a card pointer to maintain the linking) to overcome all the problems and work where all others either don't work or don't make sense.
RiiakShiNal
Programmer
 
Posts: 2185
Joined: 16 May 2011, 21:37
Has thanked: 75 times
Been thanked: 496 times

Re: General DotP 2014 Coding Questions

Postby MC Brodie » 30 Sep 2013, 15:06

What does the auto skip block actually do? I've noticed it in equipment and life gain cards. In equipment cards it looks like it is preventing something from happening if the to be equipped creature doesn't exist but the life gain one confuses me.
-----------------------------------------------------------------------
Song of the Day: 46 and 2 (cover)
MC Brodie
 
Posts: 310
Joined: 01 Jun 2013, 00:10
Has thanked: 44 times
Been thanked: 34 times

Re: General DotP 2014 Coding Questions

Postby thefiremind » 30 Sep 2013, 16:40

MC Brodie wrote:What does the auto skip block actually do?
If the AUTO_SKIP condition is true, and the "Automatic resolution" game option is enabled, the ability will resolve instantly rather than waiting for a possible answer. For example, if you are trying to equip a creature and that creature dies, it's useless to wait for other answers, because that effect won't do anything at all. Life gaining on official cards is set on auto-skip when your life total is higher than your starting life total because your opponent most likely doesn't have a way to deal 20 or more damage to you in response, so waiting is pointless. Of course, if you are playing a deck that might need to answer where the auto-skip wouldn't let you, you can disable the game option.

------------------------------

Some Q&A from here (they suit this topic better):

GrovyleXShinyCelebi wrote:Will "return true" break any loop?
Yes, "return" (with or without a return value) ends the script (from <...> to </...>). You can use "break" when you want to end the current loop rather than the whole script (sometimes it's useful for performance purposes, for example if you already found what you were searching for in your iterations).

GrovyleXShinyCelebi wrote:Can tables/arrays serve as an alternative to interrogations?
I'm not sure if I understood what you have in mind... if you need to know something that the game itself doesn't keep track of, you have to save it somewhere and retrieve it when needed, and tables could be used for that purpose. The problem is that sometimes they don't work, and I'm not sure why (there's probably something specific about Lua that I'm not aware of). When I tried to make my own table for Vraska, the Unseen, it didn't keep the values I wanted, while RiiakShiNal's ObjectDC, which is based on data chests, worked great for that. So I'd suggest to use tables only when you need to store data that you use within the same script (for my offering mechanic I needed a table because my mana functions use the filter and I can't use more than 1 filter at once), and use data chests otherwise (for example, in order to store the life gained by a player, which is needed by Angelic Accord).
< Former DotP 2012/2013/2014 modder >
Currently busy with life...
User avatar
thefiremind
Programmer
 
Posts: 3515
Joined: 07 Nov 2011, 10:55
Has thanked: 118 times
Been thanked: 721 times

Re: General DotP 2014 Coding Questions

Postby GrovyleXShinyCelebi » 05 Oct 2013, 22:11

Alright, thanks for the help with my other questions. Two things:

If I put a for/do loop in a CONTINUOUS_ACTION block, say to check hand counts for Guul Draz Specter, when does the check actually occur?

What can I put in a COST block? Do TARGET blocks work there? I'm trying to make Living Destiny, and I'm having trouble with where should I store the CMC value in LinkedDC. Should I make the COST value just "Reveal" or "Generic" and write the reveal cost manually while storing the integer in the RESOLUTION_TIME_ACTION inside the COST block?
User avatar
GrovyleXShinyCelebi
 
Posts: 294
Joined: 12 Jun 2013, 18:23
Has thanked: 14 times
Been thanked: 37 times

Re: General DotP 2014 Coding Questions

Postby thefiremind » 05 Oct 2013, 23:29

GrovyleXShinyCelebi wrote:If I put a for/do loop in a CONTINUOUS_ACTION block, say to check hand counts for Guul Draz Specter, when does the check actually occur?
Each time state-based effects are checked, continuous actions are "refreshed", that's when the check occurs. In other words, the check occurs often enough for the card to work as expected. :mrgreen:

GrovyleXShinyCelebi wrote:What can I put in a COST block? Do TARGET blocks work there? I'm trying to make Living Destiny, and I'm having trouble with where should I store the CMC value in LinkedDC. Should I make the COST value just "Reveal" or "Generic" and write the reveal cost manually while storing the integer in the RESOLUTION_TIME_ACTION inside the COST block?
No, TARGET blocks can't be used inside COST blocks... it would have been helpful for bestow. :lol:
Generic costs should be used as last resort when you really can't do what you need to do with the standard costs. A reveal cost should work for Living Destiny, provided you add LKI_shield="1" which will keep the last known information about the revealed card:
Code: Select all
    <COST type="Reveal" definition="0" compartment="0" query_tag="CARD_QUERY_CHOOSE_CARD_TO_REVEAL" item_count="1" LKI_shield="1" />
    <COST_DEFINITION id="0">
    local filter = ClearFilter()
    filter:Add( FE_TYPE, OP_IS, CARD_TYPE_CREATURE )
    filter:Add( FE_CARD_INSTANCE, OP_NOT, EffectSource() )
    filter:SetZone( ZONE_HAND, EffectController() )
    </COST_DEFINITION>
After this, you should always be able to access EffectDC():Get_Targets(0):Get_CardPtr(0) and get its CMC or whatever you need to know, even if the revealed card changes zone before resolution.
< Former DotP 2012/2013/2014 modder >
Currently busy with life...
User avatar
thefiremind
Programmer
 
Posts: 3515
Joined: 07 Nov 2011, 10:55
Has thanked: 118 times
Been thanked: 721 times

Re: General DotP 2014 Coding Questions

Postby GrovyleXShinyCelebi » 06 Oct 2013, 01:03

Ah...

By the way, Is there a list of known tags (that you put in the "<>" blocks) that DOTP 2014 uses, like with functions and pre-defined arguments in the LOL files on the slightlymagic wiki?
User avatar
GrovyleXShinyCelebi
 
Posts: 294
Joined: 12 Jun 2013, 18:23
Has thanked: 14 times
Been thanked: 37 times

Re: General DotP 2014 Coding Questions

Postby thefiremind » 06 Oct 2013, 08:32

GrovyleXShinyCelebi wrote:Ah...

By the way, Is there a list of known tags (that you put in the "<>" blocks) that DOTP 2014 uses, like with functions and pre-defined arguments in the LOL files on the slightlymagic wiki?
Yes. :wink:
< Former DotP 2012/2013/2014 modder >
Currently busy with life...
User avatar
thefiremind
Programmer
 
Posts: 3515
Joined: 07 Nov 2011, 10:55
Has thanked: 118 times
Been thanked: 721 times

Re: General DotP 2014 Coding Questions

Postby GrovyleXShinyCelebi » 13 Oct 2013, 15:44

Hey, I have two more questions:

-How would you make an effect that triggers depending on whether you spent mana of a specific colour when paying for it (i.e. Ribbons of Night, which I know was an official card in Duels 2013 so it should be doable)

-Why is it that you can't put a "ChooseItems( EffectDC():Make_Targets(1))" and "local target = EffectDC():Get_Targets(1) and EffectDC():Get_Targets(1):Get_CardPtr(i)" in the same RESOLUTION_TIME_ACTION block?
User avatar
GrovyleXShinyCelebi
 
Posts: 294
Joined: 12 Jun 2013, 18:23
Has thanked: 14 times
Been thanked: 37 times

Next

Return to Programming Talk

Who is online

Users browsing this forum: No registered users and 22 guests


Who is online

In total there are 22 users online :: 0 registered, 0 hidden and 22 guests (based on users active over the past 10 minutes)
Most users ever online was 4143 on 23 Jan 2024, 08:21

Users browsing this forum: No registered users and 22 guests

Login Form