If there's one thing mortal players hate, it's two things, poisons and diseases. They're usually quite nasty and have a habit of scaring the players out of their minds. Which is, from a coders perspective, pretty darned cool. :-)
So, for this short course, we'll have a look at poisons and diseases. They are quite similar, so once you've learned one, you've basically learned them both.
Icewind now has a very flexible and easy to use system both for diseases and poisons. You don't have to use it, but I strongly encourage you to use it, as there are a lot of considerations to remember when coding a disease or a poison. Before we have a look at this system, here is a list of things to look out for when coding your own poison from scratch:
'add_tmp_prop("poisoned",1);', and when the poison wears off, use
'add_poison(poison-name);', and when the poison wears off, use
'add_disease(poison-name,startfunc,curefunc);'. startfunc is where the disease is started (normal functionpointer), and curefunc is where the disease is stopped (normal functionpointer). The curefunc must be ready to remove the disease at any time. add_disease() returns 0 if it failed, and 1 if it succeeded.
But, if you use the disease/poison system, they're even more similar.
Let's move on to some examples:
FILENAME: rat.c FILENAME: ratfuncs.c FILENAME: ratdisease.c
These three small files are all you need to make a simple monster with an infectious disease.
FILENAME: spider.c FILENAME: spiderfuncs.c FILENAME: spiderpoison.c
These three small files are all you need to make a simple monster with a dangerous poison.
We'll be discussing both of these under one, as they are very similar.
The first thing you need to do, when creating a poison/disease, is give it a name. This name is used to identify the poison/disease, so it's important that it's a unique name, and not some general name like "poison" or "disease". Then you should deceide how long the poison/disease should run, how often it should do damage and how much damage it should do each turn. Messages sent to the player and to the other ones in the room, are always run through format_message() first. This makes it possible to use the format codes. Read more about them in 'man format_message'. The messages can also be replaced with functionpointers, making them very useful. If you want to make your poison/disease do something special each "hurt turn", you can add a functionpointer instead of a string in the set_victim_hurt_msg() functioncall. Have a look at the ratdisease for an example.
If poisons/diseases are still a mystery, have a look at the manpages for 'poison' and 'disease'. There are also a couple of more examples in /doc/examples/poisons and /doc/examples/diseases.
The main difference between a poison and a disease is that players may develop immunity against diseases, but not against poisons. As the players attract a disease several times, they slowly strengthen their immunity defenses, and will eventually be up to 80% safe. To do this, the name of the disease is stored in the player along with a value specifying just how protected the player has become. This makes it crucially important that you don't change the name of your diseases, not even change the case of them.
Although diseases in Real Life(tm) often are contagious, our current disease system doesn't support it directly. Yet. If you absolutely need this, you can easily create one using a functionpointer instead of the string in, for instance, set_victim_hurt_msg() and then just check the player's environment in that function. If there are anyone around him/her, infect them. You should, however, rather wait until our disease system support it.
That's all, folks. If you have any questions, feel free to ask.
No? Then go code some nasty diseases and poisons! Hurry!