Code blog: Taint v2
Posted: 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.
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.