Sneaky Modding Tricks

Discussion in 'Modding' started by Essence, May 29, 2012.

  1. 00face

    00face Member

    Is there any way to trigger effects that are based on your current health or mana? If, so could someone show a rough on how that would look?
     
  2. Kazeto

    Kazeto Member

    No. There are no hooks for current health nor mana in the game, so it is not possible.
     
    OmniaNigrum likes this.
  3. 00face

    00face Member

    OK, what about a trigger for amount of damage taken? So IE: if more than 50hp of damage taken do this, else this.
     
  4. Kazeto

    Kazeto Member

    That doesn't work either, unfortunately. The only requirement tags for triggers are "requirebuffontrigger" and "requirebuffonnottrigger", and I don't think I have to explain what they are doing. In the same vein, the only values you can scale to are on the list you can find in the "Visual Spell Templates and Other Quick References" thread.

    Out of weird things related to damage and current health there is only a way to check how much a given skill (for which you'd have to set the whole process up) damages for, but not only does it only check the nominal damage (meaning any resistances and stuff like that are ignored), but it's not something I'd want to write if I didn't have to. Not that the whole thing is too complicated or anything (if you know what you are doing, that is), but it just reeks of duct tape instead of anything that you could call "legit code".
     
    OmniaNigrum likes this.
  5. Alistaire

    Alistaire Member

    You can't use </br> or /n in strings, but you can use
    HTML:
    &#xa;
    It works like a newline!
     
  6. Monkooky

    Monkooky Member

    I haven't tested to make sure this works, and it's kludgy as all hell, but it's an interesting thought.

    First, cast a spell to summon a Zomby, paralyze it, and make it invisible.
    This sets your hackjob location variable.

    Later, cast a second spell. This second spell has a huge area and triggers a third spell of type targetZomby. This third spell will be targeted at your hackjob location variable.

    Of course, this does create an invisible obstruction, and completely falls apart on floor three.
     
    OmniaNigrum likes this.
  7. OmniaNigrum

    OmniaNigrum Member

    If you take out the idea of doing those things separately, that is what the Gas Canister does already. (It shoots an animation of the canister moving to its landing point then spawns the canister monster then it immediately dies and upon death does the effect of the gas.)

    But some mods have actually done exactly what you are speaking of. :)
     
    Monkooky and Kazeto like this.
  8. Lunix Vandal

    Lunix Vandal Member

    Desired effect: An on-trigger (-hit, -kill, -eat, -drink, -dodge, what have you) effect that swaps out progressively better buffs as you get more hits/kills. No messy stacks of buffs, only one buff in the chain active at a time.
    <spell name="Buff 1" type="self"/>
    <effect type="removebuffbyname" name="Buff 1" amount="0"/> <!-- remove existing stack of Buff 1 if we somehow have one -->
    <!-- Buff goes here -->
    </spell>

    <spell name="Buff 2" type="self"/>
    <effect type="removebuffbyname" name="Buff 1" amount="0"/> <!-- remove previous buff -->
    <effect type="removebuffbyname" name="Buff 2" amount="0"/> <!-- remove existing stack of Buff 2 if we somehow have one -->
    <!-- Buff goes here -->
    </spell>

    <spell name="Buff 3" type="self"/>
    <effect type="removebuffbyname" name="Buff 2" amount="0"/> <!-- and so on -->
    <effect type="removebuffbyname" name="Buff 3" amount="0"/> <!-- and so forth -->
    <!-- Buff goes here -->
    </spell>

    <!-- etc. -->
    <spell name="Buff Improvement A" type="self">
    <effect type="trigger" requirebuffontrigger="1" requirebuffontriggername="Buff 4" spell="Buff 5"/>
    <effect type="trigger" requirebuffontrigger="1" requirebuffontriggername="Buff 3" spell="Buff 4"/>
    <effect type="trigger" requirebuffontrigger="1" requirebuffontriggername="Buff 2" spell="Buff 3"/>
    <effect type="trigger" requirebuffontrigger="1" requirebuffontriggername="Buff 1" spell="Buff 2"/>
    </spell>
    And, for bonus points, the cap on the progressively better buffs rises as you skill the relevant tree. And no always-on dummy buffs or mucking about with the timing of what-casts-when. :eek:
    <ability name="Improving Buff" icon="mod/skill/icon1.png" skill="12345" level="0">
    <description text="WORDS GO HERE."/>
    <targetKillBuff percentage="100" name="Buff Improvement A"/>
    </ability>

    <ability name="Improving Buff 2" icon="mod/skills/icon2.png" skill="12345" level="1">
    <description text="MORE WORDS."/>
    <targetKillBuff percentage="100" name="Buff Improvement B"/>
    </ability>
    <spell name="Buff 5" type="self"/>
    <effect type="removebuffbyname" name="Buff 4" amount="0"/>
    <effect type="removebuffbyname" name="Buff 5" amount="0"/>
    <!-- Buff goes here -->
    </spell>

    <spell name="Buff 5 " type="self"/> <!-- With a space at the end of the name. The crossover point from Improvement A to Improvement B is the only one with the space shenanigans. This stops us from skipping Buff 5 once Buff Improvement B is skilled. -->
    <effect type="removebuffbyname" name="Buff 5" amount="0"/> <!-- no space -->
    <effect type="removebuffbyname" name="Buff 5 " amount="0"/> <!-- yes space -->
    <!-- Buff goes here, exactly the same as "Buff 5" -->
    </spell>

    <spell name="Buff 6" type="self"/>
    <effect type="removebuffbyname" name="Buff 5 " amount="0"/> <!-- also yes space -->
    <effect type="removebuffbyname" name="Buff 6" amount="0"/>
    <!-- Buff goes here -->
    </spell>

    <!-- etc. -->
    <spell name="Buff Improvement B" type="self">
    <effect type="trigger" requirebuffontrigger="1" requirebuffontriggername="Buff 7" spell="Buff 8"/>
    <effect type="trigger" requirebuffontrigger="1" requirebuffontriggername="Buff 6" spell="Buff 7"/>
    <effect type="trigger" requirebuffontrigger="1" requirebuffontriggername="Buff 5 " spell="Buff 6"/> <!-- yes space -->
    <effect type="trigger" requirebuffontrigger="1" requirebuffontriggername="Buff 5" spell="Buff 5 "/> <!-- no space then yes space -->
    </spell>
    Means of acquiring Buff 1 to get the ball rolling is left to the reader's imagination -- I used an If-Then-Else tree (called as another trigger in Buff Improvement A and as a separate on-hit effect) to do it in PIXELS, with Buff 1 getting activated if and only if none of the other, higher buffs were found.
     
  9. mining

    mining Member

    This is going to be a painful post, and a complete work in progress. I need a good spot to keep my tinkering / observation as I go:

    Arbitrary Logic on Arbitrary Values (except resistances and added damage because screw you)

    My first realization was that you can view the player as a straight up map< string, int>, with buff names provided the string, and the stack of buffs size being the int, and that monsters can be used as calculators, as with the wand entropy 'dead stat'.

    Extracting each stat
    To extract any primary or secondary stat, create a summon (I am unsure of if this can be done with no side effects without making an aggressive mob, but an aggressive summon is suitable - and a side effect is required in that a mob must be created somewhere.)

    Kill the mob with 1 damage, and push a buff onto a stack every time you damage it.

    Proceed to resurrect the mob (which must have a lot of starting health) and take it down to 1 HP (by popping a buff off of the stack, and then recursively popping buffs off and doing damage).

    Now, heal the mob with a spell that does 0 base healing and +1 healing per [STAT_DESIRED]. Proceed to kill the mob with 1 damage, pushing a buff onto a stack (e.g. a buff called pc_caddishness).

    The number of stacks of pc_caddishness is the pc's caddishness.

    Copying a variable
    Copying a variable is simple, but requires a lot of pushing and popping steps.

    Copy a var from variable1 to variable2:
    0) Set variable2 to 0.

    1) pop buffs off the first variable's stack, push buffs onto a temp stack.

    2) pop buffs off the temp stack, push buffs onto the first variable's stack and the second variable's stack.

    Arithmetic
    Four main things we'd want to do; subtraction addition, division, multiplication.
    z = x + y
    0) Set z to 0.

    1) pop buffs off x's stack, push buffs onto a temp stack.

    2) pop buffs off the temp stack, push buffs onto x's stack and z's stack.

    3) pop buffs off y's stack, push buffs onto a temp stack.

    4) pop buffs off the temp stack, push buffs onto y's stack and z's stack.

    z = x - y
    0) set z to 0.

    1) pop buffs off x's stack, push buffs onto a temp stack.

    2) pop buffs off the temp stack, push buffs onto x's stack and z's stack.


    3) pop buffs off y's stack, push buffs onto a temp stack.

    4) pop buffs off the temp stack, push buffs onto y's stack and pop buffs off of z's stack. If z runs out of stacks, push a 'negative value' buff onto a stack instead.

    z = x * y //integer multiplication
    0) set z to 0.

    1) copy y to a temp variable.

    2) recursively pop buffs off of the temp variable of y and add x to z.

    z = x / y //integer division
    0) set z to 0

    1) copy x and y to temp variables (say, x1 and y1)

    2) recursively pop y1 many stacks off of x1, and push a stack on Z.

    Rational multiplication and division can be done with a combination of integer multiplication and integer division, within some error.

    Predicates
    i.e. a < b, a > b, etc.

    Make two temp vars. recursively pop from each, testing for each buff not being present.
    If: a AND b are not present, a == b.
    If: a is not present, a < b
    If: b is not present, b > a

    If statements and connectors like 'or' and 'and' are already fairly well understood, so I won't go into that.



    Mmm, I feel like I'm forgetting stuff... Post any stuff you'd like me to nut out / do, and I'll see if I can theory it. I'm not particularly looking forward to writing XML to handle all of this either, if someone else insane wants to work with me on it.
     
  10. Essence

    Essence Will Mod for Digglebucks

    Wow...so we can build a Turing-complete computer entirely out of buffs and summons?

    Sweet -- let's see if we can get it to run a programming language next!
     
    Kazeto and OmniaNigrum like this.
  11. Xavion

    Xavion Member

    As long as you can recursively call a spell in some way without dredmor breaking down it would be relatively simple to design a bf runner, not sure how you'd deal with inputting a program but a series of carefully controlled summons and templates based off the game of life stuff should be able to work. Actually looping would screw that up, you might need to input it into xml. Then you've just got looping (cast a spell if a given buff exists), add or subtract by one (remove/add a buff), output (summons/buffs?), input (monsters/buffs?), and moving the pointer (create a buff based on the presence of another buff). Really it would likely tend towards large length then large complexity except when it comes to inputting programs, that's your major hurdle.
     
    Kazeto and OmniaNigrum like this.
  12. mining

    mining Member

    'programs' would just be mods which run on top of a 'computer' mod, I'd imagine.
     
    Kazeto and OmniaNigrum like this.
  13. Xavion

    Xavion Member

    Well then the hardest part is the pointer, and that can just be a matter of make a gazillion tiered buffs for each cell unless there is another way to make it target a specific buff based off a value. Since I'm not sure of the effectiveness there I'd leave it to the more experienced people as to whether buff stacking or tiered buffs works better for being able to target a different buff for each value.
     
    Kazeto and OmniaNigrum like this.
  14. Kazeto

    Kazeto Member

    Definitely buff stacking - tiered buffs are fun and all, but when you need something with a "high" upper limit that shuffles through many possible tiers in one turn, you don't want to use multiple buffs when just one will suffice as doing that means hoping the whole thing doesn't choke on the icons (since these are used by DoD to recognise buffs, for whatever reason).
     
    OmniaNigrum likes this.
  15. Xavion

    Xavion Member

    How would you go about it then? Having different spells cast based on the amount of buffs in a stack that is. I've had a couple of ideas but they all involve counting from the top not the bottom which is useless as you'd need it the other way around. And you'd need a massive ton of buffs anyway as you'd need one stack per cell in the array which could easily add up to a lot.
     
    OmniaNigrum likes this.
  16. mining

    mining Member

    You don't want to simulate a von neumann machine here if you don't want to deal with infinite pain.

    Seriously, you have access to one data store:
    <string, int>

    You can consider the strings to be your memory addresses, and the ints the value of them if you really like...
     
    OmniaNigrum and Kazeto like this.
  17. Xavion

    Xavion Member

    So let me put it in those terms then. How do we get a string from an int? as unless we can do that we can't really simulate much at all.
     
    OmniaNigrum likes this.
  18. mining

    mining Member

    You really can't do a computer as in the one you're typing on now, lol.

    You could write some immensely complicated logic given a huge room to print out characters based on ascii codes, but the user can barely provide input - the limits here are far too constrained to pull off anything particularly amazing.
     
    OmniaNigrum and Kazeto like this.
  19. Kazeto

    Kazeto Member

    Count from the top to the bottom, one step at a time, executing spell which is to be executed for the given amount of buffs or going lower and checking the next step (with the lower amount of buffs; repeat until you reach one buff on a stack or anything like that), depending on whether there are enough buffs on the stack or not (if yes, execute and remove the corresponding amount of buffs; if not, check the next step).
    The only real constraint in this case is that you have to know what is the triggering value and start from that, and apart from this it's not really difficult to get it working if you have any idea what to do about it.

    And besides, compared to using a lot of different buffs, there is one definite advantage. You don't clutter the code with needless copy-pasted dummy buffs which do nothing outside of showing you how many buffs would be there in a corresponding "stack". Yeah, sure, if you don't mind your code growing larger it is more elegant to make it into a series of buffs, but it's easier to break something then if you don't know how to do it.

    And based on your question, you might not know how to do it.

    It's not exactly a "string", but you can use different bits of an int value to control different things. On the binary level, an int value already is a "string" - of bits.
     
    mining and OmniaNigrum like this.
  20. Xavion

    Xavion Member

    So duplicate the pointer stack to a tempstack then run a series of effects that trigger if the stack is empty or remove one and call the next effect if not empty. Incrementing or decrementing the pointer/value is a simple matter of adding/removing a buff. Input/Output is buff counting/monster summoning. Looping is recursively calling a spell chain dependent on the presence of a buff.

    Assuming the recursive spell chains are possible then that's a plan to functional bf. Although given the game of life implementation we already knew it was turing complete even if something like bf is easier to program.
     
    OmniaNigrum and Kazeto like this.