It is currently 19 Aug 2019, 04:03
   
Text Size

A good solution for Vorel of the Hull Clade

Moderators: Xander9009, CCGHQ Admins

A good solution for Vorel of the Hull Clade

Postby thefiremind » 12 May 2013, 13:02

I think some people will be interested in knowing that I made a working Vorel of the Hull Clade, and invented a "support structure" for him that could be useful for other cards as well (I can't think of any at the moment, but still... :mrgreen:).

The main problem about Vorel is that he needs to know which counters are on his target if he wants to double them. Checking all the possible counter indexes in a "for" loop would be a performance killer because counter indexes can be generated on the whole signed integer's range, but if we keep track of the counter indexes used during the duel, we have a limited set to check. I tried to keep track of them inside Vorel's ObjectDC, but couldn't retain the values on zonechange (why RetainDataChest worked for Serra Avenger and Shape of the Wiitigo, but not for Vorel, is still a mystery to me). So I thought: why not keeping track in the DuelDataChest?

I saved the following constant and function in my LOL files:
Code: Select all
DUEL_UTILITY_COMPARTMENT_ID_USED_COUNTERS = 999

UpdateUsedCountersChest = function()
-- use this in a COUNTERS_CHANGED trigger
-- updates a duel chest that saves the indexes of all the counters used during the duel
   local current_index = CounterTypeIndex()
   if current_index == nil or current_index == 0 then
      return
   end
   local i=0
   local chest = MTG():DuelDataChest():Get_Chest(DUEL_UTILITY_COMPARTMENT_ID_USED_COUNTERS)
   if chest == nil then
      chest = MTG():DuelDataChest():Make_Chest(DUEL_UTILITY_COMPARTMENT_ID_USED_COUNTERS)
   else
      local index = chest:Get_Int(i)
      while index ~= 0 do
         if index == current_index then
            return
         end
         i=i+1
         index = chest:Get_Int(i)
      end
   end
   chest:Set_Int(i, current_index)
end
The function searches the chest for the trigger's counter index, and adds it if needed. Multiple calls during the same triggering event don't interfere because the index is added only when it's missing.

With this function, coding Vorel becomes possible:
Code: Select all
<?xml version='1.0' encoding='UTF-8'?>
<CARD_V2>
  <FILENAME text="VOREL_OF_THE_HULL_CLADE_369045" />
  <CARDNAME text="VOREL_OF_THE_HULL_CLADE" />
  <TITLE>
    <LOCALISED_TEXT LanguageCode="en-US"><![CDATA[Vorel of the Hull Clade]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="fr-FR"><![CDATA[Vorel du Cladus Coque]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="es-ES"><![CDATA[Vorel del Clado de la Vaina]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="de-DE"><![CDATA[Vorel von der Hülsenklade]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="it-IT"><![CDATA[Vorel del Clade del Carapace]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="jp-JA"><![CDATA[育殻組のヴォレル]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="ko-KR"><![CDATA[헐 클레이드의 보렐]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="ru-RU"><![CDATA[Ворел из Клады Оболочки]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="pt-BR"><![CDATA[Vorel da Cepa do Casco]]></LOCALISED_TEXT>
  </TITLE>
  <MULTIVERSEID value="369045" />
  <ARTID value="A369045" />
  <ARTIST name="Mike Bierek" />
  <CASTING_COST cost="{1}{G}{U}" />
  <FLAVOURTEXT>
    <LOCALISED_TEXT LanguageCode="en-US"><![CDATA[“I used to hurl rocks and eat scraps of meat burned over a fire. Look at what I’ve become and tell me Simic does not hold infinite possibility.”]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="fr-FR"><![CDATA[« Avant, je lançais des pierres et me nourrissais de lambeaux de viande grillés au feu de bois. Regardez ce que je suis devenu et osez prétendre que Simic n’ouvre pas des perspectives illimitées. »]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="es-ES"><![CDATA[“Solía lanzar rocas y comer restos de carne quemados en una hoguera. Mira en qué me he convertido y dime si los simic no albergan posibilidades infinitas.”]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="de-DE"><![CDATA[„Früher habe ich mit Steinen geworfen und am offenen Feuer verkohlte Fleischbrocken gegessen. Sieh dir an, was aus mir geworden ist, und erzähl mir noch, dass die Simic keine unbegrenzten Möglichkeiten bieten.”]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="it-IT"><![CDATA[“Una volta scagliavo pietre e mangiavo pezzi di carne bruciati su un fuoco. Guarda cosa sono diventato e dimmi se essere un Simic non apre possibilità infinite.”]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="jp-JA"><![CDATA[「私はかつて石を投げ、肉片を火で炙って食していた。今の私を見ろ。これでもシミックに無限の可能性がないと言えるのか?」]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="ko-KR"><![CDATA[“예전의 나는 돌을 던지고 모닥불에 고기 찌꺼기나 구워먹던 하찮은 존재였지. 지금의 나를 보게. 이것이 바로 시믹이 선사하는 무한한 가능성이라네.”]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="ru-RU"><![CDATA[«Когда-то я швырял камни и питался кусками мяса, обожженными на костре. Посмотри, кем я стал теперь. Разве возможности Симиков не безграничны?»]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="pt-BR"><![CDATA[“Eu costumava jogar pedras e comer restos de carne queimada numa fogueira. Vejam o que eu me tornei e digam se os Simic não oferecem infinitas possibilidades.”]]></LOCALISED_TEXT>
  </FLAVOURTEXT>
  <SUPERTYPE metaname="Legendary" />
  <TYPE metaname="Creature" />
  <SUB_TYPE metaname="Human" order_fr-FR="0" order_es-ES="1" order_de-DE="0" order_it-IT="1" order_jp-JA="0" order_ko-KR="0" order_ru-RU="0" order_pt-BR="0" />
  <SUB_TYPE metaname="Merfolk" order_fr-FR="1" order_es-ES="0" order_de-DE="1" order_it-IT="0" order_jp-JA="1" order_ko-KR="1" order_ru-RU="1" order_pt-BR="1" />
  <EXPANSION value="DGM" />
  <RARITY metaname="R" />
  <POWER value="1" />
  <TOUGHNESS value="4" />
  <ACTIVATED_ABILITY>
    <LOCALISED_TEXT LanguageCode="en-US"><![CDATA[{G}{U}, {T}: For each counter on target artifact, creature, or land, put another of those counters on that permanent.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="fr-FR"><![CDATA[{G}{U}, {T} : Pour chaque marqueur sur l’artefact ciblé, la créature ciblée ou le terrain ciblé, mettez un autre de ces marqueurs sur ce permanent.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="es-ES"><![CDATA[{G}{U}, {T}: Por cada contador sobre el artefacto, criatura o tierra objetivo, pon otro de esos contadores sobre ese permanente.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="de-DE"><![CDATA[{G}{U}, {T}: Lege für jede Marke auf einem Artefakt, einer Kreatur oder einem Land deiner Wahl eine weitere Marke dieser Art auf diese bleibende Karte.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="it-IT"><![CDATA[{G}{U}, {T}: Per ogni segnalino su un artefatto, una creatura o una terra bersaglio, metti un altro di quei segnalini su quel permanente.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="jp-JA"><![CDATA[{G}{U}, {T}:アーティファクト1つかクリーチャー1体か土地1つを対象とする。それの上に置かれている各カウンター1個につき、それと同じカウンターをもう1個そのパーマネントの上に置く。]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="ko-KR"><![CDATA[{G}{U}, {T}: 마법물체, 생물 또는 대지 한 개를 목표로 정한다. 그 지속물에 올려진 카운터 종류마다 그 종류의 카운터를 하나씩 더 올려놓는다.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="ru-RU"><![CDATA[{G}{U}, {T}: за каждый жетон на целевом артефакте, существе или земле положите на тот перманент еще один такой же жетон.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="pt-BR"><![CDATA[{G}{U}, {T}: Para cada marcador no artefato, criatura ou terreno alvo, coloque outro desses marcadores naquela permanente.]]></LOCALISED_TEXT>
    <COST type="Mana" cost="{G}{U}" />
    <COST type="TapSelf" />
    <TARGET_DEFINITION id="0">
    local filter = Object():GetFilter()
    filter:Clear()
    filter:SetZone( ZONE_IN_PLAY )
    filter:AddCardType( CARD_TYPE_ARTIFACT )
    filter:AddCardType( CARD_TYPE_CREATURE )
    filter:AddCardType( CARD_TYPE_LAND )
    filter:SetHint( HINT_NEUTRAL, EffectController() )
    </TARGET_DEFINITION>
    <TARGET_DETERMINATION>
    return AtLeastOneTargetFromDefinition(0)
    </TARGET_DETERMINATION>
    <PLAY_TIME_ACTION target_choosing="1">
    EffectController():ChooseTarget( 0, "CARD_QUERY_CHOOSE_PERMANENT", EffectDC():Make_Targets(0) )
    </PLAY_TIME_ACTION>
    <RESOLUTION_TIME_ACTION>
    local target = EffectDC():Get_Targets(0):Get_CardPtr(0)
    if target ~= nil then
       local chest = MTG():DuelDataChest():Get_Chest( DUEL_UTILITY_COMPARTMENT_ID_USED_COUNTERS )
       if chest ~= nil then
          local i=0
          local index = chest:Get_Int(i)
          while index ~= 0 do
             local amount = target:CountCounters(index)
             if amount &gt; 0 then
                target:AddCounters(index, amount)
             end
             i=i+1
             index = chest:Get_Int(i)
          end
       end
    end
    </RESOLUTION_TIME_ACTION>
    <AI_AVAILABILITY type="in_response" />
    <AI_AVAILABILITY step="main_1" turn="my_turn" />
    <AI_AVAILABILITY step="main_2" turn="my_turn" />
    <AI_AVAILABILITY step="declare_blockers" />
    <AI_AVAILABILITY step="end_of_turn" turn="their_turn" />
  </ACTIVATED_ABILITY>
  <TRIGGERED_ABILITY internal="1" active_zone="ZONE_ANY">
    <TRIGGER value="COUNTERS_CHANGED" />
    <RESOLUTION_TIME_ACTION>
    UpdateUsedCountersChest()
    </RESOLUTION_TIME_ACTION>
  </TRIGGERED_ABILITY>
  <SFX text="COMBAT_GREEN_MAGIC_LARGE_ATTACK" power_boundary_min="4" power_boundary_max="-1" />
  <SFX text="COMBAT_GREEN_MAGIC_SMALL_ATTACK" power_boundary_min="1" power_boundary_max="3" />
  <AI_BASE_SCORE score="600" zone="ZONE_IN_PLAY" />
</CARD_V2>
Vorel's ability scans the chest the same way as the external function does, and when it finds counters on the target, it doubles them.

Finally, here's Vorel for all your deck-building needs. For those who don't know yet, LOL files must be put in a DATA_ALL_PLATFORMS\FUNCTIONS folder. You can organize the contents of VOREL.LOL in a better way (i.e. moving the constant definition in a LOL file that only contains constant definitions) if you are managing multiple LOL files in your mod.
If something's wrong, check that register #999 of the DuelDataChest isn't used by something else (if that's the case, change 999 with some other number).
Attachments
VOREL_OF_THE_HULL_CLADE_369045.zip
card + illustration + LOL file
(113.88 KiB) Downloaded 96 times
< 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: 717 times

Re: A good solution for Vorel of the Hull Clade

Postby sumomole » 21 May 2013, 08:06

PLAYER_UTILITY_COMPARTMENT_ID_POISON_READING = 999 in 1138 mod, although its use is different. :mrgreen:
If we can create mod in D14, I think we should posting a list of compartment ID, anyone to create a new ID should notify others. :lol:
User avatar
sumomole
Programmer
 
Posts: 611
Joined: 07 Jun 2011, 08:34
Has thanked: 51 times
Been thanked: 230 times

Re: A good solution for Vorel of the Hull Clade

Postby thefiremind » 21 May 2013, 08:45

sumomole wrote:PLAYER_UTILITY_COMPARTMENT_ID_POISON_READING = 999 in 1138 mod, although its use is different. :mrgreen:
I know, but my LOL file for constants is divided into Object constants, Player constants and Duel constants, I can replicate numbers in different chests.

sumomole wrote:If we can create mod in D14, I think we should posting a list of compartment ID, anyone to create a new ID should notify others. :lol:
There are so many things I learned from DotP2013 that I should remember to do differently next time, I should start writing down a list. Let's add this one too. :lol:
< 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: 717 times


Return to Programming Talk

Who is online

Users browsing this forum: Google [Bot] and 3 guests


Who is online

In total there are 4 users online :: 1 registered, 0 hidden and 3 guests (based on users active over the past 10 minutes)
Most users ever online was 287 on 31 Mar 2019, 04:11

Users browsing this forum: Google [Bot] and 3 guests

Login Form