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:
BIN
nwn/nwnprc/trunk/others/prc_bbod001.utc
Normal file
BIN
nwn/nwnprc/trunk/others/prc_bbod001.utc
Normal file
Binary file not shown.
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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,98 +96,132 @@ 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.
|
||||||
void spellsCreateItemForSummoned()
|
void spellsCreateItemForSummoned()
|
||||||
{
|
{
|
||||||
//Declare major variables
|
//Declare major variables
|
||||||
int nStat;
|
int nStat;
|
||||||
|
|
||||||
|
// cast from scroll, we just assume +5 ability modifier
|
||||||
|
if (GetSpellCastItem() != OBJECT_INVALID)
|
||||||
|
{
|
||||||
|
nStat = 5;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int nClass = PRCGetLastSpellCastClass();
|
||||||
|
int nLevel = GetLevelByClass(nClass);
|
||||||
|
|
||||||
|
int nCha = GetAbilityModifier(ABILITY_CHARISMA,OBJECT_SELF);
|
||||||
|
int nInt = GetAbilityModifier(ABILITY_INTELLIGENCE,OBJECT_SELF);
|
||||||
|
|
||||||
|
if (nClass == CLASS_TYPE_WIZARD)
|
||||||
|
{
|
||||||
|
nStat = nInt;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nStat = nCha;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nStat >20)
|
||||||
|
{
|
||||||
|
nStat =20;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nStat <1)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
object oSummon = GetAssociate(ASSOCIATE_TYPE_SUMMONED, OBJECT_SELF, i);
|
||||||
|
while(GetIsObjectValid(oSummon))
|
||||||
|
{
|
||||||
|
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++;
|
||||||
|
oSummon = GetAssociate(ASSOCIATE_TYPE_SUMMONED, OBJECT_SELF, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!GetIsObjectValid(oSummon))
|
||||||
|
{
|
||||||
|
if(DEBUG) DoDebug("BBoD: ERROR - No valid summon found with tag " + sTargetTag);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// cast from scroll, we just assume +5 ability modifier
|
SetLocalInt(oSummon, "BBoD_Level", GetLocalInt(OBJECT_SELF, "BBoD_Level"));
|
||||||
if (GetSpellCastItem() != OBJECT_INVALID)
|
SetLocalObject(oSummon, "BBoD_Caster", OBJECT_SELF);
|
||||||
{
|
DeleteLocalInt(OBJECT_SELF, "BBoD_Level");
|
||||||
nStat = 5;
|
|
||||||
}
|
// Make the blade require concentration
|
||||||
else
|
SetLocalInt(oSummon,"X2_L_CREATURE_NEEDS_CONCENTRATION",TRUE);
|
||||||
{
|
object oWeapon;
|
||||||
int nClass = PRCGetLastSpellCastClass();
|
//Create item on the creature, equip it and add properties.
|
||||||
int nLevel = GetLevelByClass(nClass);
|
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))
|
||||||
|
{
|
||||||
|
IPSetWeaponEnhancementBonus(oWeapon, nStat);
|
||||||
|
}
|
||||||
|
SetDroppableFlag(oWeapon, FALSE);
|
||||||
|
SetPlotFlag (oSummon,TRUE);
|
||||||
|
|
||||||
|
if(GetPRCSwitch(PRC_PNP_BLACK_BLADE_OF_DISASTER))
|
||||||
|
{
|
||||||
|
if(DEBUG) DoDebug("BBoD: Processing PnP version");
|
||||||
|
|
||||||
int nStat;
|
// Remove all existing properties
|
||||||
|
itemproperty ipTest = GetFirstItemProperty(oWeapon);
|
||||||
int nCha = GetAbilityModifier(ABILITY_CHARISMA,OBJECT_SELF);
|
int nCount = 0;
|
||||||
int nInt = GetAbilityModifier(ABILITY_INTELLIGENCE,OBJECT_SELF);
|
while(GetIsItemPropertyValid(ipTest))
|
||||||
|
{
|
||||||
if (nClass == CLASS_TYPE_WIZARD)
|
nCount++;
|
||||||
{
|
if(DEBUG) DoDebug("BBoD: Removing property " + IntToString(nCount));
|
||||||
nStat = nInt;
|
RemoveItemProperty(oWeapon, ipTest);
|
||||||
}
|
ipTest = GetNextItemProperty(oWeapon);
|
||||||
else
|
}
|
||||||
{
|
if(DEBUG) DoDebug("BBoD: Removed " + IntToString(nCount) + " properties");
|
||||||
nStat = nCha;
|
|
||||||
}
|
itemproperty ipNoDam = ItemPropertyNoDamage();
|
||||||
|
AddItemProperty(DURATION_TYPE_PERMANENT, ipNoDam, oWeapon);
|
||||||
if (nStat >20)
|
if(DEBUG) DoDebug("BBoD: Added NoDamage property");
|
||||||
{
|
|
||||||
nStat =20;
|
itemproperty ipVFX = ItemPropertyVisualEffect(ITEM_VISUAL_ELECTRICAL);
|
||||||
}
|
AddItemProperty(DURATION_TYPE_PERMANENT, ipVFX, oWeapon);
|
||||||
|
if(DEBUG) DoDebug("BBoD: Added VFX property");
|
||||||
if (nStat <1)
|
|
||||||
{
|
//store the level and DC on the summon
|
||||||
nStat = 0;
|
SetLocalInt(oSummon, "BBoD_Level", GetLocalInt(OBJECT_SELF, "BBoD_Level"));
|
||||||
}
|
SetLocalObject(oSummon, "BBoD_Caster", OBJECT_SELF);
|
||||||
}
|
DeleteLocalInt(OBJECT_SELF, "BBoD_Level");
|
||||||
int i = 1;
|
//attacks are handled through a pseudoHB
|
||||||
object oSummon = GetAssociate(ASSOCIATE_TYPE_SUMMONED, OBJECT_SELF, i);
|
DoPnPAttack(oSummon, nStat);
|
||||||
while(GetIsObjectValid(oSummon))
|
}
|
||||||
{
|
|
||||||
oSummon = GetAssociate(ASSOCIATE_TYPE_SUMMONED, OBJECT_SELF, i);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
// Make the blade require concentration
|
|
||||||
SetLocalInt(oSummon,"X2_L_CREATURE_NEEDS_CONCENTRATION",TRUE);
|
|
||||||
object oWeapon;
|
|
||||||
//Create item on the creature, epuip it and add properties.
|
|
||||||
oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND,oSummon);
|
|
||||||
if (nStat > 0 && !GetPRCSwitch(PRC_PNP_BLACK_BLADE_OF_DISASTER))
|
|
||||||
{
|
|
||||||
IPSetWeaponEnhancementBonus(oWeapon, nStat);
|
|
||||||
}
|
|
||||||
SetDroppableFlag(oWeapon, FALSE);
|
|
||||||
SetPlotFlag (oSummon,TRUE);
|
|
||||||
|
|
||||||
if(GetPRCSwitch(PRC_PNP_BLACK_BLADE_OF_DISASTER))
|
|
||||||
{
|
|
||||||
itemproperty ipTest = GetFirstItemProperty(oWeapon);
|
|
||||||
while(GetIsItemPropertyValid(ipTest))
|
|
||||||
{
|
|
||||||
ipTest = GetNextItemProperty(oWeapon);
|
|
||||||
}
|
|
||||||
itemproperty ipNoDam = ItemPropertyNoDamage();
|
|
||||||
AddItemProperty(DURATION_TYPE_PERMANENT, ipNoDam, oWeapon);
|
|
||||||
itemproperty ipVFX = ItemPropertyVisualEffect(ITEM_VISUAL_ELECTRICAL);
|
|
||||||
AddItemProperty(DURATION_TYPE_PERMANENT, ipVFX, oWeapon);
|
|
||||||
//store the level on the summon
|
|
||||||
SetLocalInt(oSummon, "BBoD_Level", GetLocalInt(OBJECT_SELF, "BBoD_Level"));
|
|
||||||
DeleteLocalInt(OBJECT_SELF, "BBoD_Level");
|
|
||||||
//attacks are handled through a pseudoHB
|
|
||||||
DoPnPAttack(oSummon);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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))
|
||||||
@@ -218,4 +260,4 @@ SetLocalInt(OBJECT_SELF, "X2_L_LAST_SPELLSCHOOL_VAR", SPELL_SCHOOL_CONJURATION);
|
|||||||
|
|
||||||
DeleteLocalInt(OBJECT_SELF, "X2_L_LAST_SPELLSCHOOL_VAR");
|
DeleteLocalInt(OBJECT_SELF, "X2_L_LAST_SPELLSCHOOL_VAR");
|
||||||
// Erasing the variable used to store the spell's spell school
|
// Erasing the variable used to store the spell's spell school
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user