PnP Poison System

Introduction

Once upon a time, there was a player who was messing about with rogue/wizard and was looking for something to add a bit of extra punch against all the damn monsters in the OC. He saw the poisons appliable to weapons that had come along with HotU and went "Oooh, neat!". But all was not well, for he soon noticed that the implementation sucked much goat balls and was about as far from the PnP specifications as one could get. So he went and implemented his own system that works using the poisons defined in poison.2da instead of plain static 1d2 damage to ability X and is hopefully more useful to players (and evil DMs).

This document contains some info on how the system works and how to use it. Full implementation details are available in the header comments of the poison_*.nss script files.

Users

According to the Dungeon Master's Guide, poisons are divided into four types: Contact, Ingested, Inhaled, Injury. This distinction has been implemented using a new column in poison.2da, the values of which correspond to rows in poisontypedef.2da.

There is an item implementing a vial of poison for almost every poison with specs in (DMG|BoVD|BoED). These items have crafting recipes created for them, available from the recipe merchant in the epic spell lab, so they are accessible from any module.
The items are used through a set of item spells implementing the uses in the list above.

Builders

Items and recipes

The pre-made "poison vial" items have resrefs of 2dapoisonXXX, where XXX is the poison.2da index of the poison it's meant to be. The pre-made recipes for creating them have resrefs of ireq_poisonXXX. However, these two numberings are not relevant to the poison system.
The values used by the poison system are the tag of the item and/or a local variable called pois_idx. They indicate the poison.2da index of the poison. The value in the tag is stored in the last 3 characters, with zero-padding if necessary.

If you add your own poison items, they can have certain Cast Spell abilities, depending on the poison type. A single item may be of only a single poison at a time.

Pre-poisoned loot

It is not particularly easy to create pre-poisoned items directly in the toolset. However, it is quite straightforward by using scripting. The items need to have the following 3 local variables set on them:

In addition, the must have Cast Spell: Clean Poison Off with unlimited uses and have the following functions called via a script:

        object oItem = [the poisoned item];
        AddEventScript(oItem, EVENT_ITEM_ONACQUIREITEM,     "poison_onaquire", TRUE, FALSE);
        AddEventScript(oItem, EVENT_ITEM_ONPLAYEREQUIPITEM, "poison_onequip",  TRUE, FALSE);
        

Technical details

Poisoned weapons

When a weapon is poisoned (script poison_appl_weap), first the object being poisoned is checked out to make sure it's valid for being poisoned in this manner. Then, the script gets the index of the poison to use, either from the tag of the item being used to poison or from a local integer on it.
Then, after some more checks on the poison id, the user gets to roll for success in applying the poison.If it fails, the user gets poisoned with whatever was used. Either way, the poison is applied to the weapon.
Two local integers are set on the weapon. One is the index of the poison used in poison.2da and the other is the number of times the poison can be applied from the weapon before it wears out. An OnHitCastSpell: Unique itemproperty is also applied to the item so that the script poison_wpn_onhit can be eventhooked to it.
poison_wpn_onhit gets the index of the poison to use from the local integer and applies a corresponding EffectPoison() to the object hit. It then decrements remaining uses and if they reach 0, the local integers are removed from the item and the script is removed from the eventhook. The OnHitCast property is also removed if it wasn't already present when the weapon was poisoned.

Poisoned items

Poisoning an object first gets the poison to use. Then, it makes some validity checks. First, that the poison is a contact poison and second that the item has not been poisoned in this manner previously.
The poisoner rolls Set Trap to set DC for Spotting and removing the poison. The number of times the poison applied can affect people is calculated. These values are stored on the item poisoned and eventhook scripts are added to the item for OnEquip (poison_onequip) and OnAcquire (poison_onaquire). An object reference is stored on the item pointing at the poisoner.
In addition, a Cast Spell: Clean Poison Off itemproperty is added to the item.

The OnEquip script first checks if the equipper knows that the item is poisoned. If it does, either being the original poisoner or someone who has succeeded in a spot check to notice the poison during OnAcquire, it tries to clean the poison off first. The original poisoner is automatically successfull, others roll Disable Trap against the DC set by the poisoner.