It is currently 09 Sep 2025, 21:20
   
Text Size

Question about replacement effects

Post MTG Forge Related Programming Questions Here

Moderators: timmermac, Blacksmith, KrazyTheFox, Agetian, friarsol, CCGHQ Admins

Question about replacement effects

Postby moomarc » 07 Feb 2013, 17:24

I've been trying to add Bloodlord of Vaasgoth today and haven't been able to get one last bit right. Basically he pumps another one of those cardFactoryUtil keywords that are unpumpable (at least not so that they're effective), namely Bloodthirst.

So I had to script the various parts of the keyword and had to add some small bits of code as I went along. The basic script is:
Script | Open
Code: Select all
K:Bloodthirst 3
K:Flying
T:Mode$ SpellCast | ValidCard$ Creature.Vampire | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | Execute$ BloodPump | TriggerDescription$ Whenever you cast a Vampire creature spell, it gains bloodthirst 3.
SVar:BloodPump:AB$ Animate | Cost$ 0 | Defined$ TriggeredCard | Replacements$ etbBloodthirst | sVars$ BloodthirstETB,BloodthirstCounters | UntilLeavesPlay$ True | PumpZone$ Stack
SVar:etbBloodthirst:Event$ Moved | ValidCard$ Card.Self | Destination$ Battlefield | Bloodthirst$ True | ReplaceWith$ BloodthirstETB | Description$ Bloodthirst 3 (If an opponent was dealt damage this turn, this creature enters the battlefield with three +1/+1 counters on it.)
SVar:BloodthirstETB:AB$ ChangeZone | Cost$ 0 | Hidden$ True | Origin$ All | Destination$ Battlefield | Defined$ ReplacedCard | SubAbility$ BloodthirstCounters
SVar:BloodthirstCounters:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 3
The additional code in Animate:
Animate.java | Open
Code: Select all
        // replacement effects to add to the animated being
        final ArrayList<String> replacements = new ArrayList<String>();
        if (sa.hasParam("Replacements")) {
            replacements.addAll(Arrays.asList(sa.getParam("Replacements").split(",")));
        }
Code: Select all
...then later when applying the various bits of Animate:
            // give replacement effects
            final ArrayList<ReplacementEffect> addedReplacements = new ArrayList<ReplacementEffect>();
            if (replacements.size() > 0) {
                for (final String s : replacements) {
                    final String actualReplacement = host.getSVar(s);
                    final ReplacementEffect parsedReplacement = ReplacementHandler.parseReplacement(actualReplacement, c);
                    c.addReplacementEffect(parsedReplacement);
                    addedReplacements.add(parsedReplacement);
                }
            }
Code: Select all
...Then in the unanimate command:
                    // remove added replacement effects
                    for (final ReplacementEffect originalRE : addedReplacements) {
                        int index = -1;
                        // Card.addReplacementEffect adds a copy of the effect so need to find matching repl. effect
                        for (final ReplacementEffect copyOnCard : c.getReplacementEffects()) {
                            if ((copyOnCard.toString()).equals(originalRE.toString())) {
                                index = c.getReplacementEffects().indexOf(copyOnCard);
                                break;
                            }
                        }
                        if (index != -1) {
                            c.getReplacementEffects().get(index).setSuppressed(true);
                        }
                    }
Code: Select all
...One last bit to cover any external factors; in unanimate:
                } else if (sa.hasParam("UntilLeavesPlay")) {
                    c.addLeavesPlayCommand(unanimate);
Adding the replacement effect is fine and it works properly, it's just removing it that is giving me a hard time. At one point I had printlns that checked the replacement effects on the card before and after and the effect was definitely being removed from card. That is to say that card.getReplacementEffects() had one (or more) replacement effects in before the unanimate command, and afterwards had nothing (or just the originals). That's where it gets wierd because card info panel still showed that the replacement effect was there and Flicker ing the card would still cause the replacement to fire. I even tried using card.getReplacementEffects().clear() to make sure I wasn't missing something and the same problem happens - replacement effect fires although the card thinks it has no replacement effects. #-o ](*,)

I suppose this is why animate didn't add replacement effects already, but I'm still curious as to why it happens. :-k

(If you're wondering why I compare the replacement string; it seems that when addReplacement is called, a copy of the parsed replacement is created which is then added to the card. I tested and the original ReplacementEffect != card.getReplacementEffects().get(0) (assuming there is just the one replacement). So I decided to campare the strings and remove the first instance of it and I could finally start removing the intended replacement effects - unfortunately that just didn't help!)

Anyway, if I can get this working I should be able to crack the other cards that try pump those keywords.
-Marc
User avatar
moomarc
Pixel Commander
 
Posts: 2091
Joined: 04 Jun 2010, 15:22
Location: Johannesburg, South Africa
Has thanked: 371 times
Been thanked: 372 times

Re: Question about replacement effects

Postby moomarc » 11 Feb 2013, 15:46

Hmmm. Previous post didn't get anywhere so on to the next topic... I want to convert Dodecapod and friends to proper replacement effects so that they interact properly with Library of Leng (and hopefully I'll also manage Madness). The converted Dodecapod is working perfectly, but using the replacement effect instead of the keyword bypasses the check for good discard candidates in DiscardEffect.java, and I obviously don't want to convert something that makes the AI worse. So how do I check for a specific replacement effect type ("Discard" obviously)?
-Marc
User avatar
moomarc
Pixel Commander
 
Posts: 2091
Joined: 04 Jun 2010, 15:22
Location: Johannesburg, South Africa
Has thanked: 371 times
Been thanked: 372 times

Re: Question about replacement effects

Postby Sloth » 11 Feb 2013, 21:23

moomarc wrote:Hmmm. Previous post didn't get anywhere so on to the next topic... I want to convert Dodecapod and friends to proper replacement effects so that they interact properly with Library of Leng (and hopefully I'll also manage Madness). The converted Dodecapod is working perfectly, but using the replacement effect instead of the keyword bypasses the check for good discard candidates in DiscardEffect.java, and I obviously don't want to convert something that makes the AI worse. So how do I check for a specific replacement effect type ("Discard" obviously)?
Technically Dodecapod doesn't have any discard AI attached, because the keyword differs to the keyword of Loxodon Smiter. Predicting replacement effects is rather laborious, prone to syntax changes and has the danger of causing NPE's. Just add a new SVar DiscardMeByOpp for cards like Dodecapod, Guerrilla Tactics, Psychic Purge and Metrognome.
User avatar
Sloth
Programmer
 
Posts: 3498
Joined: 23 Jun 2009, 19:40
Has thanked: 125 times
Been thanked: 507 times


Return to Developer's Corner

Who is online

Users browsing this forum: No registered users and 34 guests

Main Menu

User Menu

Our Partners


Who is online

In total there are 34 users online :: 0 registered, 0 hidden and 34 guests (based on users active over the past 10 minutes)
Most users ever online was 7303 on 15 Jul 2025, 20:46

Users browsing this forum: No registered users and 34 guests

Login Form