It is currently 19 Apr 2024, 16:38
   
Text Size

A function for the heroic keyword

Moderator: CCGHQ Admins

A function for the heroic keyword

Postby thefiremind » 21 Sep 2013, 23:58

I made a function that acts as trigger condition for the heroic keyword ("Whenever you cast a spell that targets <this>..."). Actually, it's the same principle I used for Hindering Light, and I think it's good, even if it makes an assumption about the other cards.

This is the trigger condition:
Code: Select all
    <TRIGGER value="SPELL_PLAYED" simple_qualifier="objectyoucontrol">
    return TEST_IsTargetting( TriggerObject(), EffectSource() )
    </TRIGGER>
Quite short, isn't it?

This is the function it uses:
Test_IsTargetting function | Open
Code: Select all
TEST_IsTargetting = function(spell, ...)
-- returns true if the spell is targetting at least one of the other parameters (they can be either cards or players)
   local param_count = #arg
   if spell ~= nil and param_count > 0 then
      local spellDC = spell:GetDataChest()
      if spellDC ~= nil then
         for i=0,99 do
            local targetDC = spellDC:Get_NthTargets(i)
            if targetDC ~= nil and targetDC:Count() > 0 then
               for j=0,targetDC:Count()-1 do
                  local target_card = targetDC:Get_CardPtr(j)
                  local target_player = targetDC:Get_PlayerPtr(j)
                  for k=1,param_count do
                     local param = arg[k]
                     if param ~= nil and (param == target_card or param == target_player) then
                        return true
                     end
                  end
               end
            end
         end
      end
   end
   return false
end
Variable number of parameters (read if you don't know what "..." and "arg" mean) | Open
What you see here is an example of a Lua function with a variable number of parameters (or arguments, call them as you like most). That "..." in the function declaration means that Lua will store all the parameters (except for "spell" which is explicitly declared) in a table called "arg", which can be accessed inside the function. The indexes start from 1, and "#arg" returns their count.
It looks inside the spell's target chests from 0 to 99, and it returns true if it finds one of the targets specified as parameter (they can be any number, maybe this will help with future cards).

The assumption it makes is that no modder will ever use other chests for the targets. I think it's fair enough... we won't see a spell with 101 targets that need to stay in 101 chests, and if a modder uses target chest #100 because he feels special... well, he'll need to make his own heroic function. :lol:

A possible alternative would be to use a BECAME_TARGET_OF_SPELL trigger, but then we would need to verify that the trigger didn't already consider the same spell (it wouldn't be easy to do, sumomole knows the problem very well :mrgreen:).

If you have other ideas, feel free to post them. If you find a weak point in my idea (other than the assumption), please warn me. In the meanwhile, I'll keep using this function and try to assemble a "heroic deck". :D
< 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: A function for the heroic keyword

Postby gorem2k » 22 Sep 2013, 04:57

I don't really understand why BECAME_TARGET_OF_SPELL would be a problem.

this:
Code: Select all
    <TRIGGER value="BECAME_TARGET_OF_SPELL" simple_qualifier="self">
    return SecondaryObject():GetController() == EffectController()
    </TRIGGER>
code from BlindWillow seems ok to me! can you give an example when this would fail? or % of chance it happen
gorem2k
 
Posts: 464
Joined: 01 Apr 2013, 04:21
Has thanked: 48 times
Been thanked: 33 times

Re: A function for the heroic keyword

Postby thefiremind » 22 Sep 2013, 08:38

gorem2k wrote:I don't really understand why BECAME_TARGET_OF_SPELL would be a problem.
I haven't tested it, but I'm quite positive that BECAME_TARGET_OF_SPELL will trigger twice if you target the same heroic creature twice with the same spell, for example Common Bond (which would really shine in a heroic deck by the way :D). This, of course, would be wrong, because the heroic keyword is supposed to trigger when you cast a spell, so it should trigger once per spell, no matter how many times you target the same heroic creature with that.
< 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: A function for the heroic keyword

Postby gorem2k » 22 Sep 2013, 16:36

thefiremind wrote:
gorem2k wrote:I don't really understand why BECAME_TARGET_OF_SPELL would be a problem.
I haven't tested it, but I'm quite positive that BECAME_TARGET_OF_SPELL will trigger twice if you target the same heroic creature twice with the same spell, for example Common Bond (which would really shine in a heroic deck by the way :D). This, of course, would be wrong, because the heroic keyword is supposed to trigger when you cast a spell, so it should trigger once per spell, no matter how many times you target the same heroic creature with that.
I see. then they should have called that BECAME_TARGET_OF_SPELL_ABILITY :wink: or simply BECAME_TARGET.

EDIT: tested Common Bond and you're right, it trigger twice.
gorem2k
 
Posts: 464
Joined: 01 Apr 2013, 04:21
Has thanked: 48 times
Been thanked: 33 times

Re: A function for the heroic keyword

Postby sumomole » 24 Sep 2013, 16:21

gorem2k wrote:EDIT: tested Common Bond and you're right, it trigger twice.
I guess if you use
Code: Select all
    <TARGET tag="CARD_QUERY_CHOOSE_CREATURE_TO_GET_PLUS1_PLUS1_COUNTER" definition="0" compartment="0" count="1" />
    <TARGET tag="CARD_QUERY_CHOOSE_CREATURE_TO_GET_PLUS1_PLUS1_COUNTER" definition="1" compartment="1" count="1" />
, TRIGGER_BECAME_TARGET_OF_SPELL will be triggered twice, but if you use
Code: Select all
    <TARGET tag="CARD_QUERY_CHOOSE_CREATURE_TO_GET_PLUS1_PLUS1_COUNTER" definition="0" compartment="0" count="2" counter_assignment="1" />
, it will be triggered only once.
User avatar
sumomole
Programmer
 
Posts: 611
Joined: 07 Jun 2011, 08:34
Has thanked: 51 times
Been thanked: 234 times

Re: A function for the heroic keyword

Postby thefiremind » 24 Sep 2013, 18:03

sumomole wrote:if you use
Code: Select all
    <TARGET tag="CARD_QUERY_CHOOSE_CREATURE_TO_GET_PLUS1_PLUS1_COUNTER" definition="0" compartment="0" count="2" counter_assignment="1" />
, it will be triggered only once.
I don't know if I would go against some other rule by coding it like that: I can't think of anything right now, but I guess there must be a reason why they didn't word it as "Distribute two +1/+1 counters among any number of target creatures". However I noticed that the Japanese localised text is worded differently: the 2 abilities have different text (but I can't really be sure about what they say, Google Translate does a very poor job on them :lol:).

And what about Seeds of Strength? It doesn't give counters, so I don't know if I can use counter_assignment as well.
< 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: A function for the heroic keyword

Postby BlindWillow » 24 Sep 2013, 22:44

Can't we check in the trigger to see if the same card is being considered as SecondaryObject()?

This seems to work from some initial testing:
Code: Select all
    <TRIGGER value="BECAME_TARGET_OF_SPELL" simple_qualifier="self">
    if SecondaryObject() ~= EffectDC():Get_CardPtr(0) then
   EffectDC():Set_CardPtr( 0, SecondaryObject() )
   return SecondaryObject():GetController() == EffectController()
    end
    </TRIGGER>
BlindWillow
 
Posts: 213
Joined: 19 Jul 2012, 00:26
Has thanked: 11 times
Been thanked: 46 times

Re: A function for the heroic keyword

Postby thefiremind » 24 Sep 2013, 23:05

BlindWillow wrote:Can't we check in the trigger to see if the same card is being considered as SecondaryObject()?

This seems to work from some initial testing:
Code: Select all
    <TRIGGER value="BECAME_TARGET_OF_SPELL" simple_qualifier="self">
    if SecondaryObject() ~= EffectDC():Get_CardPtr(0) then
   EffectDC():Set_CardPtr( 0, SecondaryObject() )
   return SecondaryObject():GetController() == EffectController()
    end
    </TRIGGER>
I don't know how it could possibly work by using EffectDC, since two different triggering instances won't share it. LinkedDC works for that matter, but for heroic you would still need to check if the spell has been cast: a copy that is not cast shouldn't trigger heroic. You could add a check for WasCast, but I still think that my code is safer for heroic. The basic idea behind your code is OK for Wild Defiance and Livewire Lash, though: in fact, that's more or less how I coded those 2 cards.
< 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: A function for the heroic keyword

Postby BlindWillow » 24 Sep 2013, 23:30

I think it only seemed to work because I had forgotten to consider sumomole's point above. I was testing with Flames of the Firebrand, and of course, it doesn't target the same creature repeatedly. Thanks for the info about EffectDC() too. I had suspected that to be the case, but sometimes I'd code something that would seem to suggest otherwise. Now I can stop trying to go that route with other weird triggers like Phylactery Lich, for instance. :wink:
BlindWillow
 
Posts: 213
Joined: 19 Jul 2012, 00:26
Has thanked: 11 times
Been thanked: 46 times

Re: A function for the heroic keyword

Postby RiiakShiNal » 25 Sep 2013, 00:17

thefiremind wrote:
sumomole wrote:if you use
Code: Select all
    <TARGET tag="CARD_QUERY_CHOOSE_CREATURE_TO_GET_PLUS1_PLUS1_COUNTER" definition="0" compartment="0" count="2" counter_assignment="1" />
, it will be triggered only once.
I don't know if I would go against some other rule by coding it like that: I can't think of anything right now, but I guess there must be a reason why they didn't word it as "Distribute two +1/+1 counters among any number of target creatures". However I noticed that the Japanese localised text is worded differently: the 2 abilities have different text (but I can't really be sure about what they say, Google Translate does a very poor job on them :lol:).

And what about Seeds of Strength? It doesn't give counters, so I don't know if I can use counter_assignment as well.
The Japanese version of Common Bond says "Target one creature and target one creature. On the first put a +1/+1 counter, on the second put a +1/+1 counter." If you convert it so that it reads better in English you basically have the original English card.

Well, I guess my Japanese finally paid off. :lol:
RiiakShiNal
Programmer
 
Posts: 2185
Joined: 16 May 2011, 21:37
Has thanked: 75 times
Been thanked: 496 times

Re: A function for the heroic keyword

Postby GrovyleXShinyCelebi » 25 Sep 2013, 01:53

RiiakShiNal wrote:
thefiremind wrote:
sumomole wrote:if you use
Code: Select all
    <TARGET tag="CARD_QUERY_CHOOSE_CREATURE_TO_GET_PLUS1_PLUS1_COUNTER" definition="0" compartment="0" count="2" counter_assignment="1" />
, it will be triggered only once.
I don't know if I would go against some other rule by coding it like that: I can't think of anything right now, but I guess there must be a reason why they didn't word it as "Distribute two +1/+1 counters among any number of target creatures". However I noticed that the Japanese localised text is worded differently: the 2 abilities have different text (but I can't really be sure about what they say, Google Translate does a very poor job on them :lol:).

And what about Seeds of Strength? It doesn't give counters, so I don't know if I can use counter_assignment as well.
The Japanese version of Common Bond says "Target one creature and target one creature. On the first put a +1/+1 counter, on the second put a +1/+1 counter." If you convert it so that it reads better in English you basically have the original English card.

Well, I guess my Japanese finally paid off. :lol:
Aw, I wish Spanish and Chinese were as cool as Japanese... :(

Anyways, I'm wondering, what would be the issue of writing the function like this:

Code: Select all
TEST_IsTargetting = function(spell, source)
-- returns true if the spell is targetting at least one of the other parameters (they can be either cards or players
   if spell ~= nil and source ~= nil then
      local spellDC = spell:GetDataChest()
      if spellDC ~= nil then
         for i=0,99 do
            local targetDC = spellDC:Get_NthTargets(i)
            if targetDC ~= nil and targetDC:Count() > 0 then
               for j=0,targetDC:Count()-1 do
                  local target_card = targetDC:Get_CardPtr(j)
                  local target_player = targetDC:Get_PlayerPtr(j)
                     if (source == target_card or source == target_player) then
                        return true
                     end
               end
            end
         end
      end
   end
   return false
Also, I've always wanted to ask this: what is an LUA table? Is it just a table of values where a large amount of data or integers are stored? What's practically different between a table and data chest? And what basic functions (that work in Duels 2014) can interact with tables?
User avatar
GrovyleXShinyCelebi
 
Posts: 294
Joined: 12 Jun 2013, 18:23
Has thanked: 14 times
Been thanked: 37 times

Re: A function for the heroic keyword

Postby MC Brodie » 25 Sep 2013, 02:26

Everyone in here needs to stop bragging. I barely know English and it's my first language...
-----------------------------------------------------------------------
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: A function for the heroic keyword

Postby gorem2k » 25 Sep 2013, 02:54

the only problem I have with adding more compliant functions is , they eat more computer resources; my Pentium G850 is getting close to 100% CPU load when I have 2 planeswalkers + manual mana + hundreds of functions! I'm planning to upgrade but I need to find the money first :lol:
gorem2k
 
Posts: 464
Joined: 01 Apr 2013, 04:21
Has thanked: 48 times
Been thanked: 33 times

Re: A function for the heroic keyword

Postby GrovyleXShinyCelebi » 25 Sep 2013, 03:00

gorem2k wrote:the only problem I have with adding more compliant functions is , they eat more computer resources; my Pentium G850 is getting close to 100% CPU load when I have 2 planeswalkers + manual mana + hundreds of functions! I'm planning to upgrade but I need to find the money first :lol:
Really? I thought most functions took up very little space, and most of the data in a mod came from the art files. That said I have several mods and DOTP in total only takes up 2-3 GB in my PC. It turned out most of my used space was from backup copies of Starcraft II :roll:
User avatar
GrovyleXShinyCelebi
 
Posts: 294
Joined: 12 Jun 2013, 18:23
Has thanked: 14 times
Been thanked: 37 times

Re: A function for the heroic keyword

Postby gorem2k » 25 Sep 2013, 03:21

GrovyleXShinyCelebi wrote:Really? I thought most functions took up very little space, and most of the data in a mod came from the art files. That said I have several mods and DOTP in total only takes up 2-3 GB in my PC.
yeah, I'm not talking about RAM usage nor Hard Disk storage. but the number CPU cycles DotP has to do.

add 999 billion "for i=0, 99 do" inside another loop then you will understand what I mean by that :lol:
gorem2k
 
Posts: 464
Joined: 01 Apr 2013, 04:21
Has thanked: 48 times
Been thanked: 33 times

Next

Return to Programming Talk

Who is online

Users browsing this forum: No registered users and 35 guests


Who is online

In total there are 35 users online :: 0 registered, 0 hidden and 35 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 35 guests

Login Form