PRC8/nwn/nwnprc/trunk/spells/nw_s1_barbrage.nss
Jaysyn904 b4eb554eea Forsaker / Barbarian Rage tweak
Forsaker / Barbarian Rage tweak.  Removed duplicate class feats from Abjurant Champion, Eldritch Knight & Rage Mage.  Fixed Maul icon typo in feat.2da.  Fixed extra space typo in prc_material.2da.  Fixed typos in TLK.  Updated release archive.
2025-01-07 17:38:41 -05:00

328 lines
15 KiB
Plaintext

//::///////////////////////////////////////////////
//:: Barbarian Rage
//:: NW_S1_BarbRage
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
The Str and Con of the Barbarian increases,
Will Save are +2, AC -2.
Greater Rage starts at level 15.
Updated: 2004-01-18 mr_bumpkin: Added bonuses for exceeding +12 stat cap
Updated: 2004-2-24 by Oni5115: Added Intimidating Rage
*/
//:://////////////////////////////////////////////
//:: Created By: Preston Watamaniuk
//:: Created On: Aug 13, 2001
//:://////////////////////////////////////////////
#include "moi_inc_moifunc"
#include "inc_addragebonus"
#include "inc_npc"
#include "psi_inc_psifunc"
#include "prc_inc_factotum"
void main()
{
object oPC = OBJECT_SELF;
if(GetHasSpellEffect(SPELL_SPELL_RAGE))
{
IncrementRemainingFeatUses(OBJECT_SELF, FEAT_BARBARIAN_RAGE);
FloatingTextStringOnCreature("You can't use Barbarian Rage and Spell Rage at the same time.", OBJECT_SELF, FALSE);
return;
}
if(!GetHasFeatEffect(FEAT_BARBARIAN_RAGE) && !GetHasSpellEffect(GetSpellId()))
{
int nBBC = GetLevelByClass(CLASS_TYPE_BLACK_BLOOD_CULTIST);
//Declare major variables
int nLevel = GetLevelByClass(CLASS_TYPE_BARBARIAN)
+ GetLevelByClass(CLASS_TYPE_RUNESCARRED)
+ GetLevelByClass(CLASS_TYPE_BATTLERAGER)
+ GetLevelByClass(CLASS_TYPE_PRC_EYE_OF_GRUUMSH)
+ nBBC
+ GetLevelByClass(CLASS_TYPE_RAGE_MAGE);
int iStr, iCon, iAC;
int nSave, nBonusEss;
int nTotem = GetLevelByClass(CLASS_TYPE_TOTEM_RAGER, oPC);
// Factotum Cunning Brilliance
if (GetIsAbilitySaved(oPC, FEAT_BARBARIAN_RAGE))
nLevel = GetLevelByClass(CLASS_TYPE_FACTOTUM);
iAC = 2;
//Lock: Added compatibility for PRC Mighty Rage ability
if(nLevel > 14)
{
if(GetHasFeat(FEAT_PRC_EPIC_MIGHT_RAGE))
{
iStr = 8;
iCon = 8;
nSave = 4;
}
else
{
iStr = 6;
iCon = 6;
nSave = 3;
}
}
else
{
iStr = 4;
iCon = 4;
nSave = 2;
}
// Eye of Gruumsh ability. Additional +4 Str and -2 AC.
if(GetHasFeat(FEAT_SWING_BLINDLY))
{
iStr += 4;
iAC += 2;
}
// +2 Str/Con -2 AC
if(GetHasFeat(FEAT_RECKLESS_RAGE))
{
iStr += 2;
iCon += 2;
iAC += 2;
}
// +2 Con
if(GetHasFeat(FEAT_ETTERCAP_BERSERKER))
iCon += 2;
//(Patch 1.70 - if not silenced) play a random voice chat instead of just VOICE_CHAT_BATTLECRY1
if(!PRCGetHasEffect(EFFECT_TYPE_SILENCE))
{
int iVoice = d3(1);
switch(iVoice)
{
case 1: iVoice = VOICE_CHAT_BATTLECRY1; break;
case 2: iVoice = VOICE_CHAT_BATTLECRY2; break;
case 3: iVoice = VOICE_CHAT_BATTLECRY3; break;
}
PlayVoiceChat(iVoice);
}
//Determine the duration by getting the con modifier after being modified
//Patch 1.70 - duration calculation was bugged
int nCon = 3 + ((GetAbilityScore(OBJECT_SELF, ABILITY_CONSTITUTION) - 10 + iCon)/2);
effect eLink = EffectVisualEffect(VFX_DUR_CESSATE_POSITIVE);
eLink = EffectLinkEffects(eLink, EffectAbilityIncrease(ABILITY_CONSTITUTION, iCon));
eLink = EffectLinkEffects(eLink, EffectAbilityIncrease(ABILITY_STRENGTH, iStr));
eLink = EffectLinkEffects(eLink, EffectSavingThrowIncrease(SAVING_THROW_WILL, nSave));
eLink = EffectLinkEffects(eLink, EffectACDecrease(iAC, AC_DODGE_BONUS));
// Blazing Berserker
if(GetHasFeat(FEAT_BLAZING_BERSERKER))
{
eLink = EffectLinkEffects(eLink, EffectVisualEffect(VFX_DUR_ELEMENTAL_SHIELD));
eLink = EffectLinkEffects(eLink, EffectDamageImmunityDecrease(DAMAGE_TYPE_COLD, 50));
eLink = EffectLinkEffects(eLink, EffectDamageImmunityIncrease(DAMAGE_TYPE_FIRE, 100));
}
// Frozen Berserker
if(GetHasFeat(FEAT_FROZEN_BERSERKER))
{
eLink = EffectLinkEffects(eLink, EffectVisualEffect(VFX_DUR_ELEMENTAL_SHIELD));
eLink = EffectLinkEffects(eLink, EffectDamageImmunityDecrease(DAMAGE_TYPE_FIRE, 50));
eLink = EffectLinkEffects(eLink, EffectDamageImmunityIncrease(DAMAGE_TYPE_COLD, 100));
}
// Ice Troll Berserker
if(GetHasFeat(FEAT_ICE_TROLL_BERSERKER))
{
int nBonus = 2;
if(nLevel > 14) nBonus = 4;
eLink = EffectLinkEffects(eLink, EffectACIncrease(nBonus, AC_NATURAL_BONUS));
}
// Cobalt Rage
int nEssentia = GetEssentiaInvestedFeat(oPC, FEAT_COBALT_RAGE);
// Totem Rage from Totem Rager
if (nTotem)
{
int nTotemRage = GetMaxEssentiaCapacityFeat(oPC) - nEssentia;
int nExtraEss = max(nTotem/2, 1);
int nBoost;
if (nExtraEss >= nTotemRage)
{
nBonusEss = nExtraEss - nTotemRage;
nEssentia += nTotemRage;
}
else
nEssentia += nExtraEss;
}
if (nEssentia)
{
eLink = EffectLinkEffects(eLink, EffectSavingThrowIncrease(SAVING_THROW_WILL, nEssentia));
eLink = EffectLinkEffects(eLink, EffectDamageIncrease(IPGetDamageBonusConstantFromNumber(nEssentia), DAMAGE_TYPE_BASE_WEAPON));
}
//Make effect extraordinary
eLink = ExtraordinaryEffect(eLink);
effect eVis = EffectVisualEffect(VFX_IMP_IMPROVE_ABILITY_SCORE); //Change to the Rage VFX
SignalEvent(oPC, EventSpellCastAt(oPC, SPELLABILITY_BARBARIAN_RAGE, FALSE));
if(nCon > 0)
{
// 2004-01-18 mr_bumpkin: determine the ability scores before adding bonuses, so the values
// can be read in by the GiveExtraRageBonuses() function below.
int StrBeforeBonuses = GetAbilityScore(oPC, ABILITY_STRENGTH);
int ConBeforeBonuses = GetAbilityScore(oPC, ABILITY_CONSTITUTION);
float fDuration = RoundsToSeconds(nCon);
fDuration += GetHasFeat(FEAT_EXTENDED_RAGE, oPC) ? 30.0 : 0.0;
if (nEssentia > 5 && nTotem >= 5) fDuration += 6.0 * (nEssentia - 5);
// Terrifying Rage
if(GetHasFeat(FEAT_EPIC_TERRIFYING_RAGE))
{
effect eAOE = EffectAreaOfEffect(AOE_MOB_FEAR, "x2_s2_terrage_A");
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, ExtraordinaryEffect(eAOE), oPC, fDuration);
}
// Frostrager
int nFrost = GetLevelByClass(CLASS_TYPE_FROSTRAGER, oPC);
object oWeapL = GetItemInSlot(INVENTORY_SLOT_CWEAPON_L, oPC);
string sWeapType = "PRC_UNARMED_B";
if(nFrost>0 && GetBaseItemType(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC)) == BASE_ITEM_INVALID &&
GetIsObjectValid(oWeapL) && GetTag(oWeapL) == sWeapType) //Only applies when unarmed and you actually have a creature weapon
{
// Record that we're Frostraging
SetLocalInt(oPC, "Frostrage", TRUE);
DelayCommand(fDuration, DeleteLocalInt(oPC, "Frostrage"));
int nFrostAC = 4;
int nFrostDamage = IP_CONST_DAMAGEBONUS_1d4;
if(nFrost>3) //Improved Frost Rage
{
nFrostAC = 6;
nFrostDamage = IP_CONST_DAMAGEBONUS_1d6;
}
eLink = EffectLinkEffects(eLink, EffectACIncrease(nFrostAC, AC_NATURAL_BONUS));
AddItemProperty(DURATION_TYPE_TEMPORARY,ItemPropertyDamageBonus(IP_CONST_DAMAGETYPE_COLD,nFrostDamage),oWeapL,fDuration);
}
else if (nFrost>0)
FloatingTextStringOnCreature("Frostrage failed, invalid weapon", oPC, FALSE);
//Apply the VFX impact and the actual rage effects
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oPC, fDuration);
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oPC);
// Totem Rage bonus Essentia
if (nBonusEss)
{
SetTemporaryEssentia(oPC, nBonusEss);
DelayCommand(fDuration, SetTemporaryEssentia(oPC, nBonusEss * -1));
FloatingTextStringOnCreature("Totem Rage has granted you "+IntToString(nBonusEss)+" temporary essentia", oPC, FALSE);
}
// Shared Fury
if(GetHasFeat(FEAT_SHARED_FURY, oPC))
{
object oComp = GetFirstObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_MEDIUM, GetLocation(oPC), TRUE, OBJECT_TYPE_CREATURE);
while(GetIsObjectValid(oComp))
{
if(GetMasterNPC(oComp) == oPC && GetAssociateTypeNPC(oComp) == ASSOCIATE_TYPE_ANIMALCOMPANION)
{
PRCRemoveEffectsFromSpell(oComp, SPELLABILITY_BARBARIAN_RAGE);
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oComp, fDuration);
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oComp);
}
oComp = GetNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_MEDIUM, GetLocation(oPC), TRUE, OBJECT_TYPE_CREATURE);
}
}
// 2004-2-24 Oni5115: Intimidating Rage
if(GetHasFeat(FEAT_INTIMIDATING_RAGE, oPC))
{
//Finds nearest visible enemy within 30 ft.
object oTarget = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, oPC, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN);
if(GetDistanceBetween(oPC, oTarget) < FeetToMeters(30.0))
{
// Will save DC 10 + 1/2 Char level + Cha mod
int saveDC = 10 + (GetHitDice(oPC)/2) + GetAbilityModifier(ABILITY_CHARISMA, oPC);
int nResult = WillSave(oTarget, saveDC, SAVING_THROW_TYPE_NONE);
if(!nResult)
{
// Same effect as Doom Spell
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectShaken(), oTarget, fDuration);
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_DOOM), oTarget);
}
}
}
// Thundering Rage
if(GetHasFeat(FEAT_EPIC_THUNDERING_RAGE, oPC))
{
object oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC);
if(GetIsObjectValid(oWeapon))
{
IPSafeAddItemProperty(oWeapon, ItemPropertyMassiveCritical(IP_CONST_DAMAGEBONUS_2d6), fDuration, X2_IP_ADDPROP_POLICY_KEEP_EXISTING,TRUE,TRUE);
IPSafeAddItemProperty(oWeapon, ItemPropertyVisualEffect(ITEM_VISUAL_SONIC), fDuration, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING,FALSE,TRUE);
IPSafeAddItemProperty(oWeapon, ItemPropertyOnHitProps(IP_CONST_ONHIT_DEAFNESS,IP_CONST_ONHIT_SAVEDC_20,IP_CONST_ONHIT_DURATION_25_PERCENT_3_ROUNDS), fDuration, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING,FALSE,TRUE);
}
oWeapon = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oPC);
if(GetIsObjectValid(oWeapon))
{
IPSafeAddItemProperty(oWeapon, ItemPropertyMassiveCritical(IP_CONST_DAMAGEBONUS_2d6), fDuration, X2_IP_ADDPROP_POLICY_KEEP_EXISTING,TRUE,TRUE);
IPSafeAddItemProperty(oWeapon,ItemPropertyVisualEffect(ITEM_VISUAL_SONIC), fDuration, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING,FALSE,TRUE);
}
}
// Black Blood Cultist, don't trigger at 10th level because it becomes permanent then
if (10 > nBBC && nBBC > 0)
{
int nClawDamage = IP_CONST_MONSTERDAMAGE_1d6;
int nBiteDamage = IP_CONST_MONSTERDAMAGE_1d4;
string sResRef = "prc_claw_1d6m_";
if (nBBC >= 7)
{
nClawDamage = IP_CONST_MONSTERDAMAGE_1d8;
nBiteDamage = IP_CONST_MONSTERDAMAGE_1d6;
sResRef = "prc_claw_1d8m_";
}
// Create the creature weapon & add the base damage
object oLClaw = GetPsionicCreatureWeapon(oPC, "PRC_UNARMED_SP", INVENTORY_SLOT_CWEAPON_L, fDuration);
object oRClaw = GetPsionicCreatureWeapon(oPC, "PRC_UNARMED_SP", INVENTORY_SLOT_CWEAPON_R, fDuration);
AddItemProperty(DURATION_TYPE_TEMPORARY, ItemPropertyMonsterDamage(nClawDamage), oLClaw, fDuration);
AddItemProperty(DURATION_TYPE_TEMPORARY, ItemPropertyMonsterDamage(nClawDamage), oRClaw, fDuration);
if (nBBC >= 3)
{
object oBite = GetPsionicCreatureWeapon(oPC, "prc_bw0_bite_t", INVENTORY_SLOT_CWEAPON_B, fDuration);
AddItemProperty(DURATION_TYPE_TEMPORARY, ItemPropertyMonsterDamage(nBiteDamage), oBite, fDuration);
}
if (nBBC >= 6) // Rend, see inc_rend and prc_onhitcast
{
IPSafeAddItemProperty(oLClaw, ItemPropertyOnHitCastSpell(IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, 1), 99999.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
IPSafeAddItemProperty(oRClaw, ItemPropertyOnHitCastSpell(IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, 1), 99999.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
}
sResRef += GetAffixForSize(PRCGetCreatureSize(oPC));
AddNaturalPrimaryWeapon(oPC, sResRef, 2, TRUE);
DelayCommand(6.0f, NaturalPrimaryWeaponTempCheck(oPC, oPC, GetSpellId(), FloatToInt(fDuration) / 6, sResRef));
AddNaturalSecondaryWeapon(oPC, "prc_bw0_bite_t", 1);
DelayCommand(6.0f, NaturalSecondaryWeaponTempCheck(oPC, oPC, GetSpellId(), FloatToInt(fDuration) / 6, "prc_bw0_bite_t"));
}
// 2004-01-18 mr_bumpkin: Adds special bonuses to those barbarians who are restricted by the
// +12 attribute bonus cap, to make up for them. :)
// The delay is because you have to delay the command if you want the function to be able
// to determine what the ability scores become after adding the bonuses to them.
DelayCommand(0.1, GiveExtraRageBonuses(nCon, StrBeforeBonuses, ConBeforeBonuses, iStr, iCon, nSave, DAMAGE_TYPE_BASE_WEAPON, oPC));
if(GetLevelByClass(CLASS_TYPE_FORSAKER, oPC) >= 3) //Run feat script if Forsaker lvl3 to increase AC based on CON, then decrease again after it ends
{
ExecuteScript("prc_forsaker", oPC);
DelayCommand(fDuration + 0.1, ExecuteScript("prc_forsaker", oPC));
}
}
}
}