diff --git a/nwn/nwnprc/trunk/include/inc_switch_setup.nss b/nwn/nwnprc/trunk/include/inc_switch_setup.nss index 15182a92..bb1167f9 100644 --- a/nwn/nwnprc/trunk/include/inc_switch_setup.nss +++ b/nwn/nwnprc/trunk/include/inc_switch_setup.nss @@ -999,26 +999,6 @@ void CreateSwitchNameArray() array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_PSI_ASTRAL_CONSTRUCT_DUR_MOD); array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_PNP_RAPID_METABOLISM); array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_PSI_IMP_METAPSIONICS_USE_SUM); - array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_USECR); - array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_S_HUGE); - array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_S_LARGE); - array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_S_MEDIUM); - array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_S_SMALL); - array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_S_TINY); - array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_OUTSIDER); - array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_ELEMENTAL); - array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_CONSTRUCT); - array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_UNDEAD); - array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_DRAGON); - array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_ABERRATION); - array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_OOZE); - array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_MAGICALBEAST); - array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_GIANT); - array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_VERMIN); - array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_BEAST); - array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_ANIMAL); - array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_MONSTROUSHUMANOID); - array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_HUMANOID); array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_PNP_ELEMENTAL_DAMAGE); array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_SPELL_SNEAK_DISABLE); array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_3_5e_FIST_DAMAGE); @@ -1079,10 +1059,33 @@ void CreateSwitchNameArray() array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFTING_COST_SCALE); array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFTING_TIME_SCALE); array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CREATE_INFUSION_CASTER_LEVEL); + array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CREATE_INFUSION_OPTIONAL_HERBS); //spells //shifter + array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_WEREWOLF_HYBRID_USE_SHIFTER_SHAPECHANGE); + array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_WILDSHAPE_ALLOWS_ARMS_SLOT); + array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_USECR); + array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_S_HUGE); + array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_S_LARGE); + array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_S_MEDIUM); + array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_S_SMALL); + array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_S_TINY); + array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_OUTSIDER); + array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_ELEMENTAL); + array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_CONSTRUCT); + array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_UNDEAD); + array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_DRAGON); + array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_ABERRATION); + array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_OOZE); + array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_MAGICALBEAST); + array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_GIANT); + array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_VERMIN); + array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_BEAST); + array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_ANIMAL); + array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_MONSTROUSHUMANOID); + array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_HUMANOID); //general diff --git a/nwn/nwnprc/trunk/include/pnp_shft_poly.nss b/nwn/nwnprc/trunk/include/pnp_shft_poly.nss index ce6d8601..4df6b3da 100644 --- a/nwn/nwnprc/trunk/include/pnp_shft_poly.nss +++ b/nwn/nwnprc/trunk/include/pnp_shft_poly.nss @@ -11,8 +11,123 @@ void ShifterCheck(object oPC); #include "prc_inc_shifting" const string PRC_PNP_SHIFTING = "PRC_Shift"; +void LycanthropePoly(object oPC, int nPoly) +{ + effect eVis = EffectVisualEffect(VFX_IMP_POLYMORPH); + effect ePoly = SupernaturalEffect(EffectPolymorph(nPoly)); -////////////////Begin Werewolf////////////////// + int bMonkGloves = GetLocalInt(oPC, "WEARING_MONK_GLOVES"); + int bArmsSlotAllowed = GetPRCSwitch(PRC_WILDSHAPE_ALLOWS_ARMS_SLOT); // <--- new + + int bWeapon = StringToInt(Get2DACache("polymorph","MergeW",nPoly)) == 1; + int bArmor = StringToInt(Get2DACache("polymorph","MergeA",nPoly)) == 1; + int bItems = StringToInt(Get2DACache("polymorph","MergeI",nPoly)) == 1; + + object oWeaponOld = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC); + object oArmorOld = GetItemInSlot(INVENTORY_SLOT_CHEST,oPC); + object oRing1Old = GetItemInSlot(INVENTORY_SLOT_LEFTRING,oPC); + object oRing2Old = GetItemInSlot(INVENTORY_SLOT_RIGHTRING,oPC); + object oAmuletOld = GetItemInSlot(INVENTORY_SLOT_NECK,oPC); + object oCloakOld = GetItemInSlot(INVENTORY_SLOT_CLOAK,oPC); + object oBootsOld = GetItemInSlot(INVENTORY_SLOT_BOOTS,oPC); + object oBeltOld = GetItemInSlot(INVENTORY_SLOT_BELT,oPC); + object oHelmetOld = GetItemInSlot(INVENTORY_SLOT_HEAD,oPC); + object oShield = GetItemInSlot(INVENTORY_SLOT_LEFTHAND,oPC); + object oGlovesOld = GetItemInSlot(INVENTORY_SLOT_ARMS,oPC); + + if (GetIsObjectValid(oShield)) + { + int nShieldType = GetBaseItemType(oShield); + if (nShieldType != BASE_ITEM_LARGESHIELD && + nShieldType != BASE_ITEM_SMALLSHIELD && + nShieldType != BASE_ITEM_TOWERSHIELD) + { + oShield = OBJECT_INVALID; + } + } + + ShifterCheck(oPC); + ClearAllActions(); + + ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oPC); + ApplyEffectToObject(DURATION_TYPE_PERMANENT, ePoly, oPC); + + object oWeaponNewRight = GetItemInSlot(INVENTORY_SLOT_CWEAPON_R,oPC); + object oWeaponNewLeft = GetItemInSlot(INVENTORY_SLOT_CWEAPON_L,oPC); + object oWeaponNewBite = GetItemInSlot(INVENTORY_SLOT_CWEAPON_B,oPC); + object oArmorNew = GetItemInSlot(INVENTORY_SLOT_CARMOUR,oPC); + + /* ---------------- + Weapon merge block + If arms-slot-merge is enabled we DO NOT apply gloves here. + ---------------- */ + if (bWeapon) + { + if (!bMonkGloves) + { + if (GetIsObjectValid(oWeaponOld)) + { + if (GetIsObjectValid(oWeaponNewLeft)) IPWildShapeCopyItemProperties(oWeaponOld, oWeaponNewLeft, TRUE); + if (GetIsObjectValid(oWeaponNewRight)) IPWildShapeCopyItemProperties(oWeaponOld, oWeaponNewRight, TRUE); + if (GetIsObjectValid(oWeaponNewBite)) IPWildShapeCopyItemProperties(oWeaponOld, oWeaponNewBite, TRUE); + } + } + else if (!bArmsSlotAllowed) // only apply gloves-to-weapons here if arms-slot is NOT allowed + { + if (DEBUG) DoDebug("LycanthropePoly: Monk gloves overriding weapon merge (arms slot NOT allowed)."); + if (GetIsObjectValid(oGlovesOld)) + { + if (GetIsObjectValid(oWeaponNewLeft)) IPWildShapeCopyItemProperties(oGlovesOld, oWeaponNewLeft, TRUE); + if (GetIsObjectValid(oWeaponNewRight)) IPWildShapeCopyItemProperties(oGlovesOld, oWeaponNewRight, TRUE); + if (GetIsObjectValid(oWeaponNewBite)) IPWildShapeCopyItemProperties(oGlovesOld, oWeaponNewBite, TRUE); + } + } + } + + /* ---------------- + Armor merge block + When arms-slot-allowed is TRUE, merge gloves here into the creature's weapons + (so forms that don't normally merge weapons/items still get glove damage). + ---------------- */ + if (bArmor) + { + if (GetIsObjectValid(oArmorNew)) + { + if (GetIsObjectValid(oShield)) IPWildShapeCopyItemProperties(oShield, oArmorNew); + if (GetIsObjectValid(oHelmetOld)) IPWildShapeCopyItemProperties(oHelmetOld, oArmorNew); + if (GetIsObjectValid(oArmorOld)) IPWildShapeCopyItemProperties(oArmorOld, oArmorNew); + + /* If module allows arms-slot merging, and player is wearing monk gloves, + copy the gloves' IPs to any creature weapon slot from the armor branch. + This runs regardless of bWeapon (i.e. even if MergeW == 0). */ + if (bArmsSlotAllowed && bMonkGloves && GetIsObjectValid(oGlovesOld)) + { + if (DEBUG) DoDebug("LycanthropePoly: Arms-slot allowed -> applying gloves to creature weapons from armor branch."); + + if (GetIsObjectValid(oWeaponNewLeft)) IPWildShapeCopyItemProperties(oGlovesOld, oWeaponNewLeft, TRUE); + if (GetIsObjectValid(oWeaponNewRight)) IPWildShapeCopyItemProperties(oGlovesOld, oWeaponNewRight, TRUE); + if (GetIsObjectValid(oWeaponNewBite)) IPWildShapeCopyItemProperties(oGlovesOld, oWeaponNewBite, TRUE); + } + } + else + { + if (DEBUG) DoDebug("LycanthropePoly: MergeA set, but oArmorNew invalid."); + } + } + + if (bItems && GetIsObjectValid(oArmorNew)) + { + if (GetIsObjectValid(oRing1Old)) IPWildShapeCopyItemProperties(oRing1Old, oArmorNew); + if (GetIsObjectValid(oRing2Old)) IPWildShapeCopyItemProperties(oRing2Old, oArmorNew); + if (GetIsObjectValid(oAmuletOld)) IPWildShapeCopyItemProperties(oAmuletOld, oArmorNew); + if (GetIsObjectValid(oCloakOld)) IPWildShapeCopyItemProperties(oCloakOld, oArmorNew); + if (GetIsObjectValid(oBootsOld)) IPWildShapeCopyItemProperties(oBootsOld, oArmorNew); + if (GetIsObjectValid(oBeltOld)) IPWildShapeCopyItemProperties(oBeltOld, oArmorNew); + } +} + + +/* ////////////////Begin Werewolf////////////////// void LycanthropePoly(object oPC, int nPoly) { @@ -21,6 +136,9 @@ void LycanthropePoly(object oPC, int nPoly) ePoly = EffectPolymorph(nPoly); ePoly = SupernaturalEffect(ePoly); + + int bMonkGloves = GetLocalInt(oPC, "WEARING_MONK_GLOVES"); + //int bMonkSwitch = GetPRCSwitch(PRC_WILDSHAPE_USES_ARM_SLOTS); int bWeapon = StringToInt(Get2DACache("polymorph","MergeW",nPoly)) == 1; int bArmor = StringToInt(Get2DACache("polymorph","MergeA",nPoly)) == 1; @@ -36,6 +154,7 @@ void LycanthropePoly(object oPC, int nPoly) object oBeltOld = GetItemInSlot(INVENTORY_SLOT_BELT,oPC); object oHelmetOld = GetItemInSlot(INVENTORY_SLOT_HEAD,oPC); object oShield = GetItemInSlot(INVENTORY_SLOT_LEFTHAND,oPC); + object oGlovesOld = GetItemInSlot(INVENTORY_SLOT_ARMS,oPC); if (GetIsObjectValid(oShield)) { if (GetBaseItemType(oShield) !=BASE_ITEM_LARGESHIELD && @@ -55,16 +174,26 @@ void LycanthropePoly(object oPC, int nPoly) ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oPC); ApplyEffectToObject(DURATION_TYPE_PERMANENT, ePoly, oPC); - object oWeaponNewRight = GetItemInSlot(INVENTORY_SLOT_CWEAPON_R,oPC); - object oWeaponNewLeft = GetItemInSlot(INVENTORY_SLOT_CWEAPON_L,oPC); - object oWeaponNewBite = GetItemInSlot(INVENTORY_SLOT_CWEAPON_B,oPC); - object oArmorNew = GetItemInSlot(INVENTORY_SLOT_CARMOUR,oPC); + object oWeaponNewRight = GetItemInSlot(INVENTORY_SLOT_CWEAPON_R,oPC); + object oWeaponNewLeft = GetItemInSlot(INVENTORY_SLOT_CWEAPON_L,oPC); + object oWeaponNewBite = GetItemInSlot(INVENTORY_SLOT_CWEAPON_B,oPC); + object oArmorNew = GetItemInSlot(INVENTORY_SLOT_CARMOUR,oPC); if (bWeapon) { - IPWildShapeCopyItemProperties(oWeaponOld,oWeaponNewLeft, TRUE); - IPWildShapeCopyItemProperties(oWeaponOld,oWeaponNewRight, TRUE); - IPWildShapeCopyItemProperties(oWeaponOld,oWeaponNewBite, TRUE); + if(!bMonkGloves) + { + IPWildShapeCopyItemProperties(oWeaponOld,oWeaponNewLeft, TRUE); + IPWildShapeCopyItemProperties(oWeaponOld,oWeaponNewRight, TRUE); + IPWildShapeCopyItemProperties(oWeaponOld,oWeaponNewBite, TRUE); + } + else + { + if(DEBUG) DoDebug("pnp_shift_poly >> LycanthropePoly(): Found monk gloves in bWeapon branch."); + IPWildShapeCopyItemProperties(oGlovesOld,oWeaponNewLeft, TRUE); + IPWildShapeCopyItemProperties(oGlovesOld,oWeaponNewRight, TRUE); + IPWildShapeCopyItemProperties(oGlovesOld,oWeaponNewBite, TRUE); + } } if (bArmor) { @@ -84,7 +213,119 @@ void LycanthropePoly(object oPC, int nPoly) } -////////////////End Werewolf////////////////// +////////////////End Werewolf////////////////// */ + + +/* ////////////////Begin Werewolf////////////////// + +void LycanthropePoly(object oPC, int nPoly) +{ + + if(DEBUG) DoDebug("pnp_shift_poly >> LycanthropePoly(): Entering fucntion."); + effect eVis = EffectVisualEffect(VFX_IMP_POLYMORPH); + effect ePoly; + + ePoly = EffectPolymorph(nPoly); + ePoly = SupernaturalEffect(ePoly); + + int bMonkGloves = GetLocalInt(oPC, "WEARING_MONK_GLOVES"); + int bMonkSwitch = GetPRCSwitch(PRC_WILDSHAPE_USES_ARM_SLOTS); + + int bWeapon = StringToInt(Get2DACache("polymorph","MergeW",nPoly)) == 1; + int bArmor = StringToInt(Get2DACache("polymorph","MergeA",nPoly)) == 1; + int bItems = StringToInt(Get2DACache("polymorph","MergeI",nPoly)) == 1; + + + object oWeaponOld = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC); + object oArmorOld = GetItemInSlot(INVENTORY_SLOT_CHEST,oPC); + object oRing1Old = GetItemInSlot(INVENTORY_SLOT_LEFTRING,oPC); + object oRing2Old = GetItemInSlot(INVENTORY_SLOT_RIGHTRING,oPC); + object oAmuletOld = GetItemInSlot(INVENTORY_SLOT_NECK,oPC); + object oCloakOld = GetItemInSlot(INVENTORY_SLOT_CLOAK,oPC); + object oBootsOld = GetItemInSlot(INVENTORY_SLOT_BOOTS,oPC); + object oBeltOld = GetItemInSlot(INVENTORY_SLOT_BELT,oPC); + object oHelmetOld = GetItemInSlot(INVENTORY_SLOT_HEAD,oPC); + object oShield = GetItemInSlot(INVENTORY_SLOT_LEFTHAND,oPC); + object oGlovesOld = GetItemInSlot(INVENTORY_SLOT_ARMS,oPC); + if (GetIsObjectValid(oShield)) + { + if (GetBaseItemType(oShield) !=BASE_ITEM_LARGESHIELD && + GetBaseItemType(oShield) !=BASE_ITEM_SMALLSHIELD && + GetBaseItemType(oShield) !=BASE_ITEM_TOWERSHIELD) + { + oShield = OBJECT_INVALID; + } + } + + //check if a shifter and if shifted then unshift + ShifterCheck(oPC); + + ClearAllActions(); // prevents an exploit + + //Apply the VFX impact and effects + ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oPC); + ApplyEffectToObject(DURATION_TYPE_PERMANENT, ePoly, oPC); + + object oWeaponNewRight = GetItemInSlot(INVENTORY_SLOT_CWEAPON_R,oPC); + object oWeaponNewLeft = GetItemInSlot(INVENTORY_SLOT_CWEAPON_L,oPC); + object oWeaponNewBite = GetItemInSlot(INVENTORY_SLOT_CWEAPON_B,oPC); + object oArmorNew = GetItemInSlot(INVENTORY_SLOT_CARMOUR,oPC); + + if (bWeapon) + { + if(DEBUG) DoDebug("pnp_shift_poly >> LycanthropePoly(): Entering bWeapon branch."); + IPWildShapeCopyItemProperties(oWeaponOld,oWeaponNewLeft, TRUE); + IPWildShapeCopyItemProperties(oWeaponOld,oWeaponNewRight, TRUE); + IPWildShapeCopyItemProperties(oWeaponOld,oWeaponNewBite, TRUE); + } + + if (bArmor) + { + if(DEBUG) DoDebug("pnp_shift_poly >> LycanthropePoly(): Entering bArmor branch."); + IPWildShapeCopyItemProperties(oShield,oArmorNew); + IPWildShapeCopyItemProperties(oHelmetOld,oArmorNew); + IPWildShapeCopyItemProperties(oArmorOld,oArmorNew); + + if(bMonkGloves) + { + if(DEBUG) DoDebug("pnp_shift_poly >> LycanthropePoly(): Entering bMonkSwitch -> bMonkGloves branch."); + IPWildShapeCopyItemProperties(oGlovesOld,oWeaponNewLeft, TRUE); + IPWildShapeCopyItemProperties(oGlovesOld,oWeaponNewRight, TRUE); + IPWildShapeCopyItemProperties(oGlovesOld,oWeaponNewBite, TRUE); + } + else + { + if(DEBUG) DoDebug("pnp_shift_poly >> LycanthropePoly(): Entering bMonkSwitch -> !bMonkGloves branch."); + IPWildShapeCopyItemProperties(oGlovesOld,oArmorNew); + } + + } + if (bItems) + { + IPWildShapeCopyItemProperties(oRing1Old,oArmorNew); + IPWildShapeCopyItemProperties(oRing2Old,oArmorNew); + IPWildShapeCopyItemProperties(oAmuletOld,oArmorNew); + IPWildShapeCopyItemProperties(oCloakOld,oArmorNew); + IPWildShapeCopyItemProperties(oBootsOld,oArmorNew); + IPWildShapeCopyItemProperties(oBeltOld,oArmorNew); + + if(!bMonkGloves) + { + if(DEBUG) DoDebug("pnp_shift_poly >> LycanthropePoly(): Entering !bMonkSwitch -> !bMonkGloves branch."); + IPWildShapeCopyItemProperties(oGlovesOld, oArmorNew); + } + else + { + if(DEBUG) DoDebug("pnp_shift_poly >> LycanthropePoly(): Entering !bMonkSwitch -> bMonkGloves branch."); + IPWildShapeCopyItemProperties(oGlovesOld, oWeaponNewLeft, TRUE); + IPWildShapeCopyItemProperties(oGlovesOld, oWeaponNewRight, TRUE); + IPWildShapeCopyItemProperties(oGlovesOld, oWeaponNewBite, TRUE); + } + + } +} + +////////////////End Werewolf////////////////// */ void ShifterCheck(object oPC) { @@ -246,4 +487,6 @@ void DoTail(object oPC, int nTailType) SetCreatureTailType(nTailType, oPC); //override any stored default appearance SetPersistantLocalInt(oPC, "AppearanceStoredTail", nTailType); -} \ No newline at end of file +} + +//::void main (){} \ No newline at end of file diff --git a/nwn/nwnprc/trunk/include/prc_inc_switch.nss b/nwn/nwnprc/trunk/include/prc_inc_switch.nss index b6672623..d8a7b010 100644 --- a/nwn/nwnprc/trunk/include/prc_inc_switch.nss +++ b/nwn/nwnprc/trunk/include/prc_inc_switch.nss @@ -552,13 +552,13 @@ const string PRC_BARD_DISALLOW_NEWSPELLBOOK = "PRC_BARD_DISALLOW_NEWSPELLBOO */ const string PRC_BARD_LIGHT_ARMOR_SPELLCASTING = "PRC_BARD_LIGHT_ARMOR_SPELLCASTING"; -/** +/* * By default, CW Samurai get a plain katana and a plain wakizashi (shortsword) at 1st level. * Setting this to non-zero value prevents that. */ const string PRC_CWSAMURAI_NO_HEIRLOOM_DAISHO = "PRC_CWSAMURAI_NO_HEIRLOOM_DAISHO"; -/** +/* * Determines the number of wight henchmen a Soul Eater can have via their Soul Slave * class ability. * Default: 4 @@ -568,7 +568,7 @@ const string PRC_CWSAMURAI_NO_HEIRLOOM_DAISHO = "PRC_CWSAMURAI_NO_HEIRLOOM_DAISH const string PRC_SOUL_EATER_MAX_SLAVES = "PRC_SOUL_EATER_MAX_SLAVES"; -/** +/* * For the Psionic Slayer prestige class, this switch limits the Favored Enemy selection * to the Aberration racial type. * @@ -581,7 +581,7 @@ const string PRC_SOUL_EATER_MAX_SLAVES = "PRC_SOUL_EATER_MAX_SLAVES"; */ const string PRC_PSIONIC_SLAYER_FAV_ENEMY_ABERRATION_ONLY = "PRC_PSIONIC_SLAYER_FAV_ENEMY_ABERRATION_ONLY"; -/** +/* * For the Psionic Slayer prestige class, this switch requires a character to make a "kill" * of a specific type of creature before the class becomes available. * @@ -603,9 +603,9 @@ const string PRC_PSIONIC_SLAYER_FAV_ENEMY_ABERRATION_ONLY = "PRC_PSIONIC_S const string PRC_PSIONIC_SLAYER_REQUIRE_KILL_TOKEN = "PRC_PSIONIC_SLAYER_REQUIRE_KILL_TOKEN"; -/** +/* * By default the Werewolf class uses the Bioware Polymorph effect to perfrom its - * Hybrid Form Shapchange. + * Hybrid Form Shapechange. * * This switch allows the Werewolf class to be toggled to use the PRC Shifter * Shapchange code instead. @@ -614,9 +614,9 @@ const string PRC_PSIONIC_SLAYER_REQUIRE_KILL_TOKEN = "PRC_PSIONIC_SLAYER_R * Values: 0 [Default] (Werewolf Hybrid Shapchange uses Bioware Polymorph) * 1 (Werewolf Hybrid Shapchange uses PRC Shifter shape change code) */ -const string PRC_WEREWOLF_HYBRID_USE_SHIFTER_SHAPCHANGE = "PRC_WEREWOLF_HYBRID_USE_SHIFTER_SHAPCHANGE"; +const string PRC_WEREWOLF_HYBRID_USE_SHIFTER_SHAPECHANGE = "PRC_WEREWOLF_HYBRID_USE_SHIFTER_SHAPECHANGE"; -/** +/* * Sets the max bonus for the PnP Shifter shifting systems * * Type: Int @@ -1204,8 +1204,11 @@ const string PRC_SPELL_ALIGNMENT_RESTRICT = "PRC_SPELL_ALIGNMENT_REST */ const string PRC_APPEARNCE_CHANGE_DISABLE = "PRC_APPEARNCE_CHANGE_DISABLE"; - - +/* + * Allow "Monk" gloves to merge with a creature weapons when Wildshaped. + * Will also merge bracers with creature hides when Wildshaped. +*/ +const string PRC_WILDSHAPE_ALLOWS_ARMS_SLOT = "PRC_WILDSHAPE_ALLOWS_ARMS_SLOT"; /******************************************************************************\ * Death/Bleeding system * diff --git a/nwn/nwnprc/trunk/include/prc_inc_wpnrest.nss b/nwn/nwnprc/trunk/include/prc_inc_wpnrest.nss index 1734b3b1..1ba65716 100644 --- a/nwn/nwnprc/trunk/include/prc_inc_wpnrest.nss +++ b/nwn/nwnprc/trunk/include/prc_inc_wpnrest.nss @@ -15,6 +15,56 @@ #include "inc_item_props" #include "prc_x2_itemprop" +//:: Detects if "monk" gloves are being equipped & set a +//:: variable if TRUE for use with other functions +void DetectMonkGloveEquip(object oItem) +{ + int nItemType = GetBaseItemType(oItem); + + object oPC = GetItemPossessor(oItem); + if (!GetIsObjectValid(oItem)) + { + if (DEBUG) DoDebug("prc_inc_wpnrest >> DetectMonkGloveEquip(): Unable to determine item possessor"); + return; + } + + if(nItemType != BASE_ITEM_GLOVES && nItemType != BASE_ITEM_BRACER) {return;} + + else if (nItemType == BASE_ITEM_BRACER) + { + if(DEBUG) DoDebug("prc_inc_wpnrest >> DetectMonkGloveEquip(): Bracer found!"); + DeleteLocalInt(oPC, "WEARING_MONK_GLOVES"); + return; + } + else + { + itemproperty ipG = GetFirstItemProperty(oItem); + + while(GetIsItemPropertyValid(ipG)) + { + int nTypeG = GetItemPropertyType(ipG); + + // Damage related properties we care about + if(nTypeG == ITEM_PROPERTY_DAMAGE_BONUS + || nTypeG == ITEM_PROPERTY_ATTACK_BONUS + || nTypeG == ITEM_PROPERTY_DAMAGE_BONUS_VS_ALIGNMENT_GROUP + || nTypeG == ITEM_PROPERTY_DAMAGE_BONUS_VS_RACIAL_GROUP + || nTypeG == ITEM_PROPERTY_DAMAGE_BONUS_VS_SPECIFIC_ALIGNMENT) + { + if(DEBUG) DoDebug("prc_inc_wpnrest >> DetectMonkGloves(): Monk gloves found!"); + SetLocalInt(oPC, "WEARING_MONK_GLOVES", 1); + return; + } + else + { + if(DEBUG) DoDebug("prc_inc_wpnrest >> DetectMonkGloves(): Monk gloves not found! You should never see this."); + DeleteLocalInt(oPC, "WEARING_MONK_GLOVES"); + return; + } + } + } +} + /** * All of the following functions use the following parameters: * @@ -23,7 +73,6 @@ * @param nHand The hand the weapon is wielded in. In the form of * ATTACK_BONUS_ONHAND or ATTACK_BONUS_OFFHAND. */ - //:: returns TRUE if the wielded weapon works with the Swashbuckler's class abilities. int GetHasSwashbucklerWeapon(object oPC) { diff --git a/nwn/nwnprc/trunk/include/prc_x2_itemprop.nss b/nwn/nwnprc/trunk/include/prc_x2_itemprop.nss index 17885cdc..d6efc307 100644 --- a/nwn/nwnprc/trunk/include/prc_x2_itemprop.nss +++ b/nwn/nwnprc/trunk/include/prc_x2_itemprop.nss @@ -1612,31 +1612,140 @@ int IPGetDamageBonusConstantFromNumber(int nNumber) // oOld - Item equipped before polymorphing (source for item props) // oNew - Item equipped after polymorphing (target for item props) // bWeapon - Must be set TRUE when oOld is a weapon. -// ---------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- void IPWildShapeCopyItemProperties(object oOld, object oNew, int bWeapon = FALSE) { - if (GetIsObjectValid(oOld) && GetIsObjectValid(oNew)) - { - itemproperty ip = GetFirstItemProperty(oOld); - while (GetIsItemPropertyValid(ip)) - { - if (bWeapon) - { - if (GetWeaponRanged(oOld) == GetWeaponRanged(oNew) ) - { - AddItemProperty(DURATION_TYPE_PERMANENT,ip,oNew); - } - } - else - { - AddItemProperty(DURATION_TYPE_PERMANENT,ip,oNew); - } - ip = GetNextItemProperty(oOld); + // Invalid source/target + if (!GetIsObjectValid(oOld) || !GetIsObjectValid(oNew)) + return; + + // Determine possessor + object oPC = GetItemPossessor(oOld); + if (!GetIsObjectValid(oPC)) + oPC = GetItemPossessor(oNew); - } - } + if (!GetIsObjectValid(oPC)) + { + if (DEBUG) DoDebug("IPWS: Unable to determine item possessor"); + return; + } + + // Determine glove state once + int bMonkGloves = GetLocalInt(oPC, "WEARING_MONK_GLOVES"); + + // Weapon ranged mismatch = do nothing (intent is no partial copy) + if (bWeapon && GetWeaponRanged(oOld) != GetWeaponRanged(oNew)) + { + if (DEBUG) DoDebug("IPWS: Weapon ranged mismatch — skipping all IP copy"); + return; + } + + // Begin property copy + itemproperty ip = GetFirstItemProperty(oOld); + while (GetIsItemPropertyValid(ip)) + { + int nType = GetItemPropertyType(ip); + + // If copying from gloves and monk gloves are active + if (bMonkGloves + && (nType == ITEM_PROPERTY_DAMAGE_BONUS + || nType == ITEM_PROPERTY_DAMAGE_BONUS_VS_RACIAL_GROUP + || nType == ITEM_PROPERTY_DAMAGE_BONUS_VS_ALIGNMENT_GROUP)) + { + // Always apply glove damage IPs + AddItemProperty(DURATION_TYPE_PERMANENT, ip, oNew); + ip = GetNextItemProperty(oOld); + continue; + } + + // Normal weapon pass + if (bWeapon) + { + // If monk gloves active ? skip ALL weapon damage IPs + if (bMonkGloves + && (nType == ITEM_PROPERTY_DAMAGE_BONUS + || nType == ITEM_PROPERTY_DAMAGE_BONUS_VS_RACIAL_GROUP + || nType == ITEM_PROPERTY_DAMAGE_BONUS_VS_ALIGNMENT_GROUP)) + { + ip = GetNextItemProperty(oOld); + continue; + } + + AddItemProperty(DURATION_TYPE_PERMANENT, ip, oNew); + } + else + { + AddItemProperty(DURATION_TYPE_PERMANENT, ip, oNew); + } + + ip = GetNextItemProperty(oOld); + } } + +/* // ---------------------------------------------------------------------------- +// GZ, Sept. 30 2003 +// Special Version of Copy Item Properties for use with greater wild shape +// oOld - Item equipped before polymorphing (source for item props) +// oNew - Item equipped after polymorphing (target for item props) +// bWeapon - Must be set TRUE when oOld is a weapon. +// ---------------------------------------------------------------------------- +void IPWildShapeCopyItemProperties(object oOld, object oNew, int bWeapon = FALSE) +{ + if (!GetIsObjectValid(oOld) || !GetIsObjectValid(oNew)) + return; + + object oPC = GetItemPossessor(oOld); + if (!GetIsObjectValid(oPC)) + { + oPC = GetItemPossessor(oNew); + } + if (!GetIsObjectValid(oPC)) + { + if (DEBUG) DoDebug("IPWS: Unable to determine item possessor"); + return; + } + + int bMonkGloves = GetLocalInt(oPC, "WEARING_MONK_GLOVES"); + + itemproperty ip = GetFirstItemProperty(oOld); + while (GetIsItemPropertyValid(ip)) + { + if (bWeapon) + { + // Gloves override weapon damage — skip weapon damage properties + if (bMonkGloves) + { + int nType = GetItemPropertyType(ip); + + // skip damage props + if (nType == ITEM_PROPERTY_DAMAGE_BONUS + || nType == ITEM_PROPERTY_DAMAGE_BONUS_VS_RACIAL_GROUP + || nType == ITEM_PROPERTY_DAMAGE_BONUS_VS_ALIGNMENT_GROUP) + { + if (DEBUG) DoDebug("IPWS: SKIPPED weapon damage IP"); + } + else + { + if (DEBUG) DoDebug("IPWS: Applied non-damage weapon IP"); + AddItemProperty(DURATION_TYPE_PERMANENT, ip, oNew); + } + + } + else if (GetWeaponRanged(oOld) == GetWeaponRanged(oNew) ) + { + AddItemProperty(DURATION_TYPE_PERMANENT,ip,oNew); + } + } + else + { + AddItemProperty(DURATION_TYPE_PERMANENT,ip,oNew); + } + + ip = GetNextItemProperty(oOld); + } +} */ + // ---------------------------------------------------------------------------- // Returns the current enhancement bonus of a weapon (+1 to +20), 0 if there is // no enhancement bonus. You can test for a specific type of enhancement bonus @@ -2018,4 +2127,6 @@ int IPOnHitSaveDC(int nSaveDC) if (nSaveDC > 26) nIPBonus = IP_CONST_ONHIT_SAVEDC_26; return nIPBonus; -} */ \ No newline at end of file +} */ + +//:: void main(){} \ No newline at end of file diff --git a/nwn/nwnprc/trunk/others/ep_sum_aberrat03.utc b/nwn/nwnprc/trunk/others/ep_sum_aberrat03.utc index 9df1bc6a..63e5a844 100644 Binary files a/nwn/nwnprc/trunk/others/ep_sum_aberrat03.utc and b/nwn/nwnprc/trunk/others/ep_sum_aberrat03.utc differ diff --git a/nwn/nwnprc/trunk/racescripts/race_warforged.nss b/nwn/nwnprc/trunk/racescripts/race_warforged.nss index 2f357111..7e221d2f 100644 --- a/nwn/nwnprc/trunk/racescripts/race_warforged.nss +++ b/nwn/nwnprc/trunk/racescripts/race_warforged.nss @@ -8,8 +8,9 @@ //::////////////////////////////////////////////// //:: Created By: Fox //:: Created On: Feb 12, 2008 +//:: Updated by: Jaysyn +//:: Updated on: 2025-11-25 10:48:32 //::////////////////////////////////////////////// - #include "prc_alterations" void CreateWarforgedArmor(object oPC) @@ -49,7 +50,7 @@ void CreateWarforgedArmor(object oPC) SetDroppableFlag(oHelm, FALSE); SetItemCursedFlag(oHelm, TRUE); - // Force equip + //:: Force equip DelayCommand(1.0, AssignCommand(oPC, ActionEquipItem(oArmor, INVENTORY_SLOT_CHEST))); DelayCommand(1.0, AssignCommand(oPC, ActionEquipItem(oHelm, INVENTORY_SLOT_HEAD))); } @@ -68,13 +69,13 @@ void main() int nEvent = GetRunningEvent(); if(DEBUG) DoDebug("race_warforged running, event: " + IntToString(nEvent)); - // Init the PC. + //:: Init the PC. object oPC = OBJECT_SELF; object oItem; object oArmor; object oSkin; - // We aren't being called from any event, instead from EvalPRCFeats + //:: We aren't being called from any event, instead from EvalPRCFeats if(nEvent == FALSE) { oPC = OBJECT_SELF; @@ -83,7 +84,7 @@ void main() || GetIsObjectValid(GetItemPossessedBy(oPC, "prc_wf_mithbody")) || GetIsObjectValid(GetItemPossessedBy(oPC, "prc_wf_admtbody")) || GetIsObjectValid(GetItemPossessedBy(oPC, "prc_wf_compbody")); - // Hook in the events + //:: Hook in the events if(DEBUG) DoDebug("race_warforged: Adding eventhooks"); AddEventScript(oPC, EVENT_ONHEARTBEAT, "race_warforged", TRUE, FALSE); //may not be needed, put in just in case(ala HotU start) @@ -109,7 +110,7 @@ void main() IPSafeAddItemProperty(oSkin, ipIP, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, FALSE); if(DEBUG) DoDebug("race_warforged - ironwood - adding item property "+ItemPropertyToString(ipIP)); } - // Force equip + //:: Force equip oItem = GetItemPossessedBy(oPC, "prc_wf_woodbody"); if (oItem != GetItemInSlot(INVENTORY_SLOT_CHEST, oPC)) AssignCommand(oPC, ActionEquipItem(oItem, INVENTORY_SLOT_CHEST)); @@ -123,7 +124,7 @@ void main() IPSafeAddItemProperty(oSkin, ipIP, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, FALSE); if(DEBUG) DoDebug("race_warforged - mithril - adding item property "+ItemPropertyToString(ipIP)); } - // Force equip + //:: Force equip oItem = GetItemPossessedBy(oPC, "prc_wf_mithbody"); if (oItem != GetItemInSlot(INVENTORY_SLOT_CHEST, oPC)) AssignCommand(oPC, ActionEquipItem(oItem, INVENTORY_SLOT_CHEST)); @@ -137,20 +138,20 @@ void main() IPSafeAddItemProperty(oSkin, ipIP, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, FALSE); if(DEBUG) DoDebug("race_warforged - adamantine - adding item property "+ItemPropertyToString(ipIP)); } - // Force equip + //:: Force equip oItem = GetItemPossessedBy(oPC, "prc_wf_admtbody"); if (oItem != GetItemInSlot(INVENTORY_SLOT_CHEST, oPC)) AssignCommand(oPC, ActionEquipItem(oItem, INVENTORY_SLOT_CHEST)); } else if(GetHasFeat(FEAT_COMPOSITE_PLATING, oPC)) { - // Force equip + //:: Force equip oItem = GetItemPossessedBy(oPC, "prc_wf_compbody"); if (oItem != GetItemInSlot(INVENTORY_SLOT_CHEST, oPC)) AssignCommand(oPC, ActionEquipItem(oItem, INVENTORY_SLOT_CHEST)); } - // Delay a bit to make sure they are appropriately dressed + //:: Delay a bit to make sure they are appropriately dressed DelayCommand(0.5f, DoWarforgedCheck(oPC)); } else if(nEvent == EVENT_ONUNAQUIREITEM) diff --git a/nwn/nwnprc/trunk/scripts/prc_equip.nss b/nwn/nwnprc/trunk/scripts/prc_equip.nss index 124c6e2b..6fb7f580 100644 --- a/nwn/nwnprc/trunk/scripts/prc_equip.nss +++ b/nwn/nwnprc/trunk/scripts/prc_equip.nss @@ -10,7 +10,6 @@ //:: Created By: Georg Zoeller //:: Created On: 2003-07-16 //::////////////////////////////////////////////// - #include "prc_inc_function" #include "prc_inc_wpnrest" #include "inc_timestop" @@ -31,6 +30,9 @@ void main() if(!GetIsObjectValid(oPC)) return; + + //:: Use with bioware polymorphs + DetectMonkGloveEquip(oItem); //if(DEBUG) DoDebug("Running OnEquip, creature = '" + GetName(oPC) + "' is PC: " + DebugBool2String(GetIsPC(oPC)) + "; Item = '" + GetName(oItem) + "' - '" + GetTag(oItem) + "'"); diff --git a/nwn/nwnprc/trunk/scripts/prc_unequip.nss b/nwn/nwnprc/trunk/scripts/prc_unequip.nss index d5c9e63e..1b73c963 100644 --- a/nwn/nwnprc/trunk/scripts/prc_unequip.nss +++ b/nwn/nwnprc/trunk/scripts/prc_unequip.nss @@ -31,6 +31,27 @@ void PrcFeats(object oPC, object oItem) DeleteLocalInt(oPC,"ONEQUIP"); } +//:: Unsets a variable used for Bioware polymorphs +void DoGloveUnequip(object oItem) +{ + object oPC = OBJECT_SELF; + + int nItemType = GetBaseItemType(oItem); + + if(nItemType != BASE_ITEM_GLOVES) + { + if (DEBUG) DoDebug("prc_unequip >> DoGloveUnequip(): Not gloves."); + return; + } + + else + { + if (DEBUG) DoDebug("prc_unequip >> DoGloveUnequip(): Removing WEARING_MONK_GLOVES token."); + DeleteLocalInt(oPC, "WEARING_MONK_GLOVES"); + return; + } +} + void DoNaturalWeaponEffect(object oPC) { if (DEBUG) DoDebug("GetIsUsingPrimaryNaturalWeapons "+IntToString(GetIsUsingPrimaryNaturalWeapons(oPC))+" PrimaryNaturalWeapEffect "+IntToString(GetLocalInt(oPC, "PrimaryNaturalWeapEffect"))); @@ -55,6 +76,8 @@ void main() //if(DEBUG) DoDebug("Running OnUnEquip, creature = '" + GetName(oPC) + "' is PC: " + DebugBool2String(GetIsPC(oPC)) + "; Item = '" + GetName(oItem) + "' - '" + GetTag(oItem) + "'"); DoTimestopUnEquip(oPC, oItem); + + DoGloveUnequip(oItem); if (GetResRef(oItem) == "prc_crown_might") DestroyObject(oItem); if (GetResRef(oItem) == "prc_crown_prot") DestroyObject(oItem); diff --git a/nwn/nwnprc/trunk/scripts/prc_wwhybridwolf.nss b/nwn/nwnprc/trunk/scripts/prc_wwhybridwolf.nss index 882779aa..46f1dd3c 100644 --- a/nwn/nwnprc/trunk/scripts/prc_wwhybridwolf.nss +++ b/nwn/nwnprc/trunk/scripts/prc_wwhybridwolf.nss @@ -27,7 +27,7 @@ void main() int nPoly; // Retrieve Module flag - int iPnPShifterShapchange = GetPRCSwitch(PRC_WEREWOLF_HYBRID_USE_SHIFTER_SHAPCHANGE); + int iPnPShifterShapchange = GetPRCSwitch(PRC_WEREWOLF_HYBRID_USE_SHIFTER_SHAPECHANGE); if (GetLocalInt(oPC, "WWHybrid") != TRUE)