//:://///////////////////////////////////////////// //:: Bard Song //:: NW_S2_BardSong //:: Copyright (c) 2001 Bioware Corp. //::////////////////////////////////////////////// /* This spells applies bonuses to all of the bard's allies within 30ft for a set duration of 10 rounds. */ //::////////////////////////////////////////////// //:: Created By: Preston Watamaniuk //:: Created On: Feb 25, 2002 //::////////////////////////////////////////////// //:: Last Updated By: Georg Zoeller Oct 1, 2003 /* bugfix by Kovi 2002.07.30 - loosing temporary hp resulted in loosing the other bonuses */ #include "prc_inc_clsfunc" #include "prc_inc_combat" //for Dragonfire type getting void ApplyDragonfire(int nAmount, int nDuration, object oPC, object oCaster) { int nAppearanceType; int nDamageType = GetDragonfireDamageType(oPC); //find primary weapon to add to object oItem = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC); switch(nDamageType) { case DAMAGE_TYPE_ACID: nAppearanceType = ITEM_VISUAL_ACID; break; case DAMAGE_TYPE_COLD: nAppearanceType = ITEM_VISUAL_COLD; break; case DAMAGE_TYPE_ELECTRICAL: nAppearanceType = ITEM_VISUAL_ELECTRICAL; break; case DAMAGE_TYPE_SONIC: nAppearanceType = ITEM_VISUAL_SONIC; break; case DAMAGE_TYPE_FIRE: nAppearanceType = ITEM_VISUAL_FIRE; break; } SetLocalInt(oItem, "Insp_Dam_Type", nDamageType); SetLocalInt(oItem, "Insp_Dam_Dice", nAmount); IPSafeAddItemProperty(oItem, ItemPropertyOnHitCastSpell(IP_CONST_ONHIT_CASTSPELL_DRAGONFIRE, nAmount), RoundsToSeconds(nDuration), X2_IP_ADDPROP_POLICY_REPLACE_EXISTING); IPSafeAddItemProperty(oItem, ItemPropertyVisualEffect(nAppearanceType), RoundsToSeconds(nDuration), X2_IP_ADDPROP_POLICY_REPLACE_EXISTING,FALSE,TRUE); //add to gloves and claws too oItem = GetItemInSlot(INVENTORY_SLOT_ARMS, oPC); SetLocalInt(oItem, "Insp_Dam_Type", nDamageType); SetLocalInt(oItem, "Insp_Dam_Dice", nAmount); IPSafeAddItemProperty(oItem, ItemPropertyOnHitCastSpell(IP_CONST_ONHIT_CASTSPELL_DRAGONFIRE, nAmount), RoundsToSeconds(nDuration), X2_IP_ADDPROP_POLICY_REPLACE_EXISTING); oItem = GetItemInSlot(INVENTORY_SLOT_CWEAPON_R, oPC); SetLocalInt(oItem, "Insp_Dam_Type", nDamageType); SetLocalInt(oItem, "Insp_Dam_Dice", nAmount); IPSafeAddItemProperty(oItem, ItemPropertyOnHitCastSpell(IP_CONST_ONHIT_CASTSPELL_DRAGONFIRE, nAmount), RoundsToSeconds(nDuration), X2_IP_ADDPROP_POLICY_REPLACE_EXISTING); //do ammo for ranged attacks object oAmmo = GetItemInSlot(INVENTORY_SLOT_BOLTS, oPC); SetLocalInt(oAmmo, "Insp_Dam_Type", nDamageType); SetLocalInt(oAmmo, "Insp_Dam_Dice", nAmount); IPSafeAddItemProperty(oAmmo, ItemPropertyOnHitCastSpell(IP_CONST_ONHIT_CASTSPELL_DRAGONFIRE, nAmount), RoundsToSeconds(nDuration), X2_IP_ADDPROP_POLICY_REPLACE_EXISTING); oAmmo = GetItemInSlot(INVENTORY_SLOT_BULLETS, oPC); SetLocalInt(oAmmo, "Insp_Dam_Type", nDamageType); SetLocalInt(oAmmo, "Insp_Dam_Dice", nAmount); IPSafeAddItemProperty(oAmmo, ItemPropertyOnHitCastSpell(IP_CONST_ONHIT_CASTSPELL_DRAGONFIRE, nAmount), RoundsToSeconds(nDuration), X2_IP_ADDPROP_POLICY_REPLACE_EXISTING); oAmmo = GetItemInSlot(INVENTORY_SLOT_ARROWS, oPC); SetLocalInt(oAmmo, "Insp_Dam_Type", nDamageType); SetLocalInt(oAmmo, "Insp_Dam_Dice", nAmount); IPSafeAddItemProperty(oAmmo, ItemPropertyOnHitCastSpell(IP_CONST_ONHIT_CASTSPELL_DRAGONFIRE, nAmount), RoundsToSeconds(nDuration), X2_IP_ADDPROP_POLICY_REPLACE_EXISTING); //now check offhand and bite oItem = GetItemInSlot(INVENTORY_SLOT_CWEAPON_B, oPC); SetLocalInt(oItem, "Insp_Dam_Type", nDamageType); SetLocalInt(oItem, "Insp_Dam_Dice", nAmount); IPSafeAddItemProperty(oItem, ItemPropertyOnHitCastSpell(IP_CONST_ONHIT_CASTSPELL_DRAGONFIRE, nAmount), RoundsToSeconds(nDuration), X2_IP_ADDPROP_POLICY_REPLACE_EXISTING); oItem = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oPC); if(!GetIsShield(oItem) && oItem != OBJECT_INVALID) { SetLocalInt(oItem, "Insp_Dam_Type", nDamageType); SetLocalInt(oItem, "Insp_Dam_Dice", nAmount); IPSafeAddItemProperty(oItem, ItemPropertyOnHitCastSpell(IP_CONST_ONHIT_CASTSPELL_DRAGONFIRE, nAmount), RoundsToSeconds(nDuration), X2_IP_ADDPROP_POLICY_REPLACE_EXISTING); IPSafeAddItemProperty(oItem, ItemPropertyVisualEffect(nAppearanceType), RoundsToSeconds(nDuration), X2_IP_ADDPROP_POLICY_REPLACE_EXISTING,FALSE,TRUE); } oItem = GetItemInSlot(INVENTORY_SLOT_CWEAPON_L, oPC); SetLocalInt(oItem, "Insp_Dam_Type", nDamageType); SetLocalInt(oItem, "Insp_Dam_Dice", nAmount); IPSafeAddItemProperty(oItem, ItemPropertyOnHitCastSpell(IP_CONST_ONHIT_CASTSPELL_DRAGONFIRE, nAmount), RoundsToSeconds(nDuration), X2_IP_ADDPROP_POLICY_REPLACE_EXISTING); } void main() { if (PRCGetHasEffect(EFFECT_TYPE_SILENCE,OBJECT_SELF)) { FloatingTextStrRefOnCreature(85764,OBJECT_SELF); // not useable when silenced return; } string sTag = GetTag(OBJECT_SELF); //RemoveOldSongEffects(OBJECT_SELF,GetSpellId()); if (sTag == "x0_hen_dee" || sTag == "x2_hen_deekin") { // * Deekin has a chance of singing a doom song // * same effect, better tune if (Random(5) == 2) { // the Xp2 Deekin knows more than one doom song if (d3() == 1 && sTag == "x2_hen_deekin") { DelayCommand(0.0, PlaySound("vs_nx2deekM_050")); } else { DelayCommand(0.0, PlaySound("vs_nx0deekM_074")); DelayCommand(5.0, PlaySound("vs_nx0deekM_074")); } } } //Declare major variables int nLevel = GetLevelByClass(CLASS_TYPE_BARD) + GetLevelByClass(CLASS_TYPE_DIRGESINGER) + GetLevelByClass(CLASS_TYPE_FOCHLUCAN_LYRIST) + GetLevelByClass(CLASS_TYPE_SUBLIME_CHORD) + GetLevelByClass(CLASS_TYPE_VIRTUOSO); if (GetHasFeat(FEAT_SONG_WHITE_RAVEN, OBJECT_SELF)) nLevel += GetLevelByClass(CLASS_TYPE_CRUSADER) + GetLevelByClass(CLASS_TYPE_WARBLADE); int nRanks = GetSkillRank(SKILL_PERFORM); if (GetHasFeat(FEAT_DRAGONSONG, OBJECT_SELF)) nRanks+= 2; int nChr = GetAbilityModifier(ABILITY_CHARISMA); int nPerform = nRanks; int nDuration = 10; //+ nChr; effect eAttack; effect eDamage; effect eWill; effect eFort; effect eReflex; effect eHP; effect eAC; effect eSkill; int nAttack; int nDamage; int nWill; int nFort; int nReflex; int nHP; int nAC; int nSkill; // lingering song if(GetHasFeat(FEAT_LINGERING_SONG)) { nDuration += 5; } //Check to see if the caster has Lasting Impression and increase duration. if(GetHasFeat(FEAT_EPIC_LASTING_INSPIRATION)) { nDuration *= 10; } //SpeakString("Level: " + IntToString(nLevel) + " Ranks: " + IntToString(nRanks)); if(nPerform >= 100 && nLevel >= 30) { nAttack = 2; nDamage = 3; nWill = 3; nFort = 2; nReflex = 2; nHP = 48; nAC = 7; nSkill = 19; } else if(nPerform >= 95 && nLevel >= 29) { nAttack = 2; nDamage = 3; nWill = 3; nFort = 2; nReflex = 2; nHP = 46; nAC = 6; nSkill = 18; } else if(nPerform >= 90 && nLevel >= 28) { nAttack = 2; nDamage = 3; nWill = 3; nFort = 2; nReflex = 2; nHP = 44; nAC = 6; nSkill = 17; } else if(nPerform >= 85 && nLevel >= 27) { nAttack = 2; nDamage = 3; nWill = 3; nFort = 2; nReflex = 2; nHP = 42; nAC = 6; nSkill = 16; } else if(nPerform >= 80 && nLevel >= 26) { nAttack = 2; nDamage = 3; nWill = 3; nFort = 2; nReflex = 2; nHP = 40; nAC = 6; nSkill = 15; } else if(nPerform >= 75 && nLevel >= 25) { nAttack = 2; nDamage = 3; nWill = 3; nFort = 2; nReflex = 2; nHP = 38; nAC = 6; nSkill = 14; } else if(nPerform >= 70 && nLevel >= 24) { nAttack = 2; nDamage = 3; nWill = 3; nFort = 2; nReflex = 2; nHP = 36; nAC = 5; nSkill = 13; } else if(nPerform >= 65 && nLevel >= 23) { nAttack = 2; nDamage = 3; nWill = 3; nFort = 2; nReflex = 2; nHP = 34; nAC = 5; nSkill = 12; } else if(nPerform >= 60 && nLevel >= 22) { nAttack = 2; nDamage = 3; nWill = 3; nFort = 2; nReflex = 2; nHP = 32; nAC = 5; nSkill = 11; } else if(nPerform >= 55 && nLevel >= 21) { nAttack = 2; nDamage = 3; nWill = 3; nFort = 2; nReflex = 2; nHP = 30; nAC = 5; nSkill = 9; } else if(nPerform >= 50 && nLevel >= 20) { nAttack = 2; nDamage = 3; nWill = 3; nFort = 2; nReflex = 2; nHP = 28; nAC = 5; nSkill = 8; } else if(nPerform >= 45 && nLevel >= 19) { nAttack = 2; nDamage = 3; nWill = 3; nFort = 2; nReflex = 2; nHP = 26; nAC = 5; nSkill = 7; } else if(nPerform >= 40 && nLevel >= 18) { nAttack = 2; nDamage = 3; nWill = 3; nFort = 2; nReflex = 2; nHP = 24; nAC = 5; nSkill = 6; } else if(nPerform >= 35 && nLevel >= 17) { nAttack = 2; nDamage = 3; nWill = 3; nFort = 2; nReflex = 2; nHP = 22; nAC = 5; nSkill = 5; } else if(nPerform >= 30 && nLevel >= 16) { nAttack = 2; nDamage = 3; nWill = 3; nFort = 2; nReflex = 2; nHP = 20; nAC = 5; nSkill = 4; } else if(nPerform >= 24 && nLevel >= 15) { nAttack = 2; nDamage = 3; nWill = 2; nFort = 2; nReflex = 2; nHP = 16; nAC = 4; nSkill = 3; } else if(nPerform >= 21 && nLevel >= 14) { nAttack = 2; nDamage = 3; nWill = 1; nFort = 1; nReflex = 1; nHP = 16; nAC = 3; nSkill = 2; } else if(nPerform >= 18 && nLevel >= 11) { nAttack = 2; nDamage = 2; nWill = 1; nFort = 1; nReflex = 1; nHP = 8; nAC = 2; nSkill = 2; } else if(nPerform >= 15 && nLevel >= 8) { nAttack = 2; nDamage = 2; nWill = 1; nFort = 1; nReflex = 1; nHP = 8; nAC = 0; nSkill = 1; } else if(nPerform >= 12 && nLevel >= 6) { nAttack = 1; nDamage = 2; nWill = 1; nFort = 1; nReflex = 1; nHP = 0; nAC = 0; nSkill = 1; } else if(nPerform >= 9 && nLevel >= 3) { nAttack = 1; nDamage = 2; nWill = 1; nFort = 1; nReflex = 0; nHP = 0; nAC = 0; nSkill = 0; } else if(nPerform >= 6 && nLevel >= 2) { nAttack = 1; nDamage = 1; nWill = 1; nFort = 0; nReflex = 0; nHP = 0; nAC = 0; nSkill = 0; } else if(nPerform >= 3 && nLevel >= 1) { nAttack = 1; nDamage = 1; nWill = 0; nFort = 0; nReflex = 0; nHP = 0; nAC = 0; nSkill = 0; } effect eVis = EffectVisualEffect(VFX_DUR_BARD_SONG); effect eLink; eAttack = EffectAttackIncrease(nAttack); eDamage = EffectDamageIncrease(nDamage, DAMAGE_TYPE_BLUDGEONING); if(GetLocalInt(OBJECT_SELF, "DragonFireInspOn")) { eLink = EffectVisualEffect(VFX_DUR_CESSATE_POSITIVE); } else { effect eDur = EffectVisualEffect(VFX_DUR_CESSATE_POSITIVE); eLink = EffectLinkEffects(eAttack, eDamage); eLink = EffectLinkEffects(eLink, eDur); } if(nWill > 0) { eWill = EffectSavingThrowIncrease(SAVING_THROW_WILL, nWill); eLink = EffectLinkEffects(eLink, eWill); } if(nFort > 0) { eFort = EffectSavingThrowIncrease(SAVING_THROW_FORT, nFort); eLink = EffectLinkEffects(eLink, eFort); } if(nReflex > 0) { eReflex = EffectSavingThrowIncrease(SAVING_THROW_REFLEX, nReflex); eLink = EffectLinkEffects(eLink, eReflex); } if(nHP > 0) { //SpeakString("HP Bonus " + IntToString(nHP)); eHP = EffectTemporaryHitpoints(nHP); // eLink = EffectLinkEffects(eLink, eHP); } if(nAC > 0) { eAC = EffectACIncrease(nAC, AC_DODGE_BONUS); eLink = EffectLinkEffects(eLink, eAC); } if(nSkill > 0) { eSkill = EffectSkillIncrease(SKILL_ALL_SKILLS, nSkill); eLink = EffectLinkEffects(eLink, eSkill); } effect eImpact = EffectVisualEffect(VFX_IMP_HEAD_SONIC); effect eFNF = EffectVisualEffect(VFX_FNF_LOS_NORMAL_30); ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eFNF, GetLocation(OBJECT_SELF)); object oTarget = MyFirstObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_COLOSSAL, GetLocation(OBJECT_SELF)); eHP = ExtraordinaryEffect(eHP); eLink = ExtraordinaryEffect(eLink); int nRace; while(GetIsObjectValid(oTarget)) { // * GZ Oct 2003: If we are silenced, we can not benefit from bard song if (!PRCGetHasEffect(EFFECT_TYPE_SILENCE,oTarget) && !PRCGetHasEffect(EFFECT_TYPE_DEAF,oTarget)) { RemoveSongEffects(GetSpellId(),OBJECT_SELF,oTarget); nRace = MyPRCGetRacialType(oTarget); // Undead and Constructs are immune to mind effecting abilities. // A bard with requiem can effect undead if ((nRace == RACIAL_TYPE_UNDEAD && GetHasFeat(FEAT_REQUIEM, OBJECT_SELF)) || (nRace != RACIAL_TYPE_UNDEAD && nRace != RACIAL_TYPE_CONSTRUCT) || GetIsWarforged(oTarget)) { // Even with requiem, they have half duration if (nRace == RACIAL_TYPE_UNDEAD) nDuration /= 2; if(oTarget == OBJECT_SELF) { effect eLinkBard = EffectLinkEffects(eLink, eVis); eLinkBard = ExtraordinaryEffect(eLinkBard); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLinkBard, oTarget, RoundsToSeconds(nDuration)); //StoreSongRecipient(oTarget, OBJECT_SELF, GetSpellId(), nDuration); if (nHP > 0) { ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eHP, oTarget, RoundsToSeconds(nDuration)); } if(GetLocalInt(OBJECT_SELF, "DragonFireInspOn")) { ApplyDragonfire(nAttack, nDuration, OBJECT_SELF, OBJECT_SELF); } } else if(GetIsFriend(oTarget)) { ApplyEffectToObject(DURATION_TYPE_INSTANT, eImpact, oTarget); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oTarget, RoundsToSeconds(nDuration)); //StoreSongRecipient(oTarget, OBJECT_SELF, GetSpellId(), nDuration); if (nHP > 0) { ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eHP, oTarget, RoundsToSeconds(nDuration)); } if(GetLocalInt(OBJECT_SELF, "DragonFireInspOn")) { ApplyDragonfire(nAttack, nDuration, oTarget, OBJECT_SELF); } } } } oTarget = MyNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_COLOSSAL, GetLocation(OBJECT_SELF)); } //:: Crystal Echoblade effect eEffect = GetFirstEffect(OBJECT_SELF); //:: Prevent stacking while(GetIsEffectValid(eEffect)) { if(GetEffectTag(eEffect) == "Echoblade") RemoveEffect(OBJECT_SELF, eEffect); eEffect = GetNextEffect(OBJECT_SELF); } if(IPGetHasItemPropertyByConst(ITEM_PROPERTY_ECHOBLADE, GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, OBJECT_SELF)) || //:: 104/*ITEM_PROPERTY_ECHOBLADE*/ (IPGetHasItemPropertyByConst(ITEM_PROPERTY_ECHOBLADE, GetItemInSlot(INVENTORY_SLOT_LEFTHAND, OBJECT_SELF)))) { int nSonic = IPGetDamageBonusConstantFromNumber(nLevel / 2); effect eEchoblade = EffectDamageIncrease(nSonic, DAMAGE_TYPE_SONIC); eEchoblade = ExtraordinaryEffect(eEchoblade); eEchoblade = TagEffect(eEchoblade, "Echoblade"); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eEchoblade, OBJECT_SELF, RoundsToSeconds(nDuration)); } }