From 4f752c6677acb529bbd17fbe6b46bc9e79b68cab Mon Sep 17 00:00:00 2001 From: Jaysyn904 <68194417+Jaysyn904@users.noreply.github.com> Date: Thu, 22 May 2025 19:53:27 -0400 Subject: [PATCH] Lashing Whip works better. Lashing Whip works better. Added documentation for RemoveSpecificProperty(). Power Attack NUI work in progress. --- nwn/nwnprc/trunk/include/inc_item_props.nss | 17 ++ nwn/nwnprc/trunk/scripts/prc_lasher.nss | 145 +++++++++++++++++- nwn/nwnprc/trunk/scripts/prc_lasher_lashw.nss | 11 +- .../trunk/users/jaysyn/hp_pa_script.nss | 75 +++++++++ 4 files changed, 237 insertions(+), 11 deletions(-) create mode 100644 nwn/nwnprc/trunk/users/jaysyn/hp_pa_script.nss diff --git a/nwn/nwnprc/trunk/include/inc_item_props.nss b/nwn/nwnprc/trunk/include/inc_item_props.nss index 6163cd27..b1edfc27 100644 --- a/nwn/nwnprc/trunk/include/inc_item_props.nss +++ b/nwn/nwnprc/trunk/include/inc_item_props.nss @@ -331,6 +331,23 @@ itemproperty GetSpecificProperty(object oItem, int iType, int iSubType = -1, int return ip; } +// Removes one or more item properties from an item that match the specified criteria. +// +// Parameters: +// oItem - The item object from which the property or properties will be removed. +// iType - The item property type (e.g., ITEM_PROPERTY_ENHANCEMENT_BONUS). +// iSubType - Optional. The property subtype to match. Use -1 to match any subtype. +// iCostVal - Optional. The cost table value to match. Use -1 to match any value. +// iNum - Optional. The number of matching properties to remove. Use -1 to remove all matches. Default is 1. +// sFlag - Optional. A local string/int flag name to clear on the item after removal. Default is "" (does nothing). +// iParam1 - Optional. Additional property-specific parameter to match (e.g., for saving throw bonuses). Use -1 to ignore. +// iDuration - Optional. Duration type of the property to match (e.g., DURATION_TYPE_PERMANENT). Use -1 to match any. +// +// Notes: +// - This function loops through item properties and removes the first `iNum` that match the given filters. +// - If iNum is -1, it removes all matching properties. +// - After removal, if sFlag is not an empty string, the local int with name sFlag is cleared on the item. + void RemoveSpecificProperty(object oItem, int iType, int iSubType = -1, int iCostVal = -1, int iNum = 1, string sFlag = "", int iParam1 = -1, int iDuration = DURATION_TYPE_PERMANENT) { diff --git a/nwn/nwnprc/trunk/scripts/prc_lasher.nss b/nwn/nwnprc/trunk/scripts/prc_lasher.nss index 5a07170a..0763cd7d 100644 --- a/nwn/nwnprc/trunk/scripts/prc_lasher.nss +++ b/nwn/nwnprc/trunk/scripts/prc_lasher.nss @@ -26,13 +26,13 @@ //#include "inc_2dacache" #include "prc_inc_spells" -void ApplyLashing(object oPC) //ripped off the tempest +/* void ApplyLashing(object oPC) //ripped off the tempest { if(!GetHasSpellEffect(SPELL_LASHER_LASHW, oPC)) ActionCastSpellOnSelf(SPELL_LASHER_LASHW); -} +} */ -void ApplyBonuses(object oPC, object oWeapon) +/* void ApplyBonuses(object oPC, object oWeapon) { object oSkin = GetPCSkin(oPC); int iClassLevel = GetLevelByClass(CLASS_TYPE_LASHER, oPC); @@ -63,8 +63,9 @@ void ApplyBonuses(object oPC, object oWeapon) IPSafeAddItemProperty(oSkin, PRCItemPropertyBonusFeat(IP_CONST_FEAT_PRC_IMPROVED_DISARM)); } } + */ -void RemoveBonuses(object oPC, object oWeapon) +/* void RemoveBonuses(object oPC, object oWeapon) { object oSkin = GetPCSkin(oPC); @@ -113,8 +114,142 @@ void RemoveBonuses(object oPC, object oWeapon) FloatingTextStringOnCreature("*Crack of Doom Deactivated*", oPC, FALSE); } } + */ + +void RemoveFeatBonuses(object oPC) +{ + object oSkin = GetPCSkin(oPC); + + SendMessageToPC(oPC, "prc_lasher: Running RemoveFeatBonuses"); + + if(GetHasSpellEffect(SPELL_LASHER_CRACK_FATE, oPC)) + { + PRCRemoveEffectsFromSpell(oPC, SPELL_LASHER_CRACK_FATE); + FloatingTextStringOnCreature("*Crack of Fate Deactivated*", oPC, FALSE); + } + if(GetHasSpellEffect(SPELL_LASHER_CRACK_DOOM, oPC)) + { + PRCRemoveEffectsFromSpell(oPC, SPELL_LASHER_CRACK_DOOM); + FloatingTextStringOnCreature("*Crack of Doom Deactivated*", oPC, FALSE); + } +} + +void ApplyWhipBonuses(object oPC, object oWhip, int iClassLevel) +{ + if (!GetIsObjectValid(oWhip)) return; + + // Only apply bonuses if the item is a whip + if (GetBaseItemType(oWhip) != BASE_ITEM_WHIP) return; + + SendMessageToPC(oPC, "prc_lasher: Running ApplyWhipBonuses"); + + RemoveSpecificProperty(oWhip, ITEM_PROPERTY_DAMAGE_BONUS, IP_CONST_DAMAGETYPE_SLASHING, IP_CONST_DAMAGEBONUS_2, 1, "SLASHING_WHIP", -1, DURATION_TYPE_TEMPORARY); + + object oSkin = GetPCSkin(oPC); + + if(iClassLevel > 1 /* && !GetHasFeat(FEAT_IMPROVED_TRIP) */) + IPSafeAddItemProperty(oSkin, PRCItemPropertyBonusFeat(IP_CONST_FEAT_IMPROVED_TRIP)); + + if(iClassLevel > 5 /* && !GetHasFeat(FEAT_PRC_IMP_DISARM) */) + IPSafeAddItemProperty(oSkin, PRCItemPropertyBonusFeat(IP_CONST_FEAT_PRC_IMPROVED_DISARM)); + + itemproperty ip = ItemPropertyDamageBonus(IP_CONST_DAMAGETYPE_SLASHING, IP_CONST_DAMAGEBONUS_2); + IPSafeAddItemProperty(oWhip, ip, 9999.0f); + SetLocalInt(oWhip, "SLASHING_WHIP", 1); +} void main() +{ + //Declare main variables. + int nEvent = GetRunningEvent(); + object oPC; + switch(nEvent) + { + case EVENT_ONPLAYEREQUIPITEM: oPC = GetItemLastEquippedBy(); break; + case EVENT_ONPLAYERUNEQUIPITEM: oPC = GetItemLastUnequippedBy(); break; + //case EVENT_ONHEARTBEAT: oPC = OBJECT_SELF; break; + + default: + oPC = OBJECT_SELF; + } + + object oSkin = GetPCSkin(oPC); + + int iClassLevel = GetLevelByClass(CLASS_TYPE_LASHER, oPC); + + if (nEvent == FALSE) + { + SendMessageToPC(oPC, "prc_lasher: Registering Events"); + AddEventScript(oPC, EVENT_ONPLAYEREQUIPITEM, "prc_lasher", TRUE, FALSE); + AddEventScript(oPC, EVENT_ONPLAYERUNEQUIPITEM, "prc_lasher", TRUE, FALSE); + } + else if (nEvent == EVENT_ONPLAYEREQUIPITEM) + { + if (!GetIsObjectValid(oPC)) return; + { + SendMessageToPC(oPC, "prc_lasher: Running EVENT_ONPLAYEREQUIPITEM"); + + object oMain = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC); + object oOff = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oPC); + + ApplyWhipBonuses(oPC, oMain, iClassLevel); + ApplyWhipBonuses(oPC, oOff, iClassLevel); + } + } + else if (nEvent == EVENT_ONPLAYERUNEQUIPITEM) + { + SendMessageToPC(oPC, "prc_lasher: Running EVENT_ONPLAYERUNEQUIPITEM"); + + object oItem = GetItemLastUnequipped(); + object oMain = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC); + + if (GetIsObjectValid(oItem) && GetBaseItemType(oItem) == BASE_ITEM_WHIP) + { + if(iClassLevel > 1) //improved knockdown (whip) + { + SendMessageToPC(oPC, "prc_lasher: Removing Improved Trip (Whip)"); + RemoveSpecificProperty(oSkin, ITEM_PROPERTY_BONUS_FEAT, IP_CONST_FEAT_IMPROVED_TRIP); + } + + if(iClassLevel > 5) //improved disarm (whip) + { + SendMessageToPC(oPC, "prc_lasher: Removing Improved Disarm (Whip)"); + RemoveSpecificProperty(oSkin, ITEM_PROPERTY_BONUS_FEAT, IP_CONST_FEAT_IMPROVED_DISARM); + } + + RemoveSpecificProperty(oItem, ITEM_PROPERTY_DAMAGE_BONUS, IP_CONST_DAMAGETYPE_SLASHING, IP_CONST_DAMAGEBONUS_2, 1, "SLASHING_WHIP", -1, DURATION_TYPE_TEMPORARY); + + SendMessageToPC(oPC, "prc_lasher: Removing Class Ability Bonuses"); + RemoveFeatBonuses(oPC); + + } + } +} + + + + // OFF HAND +/* if (GetIsObjectValid(oOff) && GetBaseItemType(oOff) == BASE_ITEM_WHIP) + { + itemproperty ipCheck = GetFirstItemProperty(oOff); + while (GetIsItemPropertyValid(ipCheck)) + { + if (GetItemPropertyType(ipCheck) == ITEM_PROPERTY_DAMAGE_BONUS && + GetItemPropertySubType(ipCheck) == IP_CONST_DAMAGETYPE_SLASHING && + GetItemPropertyCostTableValue(ipCheck) == IP_CONST_DAMAGEBONUS_2) + { + RemoveItemProperty(oOff, ipCheck); + } + ipCheck = GetNextItemProperty(oOff); + } + + itemproperty ip = ItemPropertyDamageBonus(IP_CONST_DAMAGETYPE_SLASHING, IP_CONST_DAMAGEBONUS_2); + AddItemProperty(DURATION_TYPE_PERMANENT, ip, oOff); + } + } */ + + +/* void main() { object oPC = OBJECT_SELF; object oWeapon; @@ -136,4 +271,4 @@ void main() ApplyBonuses(oPC, oWeapon); } -} +} */ diff --git a/nwn/nwnprc/trunk/scripts/prc_lasher_lashw.nss b/nwn/nwnprc/trunk/scripts/prc_lasher_lashw.nss index 567afa06..b852497a 100644 --- a/nwn/nwnprc/trunk/scripts/prc_lasher_lashw.nss +++ b/nwn/nwnprc/trunk/scripts/prc_lasher_lashw.nss @@ -9,18 +9,17 @@ //:: Modified: Sept 29, 2005 //::////////////////////////////////////////////// +//:: This script should be unneeded now - Jaysyn (2025-05-22 19:50:17) + #include "prc_alterations" #include "inc_2dacache" #include "prc_inc_spells" void main() { + object oPC = PRCGetSpellTargetObject(); PRCRemoveEffectsFromSpell(oPC, GetSpellId()); - ApplyEffectToObject(DURATION_TYPE_PERMANENT, - SupernaturalEffect( - EffectDamageIncrease(DAMAGE_BONUS_2, IP_CONST_DAMAGETYPE_PHYSICAL) - ), - oPC); + ApplyEffectToObject(DURATION_TYPE_PERMANENT, SupernaturalEffect(EffectDamageIncrease(DAMAGE_BONUS_2, IP_CONST_DAMAGETYPE_PHYSICAL)), oPC); -} +} \ No newline at end of file diff --git a/nwn/nwnprc/trunk/users/jaysyn/hp_pa_script.nss b/nwn/nwnprc/trunk/users/jaysyn/hp_pa_script.nss new file mode 100644 index 00000000..beeb5d0b --- /dev/null +++ b/nwn/nwnprc/trunk/users/jaysyn/hp_pa_script.nss @@ -0,0 +1,75 @@ +//:://///////////////////////////////////////////// +//:: Power Attack Script +//:: prc_powatk_chs +//::////////////////////////////////////////////// +/* + A script that sets the power attack on a player based on the amount + given. +*/ +//::////////////////////////////////////////////// +//:: Created By: Rakiov +//:: Created On: 22.05.2005 +//::////////////////////////////////////////////// + +#include "prc_spell_const" + +// +// SetPowerAttack +// Sets the power attack for a player, if the amount is less than or equal to +// the players BAB it will apply the power attack, otherwise it will tell +// the player it can't. +// +// Arguments: +// amount int the amount of power attack you want +// oPlayer object the player to apply the power attack to +// +// +void SetPowerAttack(int amount, object oPlayer); + +void SetPowerAttack(int amount, object oPlayer) +{ + //You need the power attack feat to use this + if (GetHasFeat(FEAT_POWER_ATTACK, oPlayer)) + { + // It won't work if your BAB is lower than your PA Value + if(GetBaseAttackBonus(oPlayer) <= amount) + { + int powerAttack5Amount = amount / 5; + int powerAttack1Amount = amount % 5; + + switch (powerAttack1Amount) + { + //sets the 1 values for Power attack ranging from 0,1,2,3,4 respectivly + case 0: // Power Attack 0 + ActionCastSpellAtObject(SPELL_POWER_ATTACK1, oPlayer, TRUE); + case 1: // Power Attack 1 + ActionCastSpellAtObject(SPELL_POWER_ATTACK2, oPlayer, TRUE); + case 2: // Power Attack 2 + ActionCastSpellAtObject(SPELL_POWER_ATTACK3, oPlayer, TRUE); + case 3: // Power Attack 3 + ActionCastSpellAtObject(SPELL_POWER_ATTACK4, oPlayer, TRUE); + case 4: // Power Attack 4 + ActionCastSpellAtObject(SPELL_POWER_ATTACK5, oPlayer, TRUE); + } + switch (powerAttack5Amount) + { + case 0: // Power Attack 0 + ActionCastSpellAtObject(SPELL_POWER_ATTACK6, oPlayer, TRUE); + case 1: // Power Attack 5 + ActionCastSpellAtObject(SPELL_POWER_ATTACK7, oPlayer, TRUE); + case 2: // Power Attack 10 + ActionCastSpellAtObject(SPELL_POWER_ATTACK8, oPlayer, TRUE); + case 3: // Power Attack 15 + ActionCastSpellAtObject(SPELL_POWER_ATTACK9, oPlayer, TRUE); + case 4: // Power Attack 20 + ActionCastSpellAtObject(SPELL_POWER_ATTACK10, oPlayer, TRUE); + } + } else { + FloatingTextStringOnCreature("Power Attack Higher Than BAB", oPlayer); + } + } else { + FloatingTextStringOnCreature("Need Power Attack To Use", oPlayer); + } +} + +//:: void main (){} \ No newline at end of file