Files
PRC8/nwn/nwnprc/trunk/newspellbook/inf_armor_enh.nss
Jaysyn904 038a4cf88d 2026/03/28
Added default level up package for Warblade.
Moment of Prescience should be an instant action.
Truespeak should be a class skill for Factotum.
Added Armor Enhancement, Lesser infusion.
Added Armor Enhancement infusion.
Added Armor Enhancement, Greater infusion
Added Resistance Item infusion.
Added Weapon Augmentation, Personal infusion.
Added Weapon Augmentation infusion.
Added Weapon Augmentation, Lesser infusion.
2026-03-28 23:39:46 -04:00

849 lines
32 KiB
Plaintext

// inf_armor_enh.nss
/*
Armor Enhancement, Lesser
Transmutation
Level: Artificer 1
Components: S, M
Casting Time: 1 minute
Range: Touch
Target: Armor or shield touched
Duration: 10 min./level
Saving Throw: None (object)
Spell Resistance: No (object)
The armor or shield you touch temporarily gains a special ability
commonly found on magic armor or shields.
You can choose any special ability whose market price is equivalent to
a +1 bonus or up to 5,000 gp, such as light fortification or shadow.
The armor or shield does not need to have an existing enhancement
bonus, nor does it gain one when you imbue it with this infusion.
Material Component: An ointment made from rare spices and minerals,
costing 10 gp.
Armor Enhancement
Transmutation
Level: Artificer 2
As lesser armor enhancement, but you can choose any special ability
whose market price is equivalent to a bonus of up to +3 or up to
35,000 gp, such as ghost touch or acid resistance.
Material Component: An ointment costing 50 gp.
Armor Enhancement, Greater
Transmutation
Level: Artificer 3
As lesser armor enhancement, but you can choose any special ability
whose market price is equivalent to a bonus of up to +5 or up to
100,000 gp, such as etherealness or greater fire resistance.
Material Component: An ointment costing 100 gp.
*/
#include "inc_debug"
#include "prc_craft_inc"
#include "inc_dynconv"
// Placeholder magic numbers for spell IDs
const int ARMOR_ENH_LESS = 5001;
const int ARMOR_ENH = 5002;
const int ARMOR_ENH_GREATER = 5003;
// Dynamic conversation stages
const int STAGE_PROPERTY_SELECTION = 0;
const int STAGE_CONFIRMATION = 1;
void HandleConversation(object oPC, object oArmor, int nMaxEnhancement, int nMaxCost, string sLocalVar, int nSpellID, int nCasterLevel)
{
int nValue = GetLocalInt(oPC, DYNCONV_VARIABLE);
int nStage = GetStage(oPC);
if(nValue == 0) return;
if(nValue == DYNCONV_SETUP_STAGE)
{
if(!GetIsStageSetUp(nStage, oPC))
{
if(nStage == STAGE_PROPERTY_SELECTION)
{
// Set header first
SetHeader("Select an armor enhancement:");
// Initialize default tokens BEFORE adding choices
SetDefaultTokens();
// Read directly from craft_armour.2da
int nFileEnd = PRCGetFileEnd("craft_armour");
int nChoice = 1;
int i;
for(i = 0; i <= nFileEnd; i++)
{
// Get enhancement and cost for this specific line
int nEnhancement = StringToInt(Get2DACache("craft_armour", "Enhancement", i));
int nAdditionalCost = StringToInt(Get2DACache("craft_armour", "AdditionalCost", i));
string sName = GetStringByStrRef(StringToInt(Get2DACache("craft_armour", "Name", i)));
// Debug output
SendMessageToPC(oPC, "Line " + IntToString(i) + ": " + sName + " (Enh:" + IntToString(nEnhancement) + ", Cost:" + IntToString(nAdditionalCost) + ")");
// Check if this property is within limits
if(nEnhancement <= nMaxEnhancement && nAdditionalCost <= nMaxCost)
{
AddChoice(sName, i, oPC);
nChoice++;
}
}
MarkStageSetUp(STAGE_PROPERTY_SELECTION, oPC);
}
else if(nStage == STAGE_CONFIRMATION)
{
int nPropertyLine = GetLocalInt(oPC, "ArmorEnh_SelectedProperty");
string sName = GetStringByStrRef(StringToInt(Get2DACache("craft_armour", "Name", nPropertyLine)));
SetHeader("Apply " + sName + " to the armor?");
AddChoice("Yes", TRUE, oPC);
AddChoice("No", FALSE, oPC);
MarkStageSetUp(STAGE_CONFIRMATION, oPC);
}
}
SetupTokens();
}
else if(nValue == DYNCONV_EXITED)
{
// Cleanup
DeleteLocalInt(oPC, "ArmorEnh_ConvMode");
DeleteLocalObject(oPC, "ARMOR_ENH_TARGET");
DeleteLocalInt(oPC, "ArmorEnh_SelectedProperty");
}
else if(nValue == DYNCONV_ABORTED)
{
// Cleanup
DeleteLocalInt(oPC, "ArmorEnh_ConvMode");
DeleteLocalObject(oPC, "ARMOR_ENH_TARGET");
DeleteLocalInt(oPC, "ArmorEnh_SelectedProperty");
}
else
{
int nChoice = GetChoice(oPC);
if(nStage == STAGE_PROPERTY_SELECTION)
{
// Store selection and go to confirmation
SetLocalInt(oPC, "ArmorEnh_SelectedProperty", nChoice);
nStage = STAGE_CONFIRMATION;
MarkStageNotSetUp(STAGE_PROPERTY_SELECTION, oPC);
}
else if(nStage == STAGE_CONFIRMATION)
{
if(nChoice == TRUE) // User confirmed
{
// Apply the property
object oArmor = GetLocalObject(oPC, "ARMOR_ENH_TARGET");
int nPropertyLine = GetLocalInt(oPC, "ArmorEnh_SelectedProperty");
int nCasterLevel = GetLocalInt(oPC, "ArmorEnh_CasterLevel");
float fDuration = TurnsToSeconds(nCasterLevel * 10);
int nMetaMagic = PRCGetMetaMagicFeat();
if(nMetaMagic & METAMAGIC_EXTEND)
fDuration *= 2;
// Debug output
SendMessageToPC(oPC, "Duration: " + FloatToString(fDuration) + " seconds");
// Add fallback for very small durations
if (fDuration <= 1.0) fDuration = 30.0f;
SendMessageToPC(oPC, "Fallback Duration: " + FloatToString(fDuration) + " seconds");
// Create property directly
itemproperty ip;
/* if(nPropertyLine == 0)
{
// +1 Enhancement
ip = ConstructIP(ITEM_PROPERTY_AC_BONUS, 0, 1, 0);
}
else
{ */
// Read property data from 2DA and construct
string sIPData = Get2DACache("craft_armour", "IP1", nPropertyLine);
struct ipstruct iptemp = GetIpStructFromString(sIPData);
ip = ConstructIP(iptemp.type, iptemp.subtype, iptemp.costtablevalue, iptemp.param1value);
//}
// Apply with proper duration
ip = TagItemProperty(ip, "ArmorEnhInfusion");
IPSafeAddItemProperty(oArmor, ip, fDuration, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, TRUE);
// Clean up and exit
DeleteLocalInt(oPC, "ArmorEnh_ConvMode");
DeleteLocalObject(oPC, "ARMOR_ENH_TARGET");
DeleteLocalInt(oPC, "ArmorEnh_SelectedProperty");
AllowExit(DYNCONV_EXIT_FORCE_EXIT);
}
else // User cancelled
{
// Go back to property selection
nStage = STAGE_PROPERTY_SELECTION;
MarkStageNotSetUp(STAGE_CONFIRMATION, oPC);
}
}
SetStage(nStage, oPC);
}
}
void main()
{
object oPC = GetPCSpeaker();
if(!GetIsObjectValid(oPC)) oPC = OBJECT_SELF;
// Check if we're in conversation mode
if(GetLocalInt(oPC, "ArmorEnh_ConvMode"))
{
// Retrieve parameters for conversation
object oArmor = GetLocalObject(oPC, "ARMOR_ENH_TARGET");
int nMaxEnhancement = GetLocalInt(oPC, "ArmorEnh_MaxEnh");
int nMaxCost = GetLocalInt(oPC, "ArmorEnh_MaxCost");
string sLocalVar = GetLocalString(oPC, "ArmorEnh_LocalVar");
int nSpellID = GetLocalInt(oPC, "ArmorEnh_SpellID");
int nCasterLevel = GetLocalInt(oPC, "ArmorEnh_CasterLevel");
HandleConversation(oPC, oArmor, nMaxEnhancement, nMaxCost, sLocalVar, nSpellID, nCasterLevel);
return;
}
// Normal spell execution
PRCSetSchool(SPELL_SCHOOL_TRANSMUTATION);
if (!X2PreSpellCastCode()) return;
object oCaster = OBJECT_SELF;
object oTarget = PRCGetSpellTargetObject();
int nCasterLevel = PRCGetCasterLevel(oCaster);
int nSpellID = PRCGetSpellId();
// Declare variables
int nGoldCost, nMaxEnhancement, nMaxCost;
string sLocalVar;
// Set parameters based on spell level
switch(nSpellID)
{
case ARMOR_ENH_LESS:
nGoldCost = 10;
nMaxEnhancement = 1;
nMaxCost = 5000;
sLocalVar = "ARMOR_ENH_LESS_PROPERTY";
break;
case ARMOR_ENH:
nGoldCost = 50;
nMaxEnhancement = 3;
nMaxCost = 35000;
sLocalVar = "ARMOR_ENH_PROPERTY";
break;
case ARMOR_ENH_GREATER:
nGoldCost = 100;
nMaxEnhancement = 5;
nMaxCost = 100000;
sLocalVar = "ARMOR_ENH_GREATER_PROPERTY";
break;
default:
// Default to lesser version for testing
nGoldCost = 10;
nMaxEnhancement = 1;
nMaxCost = 5000;
sLocalVar = "ARMOR_ENH_LESS_PROPERTY";
break;
}
// Check material component
if(GetGold(oCaster) < nGoldCost)
{
FloatingTextStringOnCreature("You need " + IntToString(nGoldCost) + "gp worth of rare spices and minerals.", oCaster, FALSE);
return;
}
// Get targeted armor or shield
object oArmor = GetItemInSlot(INVENTORY_SLOT_CHEST, oCaster);
//object oArmor = IPGetTargetedOrEquippedArmor(TRUE); <- don't delete
if(!GetIsObjectValid(oArmor))
{
FloatingTextStrRefOnCreature(83826, oCaster, FALSE); // "Invalid target"
return;
}
// Check if returning from conversation with a selection
int nPropertyLine = GetLocalInt(oCaster, sLocalVar);
if(nPropertyLine > 0)
{
// Apply the property
float fDuration = TurnsToSeconds(nCasterLevel * 10);
int nMetaMagic = PRCGetMetaMagicFeat();
if(nMetaMagic & METAMAGIC_EXTEND)
fDuration *= 2;
if (fDuration <= 1.0) fDuration = 30.0f;
// Create property directly
itemproperty ip;
// Read property data from 2DA and construct
string sIPData = Get2DACache("craft_armour", "IP1", nPropertyLine);
struct ipstruct iptemp = GetIpStructFromString(sIPData);
ip = ConstructIP(iptemp.type, iptemp.subtype, iptemp.costtablevalue, iptemp.param1value);
// Apply with proper duration
ip = TagItemProperty(ip, "ArmorEnhInfusion");
IPSafeAddItemProperty(oArmor, ip, fDuration, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, TRUE);
DeleteLocalInt(oCaster, sLocalVar);
return;
}
// Store parameters for conversation and start it
SetLocalInt(oPC, "ArmorEnh_ConvMode", 1);
SetLocalObject(oPC, "ARMOR_ENH_TARGET", oArmor);
SetLocalInt(oPC, "ArmorEnh_MaxEnh", nMaxEnhancement);
SetLocalInt(oPC, "ArmorEnh_MaxCost", nMaxCost);
SetLocalString(oPC, "ArmorEnh_LocalVar", sLocalVar);
SetLocalInt(oPC, "ArmorEnh_SpellID", nSpellID);
SetLocalInt(oPC, "ArmorEnh_CasterLevel", nCasterLevel);
// Start the dynamic conversation using this same script
StartDynamicConversation("inf_armor_enh", oPC, 0, FALSE, TRUE);
}
/* void HandleConversation(object oPC, object oArmor, int nMaxEnhancement, int nMaxCost, string sLocalVar, int nSpellID, int nCasterLevel)
{
int nValue = GetLocalInt(oPC, DYNCONV_VARIABLE);
int nStage = GetStage(oPC);
if(nValue == 0) return;
if(nValue == DYNCONV_SETUP_STAGE)
{
if(!GetIsStageSetUp(nStage, oPC))
{
if(nStage == STAGE_PROPERTY_SELECTION)
{
// Set header first
SetHeader("Select an armor enhancement:");
// Initialize default tokens BEFORE adding choices
SetDefaultTokens();
// Read directly from craft_armour.2da
int nFileEnd = PRCGetFileEnd("craft_armour");
int nChoice = 1;
int i;
for(i = 0; i <= nFileEnd; i++)
{
// Get enhancement and cost for this specific line
int nEnhancement = StringToInt(Get2DACache("craft_armour", "Enhancement", i));
int nAdditionalCost = StringToInt(Get2DACache("craft_armour", "AdditionalCost", i));
string sName = GetStringByStrRef(StringToInt(Get2DACache("craft_armour", "Name", i)));
// Debug output
SendMessageToPC(oPC, "Line " + IntToString(i) + ": " + sName + " (Enh:" + IntToString(nEnhancement) + ", Cost:" + IntToString(nAdditionalCost) + ")");
// Check if this property is within limits
if(nEnhancement <= nMaxEnhancement && nAdditionalCost <= nMaxCost)
{
AddChoice(sName, i, oPC);
nChoice++;
}
}
MarkStageSetUp(STAGE_PROPERTY_SELECTION, oPC);
}
else if(nStage == STAGE_CONFIRMATION)
{
int nPropertyLine = GetLocalInt(oPC, "ArmorEnh_SelectedProperty");
string sName = GetStringByStrRef(StringToInt(Get2DACache("craft_armour", "Name", nPropertyLine)));
SetHeader("Apply " + sName + " to the armor?");
AddChoice("Yes", TRUE, oPC);
AddChoice("No", FALSE, oPC);
MarkStageSetUp(STAGE_CONFIRMATION, oPC);
}
}
SetupTokens();
}
else if(nValue == DYNCONV_EXITED)
{
// Cleanup
DeleteLocalInt(oPC, "ArmorEnh_ConvMode");
DeleteLocalObject(oPC, "ARMOR_ENH_TARGET");
DeleteLocalInt(oPC, "ArmorEnh_SelectedProperty");
}
else if(nValue == DYNCONV_ABORTED)
{
// Cleanup
DeleteLocalInt(oPC, "ArmorEnh_ConvMode");
DeleteLocalObject(oPC, "ARMOR_ENH_TARGET");
DeleteLocalInt(oPC, "ArmorEnh_SelectedProperty");
}
else
{
int nChoice = GetChoice(oPC);
if(nStage == STAGE_PROPERTY_SELECTION)
{
// Store selection and go to confirmation
SetLocalInt(oPC, "ArmorEnh_SelectedProperty", nChoice);
nStage = STAGE_CONFIRMATION;
MarkStageNotSetUp(STAGE_PROPERTY_SELECTION, oPC);
}
else if(nStage == STAGE_CONFIRMATION)
{
if(nChoice == TRUE) // User confirmed
{
// Apply the property
object oArmor = GetLocalObject(oPC, "ARMOR_ENH_TARGET");
int nPropertyLine = GetLocalInt(oPC, "ArmorEnh_SelectedProperty");
int nCasterLevel = GetLocalInt(oPC, "ArmorEnh_CasterLevel");
float fDuration = TurnsToSeconds(nCasterLevel * 10);
int nMetaMagic = PRCGetMetaMagicFeat();
if(nMetaMagic & METAMAGIC_EXTEND)
fDuration *= 2;
// Debug output
SendMessageToPC(oPC, "Duration: " + FloatToString(fDuration) + " seconds");
// Add fallback for very small durations
if (fDuration <= 1.0) fDuration = 30.0f;
// Create property directly
itemproperty ip;
if(nPropertyLine == 0)
{
// +1 Enhancement
ip = ConstructIP(ITEM_PROPERTY_AC_BONUS, 0, 1, 0);
}
else
{
// Read property data from 2DA and construct
string sIPData = Get2DACache("craft_armour", "IP1", nPropertyLine);
struct ipstruct iptemp = GetIpStructFromString(sIPData);
ip = ConstructIP(iptemp.type, iptemp.subtype, iptemp.costtablevalue, iptemp.param1value);
}
// Apply with proper duration
ip = TagItemProperty(ip, "ArmorEnhInfusion");
IPSafeAddItemProperty(oArmor, ip, fDuration, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, TRUE);
// Clean up and exit
DeleteLocalInt(oPC, "ArmorEnh_ConvMode");
DeleteLocalObject(oPC, "ARMOR_ENH_TARGET");
DeleteLocalInt(oPC, "ArmorEnh_SelectedProperty");
AllowExit(DYNCONV_EXIT_FORCE_EXIT);
return;
}
else // User cancelled
{
// Go back to property selection
nStage = STAGE_PROPERTY_SELECTION;
MarkStageNotSetUp(STAGE_CONFIRMATION, oPC);
}
}
SetStage(nStage, oPC);
}
}
void main()
{
object oPC = GetPCSpeaker();
if(!GetIsObjectValid(oPC)) oPC = OBJECT_SELF;
// Check if we're in conversation mode
if(GetLocalInt(oPC, "ArmorEnh_ConvMode"))
{
// Retrieve parameters for conversation
object oArmor = GetLocalObject(oPC, "ARMOR_ENH_TARGET");
int nMaxEnhancement = GetLocalInt(oPC, "ArmorEnh_MaxEnh");
int nMaxCost = GetLocalInt(oPC, "ArmorEnh_MaxCost");
string sLocalVar = GetLocalString(oPC, "ArmorEnh_LocalVar");
int nSpellID = GetLocalInt(oPC, "ArmorEnh_SpellID");
int nCasterLevel = GetLocalInt(oPC, "ArmorEnh_CasterLevel");
HandleConversation(oPC, oArmor, nMaxEnhancement, nMaxCost, sLocalVar, nSpellID, nCasterLevel);
return;
}
// Normal spell execution
PRCSetSchool(SPELL_SCHOOL_TRANSMUTATION);
if (!X2PreSpellCastCode()) return;
object oCaster = OBJECT_SELF;
object oTarget = PRCGetSpellTargetObject();
int nCasterLevel = PRCGetCasterLevel(oCaster);
//int nSpellID = PRCGetSpellId();
int nSpellID = ARMOR_ENH_GREATER;
// Declare variables
int nGoldCost, nMaxEnhancement, nMaxCost;
string sLocalVar;
// Set parameters based on spell level
switch(nSpellID)
{
case ARMOR_ENH_LESS:
nGoldCost = 10;
nMaxEnhancement = 1;
nMaxCost = 5000;
sLocalVar = "ARMOR_ENH_LESS_PROPERTY";
break;
case ARMOR_ENH:
nGoldCost = 50;
nMaxEnhancement = 3;
nMaxCost = 35000;
sLocalVar = "ARMOR_ENH_PROPERTY";
break;
case ARMOR_ENH_GREATER:
nGoldCost = 100;
nMaxEnhancement = 5;
nMaxCost = 100000;
sLocalVar = "ARMOR_ENH_GREATER_PROPERTY";
break;
default:
// Default to lesser version for testing
nGoldCost = 10;
nMaxEnhancement = 1;
nMaxCost = 5000;
sLocalVar = "ARMOR_ENH_LESS_PROPERTY";
break;
}
// Check material component
if(GetGold(oCaster) < nGoldCost)
{
FloatingTextStringOnCreature("You need " + IntToString(nGoldCost) + "gp worth of rare spices and minerals.", oCaster, FALSE);
return;
}
// Get targeted armor or shield
object oArmor = GetItemInSlot(INVENTORY_SLOT_CHEST, oCaster);
if(!GetIsObjectValid(oArmor))
{
FloatingTextStrRefOnCreature(83826, oCaster, FALSE); // "Invalid target"
return;
}
// Store parameters for conversation and start it
SetLocalInt(oPC, "ArmorEnh_ConvMode", 1);
SetLocalObject(oPC, "ARMOR_ENH_TARGET", oArmor);
SetLocalInt(oPC, "ArmorEnh_MaxEnh", nMaxEnhancement);
SetLocalInt(oPC, "ArmorEnh_MaxCost", nMaxCost);
SetLocalString(oPC, "ArmorEnh_LocalVar", sLocalVar);
SetLocalInt(oPC, "ArmorEnh_SpellID", nSpellID);
SetLocalInt(oPC, "ArmorEnh_CasterLevel", nCasterLevel);
// Start the dynamic conversation using this same script
DelayCommand(0.1f, StartDynamicConversation("inf_armor_enh", oPC, 0, FALSE, TRUE));
} */
/* void HandleConversation(object oPC, object oArmor, int nMaxEnhancement, int nMaxCost, string sLocalVar, int nSpellID, int nCasterLevel)
{
int nValue = GetLocalInt(oPC, DYNCONV_VARIABLE);
int nStage = GetStage(oPC);
if(nValue == 0) return;
if(nValue == DYNCONV_SETUP_STAGE)
{
if(!GetIsStageSetUp(nStage, oPC))
{
if(nStage == STAGE_PROPERTY_SELECTION)
{
// Set header first
SetHeader("Select an armor enhancement:");
// Initialize default tokens BEFORE adding choices
SetDefaultTokens();
// Read directly from craft_armour.2da
int nFileEnd = PRCGetFileEnd("craft_armour");
int nChoice = 1;
int i;
AddChoice("Enhancement +1", 0, oPC);
for(i = 1; i <= nFileEnd; i++)
{
// Get enhancement and cost for this specific line
int nEnhancement = StringToInt(Get2DACache("craft_armour", "Enhancement", i));
int nAdditionalCost = StringToInt(Get2DACache("craft_armour", "AdditionalCost", i));
string sName = GetStringByStrRef(StringToInt(Get2DACache("craft_armour", "Name", i)));
// Debug output
SendMessageToPC(oPC, "Line " + IntToString(i) + ": " + sName + " (Enh:" + IntToString(nEnhancement) + ", Cost:" + IntToString(nAdditionalCost) + ")");
// Check if this property is within limits
if(nEnhancement <= nMaxEnhancement && nAdditionalCost <= nMaxCost)
{
AddChoice(sName, i, oPC);
nChoice++;
}
}
MarkStageSetUp(STAGE_PROPERTY_SELECTION, oPC);
}
else if(nStage == STAGE_CONFIRMATION)
{
int nPropertyLine = GetLocalInt(oPC, "ArmorEnh_SelectedProperty");
string sName;
if(nPropertyLine == 0)
sName = "Enhancement +1";
else
sName = GetStringByStrRef(StringToInt(Get2DACache("craft_armour", "Name", nPropertyLine)));
SetHeader("Apply " + sName + " to the armor?");
AddChoice("Yes", TRUE, oPC);
AddChoice("No", FALSE, oPC);
MarkStageSetUp(STAGE_CONFIRMATION, oPC);
}
}
SetupTokens();
}
else if(nValue == DYNCONV_EXITED)
{
// Cleanup
DeleteLocalInt(oPC, "ArmorEnh_ConvMode");
DeleteLocalObject(oPC, "ARMOR_ENH_TARGET");
DeleteLocalInt(oPC, "ArmorEnh_SelectedProperty");
}
else if(nValue == DYNCONV_ABORTED)
{
// Cleanup
DeleteLocalInt(oPC, "ArmorEnh_ConvMode");
DeleteLocalObject(oPC, "ARMOR_ENH_TARGET");
DeleteLocalInt(oPC, "ArmorEnh_SelectedProperty");
}
else
{
int nChoice = GetChoice(oPC);
if(nStage == STAGE_PROPERTY_SELECTION)
{
// Store selection and go to confirmation
SetLocalInt(oPC, "ArmorEnh_SelectedProperty", nChoice);
nStage = STAGE_CONFIRMATION;
MarkStageNotSetUp(STAGE_PROPERTY_SELECTION, oPC);
}
else if(nStage == STAGE_CONFIRMATION)
{
if(nChoice == TRUE) // User confirmed
{
// Apply the property
object oArmor = GetLocalObject(oPC, "ARMOR_ENH_TARGET");
int nPropertyLine = GetLocalInt(oPC, "ArmorEnh_SelectedProperty");
int nCasterLevel = GetLocalInt(oPC, "ArmorEnh_CasterLevel");
float fDuration = TurnsToSeconds(nCasterLevel * 10);
int nMetaMagic = PRCGetMetaMagicFeat();
if(nMetaMagic & METAMAGIC_EXTEND)
fDuration *= 2;
// Debug output
SendMessageToPC(oPC, "Duration: " + FloatToString(fDuration) + " seconds");
// Add fallback for very small durations
if (fDuration <= 1.0) fDuration = 30.0f;
// Create property directly
itemproperty ip;
if(nPropertyLine == 0)
{
// +1 Enhancement
ip = ConstructIP(ITEM_PROPERTY_AC_BONUS, 0, 1, 0);
}
else
{
// Read property data from 2DA and construct
string sIPData = Get2DACache("craft_armour", "IP1", nPropertyLine);
struct ipstruct iptemp = GetIpStructFromString(sIPData);
ip = ConstructIP(iptemp.type, iptemp.subtype, iptemp.costtablevalue, iptemp.param1value);
}
// Apply with proper duration
ip = TagItemProperty(ip, "ArmorEnhInfusion");
IPSafeAddItemProperty(oArmor, ip, fDuration, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, TRUE);
// Clean up and exit
DeleteLocalInt(oPC, "ArmorEnh_ConvMode");
DeleteLocalObject(oPC, "ARMOR_ENH_TARGET");
DeleteLocalInt(oPC, "ArmorEnh_SelectedProperty");
AllowExit(DYNCONV_EXIT_FORCE_EXIT);
}
else // User cancelled
{
// Go back to property selection
nStage = STAGE_PROPERTY_SELECTION;
MarkStageNotSetUp(STAGE_CONFIRMATION, oPC);
}
}
SetStage(nStage, oPC);
}
}
void main()
{
object oPC = GetPCSpeaker();
if(!GetIsObjectValid(oPC)) oPC = OBJECT_SELF;
// Check if we're in conversation mode
if(GetLocalInt(oPC, "ArmorEnh_ConvMode"))
{
// Retrieve parameters for conversation
object oArmor = GetLocalObject(oPC, "ARMOR_ENH_TARGET");
int nMaxEnhancement = GetLocalInt(oPC, "ArmorEnh_MaxEnh");
int nMaxCost = GetLocalInt(oPC, "ArmorEnh_MaxCost");
string sLocalVar = GetLocalString(oPC, "ArmorEnh_LocalVar");
int nSpellID = GetLocalInt(oPC, "ArmorEnh_SpellID");
int nCasterLevel = GetLocalInt(oPC, "ArmorEnh_CasterLevel");
HandleConversation(oPC, oArmor, nMaxEnhancement, nMaxCost, sLocalVar, nSpellID, nCasterLevel);
return;
}
// Normal spell execution
PRCSetSchool(SPELL_SCHOOL_TRANSMUTATION);
if (!X2PreSpellCastCode()) return;
object oCaster = OBJECT_SELF;
object oTarget = PRCGetSpellTargetObject();
int nCasterLevel = PRCGetCasterLevel(oCaster);
int nSpellID = PRCGetSpellId();
// Declare variables
int nGoldCost, nMaxEnhancement, nMaxCost;
string sLocalVar;
// Set parameters based on spell level
switch(nSpellID)
{
case ARMOR_ENH_LESS:
nGoldCost = 10;
nMaxEnhancement = 1;
nMaxCost = 5000;
sLocalVar = "ARMOR_ENH_LESS_PROPERTY";
break;
case ARMOR_ENH:
nGoldCost = 50;
nMaxEnhancement = 3;
nMaxCost = 35000;
sLocalVar = "ARMOR_ENH_PROPERTY";
break;
case ARMOR_ENH_GREATER:
nGoldCost = 100;
nMaxEnhancement = 5;
nMaxCost = 100000;
sLocalVar = "ARMOR_ENH_GREATER_PROPERTY";
break;
default:
// Default to lesser version for testing
nGoldCost = 10;
nMaxEnhancement = 1;
nMaxCost = 5000;
sLocalVar = "ARMOR_ENH_LESS_PROPERTY";
break;
}
// Check material component
if(GetGold(oCaster) < nGoldCost)
{
FloatingTextStringOnCreature("You need " + IntToString(nGoldCost) + "gp worth of rare spices and minerals.", oCaster, FALSE);
return;
}
// Get targeted armor or shield
object oArmor = GetItemInSlot(INVENTORY_SLOT_CHEST, oCaster);
if(!GetIsObjectValid(oArmor))
{
FloatingTextStrRefOnCreature(83826, oCaster, FALSE); // "Invalid target"
return;
}
// Check if item already has an infusion
itemproperty ipExisting = GetFirstItemProperty(oArmor);
while(GetIsItemPropertyValid(ipExisting))
{
if(GetItemPropertyTag(ipExisting) == "ArmorEnhInfusion")
{
FloatingTextStringOnCreature("This armor already has an armor enhancement infusion.", oCaster, FALSE);
return;
}
ipExisting = GetNextItemProperty(oArmor);
}
// Check if returning from conversation with a selection
int nPropertyLine = GetLocalInt(oCaster, sLocalVar);
if(nPropertyLine > 0)
{
// Apply the property
float fDuration = TurnsToSeconds(nCasterLevel * 10);
int nMetaMagic = PRCGetMetaMagicFeat();
if(nMetaMagic & METAMAGIC_EXTEND)
fDuration *= 2;
if (fDuration <= 1.0) fDuration = 30.0f;
// Create property directly
itemproperty ip;
if(nPropertyLine == 0)
{
// +1 Enhancement
ip = ConstructIP(ITEM_PROPERTY_AC_BONUS, 0, 1, 0);
}
else
{
// Read property data from 2DA and construct
string sIPData = Get2DACache("craft_armour", "IP1", nPropertyLine);
struct ipstruct iptemp = GetIpStructFromString(sIPData);
ip = ConstructIP(iptemp.type, iptemp.subtype, iptemp.costtablevalue, iptemp.param1value);
}
// Apply with proper duration
ip = TagItemProperty(ip, "ArmorEnhInfusion");
IPSafeAddItemProperty(oArmor, ip, fDuration, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, TRUE);
DeleteLocalInt(oCaster, sLocalVar);
return;
}
// Store parameters for conversation and start it
SetLocalInt(oPC, "ArmorEnh_ConvMode", 1);
SetLocalObject(oPC, "ARMOR_ENH_TARGET", oArmor);
SetLocalInt(oPC, "ArmorEnh_MaxEnh", nMaxEnhancement);
SetLocalInt(oPC, "ArmorEnh_MaxCost", nMaxCost);
SetLocalString(oPC, "ArmorEnh_LocalVar", sLocalVar);
SetLocalInt(oPC, "ArmorEnh_SpellID", nSpellID);
SetLocalInt(oPC, "ArmorEnh_CasterLevel", nCasterLevel);
// Start the dynamic conversation using this same script
StartDynamicConversation("inf_armor_enh", oPC, 0, FALSE, TRUE);
}
*/