2026/05/25 Memorial Day Update
Attune Gem was using the wrong prereqs. Attune Gem didn't handle radial spells properly. Attune Gem incorrectly allowed divine spells. Attune Gem was checking the wrong resref for vanilla gems. Attune Gem didn't handle stacks of gems properly. Updated Attune Gem's TLK entry. PRCGetSaveDC() wasn't using PRCGetSpellCastItem(). Damning Darkness' vfx_persistent.2da entry was typoed. Damning Darkness was checking the wrong object for inventory item for validity. Darkness invocation was checking the wrong object for inventory item for validity. Deeper Darkness was checking the wrong object for inventory item for validity. Darkness was checking the wrong object for inventory item for validity. Fixed Dragon's Tooth range & save. Hopefully fixed Seize Items' VFX. Fixed Acolyte of the Skin's DR. Updated PRC8 Changelog doc.
This commit is contained in:
@@ -2473,7 +2473,7 @@
|
||||
2469 TribalFrenzy 16825723 16825718 ife_cfrenzy **** **** **** **** **** **** **** **** **** **** 0 0 0 **** **** 1597 **** 1 -1 **** 1 **** **** **** **** **** **** **** **** **** **** 4 **** **** **** **** **** 0 0
|
||||
2470 AbilityBoost 16825719 16825720 ife_X2GrCha1 **** **** **** **** **** **** **** **** **** **** 0 0 0 **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** FEAT_ALERTNESS 5 **** **** **** **** **** 0 1
|
||||
2471 DevotedBodyguards 16825721 16825722 ife_epAlliedMa **** **** **** **** **** **** **** **** **** **** 0 0 0 **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** FEAT_ALERTNESS 5 **** **** **** **** **** 0 1
|
||||
2472 AttuneGem 16822665 16822666 ife_X2PlnrTurn **** **** **** 13 **** **** **** **** **** **** 0 0 1 **** **** 1781 **** 1 -1 **** 0 **** **** **** **** **** **** **** **** **** **** 4 **** **** **** **** **** 0 0
|
||||
2472 AttuneGem 16822665 16822666 ife_X2PlnrTurn **** **** **** 13 **** **** **** **** **** **** 0 0 1 **** **** 1781 **** 1 -1 **** 0 **** **** **** **** **** **** **** **** **** **** 4 **** 5 **** **** **** 0 0
|
||||
2473 WidenSpell 16822648 16822649 ife_X2PlnrTurn **** **** **** **** **** **** **** **** **** **** 0 0 0 **** **** 1637 **** 1 35 **** 1 **** **** **** **** **** **** **** **** **** **** 4 **** **** **** **** **** 0 0
|
||||
2474 EnlargeSpellArea 16822650 16822651 ife_legendaryart **** **** **** **** **** **** **** **** **** **** 0 0 0 **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** FEAT_ALERTNESS 5 **** **** **** **** **** 0 1
|
||||
2475 StunningStrike 16827037 16827038 ife_X2SpTghBne **** **** **** **** **** **** **** **** **** **** 0 0 0 **** **** 2470 **** 1 5 **** **** **** **** **** **** **** **** **** **** **** **** 4 **** **** **** **** **** 0 1
|
||||
|
||||
@@ -1783,7 +1783,7 @@
|
||||
1779 ShieldAlly 16827626 ife_mastelem T M 0 **** 0x03 prc_knght_shally **** **** **** **** **** **** 9 0 head **** vco_smhanevil01 **** sco_mehannatr01 vs_chant_ench_lm vs_chant_ench_lf self 0 **** **** **** **** 0 **** **** **** **** **** **** 0 **** **** **** **** **** 10 **** 3 **** 0 0 **** 0 2843 **** **** 0 **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ****
|
||||
1780 ImprovedShieldAlly 16827628 ife_mastelem T M 0 **** 0x03 prc_knght_ishlly **** **** **** **** **** **** 9 0 head **** vco_smhanevil01 **** sco_mehannatr01 vs_chant_ench_lm vs_chant_ench_lf self 0 **** **** **** **** 0 **** **** **** **** **** **** 0 **** **** **** **** **** 10 **** 3 **** 0 0 **** 0 2844 **** **** 0 **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ****
|
||||
1781 AttuneGem 16822665 is_divprot G L v **** 0x09 prc_radialbug **** **** **** **** **** **** 1 1500 hand **** vco_mehanodd02 vco_lgrinodd01 sco_lgrinodd01 vs_chant_conj_hm vs_chant_conj_hf out 1000 **** **** **** **** 0 **** **** **** **** **** **** 0 1782 1783 **** **** **** 15 **** 1 16828494 1 0 **** 0 2472 **** **** 0 **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ****
|
||||
1782 AttuneGemCraft 16822665 is_divprot G L v **** 0x09 prc_ft_attunegem **** **** **** **** **** **** 1 1500 hand **** vco_mehanelec02 vco_lgrinelec01 sco_lgrinelec01 vs_chant_conj_hm vs_chant_conj_hf out 1000 **** **** **** **** 0 **** **** **** **** **** **** 0 **** **** **** **** **** 15 1781 1 16828494 1 0 **** 0 392694184 **** **** 0 **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ****
|
||||
1782 AttuneGemCraft 16822665 is_divprot G L v **** 0x01 prc_ft_attunegem **** **** **** **** **** **** 1 1500 hand **** vco_mehanelec02 vco_lgrinelec01 sco_lgrinelec01 vs_chant_conj_hm vs_chant_conj_hf out 1000 **** **** **** **** 0 **** **** **** **** **** **** 0 **** **** **** **** **** 15 1781 1 16828494 1 0 **** 0 392694184 **** **** 0 **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ****
|
||||
1783 AttuneGemCheckGem 16822665 is_curpfail G L v **** 0x09 prc_ft_attngemsl **** **** **** **** **** **** 1 1500 hand **** vco_mehanacid02 vco_lgrinacid01 sco_lgrinelec01 vs_chant_conj_hm vs_chant_conj_hf out 1000 **** **** **** **** 0 **** **** **** **** **** **** 0 **** **** **** **** **** 15 1781 1 16828494 1 0 **** 0 392759720 **** **** 0 **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ****
|
||||
1784 SummonUndeadI 16847420 is_SumUndead1 C S vs 0x3a 0x2c sp_sum_undead **** 1 **** **** **** 1 1 1500 hand **** vco_mebalsonc01 **** sco_mebalsonc01 vs_chant_necr_lm vs_chant_necr_lf touch 1000 **** **** **** **** 0 **** **** **** **** **** **** 0 **** **** **** **** **** 15 **** 1 16847421 1 0 **** 0 **** **** **** 0 **** **** **** **** **** **** **** **** **** **** 1 **** **** **** **** **** **** ****
|
||||
1785 SummonUndeadII 16847422 is_SumUndead2 C S vs 0x3a 0x2c sp_sum_undead **** 2 **** **** **** 2 2 1500 hand **** vco_mebalsonc01 **** sco_mebalsonc01 vs_chant_necr_lm vs_chant_necr_lf touch 1000 **** **** **** **** 0 **** **** **** **** **** **** 0 **** **** **** **** **** 15 **** 1 16847423 1 0 **** 0 **** **** **** 0 **** **** **** **** **** **** **** **** **** **** 2 **** **** **** **** **** **** ****
|
||||
|
||||
@@ -204,7 +204,7 @@
|
||||
200 VFX_PER_FOGFREEZE C 5 **** **** **** **** **** 0 **** vps_fogfreeze vps_fogfreeze vps_fogfreeze 5 10 5 3400 1100 1900 0 0.25 0.25 **** sps_fog_loop **** sps_fog 0.3 vps_fogfreeze_L vps_fogfreeze_L vps_fogfreeze_L
|
||||
201 VFX_PER_FOGYELLOW C 5 **** **** **** **** **** 0 **** vps_fogyell vps_fogyell vps_fogyell 5 10 5 3400 1100 1900 0 0.25 0.25 **** sps_fog_loop **** sps_fog 0.3 vps_fogyell_L vps_fogyell_L vps_fogyell_L
|
||||
202 VFX_PER_FOGPURPLE C 5 **** **** **** **** **** 0 **** vps_fogpurp vps_fogpurp vps_fogpurp 5 10 5 3400 1100 1900 0 0.25 0.25 **** sps_fog_loop **** sps_fog 0.3 vps_fogpurp_L vps_fogpurp_L vps_fogpurp_L
|
||||
203 AOE_PER_DAMNDARK C 6.7 **** **** sp_damn_darkA sp_damn_darkB **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ****
|
||||
203 AOE_PER_DAMNDARK C 6.7 **** **** sp_damng_darka sp_damng_darkb **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ****
|
||||
204 VFX_MOB_BRILLIANT_EMANATION C 30.48 **** **** sp_brill_emanA sp_brill_emanB **** 0 **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ****
|
||||
205 VFX_PER_UTTERDARK C 50 **** **** sp_utterdarkA sp_utterdarkB **** 0 844 **** **** **** **** **** **** **** **** **** **** **** **** sps_darkness **** **** **** **** **** **** ****
|
||||
206 VFX_PER_ACHAIERAI C 3.048 **** **** sp_cloud_achai sp_cloud_achaiB **** 0 845 **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ****
|
||||
|
||||
@@ -690,7 +690,7 @@ int PRCGetSpellSaveDC(int nSpellID = -1, int nSchool = -1, object oCaster = OBJE
|
||||
|
||||
int PRCGetSaveDC(object oTarget, object oCaster, int nSpellID = -1)
|
||||
{
|
||||
object oItem = GetSpellCastItem();
|
||||
object oItem = PRCGetSpellCastItem();
|
||||
if(nSpellID == -1)
|
||||
nSpellID = PRCGetSpellId();
|
||||
int nSchool = GetSpellSchool(nSpellID);
|
||||
|
||||
@@ -1968,16 +1968,24 @@ int AttuneGem(object oTarget = OBJECT_INVALID, object oCaster = OBJECT_INVALID,
|
||||
return TRUE; // tried item creation but do not know how to do it
|
||||
}
|
||||
|
||||
// No point scribing Gems from items, and its not allowed.
|
||||
if (oItem != OBJECT_INVALID)
|
||||
{
|
||||
FloatingTextStringOnCreature("You cannot attune a Gem from an item.", oCaster, FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
// Only allow arcane spellcasters
|
||||
int nClass = PRCGetLastSpellCastClass();
|
||||
if (!GetIsArcaneClass(nClass, oCaster))
|
||||
{
|
||||
FloatingTextStringOnCreature("Only arcane casters can attune gems.", oCaster, FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// No point scribing Gems from items, and its not allowed.
|
||||
if (oItem != OBJECT_INVALID)
|
||||
{
|
||||
FloatingTextStringOnCreature("You cannot attune a Gem from an item.", oCaster, FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
// oTarget here should be the gem. If it's not, fail.
|
||||
if(!GetIsObjectValid(oTarget)) oTarget = PRCGetSpellTargetObject();
|
||||
// Only accepts bioware gems & Craftable Natural Resources gems, but not gem dust.
|
||||
int bIsBioGem = (GetStringLeft(GetResRef(oTarget), 5) == "it_gem");
|
||||
int bIsBioGem = (GetStringLeft(GetResRef(oTarget), 9) == "nw_it_gem");
|
||||
int bIsCNRGem = (GetStringLeft(GetResRef(oTarget), 6) == "cnrgem");
|
||||
int bIsDust = (GetStringLeft(GetResRef(oTarget), 10) == "cnrgemdust");
|
||||
|
||||
@@ -1987,21 +1995,12 @@ int AttuneGem(object oTarget = OBJECT_INVALID, object oCaster = OBJECT_INVALID,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* if ((GetStringLeft(GetResRef(oTarget), 5) == "it_gem") || (GetStringLeft(GetResRef(oTarget), 6) == "cnrgem") && (GetStringLeft(GetResRef(oTarget), 10) != "cnrgemdust"))
|
||||
{
|
||||
FloatingTextStringOnCreature("Spell target is not a valid gem.", oCaster, FALSE);
|
||||
// And out we go
|
||||
return TRUE;
|
||||
} */
|
||||
|
||||
int nCaster = GetAlternativeCasterLevel(oCaster, PRCGetCasterLevel(oCaster));
|
||||
int nDC = PRCGetSaveDC(oTarget, oCaster);
|
||||
if(!nSpell) nSpell = PRCGetSpellId();
|
||||
int nSpellLevel;
|
||||
|
||||
if (PRCGetLastSpellCastClass() == CLASS_TYPE_CLERIC || PRCGetLastSpellCastClass() == CLASS_TYPE_UR_PRIEST) nSpellLevel = StringToInt(lookup_spell_cleric_level(nSpell));
|
||||
else if (PRCGetLastSpellCastClass() == CLASS_TYPE_DRUID) nSpellLevel = StringToInt(lookup_spell_druid_level(nSpell));
|
||||
else if (PRCGetLastSpellCastClass() == CLASS_TYPE_WIZARD || PRCGetLastSpellCastClass() == CLASS_TYPE_SORCERER) nSpellLevel = StringToInt(lookup_spell_level(nSpell));
|
||||
if (PRCGetLastSpellCastClass() == CLASS_TYPE_WIZARD || PRCGetLastSpellCastClass() == CLASS_TYPE_SORCERER) nSpellLevel = StringToInt(lookup_spell_level(nSpell));
|
||||
// If none of these work, check the innate level of the spell
|
||||
if (nSpellLevel == 0) nSpellLevel = StringToInt(lookup_spell_innate(nSpell));
|
||||
// Minimum level.
|
||||
@@ -2034,13 +2033,13 @@ int AttuneGem(object oTarget = OBJECT_INVALID, object oCaster = OBJECT_INVALID,
|
||||
|
||||
if (!GetHasGPToSpend(oCaster, costs.nGoldCost))
|
||||
{
|
||||
FloatingTextStringOnCreature("You do not have enough gold to scribe this Gem.", oCaster, FALSE);
|
||||
FloatingTextStringOnCreature("You do not have enough gold to attue this Gem.", oCaster, FALSE);
|
||||
// Since they don't have enough, the spell casts normally
|
||||
return TRUE;
|
||||
}
|
||||
if (!GetHasXPToSpend(oCaster, costs.nXPCost) )
|
||||
{
|
||||
FloatingTextStringOnCreature("You do not have enough experience to scribe this Gem.", oCaster, FALSE);
|
||||
FloatingTextStringOnCreature("You do not have enough experience to attune this Gem.", oCaster, FALSE);
|
||||
// Since they don't have enough, the spell casts normally
|
||||
return TRUE;
|
||||
}
|
||||
@@ -2057,7 +2056,24 @@ int AttuneGem(object oTarget = OBJECT_INVALID, object oCaster = OBJECT_INVALID,
|
||||
}
|
||||
|
||||
// Steal all the code from craft wand.
|
||||
int nPropID = IPGetIPConstCastSpellFromSpellID(nSpell);
|
||||
//int nPropID = IPGetIPConstCastSpellFromSpellID(nSpell);
|
||||
|
||||
// Handle subradial spells - keep original for radial menu
|
||||
int nSpellOriginal = nSpell;
|
||||
int nSpellMaster = nSpellOriginal;
|
||||
if (GetIsSubradialSpell(nSpellOriginal))
|
||||
{
|
||||
nSpellMaster = GetMasterSpellFromSubradial(nSpellOriginal);
|
||||
}
|
||||
|
||||
// Prefer iprp mapping for original subradial, fallback to master
|
||||
int nPropID = IPGetIPConstCastSpellFromSpellID(nSpellOriginal);
|
||||
int nSpellUsedForIP = nSpellOriginal;
|
||||
if (nPropID < 0)
|
||||
{
|
||||
nPropID = IPGetIPConstCastSpellFromSpellID(nSpellMaster);
|
||||
nSpellUsedForIP = nSpellMaster;
|
||||
}
|
||||
|
||||
// * GZ 2003-09-11: If the current spell cast is not acid fog, and
|
||||
// * returned property ID is 0, bail out to prevent
|
||||
@@ -2075,22 +2091,71 @@ int AttuneGem(object oTarget = OBJECT_INVALID, object oCaster = OBJECT_INVALID,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (nPropID != -1)
|
||||
if (nPropID != -1)
|
||||
{
|
||||
// Handle stack - reduce original stack by 1
|
||||
int nOriginalStack = GetItemStackSize(oTarget);
|
||||
if (nOriginalStack > 1)
|
||||
SetItemStackSize(oTarget, nOriginalStack - 1);
|
||||
|
||||
// Create a NEW single gem in a work container to prevent auto-stacking
|
||||
string sResRef = GetResRef(oTarget);
|
||||
object oWorkContainer = IPGetIPWorkContainer(oCaster);
|
||||
object oWorkGem = CreateItemOnObject(sResRef, oWorkContainer, 1);
|
||||
|
||||
// Add properties to the NEW gem only
|
||||
itemproperty ipLevel = ItemPropertyCastSpellCasterLevel(nSpellUsedForIP, PRCGetCasterLevel());
|
||||
AddItemProperty(DURATION_TYPE_PERMANENT,ipLevel, oWorkGem);
|
||||
itemproperty ipMeta = ItemPropertyCastSpellMetamagic(nSpellUsedForIP, PRCGetMetaMagicFeat());
|
||||
AddItemProperty(DURATION_TYPE_PERMANENT,ipMeta, oWorkGem);
|
||||
itemproperty ipDC = ItemPropertyCastSpellDC(nSpellUsedForIP, PRCGetSaveDC(PRCGetSpellTargetObject(), OBJECT_SELF));
|
||||
AddItemProperty(DURATION_TYPE_PERMANENT,ipDC, oWorkGem);
|
||||
|
||||
int nUseType = IP_CONST_CASTSPELL_NUMUSES_1_CHARGE_PER_USE;
|
||||
if (nCharges == 1)
|
||||
{
|
||||
nUseType = IP_CONST_CASTSPELL_NUMUSES_2_CHARGES_PER_USE;
|
||||
nCharges = 3;
|
||||
}
|
||||
itemproperty ipProp = ItemPropertyCastSpell(nPropID, nUseType);
|
||||
AddItemProperty(DURATION_TYPE_PERMANENT, ipProp, oWorkGem);
|
||||
|
||||
SetItemCharges(oWorkGem, nCharges);
|
||||
SetXP(oCaster, nNewXP);
|
||||
TakeGoldFromCreature(costs.nGoldCost, oCaster, TRUE);
|
||||
|
||||
string sName;
|
||||
sName = Get2DACache("spells", "Name", nSpellUsedForIP);
|
||||
sName = "Gem of "+GetStringByStrRef(StringToInt(sName));
|
||||
SetName(oWorkGem, sName);
|
||||
|
||||
// Copy the work gem to create the final attuned gem in caster's inventory
|
||||
object oNewGem = CopyObject(oWorkGem, GetLocation(oCaster), oCaster, "prc_attunegem");
|
||||
|
||||
// Destroy the work gem
|
||||
DestroyObject(oWorkGem, 0.1);
|
||||
|
||||
// If original stack was 1, destroy it too
|
||||
if (nOriginalStack == 1)
|
||||
DestroyObject(oTarget, 0.1);
|
||||
}
|
||||
|
||||
/* if (nPropID != -1)
|
||||
{
|
||||
itemproperty ipLevel = ItemPropertyCastSpellCasterLevel(nSpell, PRCGetCasterLevel());
|
||||
// Handle stack splitting - reduce original stack and create single gem to work with
|
||||
int nOriginalStack = GetItemStackSize(oTarget);
|
||||
if (nOriginalStack > 1)
|
||||
{
|
||||
SetItemStackSize(oTarget, nOriginalStack - 1);
|
||||
oTarget = CreateItemOnObject(GetResRef(oTarget), oCaster, 1);
|
||||
}
|
||||
|
||||
itemproperty ipLevel = ItemPropertyCastSpellCasterLevel(nSpell, PRCGetCasterLevel());
|
||||
AddItemProperty(DURATION_TYPE_PERMANENT,ipLevel, oTarget);
|
||||
itemproperty ipMeta = ItemPropertyCastSpellMetamagic(nSpell, PRCGetMetaMagicFeat());
|
||||
AddItemProperty(DURATION_TYPE_PERMANENT,ipMeta, oTarget);
|
||||
itemproperty ipDC = ItemPropertyCastSpellDC(nSpell, PRCGetSaveDC(PRCGetSpellTargetObject(), OBJECT_SELF));
|
||||
AddItemProperty(DURATION_TYPE_PERMANENT,ipDC, oTarget);
|
||||
|
||||
/* if (nCharges == 1) // This is to handle one use Gems so the spellhooking works
|
||||
{
|
||||
itemproperty ipProp = ItemPropertyCastSpell(nPropID,IP_CONST_CASTSPELL_NUMUSES_2_CHARGES_PER_USE);
|
||||
AddItemProperty(DURATION_TYPE_PERMANENT,ipProp, oTarget);
|
||||
// This is done so the item exists when it is used for the game to read data off of
|
||||
nCharges = 3;
|
||||
} */
|
||||
|
||||
int nUseType = IP_CONST_CASTSPELL_NUMUSES_1_CHARGE_PER_USE;
|
||||
if (nCharges == 1)
|
||||
@@ -2139,7 +2204,7 @@ int AttuneGem(object oTarget = OBJECT_INVALID, object oCaster = OBJECT_INVALID,
|
||||
object oNewGem = CopyObject(oTarget, GetLocation(oCaster), oCaster, "prc_attunegem");
|
||||
DestroyObject(oTarget, 0.1);
|
||||
}
|
||||
|
||||
*/
|
||||
// If we have made it this far, they have crafted the Gem and the spell has been used up, so it returns false.
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -3503,6 +3503,21 @@ int X2PreSpellCastCode2()
|
||||
nContinue = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Attuned Gem Use check
|
||||
//---------------------------------------------------------------------------
|
||||
if(nContinue && (GetBaseItemType(oSpellCastItem) == BASE_ITEM_GEM) && (GetTag(oSpellCastItem) == "prc_attunegem"))
|
||||
{
|
||||
int bIsSubradial = GetIsSubradialSpell(nSpellID);
|
||||
|
||||
if(bIsSubradial)
|
||||
{
|
||||
nSpellID = GetMasterSpellFromSubradial(nSpellID);
|
||||
}
|
||||
int nItemCL = GetCastSpellCasterLevelFromItem(oSpellCastItem, nSpellID);
|
||||
if(DEBUG) DoDebug("x2_inc_spellhook >> X2PreSpellCastCode2: Attuned Gem Found");
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// No casting while using expertise
|
||||
|
||||
@@ -39,14 +39,14 @@ void main()
|
||||
if(iAttackRoll > 0)
|
||||
{
|
||||
oItemTarget = GetItemInSlot(INVENTORY_SLOT_CHEST, oTarget);
|
||||
if(!GetIsObjectValid(oTarget))
|
||||
if(!GetIsObjectValid(oItemTarget))
|
||||
{
|
||||
//no armor, check other slots
|
||||
int i;
|
||||
for(i=0;i<14;i++)
|
||||
{
|
||||
oItemTarget = GetItemInSlot(i, oTarget);
|
||||
if(GetIsObjectValid(oTarget))
|
||||
if(GetIsObjectValid(oItemTarget))
|
||||
break;//end for loop
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
----------------
|
||||
|
||||
27/01/08 by Stratovarius
|
||||
|
||||
Fixed by: Jaysyn
|
||||
On: 2026-05-25 19:11:53
|
||||
|
||||
*/ /** @file
|
||||
|
||||
Dragon's Tooth
|
||||
@@ -23,7 +27,7 @@ void main()
|
||||
{
|
||||
object oInitiator = OBJECT_SELF;
|
||||
object oCreature = CreateObject(OBJECT_TYPE_PLACEABLE, "tob_dpst_pillar", PRCGetSpellTargetLocation());
|
||||
object oProneTarget = MyFirstObjectInShape(SHAPE_SPHERE, FeetToMeters(10.0), GetLocation(oInitiator));
|
||||
object oProneTarget = MyFirstObjectInShape(SHAPE_SPHERE, FeetToMeters(60.0), PRCGetSpellTargetLocation());
|
||||
while(GetIsObjectValid(oProneTarget))
|
||||
{
|
||||
int nDC = 10 + GetHitDice(oInitiator)/2 + GetAbilityModifier(ABILITY_STRENGTH, oInitiator);
|
||||
@@ -34,11 +38,11 @@ void main()
|
||||
nDC += 1;
|
||||
}
|
||||
// Save check
|
||||
if (!PRCMySavingThrow(SAVING_THROW_WILL, oProneTarget, nDC))
|
||||
if (!PRCMySavingThrow(SAVING_THROW_REFLEX, oProneTarget, nDC))
|
||||
{
|
||||
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, ExtraordinaryEffect(EffectKnockdown()), oProneTarget, 6.0);
|
||||
}
|
||||
|
||||
oProneTarget = MyNextObjectInShape(SHAPE_SPHERE, FeetToMeters(10.0), GetLocation(oInitiator));
|
||||
oProneTarget = MyNextObjectInShape(SHAPE_SPHERE, FeetToMeters(60.0), PRCGetSpellTargetLocation());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +76,6 @@ void main()
|
||||
}
|
||||
|
||||
// Impact Effects
|
||||
//ApplyEffectAtLocation(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_DUR_FLOATING_DISK), GetLocation(oTarget));
|
||||
ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, EffectVisualEffect(VFX_DUR_FLOATING_DISK), GetLocation(oTarget), 3.0f);
|
||||
ApplyEffectAtLocation(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_BIGBYS_FORCEFUL_HAND), GetLocation(oTarget));
|
||||
}// end if - Successful utterance
|
||||
}
|
||||
|
||||
@@ -26,8 +26,10 @@ void AcolyteSymbiosis(object oPC, object oSkin, int iLevel)
|
||||
{
|
||||
if(GetLocalInt(oSkin, "AcolyteSymbBonus") == iLevel) return;
|
||||
|
||||
RemoveSpecificProperty(oSkin, ITEM_PROPERTY_DAMAGE_REDUCTION, GetLocalInt(oSkin, "AcolyteSymbBonus"), IP_CONST_DAMAGESOAK_20_HP, 1, "AcolyteSymbBonus");
|
||||
AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyDamageReduction(iLevel, IP_CONST_DAMAGESOAK_20_HP), oSkin);
|
||||
//RemoveSpecificProperty(oSkin, ITEM_PROPERTY_DAMAGE_REDUCTION, GetLocalInt(oSkin, "AcolyteSymbBonus"), IP_CONST_DAMAGESOAK_20_HP, 1, "AcolyteSymbBonus");
|
||||
RemoveSpecificProperty(oSkin, ITEM_PROPERTY_DAMAGE_REDUCTION, IP_CONST_DAMAGESOAK_20_HP, GetLocalInt(oSkin, "AcolyteSymbBonus"), 1, "AcolyteSymbBonus");
|
||||
//AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyDamageReduction(iLevel, IP_CONST_DAMAGESOAK_20_HP), oSkin);
|
||||
AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyDamageReduction(IP_CONST_DAMAGESOAK_20_HP, iLevel), oSkin);
|
||||
SetLocalInt(oSkin, "AcolyteSymbBonus", iLevel);
|
||||
}
|
||||
|
||||
|
||||
@@ -65,14 +65,14 @@ int DoSpell(object oCaster, object oTarget, int nCasterLevel)
|
||||
if(iAttackRoll > 0)
|
||||
{
|
||||
oItemTarget = GetItemInSlot(INVENTORY_SLOT_CHEST, oTarget);
|
||||
if(!GetIsObjectValid(oTarget))
|
||||
if(!GetIsObjectValid(oItemTarget))
|
||||
{
|
||||
//no armor, check other slots
|
||||
int i;
|
||||
for(i=0;i<14;i++)
|
||||
{
|
||||
oItemTarget = GetItemInSlot(i, oTarget);
|
||||
if(GetIsObjectValid(oTarget))
|
||||
if(GetIsObjectValid(oItemTarget))
|
||||
break;//end for loop
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,14 +82,14 @@ int DoSpell(object oCaster, object oTarget, int nCasterLevel)
|
||||
if(iAttackRoll > 0)
|
||||
{
|
||||
oItemTarget = GetItemInSlot(INVENTORY_SLOT_CHEST, oTarget);
|
||||
if(!GetIsObjectValid(oTarget))
|
||||
if(!GetIsObjectValid(oItemTarget))
|
||||
{
|
||||
//no armor, check other slots
|
||||
int i;
|
||||
for(i=0;i<14;i++)
|
||||
{
|
||||
oItemTarget = GetItemInSlot(i, oTarget);
|
||||
if(GetIsObjectValid(oTarget))
|
||||
if(GetIsObjectValid(oItemTarget))
|
||||
break;//end for loop
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,14 +53,14 @@ int DoSpell(object oCaster, object oTarget, int nCasterLevel)
|
||||
if(iAttackRoll > 0)
|
||||
{
|
||||
oItemTarget = GetItemInSlot(INVENTORY_SLOT_CHEST, oTarget);
|
||||
if(!GetIsObjectValid(oTarget))
|
||||
if(!GetIsObjectValid(oItemTarget))
|
||||
{
|
||||
//no armor, check other slots
|
||||
int i;
|
||||
for(i=0;i<14;i++)
|
||||
{
|
||||
oItemTarget = GetItemInSlot(i, oTarget);
|
||||
if(GetIsObjectValid(oTarget))
|
||||
if(GetIsObjectValid(oItemTarget))
|
||||
break;//end for loop
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -7347,7 +7347,7 @@ You make yourself - including clothing, armor, weapons and equipment - look diff
|
||||
<entry id="45448" lang="en" sex="m">Disguise Self, Normal Form</entry>
|
||||
<entry id="45449" lang="en" sex="m">Attune Gem</entry>
|
||||
<entry id="45450" lang="en" sex="m">Type of Feat: Item Creation
|
||||
Prerequisite: Intelligence 13, Arcane Spells level 2.
|
||||
Prerequisite: Intelligence 13, Arcane Spells level 3.
|
||||
Specifics: You can cast any arcane spell you have prepared as a gem. The caster must have the spell memorized to be able to create the gem. Crafting a gem costs Spell level * Caster level * 50 in gold pieces for a normal caster (half base cost). It also takes XP equal to 1/25th of the base cost. If you cannot pay the casting cost or the XP loss would drop you a level, the crafting will fail, and the spell will be lost. Crafting the gem requires a gem with a value of 50gp * spell level. A gem is permanent until used. Gems target those who activate them.
|
||||
Use: Selected.</entry>
|
||||
<entry id="45451" lang="en" sex="m">Epic Scout</entry>
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user