ff_u_dyn_hp
Dynamic hit points: add random hit points to creatures when they are created.
When a creature is created, it gets a d8 per class level on top of its original maximum hit points. Each roll is uniform between HITPOINT_MINIMUM and 8. Its maximum and current hit points are set to the new total.
Creatures are caught when created by script, and when they first enter an area (placed creatures, encounter spawns). Each creature is only handled once.
Ignored creatures:
PCs and DMs.
Creatures of the Commoner, Merchant and Defender factions.
Variables
ENABLE__FF_U_DYN_HP or ENABLE__FF_U_DYNAMIC_HP: (string) (opt-in) Set either to "Y" on module to enable the unit.
HITPOINT_MINIMUM: (int) Minimum value of each d8 roll, from 1 to 8. Read from the creature, then its area, then the module. Defaults to 4. A value of 0 is the same as unset.
Source code
// @code
#include "ff_i_core"
const string ENABLE__FF_U_DYN_HP = "ENABLE__FF_U_DYN_HP";
const string ENABLE__FF_U_DYNAMIC_HP = "ENABLE__FF_U_DYNAMIC_HP";
const string HITPOINT_MINIMUM = "HITPOINT_MINIMUM";
// Default minimum value of each d8 roll
const int DEFAULT_HITPOINT_MINIMUM = 4;
// Local int set on a creature once its hit points were changed
const string FF_U_DYN_HP = "__FF_U_DYN_HP";
// Faction ids of the standard factions (repute.fac), as returned by NWNX_Creature_GetFaction()
const int FACTION_ID_COMMONER = STANDARD_FACTION_COMMONER + 1;
const int FACTION_ID_MERCHANT = STANDARD_FACTION_MERCHANT + 1;
const int FACTION_ID_DEFENDER = STANDARD_FACTION_DEFENDER + 1;
// -----------------------------------------------------------------------------
//! @brief Return TRUE if oCreature must get random hit points.
//! @param oCreature An object.
int IsEligible(object oCreature);
int IsEligible(object oCreature)
{
if (GetObjectType(oCreature) != OBJECT_TYPE_CREATURE)
return FALSE;
if (GetIsPC(oCreature) || GetIsDM(oCreature))
return FALSE;
int nFaction = NWNX_Creature_GetFaction(oCreature);
if (nFaction == FACTION_ID_COMMONER || nFaction == FACTION_ID_MERCHANT || nFaction == FACTION_ID_DEFENDER)
return FALSE;
return TRUE;
}
// -----------------------------------------------------------------------------
//! @brief Add a roll between HITPOINT_MINIMUM and 8 per class level to the hit points of oCreature.
//! @param oCreature An eligible creature.
void AddHitPoints(object oCreature);
void AddHitPoints(object oCreature)
{
if (GetLocalInt(oCreature, FF_U_DYN_HP))
return;
SetLocalInt(oCreature, FF_U_DYN_HP, TRUE);
int nMinimum = GetRecursiveInt(oCreature, HITPOINT_MINIMUM, DEFAULT_HITPOINT_MINIMUM);
nMinimum = min(max(nMinimum, 1), 8);
// Uniform roll between nMinimum and 8, so the minimum is not more likely than other values
int nLevels = GetHitDice(oCreature);
int nAdd = 0;
int i;
for (i = 0; i < nLevels; i++)
nAdd += nMinimum + Random(8 - nMinimum + 1);
// NWNX sets the base hit points, and the engine adds the Constitution and feat
// bonuses on top: set the base to the current maximum to measure these bonuses.
int nMax = GetMaxHitPoints(oCreature);
NWNX_Object_SetMaxHitPoints(oCreature, nMax);
int nBonus = GetMaxHitPoints(oCreature) - nMax;
// Base so that base + bonus = nMax + nAdd
int nBase = nMax + nAdd - nBonus;
if (nBase < 1)
nBase = 1;
NWNX_Object_SetMaxHitPoints(oCreature, nBase);
SetCurrentHitPoints(oCreature, GetMaxHitPoints(oCreature));
LogDebug(__FILE__, GetObjectInfo(oCreature) + " hit points: "
+ IntToString(nMax) + " + " + IntToString(nAdd)
+ " = " + IntToString(GetCurrentHitPoints(oCreature))
+ " / " + IntToString(GetMaxHitPoints(oCreature)));
}
// -----------------------------------------------------------------------------
void main()
{
string sEvent = NWNX_Events_GetCurrentEvent();
if (sEvent == ON_REGISTER)
{
if (!GetModuleFlag(ENABLE__FF_U_DYN_HP, FALSE) && !GetModuleFlag(ENABLE__FF_U_DYNAMIC_HP, FALSE))
return;
SubscribeToEvent(ON_AFTER_OBJECT_CREATED, __FILE__);
SubscribeToEvent(ON_DEFAULT_AREA_ENTER, __FILE__);
}
else if (sEvent == ON_AFTER_OBJECT_CREATED)
{
object oCreated = StringToObject(NWNX_Events_GetEventData("OBJECT"));
if (IsEligible(oCreated))
AddHitPoints(oCreated);
}
// Catches creatures not created by script, such as placed creatures and encounter spawns
else if (sEvent == ON_DEFAULT_AREA_ENTER)
{
object oEntering = GetEnteringObject();
if (IsEligible(oEntering))
AddHitPoints(oEntering);
}
}