Penalties for armor in hot weather climes

One problem I have with warm weather modules (tropical or desert) is that the players don’t suffer penalties for wearing heavy armor or medium armor. Does anyone know of a way to penalize the use of different classes of armor?

There are d20 rules for heat effects that basically apply non-lethal damage on a failed Fort save with a modifier for heavy armor.

1 Like

It can be done easily with the use of OnEquiped/OnUnequiped module scripts, if you ask about the technical aspect of this problem.

1 Like

Ahhh the fun of Dark Sun campaigns.

1 Like

That’s more of what I was asking.

I do an ACP penalty thing re. Reflex saves (for wearing armor and/or using a shield). So here’s a parsed out a template that could be adapted for something similar …

if you don’t want shields, take those bits out; thought i’d leave them in to better show the idea

in the Modules’ OnEquip and OnUnequip:

    SendMessageToPC(GetFirstPC(FALSE), "OnEquip/Unequip for " + GetName(oTarget)); // debug to chat
    PrintString("OnEquip/Unequip for " + GetName(oTarget)); // debug to logfile during load

    switch (GetBaseItemType(oItem))
    {
        case BASE_ITEM_SMALLSHIELD:
        case BASE_ITEM_LARGESHIELD:
        case BASE_ITEM_TOWERSHIELD:
        case BASE_ITEM_ARMOR:
            HeatPenalty(oTarget);
            break;
    }

the function:

const int SPELLID_HEAT_PENALTY = 92375; // an arbitrary but unique pseudo spellId

// When party loads into a module, items get equipped and fire the OnEquip
// script multiple times. This var prevents firing the function multiple times
// when it really needs to run only once.
// It's also necessary to delay the OnUnequipped run else the item will still
// be considered equipped.
const string VAR_HEAT_DELAYED = "heatpen";

// public
void HeatPenalty(object oTarget = OBJECT_SELF)
{
    SendMessageToPC(GetFirstPC(FALSE), "HeatPenalty() for " + GetName(oTarget)); // debug to chat
    PrintString("HeatPenalty() for " + GetName(oTarget)); // debug to logfile during load

    if (!GetLocalInt(oTarget, VAR_HEAT_DELAYED))
    {
        SetLocalInt(oTarget, VAR_HEAT_DELAYED, TRUE);
        DelayCommand(0.f, HeatPenaltyDelayed(oTarget));
    }
}

// private
void HeatPenaltyDelayed(object oTarget)
{
    SendMessageToPC(GetFirstPC(FALSE), "HeatPenaltyDelayed() for " + GetName(oTarget)); // debug to chat
    PrintString("HeatPenaltyDelayed() for " + GetName(oTarget)); // debug to logfile module load

    DeleteLocalInt(oTarget, VAR_HEAT_DELAYED);

    int iHeat = 0;

    object oArmor = GetItemInSlot(INVENTORY_SLOT_CHEST, oTarget);
    if (GetIsObjectValid(oArmor))
    {
        // calculate the heat-penalty
        iHeat = ;
    }

    object oShield = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oTarget);
    if (GetIsObjectValid(oShield))
    {
        int iBaseType = GetBaseItemType(oShield);
        switch (iBaseType)
        {
            case BASE_ITEM_SMALLSHIELD:
            case BASE_ITEM_LARGESHIELD:
            case BASE_ITEM_TOWERSHIELD:
                // WARNING: Shields use the armor-stats in BaseItems.2da,
                // not those they should in ArmorRuleStats.2da

                // calculate the heat-penalty (or other if applicable)
                iHeat += ;
                break;
        }
    }

    // NOTE: This cannot rely on a stored penalty being the same as the new
    // penalty because when loading into a different campaign-module the effect
    // will be cleared but the stored penalty won't be reset (unless changes are
    // made to module-loading scripts). So this function would think "oh he's
    // wearing the same armor" - but in fact the effect is gone and needs to be
    // reapplied.

    effect eScan = GetFirstEffect(oTarget);
    while (GetIsEffectValid(eScan))
    {
        if (GetEffectSpellId(eScan) == SPELLID_HEAT_PENALTY)
        {
            RemoveEffect(oTarget, eScan);
            eScan = GetFirstEffect(oTarget);
        }
        else
            eScan = GetNextEffect(oTarget);
    }

    if (iHeat > 0)
    {
        effect eHeat = ;

        eHeat = SupernaturalEffect(eHeat);
        eHeat = SetEffectSpellId(eHeat, SPELLID_HEAT_PENALTY);

        // note: The effect-icon might not be applied properly without a delay.
        DelayCommand(0.f, ApplyEffectToObject(DURATION_TYPE_PERMANENT, eHeat, oTarget));
    }
}
1 Like
int ARMOR_RANK_NONE   = 0;
int ARMOR_RANK_LIGHT  = 1;
int ARMOR_RANK_MEDIUM = 2;
int ARMOR_RANK_HEAVY  = 3;

int GetArmorRank(object oItem);

that’s one way to get a val

1 Like

Thanks kevL_s. I’ll mess with the code and see what I can come up with. I’m thinking since Medieval armor causes the need for twice the energy for walking around perhaps the effect for being in an intense heat climate, the effect should be something like making the PC/NPC heavily encumbered if wearing heavy armor and encumbered if wearing medium.

1 Like

there’s also an effect called Fatigued and when fatigued for too long, Exhausted … I think it’s a 3.5e defined effect, so in Nwn2 it’s a synthetic effect comprised of 3 stock effects – see nwn2_inc_spells under “Simulated Effects”. reduces Str, Dex, and movement speed.

/just another idea …

but, you know, doing that might require a recursive script (pseudo heartbeat, or even use the real HB) to track things as time advances …

If you can get the engine to think that a char’s encumbered state is stepped up by a notch that’d be good too  :)

i mean there’s no shortage of reasonable penalties for heatstroke, the crusades musta been h*ll

1 Like

For those interested . . . this was a study done back in 2011 - https://www.livescience.com/15128-armor-drained-medieval-knight-energy.html

2 Likes