ff_u_itm_torch

Equipped torches dim, then burn out after 30 real-time minutes.

A torch whose tag is ff_u_itm_torch burns while it is equipped in either hand. It lasts 30 real-time minutes, and its light dims near the end: normal brightness with 6 minutes left, low with 4 minutes left, and dim with 2 minutes left. When it runs out, the player is told that the torch has burned out, and the torch is destroyed.

The time left is saved on the torch: an unequipped torch stops burning, and burns on from where it stopped when it is equipped again. A torch with Continual Light cast on it never burns out.

Source code

// @code

#include "ff_i_core"
#include "x2_inc_itemprop"

const string TICKS = "TICKS";

const int DURATION = 30; // 30 units, one per real minute

// -----------------------------------------------------------------------------
void PulseMinute(object oTorch)
{
  // If continual light has been cast on torch, exit
  if (GetLocalInt(oTorch, "x0_s0_clight"))
    return;
  if (NWNX_Object_GetInt(oTorch, "x0_s0_clight"))
    return;

  // Check if still equipped:
  object oPC = GetItemPossessor(oTorch);
  oPC = GetPC(oPC);
  if (!GetIsObjectValid(oPC))
    return;

  object oItemL = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oPC);
  object oItemR = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC);

  if (FALSE) {}
  else if (oItemL == oTorch && oItemL != OBJECT_INVALID) {}
  else if (oItemR == oTorch && oItemR != OBJECT_INVALID) {}
  else
    return;

  // One tick is 1 minute.
  int nTicks = NWNX_Object_GetInt(oTorch, TICKS);
  if (nTicks == 0)
    nTicks = DURATION;
  else if (nTicks == 6)
  {
    itemproperty ip = ItemPropertyLight(IP_CONST_LIGHTBRIGHTNESS_NORMAL, IP_CONST_LIGHTCOLOR_YELLOW);
    IPSafeAddItemProperty(oTorch, ip, 0.0f, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, TRUE, TRUE);
  }
  else if (nTicks == 4)
  {
    itemproperty ip = ItemPropertyLight(IP_CONST_LIGHTBRIGHTNESS_LOW, IP_CONST_LIGHTCOLOR_YELLOW);
    IPSafeAddItemProperty(oTorch, ip, 0.0f, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, TRUE, TRUE);
  }
  else if (nTicks == 2)
  {
    itemproperty ip = ItemPropertyLight(IP_CONST_LIGHTBRIGHTNESS_DIM, IP_CONST_LIGHTCOLOR_YELLOW);
    IPSafeAddItemProperty(oTorch, ip, 0.0f, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, TRUE, TRUE);
  }
  nTicks -= 1;
  NWNX_Object_SetInt(oTorch, "TICKS", nTicks, TRUE);
  LogDebug(__FILE__, "torch has " + IntToString(nTicks) + " ticks left");

  if (nTicks <= 0)
  {
    if (GetIsPC(oPC))
      FloatingTextStringOnCreature("The torch has burned out.", oPC, FALSE);
    DestroyObject(oTorch);
    return;
  }

  DelayCommand(60.f, PulseMinute(oTorch));
}


// =============================================================================

void main()
{
  string sEvent = NWNX_Events_GetCurrentEvent();
  if (sEvent != NWNX_ON_RUN_EVENT_SCRIPT_BEFORE)
    return;
  if (GetCurrentlyRunningEvent() != EVENT_SCRIPT_MODULE_ON_EQUIP_ITEM)
    return;

  object oItem = GetPCItemLastEquipped();
  DelayCommand(0.1f, PulseMinute(oItem));
}