FORUM ARCHIVED

Questions: Invisible buffs, effects triggered on a specific monster being killed, and more!

Discussion in 'Modding' started by Grasida, Apr 1, 2013.

  1. Grasida

    Grasida Member

    I have a string of questions about whether certain wacky things I'm trying to do are possible or not.

    First of all, are invisible buffs (As in a buff that is active on the player, but runs only behind the scenes and can't be detected in the game) possible?

    Second, is it possible to have an effect trigger on a specific monster being killed? For example, you debuff a monster, then if you kill it before the debuff runs out, you are healed by a certain amount. I tried to do something similar to this with a spell mine, where it would run a trigger to call a spell that targets corpses and if the spell goes off, it destroys everything on the square and applies the buff (idea partially stolen from Essence's Archmage). Of course, the problem with this is that there's nothing to stop you from simply casting the mine on a tile already containing a corpse to get the buff.

    Third, what exactly is the deal with dodgeBuff and friends? I have one dodgeBuff inside a buff that seems to be working and another given in skillDB that doesn't. Are there specific rules about where and how these tags can be used?

    Third, I'm trying to create a skill with a charge system. You can get five ranks of charge, each rank being a buff that replaces the last. I originally had it that if the timer ran out on any level of charge, the buff would disappear. That was working fine, but I decided I want to have it so that when the timer runs out, the buff demotes to the lower tier of charge rather than disappearing entirely. So you get tier 3 charge, which lasts for 10 turns. After that runs out, it demotes to two, rather than simply being removed. I tried to implement this with a system in which when the charge tiers themselves are permanent. However, when they are applied, they in turn apply another buff that does nothing and lasts for 10 turns. They also trigger a spell that checks if you have this dummy buff, and if you don't (i.e. the timer has run out), demotes your charge. My issue is that if I set the timer on the trigger to 10 turns, nothing happens, and if I set it to 11, it crashes the game. Further complicating matters is that I have a "stance" intended to slow down charge degrade when active. I'm sure my implementation is horrendously messy, does anyone have a better idea about how to do this?

    This is my first attempt to mod Dredmor and my first experience with XML. I'm sure it shows. I was originally trying to figure things out for myself, thinking it would be a "learning experience". What I have learned from the experience is that this was not a very good first project and it would probably be a more constructive "learning experience" to simply ask. As such, here is my code from a small part of the charge system.

    Code:
     
    <spell name="Mist Fade" type="self">
        <buff useTimer="1" time="10" allowstacking="0" stacksize="1" self="1" icon="skills/spells/lethian_mist64.png" smallIcon="skills/spells/lethian_mist32.png" bad="0">
        <description text="Your store of mist energy is slowly depleting."/>
        </buff>
    </spell>
     
    <spell name="Mist Fade " type="self">
        <buff useTimer="1" time="6" allowstacking="0" stacksize="1" self="1" icon="skills/spells/lethian_mist64.png" smallIcon="skills/spells/lethian_mist32.png" bad="0">
        <description text="Your store of mist energy is depleting!"/>
        </buff>
    </spell>
     
                <!--Mist Affinity Cluster****-->
     
    <spell name="AffinityKilla1" type="self">
        <effect type="removebuffbyname" name="Mist Affinity 1"/>
    </spell>
     
    <spell name="AffinityKilla1 trigger" type="self">
        <effect type="trigger" requirebuffonnottrigger="1" requirebuffonnottriggername="Mist Fade " spell="AffinityKilla1"/>
    </spell>
     
    <spell name="Mist Affinity 1" type="self">
        <buff useTimer="0" allowstacking="0" stacksize="1" self="1" icon="expansion2/skills/voltaic_magic_inversion64.png" smallIcon="expansion2/skills/voltaic_magic_inversion64.png" bad="0">
            <secondarybuff id="6" amount="5"/> <!--dodge-->
            <resistbuff blasting="-1"/>
            <description text="You feel attuned with the mist."/>
        </buff>
        <effect type="trigger" requirebuffonnottrigger="1" requirebuffonnottriggername="Nebulous Veil " spell="Mist Fade "/>
        <effect type="trigger" requirebuffonnottrigger="1" requirebuffonnottriggername="Nebulous Veil " amount="6" [B]NOTE TO READERS: DOES NOTHING[/B] spell="AffinityKilla1 trigger"/>
    </spell>
     
    <spell name="FastKilla2" type="self">
        <effect type="removebuffbyname" name="Mist Affinity 2"/>
        <effect type="trigger" spell="Mist Affinity 1"/>
    </spell>
     
    <spell name="FastKilla2 trigger" type="self">
        <effect type="trigger" requirebuffonnottrigger="1" requirebuffonnottriggername="Mist Fade " spell="FastKilla2"/>
    </spell>
     
    <spell name="SlowKilla2" type="self">
        <effect type="removebuffbyname" name="Mist Affinity 2"/>
        <effect type="trigger" spell="Mist Affinity 1"/>
    </spell>
     
    <spell name="SlowKilla2 trigger" type="self">
        <effect type="trigger" requirebuffonnottrigger="1" requirebuffonnottriggername="Mist Fade" spell="SlowKilla2"/>
    </spell>
     
    <spell name="Mist Affinity 2" type="self">
        <buff useTimer="0" allowstacking="0" stacksize="1" self="1" icon="expansion2/skills/hyperborean_magic_inversion64.png" smallIcon="expansion2/skills/hyperborean_magic_inversion32.png" bad="0">
            <secondarybuff id="6" amount="10"/> <!--dodge-->
            <secondarybuff id="2" amount="-1"/> <!--melee power-->
            <resistbuff blasting="-2"/>
            <description text="You feel more attuned with the mist."/>
        </buff>
        <effect type="trigger" requirebuffonnottrigger="1" requirebuffonnottriggername="Nebulous Veil " spell="Mist Fade "/>
        <effect type="trigger" requirebuffontrigger="1" requirebuffontriggername="Nebulous Veil " spell="Mist Fade"/>
        <effect type="trigger" amount="6"[B] NOTE TO READERS: DOES NOTHING [/B]requirebuffonnottrigger="1" requirebuffonnottriggername="Nebulous Veil " spell="FastKilla2 trigger"/>
        <effect type="trigger" amount="11" [B]NOTE TO READERS: CRASHES GAME[/B] requirebuffontrigger="1" requirebuffontriggername="Nebulous Veil " spell="SlowKilla2 trigger"/>
    </spell>
    Edit: Okay, changing the order so that the "killa" spells to come after the Affinity spell made it so that it works, but my game still crashed when the charge ran out after I had tried it several times. I will keep poking at it to figure out what's up. Edit 2: Nevermind, stopped working.
     
  2. Kazeto

    Kazeto Member

    Re.1: No. Not for buffs, in any case. You can get automatically triggering abilities to work that way without any buffs appearing, but I doubt you know how to do it (well, had you known, you would not have asked your question about it).

    Re.2: Well, it's slightly tricky due to the fact that monsters can move and there can be more than one monster at a time, not to even mention teleporting/charging monsters, which means that some methods aren't available there. But there is a way, if you don't care about losing part of your sanity.
    To start, make a dummy buff that would trigger a spell every turn for as long as it lasted, and applied another dummy buff on you for every corpse on the tile the monster ended its turn on. Then, make the spell trigger, on the next turn, another spell which would run as many times as there are corpses on the same tile and apply the desired effect if there are no stacks of the other dummy buff or take one stack of said buff if there are any.
    That way it would only trigger if the number of corpses on that particular tile changed. Admittedly it is not a perfect method of doing it, but it is still reliable enough for what you seem to be desiring to make.

    Re.3: Some of these triggers don't have data hooks to work from certain places. Generally speaking, some of them work from skills, some work from items, and some work from buffs. Some of them also don't want to trigger when placed on monsters.

    Re.3.2: First of all, there is the question of "what are the charge levels supposed to be doing to you?". Is it supposed to be just a buff? A base for an activated ability? Both at the same time? I do guess that the code below your question is the code I am supposed to look at, but I do not know know what your final plans as to this one are (probably because I'm too tired to see it now) so I can't (as of yet) give you anything exact outside of just advice or notifying you of obvious errors.

    Now, the code I have yet to take a serious look at due to the fact that I am rather tired and short on time now, but I can post my thoughts about it tomorrow unless someone else does it first.
    Though the "note to readers" makes me want to hit you with a shovel (fortunately, I seem not to have one nearby) - no, it clearly does do something, since it is not commented out, so either comment it out or find out what is it that it does.
    Oh, and the first "Mist Affinity" seems to have some shenanigans with the small icon.
     
    mining and Syphonix like this.
  3. Syphonix

    Syphonix Member

    This REALLY depends on what you are trying to do. As Kazeto said, you can just trigger effects, delayed or otherwise. DoT effects can do some very nice things as well. If you're trying to grant stats that can't be seen with this invisible buff... well, not so much. More information is required on what exactly you are trying to do.

    This won't work as stated because the buff is technically still on you on that 10th turn. The buff won't go away until other calculations and triggered spells happen. Now, it may be possible to use the after="1" here. I'm not sure it would be recognized. I think, honestly, that amount="11" should have worked. But, don't put this in the actual buff spell. Have the buff trigger a dummy spell that then triggers the delayed check. Here's the thing, though: it will trigger in 11 turns no matter what. Say you're in tier 2, and it triggered up a delayed check. In 11 turns, it's gonna check if you still have tier 2, as you have it set up now. But let's say the player has gotten to tier 4 by the 11th turn. Without proper fail-safes it will just go, "hey, this guy doesn't have tier 2 anymore, I guess it's time to downgrade to tier 1." So now you have both tier 1 and tier 4 active at the same time, and next turn you have the tier 3 delayed trigger going off giving you tier 2. Now you have 3 tiers active at once, and each one of those smug bastards is taking turns tea-bagging your tier system. See also, this:

    An alternative option is to have each tier of the buff grant a DoT effect which checks each turn if you still have the buff. The DoT should be able to last 1 turn past the buff without incident, as far as I know. This gets kind of messy because you need ALOT of fail-safes and quickly turns your mod into a 1000-line nightmare. The DoT would need to go through a series of gates to check if you still have that tier of the buff. If not, it then needs to check if you have any OTHER tier of the buff before granting you the downgraded tier. On top of that, it needs a way to take in to account if you didn't have ANY tier of the buff, which likely would require a whole other buff keeping track if you are even in the series of tiers at all. This is important because each buff's dot is going to continue to check for 11 turns. You could have already gone through a full 5-tier cycle by then, but each tier's dot is still going, "ok, he doesn't have that tier or any tier at all. I think I'll just give him the previous tier." And next thing you know you want to punch a small child because you have to sift through 7 light-years of XML.

    What I think I'm getting at before I stopped listening to myself is, you are better off to go with tiers that don't expire and just upgrade. You're treading on some unholy ground here, especially for a first-time dive with DoD modding. But, if you're persistent, I'm sure we can help. I read your code for the tier series and it is sketchy at best. I can tell that you clearly know WHAT you need it to do.

    Also, this:

    icon="expansion2/skills/hyperborean_magic_inversion64.png"

    should be this:

    icon="skills/hyperborean_magic_inversion64.png"

    You don't want to use the expansion folder names whenever you reference anything within them. It's easier just to pretend that the files are part of the base game. Also, you have 2 buffs with VERY similar names. I don't know if the game considers "Mist Fade" and "Mist Fade " to even be different at all. I've never attempted anything like that. If I were you, I would change up the names a bit.
     
  4. Grasida

    Grasida Member

    Thanks for the help.

    Well, I thought it was fairly clear that meant it was not having any noticeable effect on the charge tiers in the game. I'm not saying it does nothing at all, which would, indeed, be a stupid thing to say. The issue with this was that the buff was still considered on the player at the time the trigger was firing, so, it, in fact, wasn't doing anything. I suspected that was true. I didn't know (and still don't) why having the trigger fire one turn later crashes the game.

    This is why there are two buffs. One is the actual charge, one is a buff that does nothing but count the turns until it's legal to demote the charge. Presumably when you have tier one, and go up to tier two, the trigger for tier one fires, but finds you still have the dummy buff (because it's also applied by tier two) and does nothing.

    The game knows the difference. The real danger here is that I won't at some point in the future. I had wanted the buffs to appear to have the same name within the game itself.

    Both. For example, my other major issue right now is that I have a buff (the other "stance") that gives a dodgeBuff that is only supposed to work when you have over the second tier of charge. It works fine when you do have the charge, but crashes the game when you don't. Otherwise the whole system appears to work. Barely. For now. Except for the other dodgeBuff in skillDB.

    So far, simply moving all the triggers out of the buff itself and into another trigger called by the buff when it's applied seems to have stopped the crashing. I'm sure something else will go horribly wrong as I test this whole thing further.
     
    Kazeto likes this.
  5. Grasida

    Grasida Member

    Sorry for the double post. I have several more questions.

    1. I've noticed that buffs are sometimes applied for one turn longer than their listed duration. It seems like this is not just at random, but I can't figure out exactly when and why it happens. Does anyone know?

    Of course, not knowing exactly how many turns a buff will be on the player makes it difficult to have that buff trigger something the turn it goes off. I've gotten around that with a hellish system involving a double loop that checks for two different buffs every turn and casts a spell the turn after one of them has expired. It seems to work all the time except for when I save and reload. I figure there's no way around that, but nor is it that big a deal.

    2. I want to make a melee attack that applies a buff on the player when it hits. The issue I'm having is that if I put the trigger in the spell itself (type="adjacent") the buff will go off whether I hit a monster or not. If I put the buff in a triggered spell with type="targetmonster" the buff won't go off if the melee attack kills the monster, presumably because there's no longer any monster there for the type="targetmonster" spell to target. I feel like I'm missing something obvious here, but I can't figure out what it is. Is there any way around this?

    3. Is there any way to make spell destroy all the corpses (and only corpses) on the tile on which it's cast? I am under the impression, at least, that targetcorpse only destroys one corpse. I tried to make a loop between two targetcorpse spells, but of course that just crashed the game.

    4. What is after="1"? Dredmod mentions it, but gives no explanation of what it means nor can I find an explanation anywhere else.
     
  6. Syphonix

    Syphonix Member

    1) I believe this has to do with the buffs being called on or calling on many spells or triggers. I can't say exactly what causes it, because I don't know, but the circumstances point to many layers of spells going off on the same turn.

    2) Yes. Have the type="adjacent" spell trigger another dummy spell with type="self". Have that spell then call on the buff.

    3) I believe you're right that targetcorpse only destroys one corpse. I don't think you're going to find a good way to do this. However, if you do, please let us all know.

    4) after="1" causes the effect to trigger AFTER all other calculations, such as combat. It is used for things such as blackjack in the Assassination tree. Without it, the sleep would go off and then be removed instantly by combat damage.
     
  7. Grasida

    Grasida Member

    Unfortunately, that will trigger the buff regardless of whether or not I use the skill to hit a monster. The only thing I can think of is to give the player a targethiteffectbuff through the type="adjacent" spell that will let him trigger the buff on his next attack. That's a somewhat ugly solution, but it at least guarantees you can only get the buff by attacking in melee.

    Does anyone know exactly the order in which everything resolves on a combat turn? My image of it is something like this: mines fire, buffs degrade, player acts, damage is applied, triggers fire, monsters act etc.
     
  8. mining

    mining Member

    Make the spell do this, in the following order:

    1) Give the player an onhit buff.
    1.1) The onhit buff triggers the buff you want to give.

    2) Try to hit the enemy
     
    Kazeto likes this.
  9. Grasida

    Grasida Member

    This is the skill as I have it now.

    Code:
       
    <spell name="Wispbind freeze" type="target">
    <effect type="damage" hyperborean="1" hyperboreanF=".12"/>
    </spell>
     
    <spell name="Wispbind DoT" type="target">
        <buff useTimer="1" time="5" self="0" allowstacking="0" icon="skills/spells/arctic_vortex64.png" smallicon="skills/spells/arctic_vortex32.png" stacksize="1" bad="1" >
            <halo name="sprites/sfx/arctic_vortex/arctic_vortex" first="0" num="6" frameRate="100" />
          </buff>
        <effect type="dot" amount="6" spell="Wispbind freeze"/>
    </spell>
     
    <spell name="Wispbind Charge" type="self">
        <buff useTimer="1" time="8" allowstacking="0" stacksize="1" self="1" icon="skills/spells/hyperborean_vitrification64.png" smallicon="skills/spells/hyperborean_vitrification32.png" bad="0">
        <description text="You have already gained affinity from Wispbind Strike and cannot gain more for a brief time."/>
        </buff>
        <effect type="trigger" spell="counter 1"/>
    </spell>
     
    <spell name="wispbind Affinityer" type="self">
        <effect type="trigger" requirebuffonnottrigger="1" requirebuffonnottriggername="Wispbind Charge" spell="Wispbind Charge"/>
    </spell>
     
    <spell name="Wispbind hit" type="targetmonster">
        <effect type="damage" hyperborean="1" hyperboreanF=".15"/>
        <effect type="trigger" amount="1" spell="Wispbind DoT"/>
        <effect type="lockdown" amount="6"/>
     
    </spell>
     
    <spell name="Wispbind Primer" type="self">
        <buff usetimer="1" time="4" attacks="1" allowstacking="0" stacksize="1" bad="0" self="1" removable="0" icon="skills/spells/hyperborean_vitrification64.png" smallicon="skills/spells/hyperborean_vitrification32.png">
        <targethiteffectbuff percentage="100" name="wispbind Affinityer"/>
        <description text="You have drawn power from striking your foe. Your next attack will build mist affinity.">
        </buff>
    </spell>
     
    <spell name="Wispbind Strike" downtime="3" type="adjacent" attack="1" icon="skills/spells/hyperborean_vitrification32.png">
        <effect type="trigger" spell="Wispbind hit"/>
        <effect type="trigger" requirebuffonnottrigger="1" requirebuffonnottriggername="Wispbind Charge" spell="Wispbind Primer"/>
        <description text="As you strike at an enemy, you conjure strands of frozen mist that bind it in place. This leaves you more attuned to the mist for a short time."/>
        </spell>
    I might actually prefer it this way, requiring two turn to build charge rather than one. I don't know if it would be possible to have Wispbind Strike itself consume Wispbind Primer and so trigger wispbind Affinityer on the same turn, but I'm not very committed to working it out since I'm basically satisfied with this.
     
  10. mining

    mining Member


    Your method seems pretty complicated. You have a 3 downtime skill that triggers a 4 round buff, that can't be triggered more than once every 8 rounds. The 3 downtime spell additionally applies a grabbag of spells to the target monster. (if counter does something nifty, I don't know ;))

    So, a simpler way to implement this might be:


    grabbag_of_effects ;;trigger whatever you like here.
    trigger_whatever

    8_round_dummy_buff ;;Holds info to when you can next have 4 round buff.
    trigger_blah

    4_round_cool_buff ;;Gives your buffy stuff.
    trigger_other_stuff

    attack_spell
    trigger 4_round_cool_buff
    trigger 8_round_dummy_buff amount="1" ;;amount="1" delays it 'til the /end/ of your round
    trigger grabbag_of_effects


    That ought to:
    Attack -> give cool buff -> trigger grabbag of effects -> end of round -> 8 round dummy buff.

    Alternatively, you can add another spell to apply the 4 round cool buff to the actual attack.
     
    Kazeto likes this.
  11. Grasida

    Grasida Member

    Yeah, that would be much simpler. The reason this spell (and the whole skill, to be honest) is like this is because not only have I had to revise my methods many times because I didn't know how to do anything, but also because I have already changed what I actually want the spells to do several times. Really, I ought to just rewrite the whole thing from the start, but I have long given up on this being well-coded. I'm largely continuing to work on it now just out of stubbornness and because I want to finally be able to play the thing.

    Counter 1, by the way, counts your current level of charge and upgrades you by one tier.
     
    Syphonix and mining like this.