2026/04/20 Update 2

The PnP version of Black Blade of Disaster now actually follows 3e PnP.
The onSpawn call for incorporeal creatures now uses SetIncorporeal().
Fixed minor typo in prc_fact_cunconv
This commit is contained in:
Jaysyn904
2026-04-20 23:37:32 -04:00
parent 0e9dabdfb3
commit 427e48a81e
4 changed files with 143 additions and 96 deletions

Binary file not shown.

View File

@@ -29,7 +29,7 @@
#include "x0_i0_anims" #include "x0_i0_anims"
// #include "x0_i0_walkway" - in x0_i0_anims // #include "x0_i0_walkway" - in x0_i0_anims
#include "x0_i0_treasure" #include "x0_i0_treasure"
#include "prc_inc_spells"
#include "x2_inc_switches" #include "x2_inc_switches"
void main() void main()
@@ -297,7 +297,12 @@ void main()
// ***** ADD ANY SPECIAL ON-SPAWN CODE HERE ***** // // ***** ADD ANY SPECIAL ON-SPAWN CODE HERE ***** //
// * If Incorporeal, apply changes // * If Incorporeal, apply changes
if (GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_IS_INCORPOREAL) == TRUE) if (GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_IS_INCORPOREAL) == TRUE)
{
SetIncorporeal(OBJECT_SELF, 0.0f, 2, TRUE);
}
/* if (GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_IS_INCORPOREAL) == TRUE)
{ {
effect eConceal = EffectConcealment(50, MISS_CHANCE_TYPE_NORMAL); effect eConceal = EffectConcealment(50, MISS_CHANCE_TYPE_NORMAL);
eConceal = ExtraordinaryEffect(eConceal); eConceal = ExtraordinaryEffect(eConceal);
@@ -306,7 +311,7 @@ void main()
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eConceal, OBJECT_SELF); ApplyEffectToObject(DURATION_TYPE_PERMANENT, eConceal, OBJECT_SELF);
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eGhost, OBJECT_SELF); ApplyEffectToObject(DURATION_TYPE_PERMANENT, eGhost, OBJECT_SELF);
} } */
// * Give the create a random name. // * Give the create a random name.
// * If you create a script named x3_name_gen in your module, you can // * If you create a script named x3_name_gen in your module, you can

View File

@@ -185,7 +185,7 @@ void main()
if (!GetIsAbilitySaved(oPC, FEAT_USE_POISON)) AddChoice("Ninja: Poison Use", FEAT_USE_POISON); if (!GetIsAbilitySaved(oPC, FEAT_USE_POISON)) AddChoice("Ninja: Poison Use", FEAT_USE_POISON);
if (!GetIsAbilitySaved(oPC, FEAT_DIVINE_HEALTH)) AddChoice("Paladin: Divine Health", FEAT_DIVINE_HEALTH); if (!GetIsAbilitySaved(oPC, FEAT_DIVINE_HEALTH)) AddChoice("Paladin: Divine Health", FEAT_DIVINE_HEALTH);
if (!GetIsAbilitySaved(oPC, FEAT_CRIPPLING_STRIKE)) AddChoice("Rogue: Crippling Strike", FEAT_CRIPPLING_STRIKE); if (!GetIsAbilitySaved(oPC, FEAT_CRIPPLING_STRIKE)) AddChoice("Rogue: Crippling Strike", FEAT_CRIPPLING_STRIKE);
if (!GetIsAbilitySaved(oPC, FEAT_DEFENSIVE_ROLL)) AddChoice("Rogue: Defensive Strike", FEAT_DEFENSIVE_ROLL); if (!GetIsAbilitySaved(oPC, FEAT_DEFENSIVE_ROLL)) AddChoice("Rogue: Defensive Roll", FEAT_DEFENSIVE_ROLL);
if (!GetIsAbilitySaved(oPC, FEAT_OPPORTUNIST)) AddChoice("Rogue: Opportunist", FEAT_OPPORTUNIST); if (!GetIsAbilitySaved(oPC, FEAT_OPPORTUNIST)) AddChoice("Rogue: Opportunist", FEAT_OPPORTUNIST);
if (!GetIsAbilitySaved(oPC, FEAT_SLIPPERY_MIND)) AddChoice("Rogue: Slippery Mind", FEAT_SLIPPERY_MIND); if (!GetIsAbilitySaved(oPC, FEAT_SLIPPERY_MIND)) AddChoice("Rogue: Slippery Mind", FEAT_SLIPPERY_MIND);
if (!GetIsAbilitySaved(oPC, FEAT_SNEAK_ATTACK)) AddChoice("Rogue: Sneak Attack", FEAT_SNEAK_ATTACK); if (!GetIsAbilitySaved(oPC, FEAT_SNEAK_ATTACK)) AddChoice("Rogue: Sneak Attack", FEAT_SNEAK_ATTACK);

View File

@@ -19,13 +19,13 @@
#include "prc_inc_sp_tch" #include "prc_inc_sp_tch"
#include "prc_add_spell_dc" #include "prc_add_spell_dc"
void DoPnPAttack(object oSummon) void DoPnPAttack(object oSummon, int nAttackBonus)
{ {
object oTarget = GetAttackTarget(oSummon); object oTarget = GetAttackTarget(oSummon);
if(GetIsObjectValid(oTarget) if(GetIsObjectValid(oTarget)
&& GetDistanceBetween(oTarget, oSummon) < 5.0) && GetDistanceBetween(oTarget, oSummon) < 5.0)
{ {
int nAttackResult = PRCDoMeleeTouchAttack(oTarget);; int nAttackResult = PRCDoMeleeTouchAttack(oTarget, TRUE, OBJECT_SELF, nAttackBonus);
if(nAttackResult) if(nAttackResult)
{ {
//hit or critical hit //hit or critical hit
@@ -65,7 +65,11 @@ void DoPnPAttack(object oSummon)
// be used instead. // be used instead.
// Test done. Result: It does kill them. // Test done. Result: It does kill them.
int nDamage = 9999; int nDamage = 9999;
if (PRCMySavingThrow(SAVING_THROW_FORT, oTarget, PRCGetSaveDC(oTarget,OBJECT_SELF), SAVING_THROW_TYPE_SPELL)) //if (PRCMySavingThrow(SAVING_THROW_FORT, oTarget, PRCGetSaveDC(oTarget,OBJECT_SELF), SAVING_THROW_TYPE_SPELL))
object oCaster = GetLocalObject(oSummon, "BBoD_Caster");
int nDC = PRCGetSaveDC(oTarget, oCaster);
if (PRCMySavingThrow(SAVING_THROW_FORT, oTarget, nDC, SAVING_THROW_TYPE_SPELL))
{ {
nDamage = PRCGetMetaMagicDamage(DAMAGE_TYPE_MAGICAL, 1 == nAttackResult ? 5 : 10, 6); nDamage = PRCGetMetaMagicDamage(DAMAGE_TYPE_MAGICAL, 1 == nAttackResult ? 5 : 10, 6);
nDamage += SpellDamagePerDice(OBJECT_SELF, 5); nDamage += SpellDamagePerDice(OBJECT_SELF, 5);
@@ -92,7 +96,7 @@ void DoPnPAttack(object oSummon)
} }
} }
if(GetIsObjectValid(oSummon)) if(GetIsObjectValid(oSummon))
DelayCommand(6.0, DoPnPAttack(oSummon)); DelayCommand(6.0, DoPnPAttack(oSummon, nAttackBonus));
} }
//Creates the weapon that the creature will be using. //Creates the weapon that the creature will be using.
@@ -111,8 +115,6 @@ void spellsCreateItemForSummoned()
int nClass = PRCGetLastSpellCastClass(); int nClass = PRCGetLastSpellCastClass();
int nLevel = GetLevelByClass(nClass); int nLevel = GetLevelByClass(nClass);
int nStat;
int nCha = GetAbilityModifier(ABILITY_CHARISMA,OBJECT_SELF); int nCha = GetAbilityModifier(ABILITY_CHARISMA,OBJECT_SELF);
int nInt = GetAbilityModifier(ABILITY_INTELLIGENCE,OBJECT_SELF); int nInt = GetAbilityModifier(ABILITY_INTELLIGENCE,OBJECT_SELF);
@@ -135,18 +137,46 @@ void spellsCreateItemForSummoned()
nStat = 0; nStat = 0;
} }
} }
// Find the correct summon based on PnP switch
string sTargetTag = GetPRCSwitch(PRC_PNP_BLACK_BLADE_OF_DISASTER) ? "prc_bbod001" : "x2_s_bblade";
if(DEBUG) DoDebug("BBoD: Looking for summon with tag: " + sTargetTag);
int i = 1; int i = 1;
object oSummon = GetAssociate(ASSOCIATE_TYPE_SUMMONED, OBJECT_SELF, i); object oSummon = GetAssociate(ASSOCIATE_TYPE_SUMMONED, OBJECT_SELF, i);
while(GetIsObjectValid(oSummon)) while(GetIsObjectValid(oSummon))
{ {
oSummon = GetAssociate(ASSOCIATE_TYPE_SUMMONED, OBJECT_SELF, i); string sTag = GetTag(oSummon);
if(DEBUG) DoDebug("BBoD: Found associate " + IntToString(i) + " with tag: " + sTag);
// Use case-insensitive comparison
if(GetStringLowerCase(sTag) == GetStringLowerCase(sTargetTag))
{
if(DEBUG) DoDebug("BBoD: Found matching summon");
break;
}
i++; i++;
oSummon = GetAssociate(ASSOCIATE_TYPE_SUMMONED, OBJECT_SELF, i);
} }
if(!GetIsObjectValid(oSummon))
{
if(DEBUG) DoDebug("BBoD: ERROR - No valid summon found with tag " + sTargetTag);
return;
}
SetLocalInt(oSummon, "BBoD_Level", GetLocalInt(OBJECT_SELF, "BBoD_Level"));
SetLocalObject(oSummon, "BBoD_Caster", OBJECT_SELF);
DeleteLocalInt(OBJECT_SELF, "BBoD_Level");
// Make the blade require concentration // Make the blade require concentration
SetLocalInt(oSummon,"X2_L_CREATURE_NEEDS_CONCENTRATION",TRUE); SetLocalInt(oSummon,"X2_L_CREATURE_NEEDS_CONCENTRATION",TRUE);
object oWeapon; object oWeapon;
//Create item on the creature, epuip it and add properties. //Create item on the creature, equip it and add properties.
oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND,oSummon); oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND,oSummon);
if(DEBUG) DoDebug("BBoD: Weapon valid: " + IntToString(GetIsObjectValid(oWeapon)));
if (nStat > 0 && !GetPRCSwitch(PRC_PNP_BLACK_BLADE_OF_DISASTER)) if (nStat > 0 && !GetPRCSwitch(PRC_PNP_BLACK_BLADE_OF_DISASTER))
{ {
IPSetWeaponEnhancementBonus(oWeapon, nStat); IPSetWeaponEnhancementBonus(oWeapon, nStat);
@@ -156,34 +186,42 @@ void spellsCreateItemForSummoned()
if(GetPRCSwitch(PRC_PNP_BLACK_BLADE_OF_DISASTER)) if(GetPRCSwitch(PRC_PNP_BLACK_BLADE_OF_DISASTER))
{ {
if(DEBUG) DoDebug("BBoD: Processing PnP version");
// Remove all existing properties
itemproperty ipTest = GetFirstItemProperty(oWeapon); itemproperty ipTest = GetFirstItemProperty(oWeapon);
int nCount = 0;
while(GetIsItemPropertyValid(ipTest)) while(GetIsItemPropertyValid(ipTest))
{ {
nCount++;
if(DEBUG) DoDebug("BBoD: Removing property " + IntToString(nCount));
RemoveItemProperty(oWeapon, ipTest);
ipTest = GetNextItemProperty(oWeapon); ipTest = GetNextItemProperty(oWeapon);
} }
if(DEBUG) DoDebug("BBoD: Removed " + IntToString(nCount) + " properties");
itemproperty ipNoDam = ItemPropertyNoDamage(); itemproperty ipNoDam = ItemPropertyNoDamage();
AddItemProperty(DURATION_TYPE_PERMANENT, ipNoDam, oWeapon); AddItemProperty(DURATION_TYPE_PERMANENT, ipNoDam, oWeapon);
if(DEBUG) DoDebug("BBoD: Added NoDamage property");
itemproperty ipVFX = ItemPropertyVisualEffect(ITEM_VISUAL_ELECTRICAL); itemproperty ipVFX = ItemPropertyVisualEffect(ITEM_VISUAL_ELECTRICAL);
AddItemProperty(DURATION_TYPE_PERMANENT, ipVFX, oWeapon); AddItemProperty(DURATION_TYPE_PERMANENT, ipVFX, oWeapon);
//store the level on the summon if(DEBUG) DoDebug("BBoD: Added VFX property");
SetLocalInt(oSummon, "BBoD_Level", GetLocalInt(OBJECT_SELF, "BBoD_Level"));
DeleteLocalInt(OBJECT_SELF, "BBoD_Level"); //store the level and DC on the summon
SetLocalInt(oSummon, "BBoD_Level", GetLocalInt(OBJECT_SELF, "BBoD_Level"));
SetLocalObject(oSummon, "BBoD_Caster", OBJECT_SELF);
DeleteLocalInt(OBJECT_SELF, "BBoD_Level");
//attacks are handled through a pseudoHB //attacks are handled through a pseudoHB
DoPnPAttack(oSummon); DoPnPAttack(oSummon, nStat);
} }
} }
void main() void main()
{ {
DeleteLocalInt(OBJECT_SELF, "X2_L_LAST_SPELLSCHOOL_VAR"); DeleteLocalInt(OBJECT_SELF, "X2_L_LAST_SPELLSCHOOL_VAR");
SetLocalInt(OBJECT_SELF, "X2_L_LAST_SPELLSCHOOL_VAR", SPELL_SCHOOL_CONJURATION); SetLocalInt(OBJECT_SELF, "X2_L_LAST_SPELLSCHOOL_VAR", SPELL_SCHOOL_CONJURATION);
/*
Spellcast Hook Code
Added 2003-07-07 by Georg Zoeller
If you want to make changes to all spells,
check x2_inc_spellhook.nss to find out more
*/
if (!X2PreSpellCastCode()) if (!X2PreSpellCastCode())
{ {
@@ -191,13 +229,17 @@ SetLocalInt(OBJECT_SELF, "X2_L_LAST_SPELLSCHOOL_VAR", SPELL_SCHOOL_CONJURATION);
return; return;
} }
// End of Spell Cast Hook
//Declare major variables //Declare major variables
int nMetaMagic = PRCGetMetaMagicFeat(); int nMetaMagic = PRCGetMetaMagicFeat();
int nDuration = PRCGetCasterLevel(OBJECT_SELF); int nDuration = PRCGetCasterLevel(OBJECT_SELF);
effect eSummon = EffectSummonCreature("x2_s_bblade"); effect eSummon;
if(GetPRCSwitch(PRC_PNP_BLACK_BLADE_OF_DISASTER))
{
eSummon = EffectSummonCreature("prc_bbod001");
}
else
eSummon = EffectSummonCreature("x2_s_bblade");
effect eVis = EffectVisualEffect(VFX_FNF_SUMMON_MONSTER_3); effect eVis = EffectVisualEffect(VFX_FNF_SUMMON_MONSTER_3);
//Make metamagic check for extend //Make metamagic check for extend
if ((nMetaMagic & METAMAGIC_EXTEND)) if ((nMetaMagic & METAMAGIC_EXTEND))