Code blog: Taint v2

... sit down, kick back and relax, and talk about anything that doesn't belong on one of the other forums.
Aureus
Posts: 968
Joined: Mon Dec 28, 2020 11:13 pm

Code blog: Taint v2

Post by Aureus » Sun May 22, 2022 11:02 pm

I decided to go ahead and share a code blog to document the progress on a larger feature: taint v2. I will no doubt be far less entertaining than Itesh, but that's the burden I have to bear.

It's a Sunday morning (~10am), and I've decided to get started on this one. I have a fairly decently written high-level mechanical design document already that we've reviewed, debated and aligned on at the Staff level. I do not have a list of the specific changes I will need to make.

I'm using Trello for the project management side of this (and all code changes), so I create a new Trello card and start to detail out the list of individual tasks, which roughly equate to concrete things I need to either implement (such as the various taint effects) or other things I need to check or do (such as create some helper functions to make taint gain consistent, and removing the old taint effects). It includes checking whether I need to make large changes to the data structure of the stored player file, which would require help from Flash and significantly lengthen this project.

This takes awhile to translate from the design doc. There are 24 items (to start) on the list. Many are pretty high level and don't include any of the details for how I will accomplish those things.

Now, since we are hoping to greatly increase the range of taint (behind the scenes, taint only goes from 0 - 250 points today, and we want to increase it up to ~50k), I need to check whether there is the right size of variable allocated to store taint. I am fairly sure there is, since I looked at this previously. Good news, there is!

I start by updating the max taint limit to 50k. This requires updating some helper functions used to support imm commands and the like, but is fairly straightforward. I also add in a hard cap to the value, because this is old code and fairly poorly written, so it didn't have decent safety checks in place before.

It is now noon, and I am being pestered to make "breakfast", so I take a break.

Now that it's ~2pm, I go back to it.

Next I remove the old taint (command randomization and the like). My initial idea is to comment out that code entirely. Then I realize there is a "temporary taint" effect that's used in the Ways, but doesn't permanently stick with the character and dissipates quickly on its own. Hrm, this is the first new decision I will need to make. Frequently we run into these sorts of things when digging deeper into the code. I debate for a bit whether to remove that too. In the end, I decide it's easiest to simply leave the "temporary (Ways) taint" in place in case we want to use it for something down the road, and the new saidin taint design is very focused on channelers (so not appropriate for e.g., a warrior or hunter). It's also my preference to minimize unrelated gameplay changes when running into an unanticipated decision, and this accomplishes that. So I unhook the "saidin taint" from the command randomization, but leave it in place for the "temporary taint" used in the Ways.

I update how the game looks up how much taint the character has to separate the "saidin taint" from the "temporary (Ways) taint" as well. They are now distinct mechanics.

I also make a note that the ruby dagger continues to give "saidin taint". Hrm. That is not really desirable. Perhaps temporary taint is a better fit? Though temporary is not right there from a lore perspective, so I decide not to move that over to temporary taint. Perhaps later in the project I will look at making the taint slightly different for channelers and non-channelers -- I make a note to do that on the Trello card. It might also be nice to let the Yellow Ajah cure ruby dagger taint on non-channelers (it would not be bookish to cure saidin taint for male channelers), though that would require a brand new weave or maybe we just mobol something, so perhaps a project for another day. And the ruby dagger isn't in the game anyway, so it's a bit moot. It is also now ~3:30pm.

Now that the taint limit is increased and the old taint removed, it's time to start with having male channelers gain taint. I've decided to centralize how this is handled so it's consistent everywhere (because, I note, a few obscure places where MCs gain taint don't respect Darkfriends' protection against it, and also it's just a good practice). I create a new, empty function, and make channeling as a male call to that function. Then I start filling out the function -- the amount of taint gained will be proportional to how much saidin is channeled, so I look up the spell cost of the spell and use that. There is also a very small chance of gaining taint from seizing saidin, so I add that. I add in the appropriate checks so that NPCs, Imms, Darkfriends, and Dreadlords don't gain taint. That last one is new - previously we had to flag Dreadlords as Darkfriends, and we had at least one case of a Trolloc remorting to a Dreadlord where someone forgot to apply that flag and they were becoming tainted. I also decide to add in a bit of an easter egg for some nostalgia, and this ends up taking quite a bit longer than anticipated, but I'm quite pleased with it. It is now 6pm.

I decide to start with some simple effects of the taint. The first are some flavor messages. These are quite simple and it goes smoothly.

Then I decide to start with another effect that's a bit more fun and a bit out of order of my task list: one where very-tainted characters will sometimes weave on the wrong target. This requires writing a new function to find a random player in the room, and modifying how spell targeting works. It takes some fiddling around, and I have to spend some time Googling vectors in C++ to remember how they work since it's been awhile since I've used one. But this gets done.

It's now 7:30pm. I've written a fair amount of code, so time to see if it compiles. I start writing this blog post while it compiles. It does not -- I made a simple typo (forgot a "*") and treated a pointer as a literal variable, and the compiler catches this. I fix it, and recompile. It works, and so I will be able to play with this on the test mud, which I'm quite looking forward to.

But it's now 8pm and time to cook dinner. Fun Sunday coding, but not as much progress as I'd liked and this project is a large one, so this will be a fairly decent chunk of time.

Aureus
Posts: 968
Joined: Mon Dec 28, 2020 11:13 pm

Re: Code blog: Taint v2

Post by Aureus » Mon May 23, 2022 2:02 am

It's now 10:30pm and I have a spare hour or so before bed. So I want to test out the changes. I boot up the test mud, which promptly crashes as it boots up. Hrm. Ah, I see in the crash log that I have forgotten an NPC check when I made the "temporary (Ways) taint" a distinct mechanic from normal taint, and this has caused the game to crash when the Guardian started to load mobs as part of zone setup. But the Guardian is a mob and mobs do not have taint, so checking its taint crashes the game. That's an easy fix.

Now that it's working, I create Aureus (he is a 105 there) and Atest, my poor test character who is going to suffer horrific taint. Let's check that gaining taint works properly.

I have added in some debug messages to make this easier to test.
Execution Square
The streets open up into a large square meant for executions. Large steel
cages hang in corners, and very few of the stocks remain empty. Several
mean looking guards stand watch in the crowd. A large wooden platform has
been erected in the center of the square, and a bloodied block of wood
rests on top. Several strange sharp utensils can be seen on a table nearby,
and a large axe rests against the platform.
[ obvious exits: N E ]
A man walks among the horses here feeding them and rubbing them down.
Aureus the Creator is standing here.

* HP:Healthy SP:None MV:Fresh > seize
You feel the flows of saidin coursing through your body.
DEBUG: rolling taint for spell_cost=1.
Success! Now let's try a weave...
* HP:Healthy SP:None MV:Fresh > h
[channel 'heal' hand]
You begin to weave the appropriate flows...

-
DEBUG: rolling taint for spell_cost=1.
Ok.
You channel flows of Air and Spirit into a stable hand, healing him.
Hrm, not as intended. After some debugging I see that I have put the call to roll for taint in the wrong location, where the sp cost hasn't been figured out yet. This takes ~15 minutes to figure out and patch up. Let's try again.
* HP:Healthy SP:None MV:Fresh > seize
You feel the flows of saidin coursing through your body.
DEBUG: rolling taint for spell_cost=1.

* HP:Healthy SP:None MV:Fresh > h
[channel 'heal' hand]
You begin to weave the appropriate flows...

-
DEBUG: rolling taint for spell_cost=100.
DEBUG: got taint. taint=1/50000.
Ok.
You channel flows of Air and Spirit into a stable hand, healing him.
Aha. Very excellent.

Aureus
Posts: 968
Joined: Mon Dec 28, 2020 11:13 pm

Re: Code blog: Taint v2

Post by Aureus » Mon May 23, 2022 2:12 am

Now to test out some of the functionality:
* HP:Healthy SP:Bursting MV:Fresh > <special imm command>
Atest's taint set to: 50000.
He's set to max!
* HP:Healthy SP:Bursting MV:Fresh > s
[seize ]
You feel the flows of saidin coursing through your body.
Along with saidin comes an oily foulness.

* HP:Healthy SP:Bursting MV:Fresh > rel
s
Ok.

* HP:Healthy SP:Bursting MV:Fresh > [seize ]
You feel the flows of saidin coursing through your body.
A rancid slick of oil fouls the surface of saidin.
Some of the flavor messages are looking good! Let's try the target swapping:
Execution Square
The streets open up into a large square meant for executions. Large steel
cages hang in corners, and very few of the stocks remain empty. Several
mean looking guards stand watch in the crowd. A large wooden platform has
been erected in the center of the square, and a bloodied block of wood
rests on top. Several strange sharp utensils can be seen on a table nearby,
and a large axe rests against the platform.
[ obvious exits: N E ]
A wisdom stands here ready to help.
A man walks among the horses here feeding them and rubbing them down.
Aureus the Creator is standing here.

* HP:Healthy SP:Bursting MV:Fresh > h
[channel 'heal' hand]
You begin to weave the appropriate flows...

-
Ok.
You channel flows of Air and Spirit into Aureus, healing him.
Quite nice as well. With that, time to start winding down for bed, and that is as far as I've gotten today. I've spent most of the day coding, which is unusual for a weekend to have as much time (and attention) for it. But the basic framework is in place, so I should be able to chip away at it.

Itesh
Posts: 828
Joined: Sat Feb 14, 2015 4:59 am

Re: Code blog: Taint v2

Post by Itesh » Mon May 23, 2022 3:18 am

Can't even use the dereferencing operator, eh? Code access WITHDRAWN.

:D

Talasia
Posts: 71
Joined: Fri Dec 06, 2019 10:26 am

Re: Code blog: Taint v2

Post by Talasia » Mon May 23, 2022 10:43 am

Aureus wrote:
Sun May 22, 2022 11:02 pm
I add in the appropriate checks so that NPCs, Imms, Darkfriends, and Dreadlords don't gain taint. That last one is new - previously we had to flag Dreadlords as Darkfriends, and we had at least one case of a Trolloc remorting to a Dreadlord where someone forgot to apply that flag and they were becoming tainted.
I think that it would be more fun if NPCs tainted. We need some random villager mobs throughout the world that look like normal villagers, but turn out to secretly be MCs that taint throughout the day and get progressively more dangerous until reboot.

I find the trolloc-remort tainting hilarious!

Aureus
Posts: 968
Joined: Mon Dec 28, 2020 11:13 pm

Re: Code blog: Taint v2

Post by Aureus » Mon May 23, 2022 8:52 pm

Well it's Monday evening and I'm feeling a little motivated to make some more progress. So I've spent a couple more hours (~3) doing a simple change to highly tainted characters' appearance on look, since we know from the books that this is described as a rotting disease or wasting sickness. In one future seen in the arches, Rand has lost some limbs because of it. This part is fairly straightforward because we already have some code that does this, such as when looking at a Damane. So I just copy that code and modify it. I decide to make two different levels of it -- one at higher levels of taint where it's progressed further and is a bit nastier.

Then I decide to take on one of the trickier parts of the change, which is to have damage weaves have a chance at high taint levels to "splash" damage onto other people in the room. The messages will need to be unique for the primary element of the weave for it to make much sense. I decide to create a central function to manage this (checking whether the person is tainted, a male channeler, and so on, where having it in one place makes it consistent), and just keep track of which element was used. Call Lightning is a bit of an odd one since it's not quite fire and not quite air, so I decide to handle that as a unique special case: we will have 5 element-based versions of the messages, and one special case for lightning. This creates a bit more work.

Then I need to strike random people in the room -- fortunately I've already written a helper function to get random people in the room for the prior change to weave targeting, so I can copy that code. I do need to modify it a bit because I want to apply some different restrictions to just grabbing any random old person in the room: in this case I do not want it to hit the primary target of the weave (this is splash damage, not bonus damage), and I also don't want it to hit the male channeler's ridden horse. This would make the male channeler unplayable I think, and plus everyone needs a friend, even if you're incurably insane. Likewise, I don't want to grab completely random targets in the room each time, because I don't want it to double-up and hit the same target multiple times. So I need to store a list of all the eligible targets in the room so I can pick from it at random, keeping track of who's already been hit and who hasn't been.

Then I need to decide the odds of this going off, which I tie to how tainted the person is. I also need to decide how many targets it hits, which again I decide to make random but with a maximum based on how tainted the person is. Lastly I need to decide damage, which (you guessed it) I also make dependent on how tainted the person is. To prevent abuse by newbies/lowbies creating highly tainted characters and then going on a rampage, I also make the damage reduce if the male channeler is low level.

Then, I need to write a bunch of flavor messages. This is not really my forte but I make due. I spend an inordinate amount of time googling Earth weaves for something more interesting than another-earthquake. Hrm, not a lot of help there. Stone spikes it is.

Lastly, I need to add hooks into all the appropriate damage weaves to check this central function.

Ok, this is now a lot of code, so time to test it out and make sure it works. Sure enough, it has an error: I used "for" instead of "while" in one of my loops and the compiler lets me know I've used improper syntax. It takes me ~10 mins to identify the issue, fix it, and recompile. Now it works, and I boot up the test mud and create my two test characters and set them up.

Time to test a few things here:
* R:1035 S:Inside HP:Healthy SP:Bursting MV:Fresh > <fancy imm command>
Atest's taint set to: 0.

* R:1035 S:Inside HP:Healthy SP:Bursting MV:Fresh > l atest

Atest is in excellent condition.

Atest is using:
<worn about body> a fine black coat of silk
<wielded two-handed> an oddly curved greatsword

You attempt to peek at the inventory:
You can't see anything.

* R:1035 S:Inside HP:Healthy SP:Bursting MV:Fresh > <fancy imm command>
Atest's taint set to: 10000.

* R:1035 S:Inside HP:Healthy SP:Bursting MV:Fresh > l atest

Atest looks pale and hollowed out, as if afflicted by a wasting sickness.

Atest is in excellent condition.

Atest is using:
<worn about body> a fine black coat of silk
<wielded two-handed> an oddly curved greatsword

You attempt to peek at the inventory:
You can't see anything.

* R:1035 S:Inside HP:Healthy SP:Bursting MV:Fresh > <fancy imm command>
Atest's taint set to: 50000.

* R:1035 S:Inside HP:Healthy SP:Bursting MV:Fresh > l atest

Atest looks cadaverous and appears to be rotting alive.

Atest is in excellent condition.

Atest is using:
<worn about body> a fine black coat of silk
<wielded two-handed> an oddly curved greatsword

You attempt to peek at the inventory:
You can't see anything.
And not so bad. That was the easy part. Now to test the splash damage. I fully expect something to break here, as this is fairly complex.
* HP:Healthy SP:Full MV:Fresh > l
Execution Square
The streets open up into a large square meant for executions. Large steel
cages hang in corners, and very few of the stocks remain empty. Several
mean looking guards stand watch in the crowd. A large wooden platform has
been erected in the center of the square, and a bloodied block of wood
rests on top. Several strange sharp utensils can be seen on a table nearby,
and a large axe rests against the platform.
[ obvious exits: N E ]
A giant aurochs bull stands here guarding his herd.
A giant aurochs bull stands here guarding his herd.
A giant aurochs bull stands here guarding his herd.
A giant aurochs bull stands here guarding his herd.
A giant aurochs bull stands here guarding his herd.
A giant aurochs bull stands here guarding his herd.
A giant aurochs bull stands here guarding his herd.
Aureus the Creator is standing here.

* HP:Healthy SP:Full MV:Fresh > f
[channel 'flame strike' bull]
You begin to weave the appropriate flows...

=
Ok.
Streaks of fire flow from your hands, burning a hairy aurochs.

* HP:Healthy SP:Full MV:Fresh - a hairy aurochs: Hurt > f
[channel 'flame strike' bull]
You begin to weave the appropriate flows...

+
A hairy aurochs tries to hit you, but you deflect the blow.

=
Ok.
Streaks of fire flow from your hands, burning a hairy aurochs.

* HP:Healthy SP:Strong MV:Fresh - a hairy aurochs: Wounded > f
[channel 'flame strike' bull]
You begin to weave the appropriate flows...


A hairy aurochs tries to hit you, but you parry successfully.

=
Ok.
Streaks of fire flow from your hands, burning a hairy aurochs.

* HP:Healthy SP:Strong MV:Fresh - a hairy aurochs: Wounded > f

A hairy aurochs hits your body very hard.
A hairy aurochs leaves north.
You slice a hairy aurochs's left leg very hard.
A hairy aurochs tries to hit you, but you parry successfully.

[channel 'flame strike' bull]resh - a hairy aurochs: Wounded >
You begin to weave the appropriate flows...

=
Ok.
Streaks of fire flow from your hands, burning a hairy aurochs.
Enemies, enemies everywhere! You lash out with saidin.
Gouts of fire sear out wildly, burning a hairy aurochs.
Gouts of fire sear out wildly, burning a hairy aurochs.
Very nice! Let's try a different weave...
[channel 'earthquake']
You begin to weave the appropriate flows...

+
Ok.
The earth trembles and shivers beneath your feet..!
A hairy aurochs vibrates and is knocked about.
A hairy aurochs vibrates and is knocked about.
A hairy aurochs vibrates and is knocked about.
A hairy aurochs vibrates and is knocked about.
A hairy aurochs vibrates and is knocked about.
A hairy aurochs vibrates and is knocked about.
Aureus vibrates and is knocked about.
Enemies, enemies everywhere! You lash out with saidin.
The earth heaves up, stabbing a hairy aurochs with stone spikes.
The earth heaves up, stabbing a hairy aurochs with stone spikes.
The earth heaves up, stabbing a hairy aurochs with stone spikes.
The earth heaves up, stabbing a hairy aurochs with stone spikes.
That's great! I make a note that I probably do not want this hitting imms, which I think I did not check for. I will have to check all the elements to make sure they're working, as well as check every weave I added this to so that I know I called this function properly. I will also need to ensure the various restrictions I added are working properly. Now let's check that the special kill messages are working (I target Aureus here because my ice spikes were killing the dogs before the splash damage got them):
* HP:Scratched SP:Fading MV:Fresh - Aureus: Healthy > i
[channel 'ice spikes' aureus]
You begin to weave the appropriate flows...

=
You swiftly dodge Rufferto, faithful dog of the sage's attempt to hit you.
You swiftly dodge Rufferto, faithful dog of the sage's attempt to hit you.
Aureus tries to hit you, but you deflect the blow.

=
Ok.
Spikes of solid ice form in your hands, which you launch at Aureus.
Enemies, enemies everywhere! You lash out with saidin.
Blood never gets boring, does it?
Shards of broken ice flay Rufferto, faithful dog of the sage into a glittering, wet pile of torn flesh.
Rufferto, faithful dog of the sage is dead! R.I.P.
Your blood freezes as you hear Rufferto, faithful dog of the sage's death cry.
Blood never gets boring, does it?
Shards of broken ice flay Rufferto, faithful dog of the sage into a glittering, wet pile of torn flesh.
Rufferto, faithful dog of the sage is dead! R.I.P.
Your blood freezes as you hear Rufferto, faithful dog of the sage's death cry.
Excellent. I'm fairly pleased that this all seems to be working properly on the first go-around, compiler error aside. I will spend a little more time testing the various messages and and ins-and-outs, but I think I can call this one mostly done. Total time spent on these two is about 4 hours today so far, and probably another hour for testing to go.

Aureus
Posts: 968
Joined: Mon Dec 28, 2020 11:13 pm

Re: Code blog: Taint v2

Post by Aureus » Mon May 23, 2022 10:31 pm

I have coded in some restrictions on following others. This kicks in earlier and makes following more difficult as your paranoia builds up. I just re-used how fear works here as it already exists and the message is very appropriate, only it is on a % chance. At a certain point as the taint progresses, following stops functioning entirely. Because of that, I decide not to tie the earlier % chance to taint level, because having an e.g., 1/10 chance of following working would be frustrating.
* R HP:Healthy SP:Full MV:Fresh > fol atest
You are already following yourself.

* R HP:Healthy SP:Full MV:Fresh > fol aureus
You now follow Aureus.

* R HP:Healthy SP:Full MV:Fresh > fol
You stop following Aureus.

* R HP:Healthy SP:Full MV:Fresh > fol aureus
You now follow Aureus.

* R HP:Healthy SP:Full MV:Fresh > fol
You stop following Aureus.

* R HP:Healthy SP:Full MV:Fresh > fol aureus
You now follow Aureus.

* R HP:Healthy SP:Full MV:Fresh > fol
You stop following Aureus.

* R HP:Healthy SP:Full MV:Fresh > fol aureus
Follow them? Are you crazy? he's probably plotting to kill you!
I also decide to tackle the wasting effects of the taint. We have envisioned this as an HP and MV regen malus as it progresses.

Rather than implement this as a % reduction to regen that grows over time, I decide to make it skip certain regen tics entirely. This has two advantages: it allows me to add in a flavor message that isn't super spammy, and also it is easier to scale than a constant % reduction (because HP regen involves small numbers to begin with, it would become debilitating if it scaled that way, or I would have to have it not scale very much at all). The flavor message will do a good job of helping players understand that something happened.

I set this chance relatively low, because it is a pretty strong effect when it happens, and we want male channelers to be playable.

Movement regen does not happen in the same place as HP regen, which is obnoxious. I do not want these chances to roll independently of each other, so I have to add some new state tracking to keep track of when someone has missed a regen tic due to the taint so it can be applied in both places.

I do not add it to SP regen -- the Breaking and lore suggest that even very tainted channelers seem to be strong in the One Power and dangerous, so we want them to have firepower.
* R HP:Critical SP:Bursting MV:Haggard >
You feel a sudden wave of nausea.

* R HP:Critical SP:Bursting MV:Haggard >
These are both fairly simple changes and work on the first try, but in all this has taken another hour or so to think through, implement, and test.

Now I need to take a break and head to the gym and figure out dinner.

Aureus
Posts: 968
Joined: Mon Dec 28, 2020 11:13 pm

Re: Code blog: Taint v2

Post by Aureus » Tue May 24, 2022 2:13 am

It's now after dinner and I have an hour or so before bed, so I decide to tinker on one of the easier effects, which is to have seizing saidin sometimes come with some nasty effects from the taint at high taint levels. There are three, and they are all relatively easy to code. It takes ~30 minutes to make sure I'm doing this properly, and another ~30 to compile, boot up the test mud, and test them to make sure they're working properly:
* HP:Healthy SP:Full MV:Fresh > seize
You feel the flows of saidin coursing through your body.
A putrid, rotten residue coats you.
Bile comes up and you empty your stomach, retching violently.

* HP:Healthy SP:Full MV:Fresh > rel
Ok.

* HP:Healthy SP:Full MV:Fresh > seize
You feel the flows of saidin coursing through your body.
Along with saidin comes an oily foulness.
Nausea engulfs you, the world spins around you.

* HP:Healthy SP:Full MV:Fresh > rel
Ok.

* HP:Healthy SP:Full MV:Fresh > seize
You feel the flows of saidin coursing through your body.
A putrid, rotten residue coats you.
You fight a wave of sickness, and saidin slips from your grasp.

* HP:Healthy SP:Full MV:Fresh > rel
You aren't in touch with saidin to release anything.
...and from the observer's point of view:
* R:1035 S:Inside HP:Healthy SP:Bursting MV:Fresh >
Atest empties his stomach, retching violently.
You sense Atest connecting to the True Source.

* R:1035 S:Inside HP:Healthy SP:Bursting MV:Fresh >
Atest sways unsteadily and loses his balance.
You sense Atest connecting to the True Source.

* R:1035 S:Inside HP:Healthy SP:Bursting MV:Fresh >
Atest blanches and looks unwell.
Fairly straightforward. The chance this happens is based on taint level, and Atest being at max taint makes this pretty easy to check.

I notice during testing that the anti-regen message is a bit spammy at max taint, so I mute it if the player is at full health and moves. It will now only show when it actually blocks some regen.

Another hour spent on this brings me up to about 5 hours today. I am getting some significant other aggro, so this is not quite sustainable (plus I'm neglecting some other chores), but I'm enjoying making some good progress.

Aureus
Posts: 968
Joined: Mon Dec 28, 2020 11:13 pm

Re: Code blog: Taint v2

Post by Aureus » Tue May 24, 2022 3:34 am

Perhaps you wish to play a Damer Flinn type, you say, and will suffer through the taint to bring Healing to the land. Not to worry, you are covered.

In this scenario, for highly tainted characters we also roll a chance of replacing the weave they were intending to channel with one that is potentially less benign. This is more complicated than it sounds, because behind the scenes we store a weave database number during the delay, and that number is used to check all sorts of things: not least of which is the success rate of the weave based on your practices. And a clever Damer Flinn might only practice helpful weaves. And, I cannot simply add new data into the skill delay because the variables are already full. Hrm, hrm. Well, I manage to hack something anyway that gets around this. Flash will potential be unhappy about it, we will see. And for a weave chosen by the taint, we will treat the player as having 99% in the weave.

For the purposes of testing, I set the chance of a different weave being picked to 100%. In practice, it will be far less than that and also scale with taint.

This all takes about an hour and a half.

Surprisingly, this compiles on the first go-around. Time to embark on a mission of healing!
* HP:Healthy SP:Bursting MV:Fresh > seize
You feel the flows of saidin coursing through your body.
A putrid, rotten residue coats you.
You fight a wave of sickness, and saidin slips from your grasp.

* HP:Healthy SP:Bursting MV:Fresh > seize
You feel the flows of saidin coursing through your body.
A putrid, rotten residue coats you.

* HP:Healthy SP:Bursting MV:Fresh > h
[channel 'cure light wounds' dog]
DEBUG: taint: picking new weave.
You begin to weave the appropriate flows...

=
Ok.
Streaks of fire flow from your hands, burning Rufferto, faithful dog of the sage.

* HP:Healthy SP:Full MV:Fresh - Rufferto, faithful dog of the sage: Battered > h
[channel 'cure light wounds' dog]
DEBUG: taint: picking new weave.
You begin to weave the appropriate flows...

-
You swiftly dodge Rufferto, faithful dog of the sage's attempt to hit you.

*
Ok.
You can't get close enough to them in the heat of battle.

* HP:Healthy SP:Full MV:Fresh - Rufferto, faithful dog of the sage: Battered >
Rufferto, faithful dog of the sage swiftly dodges your attempt to hit it.
You swiftly dodge Rufferto, faithful dog of the sage's attempt to hit you.

* HP:Healthy SP:Full MV:Fresh - Rufferto, faithful dog of the sage: Battered > h
[channel 'cure light wounds' dog]
DEBUG: taint: picking new weave.
You begin to weave the appropriate flows...

=
You hit Rufferto, faithful dog of the sage's head.
Rufferto, faithful dog of the sage tries to hit you, but you dodge the attack.
Ok.
Your first time! Was it good for you too?
Streaks of Fire burn through Rufferto, faithful dog of the sage, leaving only a blackened corpse.
Rufferto, faithful dog of the sage is dead! R.I.P.
Your blood freezes as you hear Rufferto, faithful dog of the sage's death cry.

* HP:Healthy SP:Strong MV:Fresh > h
[channel 'cure light wounds' dog]
DEBUG: taint: picking new weave.
You begin to weave the appropriate flows...

=
Ok.
*CRACK* A loud thunderclap resonates through the entire area..!
Rufferto, faithful dog of the sage's flesh rattles to the bone from the powerful thunderclap.
Rufferto, faithful dog of the sage's flesh rattles to the bone from the powerful thunderclap.
Rufferto, faithful dog of the sage's flesh rattles to the bone from the powerful thunderclap.
Rufferto, faithful dog of the sage's flesh rattles to the bone from the powerful thunderclap.
Rufferto, faithful dog of the sage's flesh rattles to the bone from the powerful thunderclap.
Rufferto, faithful dog of the sage's flesh rattles to the bone from the powerful thunderclap.
Enemies, enemies everywhere! You lash out with saidin.
The wind howls thunderously and sends debris slamming into Rufferto, faithful dog of the sage.
Rufferto, faithful dog of the sage is stunned, but will probably regain consciousness...
The wind howls thunderously and sends debris slamming into Rufferto, faithful dog of the sage.
The wind howls thunderously and sends debris slamming into Rufferto, faithful dog of the sage.
The wind howls thunderously and sends debris slamming into Rufferto, faithful dog of the sage.

* HP:Healthy SP:Strong MV:Fresh - Rufferto, faithful dog of the sage: Critical >
You swiftly dodge Rufferto, faithful dog of the sage's attempt to hit you.
You swiftly dodge Rufferto, faithful dog of the sage's attempt to hit you.
You swiftly dodge Rufferto, faithful dog of the sage's attempt to hit you.
You swiftly dodge Rufferto, faithful dog of the sage's attempt to hit you.
Rufferto, faithful dog of the sage tries to hit you, but you dodge the attack.
You hit Rufferto, faithful dog of the sage's right leg.
Rufferto, faithful dog of the sage is dead! R.I.P.
Oh, much better the second time around.
Your blood freezes as you hear Rufferto, faithful dog of the sage's death cry.

* HP:Healthy SP:Strong MV:Fresh > h
[channel 'cure light wounds' dog]
DEBUG: taint: picking new weave.
You begin to weave the appropriate flows...

*
Rufferto, faithful dog of the sage hits your left leg very hard.
Wimpy reset to: 244 hit points.
PANIC! You couldn't escape!
Rufferto, faithful dog of the sage tries to hit you, but you dodge the attack.
You swiftly dodge Rufferto, faithful dog of the sage's attempt to hit you.
You swiftly dodge Rufferto, faithful dog of the sage's attempt to hit you.
You swiftly dodge Rufferto, faithful dog of the sage's attempt to hit you.
Ouch! You couldn't maintain the flows.

* HP:Scratched SP:Strong MV:Fresh - Rufferto, faithful dog of the sage: Critical > h
[channel 'cure light wounds' dog]
DEBUG: taint: picking new weave.
You begin to weave the appropriate flows...

-
Rufferto, faithful dog of the sage tries to hit you, but you dodge the attack.
Rufferto, faithful dog of the sage tries to hit you, but you dodge the attack.
You swiftly dodge Rufferto, faithful dog of the sage's attempt to hit you.
You swiftly dodge Rufferto, faithful dog of the sage's attempt to hit you.
Rufferto, faithful dog of the sage tries to hit you, but you dodge the attack.

=
Ok.
Three times is the charm!
Streaks of Fire burn through Rufferto, faithful dog of the sage, leaving only a blackened corpse.
Rufferto, faithful dog of the sage is dead! R.I.P.
Your blood freezes as you hear Rufferto, faithful dog of the sage's death cry.

* HP:Scratched SP:Strong MV:Fresh > h

Rufferto, faithful dog of the sage tries to hit you, but you dodge the attack.
You swiftly dodge Rufferto, faithful dog of the sage's attempt to hit you.
Rufferto, faithful dog of the sage hits your right leg.
Rufferto, faithful dog of the sage barely hits your body.

[channel 'cure light wounds' dog] - Rufferto, faithful dog of the sage: Critical >
DEBUG: taint: picking new weave.
You begin to weave the appropriate flows...

+
Ok.
The earth trembles and shivers beneath your feet..!
Rufferto, faithful dog of the sage vibrates and is knocked about.
Rufferto, faithful dog of the sage vibrates and is knocked about.
Rufferto, faithful dog of the sage is mortally wounded, and will die soon, if not aided.
Still better. Experience pays off.
The vibrations are so incredible, Rufferto, faithful dog of the sage is shaken into little pieces.
Rufferto, faithful dog of the sage is dead! R.I.P.
Your blood freezes as you hear Rufferto, faithful dog of the sage's death cry.
Still better. Experience pays off.
The vibrations are so incredible, Rufferto, faithful dog of the sage is shaken into little pieces.
Rufferto, faithful dog of the sage is dead! R.I.P.
Your blood freezes as you hear Rufferto, faithful dog of the sage's death cry.
Enemies, enemies everywhere! You lash out with saidin.
Still better. Experience pays off.
Stone spikes erupt all around Rufferto, faithful dog of the sage, impaling it on a dozen sharp spits.
Rufferto, faithful dog of the sage is dead! R.I.P.
Your blood freezes as you hear Rufferto, faithful dog of the sage's death cry.
Still better. Experience pays off.
Stone spikes erupt all around Rufferto, faithful dog of the sage, impaling it on a dozen sharp spits.
Rufferto, faithful dog of the sage is dead! R.I.P.
Your blood freezes as you hear Rufferto, faithful dog of the sage's death cry.

* HP:Scratched SP:Strong MV:Fresh > h
[channel 'cure light wounds' dog]
DEBUG: taint: picking new weave.
Nobody here by that name.
You can see the splash damage effect working nicely in tandem with this one. Alas, there is nobody left to heal. And it is time for bed as it’s now 1am.

Itesh
Posts: 828
Joined: Sat Feb 14, 2015 4:59 am

Re: Code blog: Taint v2

Post by Itesh » Tue May 24, 2022 4:56 am

I love everything about this, especially the part where it became clear that you cook your dinner at the gym like a winner.

Post Reply