![]() |
|
#1
|
||||
|
||||
|
Currently I'm using these scripts to implement strikes for my Tome of Battle project, but I thought they might be useful to anyone trying to implement "Smite Evil" type feats or possibly spells that involve melee attacks. Essentially, these scripts rebuild the combat engine right down to the last detail (or at least I'd like them to). Haven't quite gotten my OnHit effects implemented yet, but that's due to laziness more than anything else.
I run them out of an indexing feat for the ToB, but using a standard active feat should suffice. Remember to set the CastAnim in spells 2da to 'attack'. For attack rolls, I use a modified version of Mithdradates's GetMaxAB on the Helpful Scripts thread in the NWN2 forums. Keep in mind that some of these have ToB specific stuff which should be commented out. Let's start with some includes: Code:
//Function to determine the size of the weapon being used by the creature
int GetWeaponSize(object oCreature=OBJECT_SELF)
{
object oWeapon;
if (GetObjectType(oCreature)==OBJECT_TYPE_CREATURE)
oWeapon=GetItemInSlot(INVENTORY_SLOT_RIGHTHAND,oCreature);
else
oWeapon=oCreature;
if (!GetIsObjectValid(oWeapon)) return WEAPON_SIZE_INVALID;
if (GetBaseItemType(oWeapon)==BASE_ITEM_DAGGER) return WEAPON_SIZE_TINY;
if (GetBaseItemType(oWeapon)==BASE_ITEM_DART) return WEAPON_SIZE_TINY;
if (GetBaseItemType(oWeapon)==BASE_ITEM_FALCHION) return WEAPON_SIZE_LARGE;
if (GetBaseItemType(oWeapon)==BASE_ITEM_GREATAXE) return WEAPON_SIZE_LARGE;
if (GetBaseItemType(oWeapon)==BASE_ITEM_GREATSWORD) return WEAPON_SIZE_LARGE;
if (GetBaseItemType(oWeapon)==BASE_ITEM_HALBERD) return WEAPON_SIZE_LARGE;
if (GetBaseItemType(oWeapon)==BASE_ITEM_HANDAXE) return WEAPON_SIZE_SMALL;
if (GetBaseItemType(oWeapon)==BASE_ITEM_HEAVYCROSSBOW) return WEAPON_SIZE_LARGE;
if (GetBaseItemType(oWeapon)==BASE_ITEM_KAMA) return WEAPON_SIZE_TINY;
if (GetBaseItemType(oWeapon)==BASE_ITEM_KUKRI) return WEAPON_SIZE_TINY;
if (GetBaseItemType(oWeapon)==BASE_ITEM_LIGHTHAMMER) return WEAPON_SIZE_SMALL;
if (GetBaseItemType(oWeapon)==BASE_ITEM_LONGBOW) return WEAPON_SIZE_LARGE;
if (GetBaseItemType(oWeapon)==BASE_ITEM_LIGHTMACE) return WEAPON_SIZE_SMALL;
if (GetBaseItemType(oWeapon)==BASE_ITEM_MAGICSTAFF) return WEAPON_SIZE_LARGE;
if (GetBaseItemType(oWeapon)==BASE_ITEM_QUARTERSTAFF) return WEAPON_SIZE_LARGE;
if (GetBaseItemType(oWeapon)==BASE_ITEM_SCYTHE) return WEAPON_SIZE_LARGE;
if (GetBaseItemType(oWeapon)==BASE_ITEM_SHORTSWORD) return WEAPON_SIZE_SMALL;
if (GetBaseItemType(oWeapon)==BASE_ITEM_SHURIKEN) return WEAPON_SIZE_TINY;
if (GetBaseItemType(oWeapon)==BASE_ITEM_SICKLE) return WEAPON_SIZE_SMALL;
if (GetBaseItemType(oWeapon)==BASE_ITEM_SLING) return WEAPON_SIZE_SMALL;
if (GetBaseItemType(oWeapon)==BASE_ITEM_SPEAR) return WEAPON_SIZE_LARGE;
if (GetBaseItemType(oWeapon)==BASE_ITEM_THROWINGAXE) return WEAPON_SIZE_SMALL;
if (GetBaseItemType(oWeapon)==BASE_ITEM_WARMACE) return WEAPON_SIZE_LARGE;
return WEAPON_SIZE_MEDIUM;
}
//Function to determine whether a creature is using a two-handed weapon
int IsWeaponTwoHanded(object oCreature=OBJECT_SELF)
{
object oWeapon = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oCreature);
if ((GetHasFeat(FEAT_MONKEY_GRIP, oCreature) && GetIsObjectValid(oWeapon)))
{
return FALSE;
}
else if (GetWeaponSize(oCreature) >= GetCreatureSize(oCreature) && !GetIsObjectValid(oWeapon))
{
return TRUE;
}
else return FALSE;
}
//Function to determine whether a creature is using a ranged weapon
int IsWeaponRanged(object oCreature=OBJECT_SELF)
{
object oWeapon=GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oCreature);
if (GetWeaponRanged(oWeapon)) return TRUE;
return FALSE;
}
// Determines how wide across the target is in feet.
// This is more of a practical way to determine squares than it is real size.
float GetGirth(object oTarget)
{
int nSize = GetCreatureSize(oTarget);
float fGirth;
switch (nSize)
{
case CREATURE_SIZE_INVALID: fGirth = 0.0f; break;
case CREATURE_SIZE_TINY: fGirth = FeetToMeters(2.5f); break;
case CREATURE_SIZE_SMALL: fGirth = FeetToMeters(3.5f); break;
case CREATURE_SIZE_MEDIUM: fGirth = FeetToMeters(5.0f); break;
case CREATURE_SIZE_LARGE: fGirth = FeetToMeters(10.0f); break;
case CREATURE_SIZE_HUGE: fGirth = FeetToMeters(15.0f); break;
default: fGirth = FeetToMeters(20.0f); break;
}
return fGirth;
}
// Determines if the PC is flanking the target or not. Returns TRUE if they are.
int IsFlankValid(object oPC, object oTarget)
{
object oFlanker;
float FoeGirth = GetGirth(oTarget);
float FlankerGirth;
float fDistance;
float fMaxFlankDistance;
int nFlank = FALSE;
oFlanker = GetFirstFactionMember(oPC);
FlankerGirth = GetGirth(oFlanker);
fMaxFlankDistance = FoeGirth + FlankerGirth;
fDistance = GetDistanceBetween(oPC, oFlanker);
while (GetIsObjectValid(oFlanker))
{
if ((fDistance > FoeGirth) && (fDistance < fMaxFlankDistance))
{
if (GetAttackTarget(oFlanker) == oTarget)
{
nFlank = TRUE;
return nFlank;
}
else oFlanker = GetNextFactionMember(oPC);
}
else oFlanker = GetNextFactionMember(oPC);
FlankerGirth = GetGirth(oFlanker);
fMaxFlankDistance = FoeGirth + FlankerGirth;
fDistance = GetDistanceBetween(oPC, oFlanker);
}
return nFlank;
}
Code:
#include "x2_inc_itemprop"
//Function to get the AB of the object oCreature
int GetMaxAB(object oCreature, object oWeapon, object oTarget)
{
string sMartialJournal = GetFirstName(oCreature) + "martial_journal";
object oMartialJournal = GetObjectByTag(sMartialJournal);
object oOffHand = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oCreature);
int iAB = GetBaseAttackBonus(oCreature);
int iAttackDecrease = 0;
int nWeapon = GetBaseItemType(oWeapon);
int nWFFeat = StringToInt(Get2DAString("baseitems", "FEATWpnFocus", nWeapon));
int nGWFFeat = StringToInt(Get2DAString("baseitems", "FEATGrtrWpnFocus", nWeapon));
int nEWFFeat = StringToInt(Get2DAString("baseitems", "FEATEpicWpnFocus", nWeapon));
int nWoCFeat = StringToInt(Get2DAString("baseitems", "FEATWpnOfChoice", nWeapon));
// Flanking Bonuses
if (IsFlankValid(oCreature, oTarget) == TRUE)
{
iAB += 2;
if (GetHasFeat(FEAT_TW_SUPERIOR_FLANK, oCreature) == TRUE)
{
iAB += 2;
}
if (GetHasFeat(2142, oCreature) == TRUE) // Improved Flanking
{
iAB +=2;
}
}
// Add ability modifier
if (GetWeaponRanged(oWeapon))
{
if (GetHasFeat(FEAT_ZEN_ARCHERY, oCreature, TRUE) && GetAbilityModifier(ABILITY_WISDOM, oCreature) > GetAbilityModifier(ABILITY_DEXTERITY, oCreature))
{
iAB = iAB + GetAbilityModifier(ABILITY_WISDOM, oCreature);
}
else iAB = iAB + GetAbilityModifier(ABILITY_DEXTERITY, oCreature);
if ((GetDistanceToObject(oTarget) < FeetToMeters(15.0f)) && (GetHasFeat(FEAT_POINT_BLANK_SHOT, oCreature) == FALSE))
{
iAttackDecrease += 4;
}
}
else
{
if (GetHasFeat(FEAT_WEAPON_FINESSE, oCreature, TRUE) && GetAbilityModifier(ABILITY_DEXTERITY,oCreature) > GetAbilityModifier(ABILITY_STRENGTH, oCreature) && (GetWeaponSize(oCreature)<=WEAPON_SIZE_SMALL || nWeapon == BASE_ITEM_RAPIER))
{
iAB = iAB + GetAbilityModifier(ABILITY_DEXTERITY,oCreature);
}
else iAB=iAB+GetAbilityModifier(ABILITY_STRENGTH, oCreature);
}
// Add weapon size and dual wielding effects
if (GetIsObjectValid(oOffHand) && GetWeaponSize(oCreature) > GetCreatureSize(oCreature) || GetWeaponSize(oCreature) > GetCreatureSize(oCreature)+1) iAB=iAB-2;
if (GetIsObjectValid(oOffHand) && GetBaseItemType(oOffHand)!= BASE_ITEM_SMALLSHIELD && GetBaseItemType(oOffHand)!= BASE_ITEM_LARGESHIELD)
{
if (GetBaseItemType(oOffHand) == BASE_ITEM_TOWERSHIELD) iAB=iAB-2;
if (GetHasFeat(FEAT_EPIC_PERFECT_TWO_WEAPON_FIGHTING, oCreature, TRUE))
{
iAB=iAB-0;
}
else if (GetHasFeat(FEAT_TWO_WEAPON_FIGHTING, oCreature, TRUE) || GetHasFeat(FEAT_COMBATSTYLE_RANGER_DUAL_WIELD_TWO_WEAPON_FIGHTING, oCreature, TRUE))
{
if (GetWeaponSize(oOffHand) < GetCreatureSize(oCreature)) iAB=iAB-2;
else iAB=iAB-4;
}
else
{
if (GetWeaponSize(oOffHand) < GetCreatureSize(oCreature)) iAB=iAB-4;
else iAB=iAB-6;
}
}
// Weapon feat effects
if (nWeapon == BASE_ITEM_LONGBOW)
{
if (GetHasFeat(FEAT_WEAPON_FOCUS_LONGBOW, oCreature, TRUE)) iAB=iAB+1;
if (GetHasFeat(FEAT_GREATER_WEAPON_FOCUS_LONGBOW, oCreature, TRUE)) iAB=iAB+1;
if (GetHasFeat(FEAT_EPIC_WEAPON_FOCUS_LONGBOW, oCreature, TRUE)) iAB=iAB+2;
if (GetHasFeat(FEAT_PRESTIGE_ENCHANT_ARROW_5, oCreature, TRUE)) iAB=iAB+5;
else if (GetHasFeat(FEAT_PRESTIGE_ENCHANT_ARROW_4, oCreature, TRUE)) iAB=iAB+4;
else if (GetHasFeat(FEAT_PRESTIGE_ENCHANT_ARROW_3, oCreature, TRUE)) iAB=iAB+3;
else if (GetHasFeat(FEAT_PRESTIGE_ENCHANT_ARROW_2, oCreature, TRUE)) iAB=iAB+2;
else if (GetHasFeat(FEAT_PRESTIGE_ENCHANT_ARROW_1, oCreature, TRUE)) iAB=iAB+1;
}
else if (nWeapon == BASE_ITEM_SHORTBOW)
{
if (GetHasFeat(FEAT_WEAPON_FOCUS_SHORTBOW, oCreature, TRUE)) iAB=iAB+1;
if (GetHasFeat(FEAT_GREATER_WEAPON_FOCUS_SHORTBOW, oCreature, TRUE)) iAB=iAB+1;
if (GetHasFeat(FEAT_EPIC_WEAPON_FOCUS_SHORTBOW, oCreature, TRUE)) iAB=iAB+2;
if (GetHasFeat(FEAT_PRESTIGE_ENCHANT_ARROW_5, oCreature, TRUE)) iAB=iAB+5;
else if (GetHasFeat(FEAT_PRESTIGE_ENCHANT_ARROW_4, oCreature, TRUE)) iAB=iAB+4;
else if (GetHasFeat(FEAT_PRESTIGE_ENCHANT_ARROW_3, oCreature, TRUE)) iAB=iAB+3;
else if (GetHasFeat(FEAT_PRESTIGE_ENCHANT_ARROW_2, oCreature, TRUE)) iAB=iAB+2;
else if (GetHasFeat(FEAT_PRESTIGE_ENCHANT_ARROW_1, oCreature, TRUE)) iAB=iAB+1;
}
else if (nWeapon == BASE_ITEM_SHURIKEN)
{
if (GetHasFeat(FEAT_WEAPON_FOCUS_SHURIKEN, oCreature, TRUE)) iAB=iAB+1;
if (GetHasFeat(FEAT_GREATER_WEAPON_FOCUS_SHURIKEN, oCreature, TRUE)) iAB=iAB+1;
if (GetHasFeat(FEAT_EPIC_WEAPON_FOCUS_SHURIKEN, oCreature, TRUE)) iAB=iAB+2;
if (GetHasFeat(FEAT_GOOD_AIM, oCreature, TRUE)) iAB=iAB+1;
}
else if (nWeapon == BASE_ITEM_SLING)
{
if (GetHasFeat(FEAT_WEAPON_FOCUS_SLING, oCreature, TRUE)) iAB=iAB+1;
if (GetHasFeat(FEAT_GREATER_WEAPON_FOCUS_SLING, oCreature, TRUE)) iAB=iAB+1;
if (GetHasFeat(FEAT_EPIC_WEAPON_FOCUS_SLING, oCreature, TRUE)) iAB=iAB+2;
if (GetHasFeat(FEAT_GOOD_AIM, oCreature, TRUE)) iAB=iAB+1;
}
else if (nWeapon == BASE_ITEM_THROWINGAXE)
{
if (GetHasFeat(FEAT_WEAPON_FOCUS_THROWING_AXE, oCreature, TRUE)) iAB=iAB+1;
if (GetHasFeat(FEAT_GREATER_WEAPON_FOCUS_THROWINGAXE, oCreature, TRUE)) iAB=iAB+1;
if (GetHasFeat(FEAT_EPIC_WEAPON_FOCUS_THROWINGAXE, oCreature, TRUE)) iAB=iAB+2;
if (GetHasFeat(FEAT_GOOD_AIM, oCreature, TRUE)) iAB=iAB+1;
}
else if (GetIsObjectValid(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oCreature)))
{
if (GetHasFeat(nWFFeat, oCreature, TRUE)) iAB=iAB+1;
if (GetHasFeat(nGWFFeat, oCreature, TRUE)) iAB=iAB+1;
if (GetHasFeat(nEWFFeat, oCreature, TRUE)) iAB=iAB+2;
if (GetHasFeat(nWoCFeat, oCreature, TRUE) && GetHasFeat(FEAT_SUPERIOR_WEAPON_FOCUS, oCreature, TRUE)) iAB=iAB+1;
if (GetHasFeat(nWoCFeat, oCreature, TRUE) && GetHasFeat(FEAT_EPIC_SUPERIOR_WEAPON_FOCUS, oCreature, TRUE)) iAB=iAB+1;
if (GetHasFeat(nWoCFeat, oCreature, TRUE) && GetHasFeat(FEAT_EPIC_SUPERIOR_WEAPON_FOCUS, oCreature, TRUE) && (GetLevelByClass(CLASS_TYPE_WEAPON_MASTER) > 15)) iAB=iAB+1;
if (GetHasFeat(nWoCFeat, oCreature, TRUE) && GetHasFeat(FEAT_EPIC_SUPERIOR_WEAPON_FOCUS, oCreature, TRUE) && (GetLevelByClass(CLASS_TYPE_WEAPON_MASTER) > 18)) iAB=iAB+1;
}
else if (GetIsObjectValid(GetItemInSlot(INVENTORY_SLOT_CWEAPON_L, oCreature))||GetIsObjectValid(GetItemInSlot(INVENTORY_SLOT_CWEAPON_B,oCreature))||GetIsObjectValid(GetItemInSlot(INVENTORY_SLOT_CWEAPON_R,oCreature)))
{
if (GetHasFeat(FEAT_WEAPON_FOCUS_CREATURE, oCreature, TRUE)) iAB=iAB+1;
if (GetHasFeat(FEAT_GREATER_WEAPON_FOCUS_CREATURE, oCreature, TRUE)) iAB=iAB+1;
if (GetHasFeat(FEAT_EPIC_WEAPON_FOCUS_CREATURE, oCreature, TRUE)) iAB=iAB+2;
oWeapon = GetItemInSlot(INVENTORY_SLOT_CWEAPON_R, oCreature);
if (GetIsObjectValid(oWeapon)==FALSE) oWeapon=GetItemInSlot(INVENTORY_SLOT_CWEAPON_L,oCreature);
if (GetIsObjectValid(oWeapon)==FALSE) oWeapon=GetItemInSlot(INVENTORY_SLOT_CWEAPON_B,oCreature);
}
else
{
if (GetHasFeat(FEAT_WEAPON_FOCUS_UNARMED_STRIKE, oCreature, TRUE)) iAB=iAB+1;
if (GetHasFeat(FEAT_GREATER_WEAPON_FOCUS_UNARMED, oCreature, TRUE)) iAB=iAB+1;
if (GetHasFeat(FEAT_EPIC_WEAPON_FOCUS_UNARMED, oCreature, TRUE)) iAB=iAB+2;
}
if ((GetIsFavoredEnemy(oCreature, oTarget) == TRUE) && (GetHasFeat(FEAT_EPIC_BANE_OF_ENEMIES, oCreature) == TRUE))
{
iAB += 2;
}
if (GetHasFeat(FEAT_EPIC_PROWESS, oCreature) == TRUE)
{
iAB += 1;
}
if ((GetHasFeat(2103, oCreature) == TRUE) && (nWeapon != OBJECT_TYPE_INVALID)) // Sarced Fist Code of Conduct
{
iAttackDecrease += 8;
}
// Mode Effects
if (GetActionMode(oCreature, ACTION_MODE_POWER_ATTACK) == TRUE)
{
iAttackDecrease += 3;
}
else if (GetActionMode(oCreature, ACTION_MODE_IMPROVED_POWER_ATTACK) == TRUE)
{
iAttackDecrease += 6;
}
if (GetActionMode(oCreature, ACTION_MODE_COMBAT_EXPERTISE) == TRUE)
{
iAttackDecrease += 3;
}
else if (GetActionMode(oCreature, ACTION_MODE_IMPROVED_COMBAT_EXPERTISE) == TRUE)
{
iAttackDecrease += 6;
}
if (GetActionMode(oCreature, ACTION_MODE_FLURRY_OF_BLOWS) == TRUE)
{
if ((GetLevelByClass(CLASS_TYPE_MONK)) + (GetLevelByClass(CLASS_TYPE_SACREDFIST)) < 5)
{
iAttackDecrease += 2;
}
else if ((GetLevelByClass(CLASS_TYPE_MONK)) + (GetLevelByClass(CLASS_TYPE_SACREDFIST)) < 10)
{
iAttackDecrease += 1;
}
}
if (GetActionMode(oCreature, ACTION_MODE_RAPID_SHOT) == TRUE)
{
if (GetHasFeat(FEAT_IMPROVED_RAPID_SHOT) == TRUE)
{
iAttackDecrease += 0;
}
else iAttackDecrease += 2;
}
if (GetLocalInt(oMartialJournal, "SnapKick") == 1)
{
iAttackDecrease += 2;
}
// Misc Effects and Enchantment
int iWeaponEnhancement = 0;
itemproperty ipAB = GetFirstItemProperty(oWeapon);
while (GetIsItemPropertyValid(ipAB))
{
if (GetItemPropertyType(ipAB) == ITEM_PROPERTY_ENHANCEMENT_BONUS || GetItemPropertyType(ipAB) == ITEM_PROPERTY_ATTACK_BONUS)
{
iWeaponEnhancement = iWeaponEnhancement + GetItemPropertyCostTableValue(ipAB);
}
else if (GetItemPropertyType(ipAB) == ITEM_PROPERTY_ENHANCEMENT_BONUS_VS_ALIGNMENT_GROUP || GetItemPropertyType(ipAB) == ITEM_PROPERTY_ATTACK_BONUS_VS_ALIGNMENT_GROUP)
{
int nGoodEvil = GetAlignmentGoodEvil(oTarget);
int nLawChaos = GetAlignmentLawChaos(oTarget);
if ((GetItemPropertySubType(ipAB) == nGoodEvil) || (GetItemPropertySubType(ipAB) == nLawChaos))
{
iWeaponEnhancement = iWeaponEnhancement + GetItemPropertyCostTableValue(ipAB);
}
}
else if (GetItemPropertyType(ipAB) == ITEM_PROPERTY_ENHANCEMENT_BONUS_VS_RACIAL_GROUP || GetItemPropertyType(ipAB) == ITEM_PROPERTY_ATTACK_BONUS_VS_RACIAL_GROUP)
{
int nTargetRace = GetRacialType(oTarget);
if (GetItemPropertySubType(ipAB) == nTargetRace)
{
iWeaponEnhancement = iWeaponEnhancement + GetItemPropertyCostTableValue(ipAB);
}
}
else if (GetItemPropertyType(ipAB) == ITEM_PROPERTY_ENHANCEMENT_BONUS_VS_SPECIFIC_ALIGNEMENT || GetItemPropertyType(ipAB) == ITEM_PROPERTY_ATTACK_BONUS_VS_SPECIFIC_ALIGNMENT)
{
int nAlignment = GetAlignment(oTarget);
if (GetItemPropertySubType(ipAB) == nAlignment)
{
iWeaponEnhancement = iWeaponEnhancement + GetItemPropertyCostTableValue(ipAB);
}
}
else if (GetItemPropertyType(ipAB) == ITEM_PROPERTY_DECREASED_ENHANCEMENT_MODIFIER || GetItemPropertyType(ipAB) == ITEM_PROPERTY_DECREASED_ATTACK_MODIFIER)
{
iAttackDecrease = iAttackDecrease + GetItemPropertyCostTableValue(ipAB);
}
ipAB=GetNextItemProperty(oWeapon);
}
if (!GetIsObjectValid(oWeapon)) // love for monks
{
object oArms = GetItemInSlot(INVENTORY_SLOT_ARMS);
itemproperty iArm = GetFirstItemProperty(oArms);
while (GetIsItemPropertyValid(iArm))
{
if (GetItemPropertyType(iArm) == ITEM_PROPERTY_ATTACK_BONUS)
{
iWeaponEnhancement = iWeaponEnhancement + GetItemPropertyCostTableValue(iArm);
}
else if (GetItemPropertyType(iArm) == ITEM_PROPERTY_DECREASED_ATTACK_MODIFIER)
{
iAttackDecrease = iAttackDecrease + GetItemPropertyCostTableValue(iArm);
}
iArm = GetNextItemProperty(oArms);
}
}
effect eAB = GetFirstEffect(oCreature);
while (GetIsEffectValid(eAB))
{
if (GetEffectType(eAB) == EFFECT_TYPE_ATTACK_INCREASE)
{
iWeaponEnhancement = iWeaponEnhancement + GetEffectInteger(eAB, 0);
}
else if (GetEffectType(eAB) == EFFECT_TYPE_ATTACK_DECREASE)
{
iAttackDecrease = iAttackDecrease + GetEffectInteger(eAB, 0);
}
eAB = GetNextEffect(oCreature);
}
iAB = iAB + iWeaponEnhancement - iAttackDecrease;
return iAB;
}
Code:
// Returns the low end of the critical range for the weapon the caller of the
// function has equipped.
int GetCriticalRange(object oWeapon)
{
object oPC = OBJECT_SELF;
int nWeapon = GetBaseItemType(oWeapon);
int nBaseRange = StringToInt(Get2DAString("baseitems", "CritThreat", nWeapon));
int nImprCrit = StringToInt(Get2DAString("baseitems", "FEATImprCrit", nWeapon));
int nNoStack = 0;
int nSubtract;
int nRange;
// Base crit range of the weapon.
if (nBaseRange == 1)
{
nSubtract += 0;
}
else if (nBaseRange == 2)
{
nSubtract += 1;
}
else if (nBaseRange == 3)
{
nSubtract += 2;
}
// Ki Critical feat for Weapon Masters.
if (GetHasFeat(FEAT_KI_CRITICAL))
{
int nWoC = StringToInt(Get2DAString("baseitems", "FEATWpnOfChoice", nWeapon));
if (GetHasFeat(nWoC))
{
nSubtract += 2;
}
}
// Properties that don't stack together.
if (GetItemHasItemProperty(oWeapon, ITEM_PROPERTY_KEEN) && (nNoStack == 0))
{
if (nBaseRange == 1)
{
nSubtract += 1;
nNoStack = 1;
}
else if (nBaseRange == 2)
{
nSubtract += 2;
nNoStack = 1;
}
else if (nBaseRange == 3)
{
nSubtract += 3;
nNoStack = 1;
}
}
if ((GetHasFeat(nImprCrit)) && (nNoStack == 0))
{
if (nBaseRange == 1)
{
nSubtract += 1;
nNoStack = 1;
}
else if (nBaseRange == 2)
{
nSubtract += 2;
nNoStack = 1;
}
else if (nBaseRange == 3)
{
nSubtract += 3;
nNoStack = 1;
}
}
if ((GetHasSpellEffect(SPELL_KEEN_EDGE) || GetHasSpellEffect(SPELL_WEAPON_OF_IMPACT)))
{
if (nNoStack == 0)
{
if (nBaseRange == 1)
{
nSubtract += 1;
nNoStack = 1;
}
else if (nBaseRange == 2)
{
nSubtract += 2;
nNoStack = 1;
}
else if (nBaseRange == 3)
{
nSubtract += 3;
nNoStack = 1;
}
}
}
nRange = 20 - nSubtract;
return nRange;
}
// Returns any bonuses to critical confirmation rolls.
int GetCriticalConfirmMod(object oWeapon)
{
object oPC = OBJECT_SELF;
int nWeapon = GetBaseItemType(oWeapon);
int nPowerCrit = StringToInt(Get2DAString("baseitems", "FEATPowerCrit", nWeapon));
int nConfirm;
if (GetHasFeat(nPowerCrit))
{
nConfirm += 4;
}
if (GetHasFeat(FEAT_BATTLE_ARDOR))
{
int nMyInt = GetAbilityModifier(ABILITY_INTELLIGENCE);
int nMyWBLevel = GetLevelByClass(CLASS_TYPE_WARBLADE);
if (nMyInt >= nMyWBLevel)
{
nConfirm += nMyWBLevel;
}
else nConfirm += nMyInt;
}
return nConfirm;
}
// Returns the critical multiplier of oWeapon.
int GetCriticalMultiplier(object oWeapon)
{
object oPC = OBJECT_SELF;
int nWeapon = GetBaseItemType(oWeapon);
int nCritMult = StringToInt(Get2DAString("baseitems", "CritHitMult", nWeapon));
if (GetHasFeat(FEAT_INCREASE_MULTIPLIER) == TRUE)
{
nCritMult += 1;
}
return nCritMult;
}
Code:
// Determines the result of an attack roll for strikes.
// 0 = Miss, 1 = Hit, 2 = Critical Hit.
// -oWeapon: The weapon to make an attack roll with.
// -oFoe: The the target being attacked with oWeapon.
int StrikeAttackRoll(object oWeapon, object oFoe)
{
object oPC = OBJECT_SELF;
string sMartialJournal = GetFirstName(oPC) + "martial_journal";
object oMartialJournal = GetObjectByTag(sMartialJournal);
int nFoeAC = GetAC(oFoe);
int nD20 = d20(1);
int nd20 = d20(1);
int nAB = GetMaxAB(oPC, oWeapon, oFoe);
int nCritRange = GetCriticalRange(oWeapon);
int nCritConfirmBonus = GetCriticalConfirmMod(oWeapon);
int nHit;
if (nD20 == 1)
{
nHit = 0;
}
else if ((nD20 == 20) && ((nd20 + nAB + nCritConfirmBonus) < nFoeAC))
{
nHit = 1;
}
else if ((nD20 == 20) && ((nd20 + nAB + nCritConfirmBonus) >= nFoeAC) && (GetIsImmune(oFoe, IMMUNITY_TYPE_CRITICAL_HIT) == TRUE))
{
nHit = 1;
}
else if ((nD20 == 20) && ((nd20 + nAB + nCritConfirmBonus) >= nFoeAC))
{
nHit = 2;
}
else if (IsTargetConcealed(oFoe, oPC) == TRUE)
{
effect eConcealment = GetFirstEffect(oFoe);
while (GetIsEffectValid(eConcealment))
{
if (GetEffectType(eConcealment) == EFFECT_TYPE_CONCEALMENT)
{
int nd100 = d100(1);
int nConcealed = GetEffectInteger(eConcealment, 0);
if ((GetHasFeat(FEAT_EPIC_SELF_CONCEALMENT_50, oFoe) == TRUE) && (nConcealed < 50))
{
if (nd100 < 50)
{
nHit = 0;
break;
}
}
else if ((GetHasFeat(FEAT_EPIC_SELF_CONCEALMENT_40, oFoe) == TRUE) && (nConcealed < 40))
{
if (nd100 < 40)
{
nHit = 0;
break;
}
}
else if ((GetHasFeat(FEAT_EPIC_SELF_CONCEALMENT_30, oFoe) == TRUE) && (nConcealed < 30))
{
if (nd100 < 30)
{
nHit = 0;
break;
}
}
else if ((GetHasFeat(FEAT_EPIC_SELF_CONCEALMENT_20, oFoe) == TRUE) && (nConcealed < 20))
{
if (nd100 < 20)
{
nHit = 0;
break;
}
}
else if ((GetHasFeat(FEAT_EPIC_SELF_CONCEALMENT_10, oFoe) == TRUE) && (nConcealed < 10))
{
if (nd100 < 10)
{
nHit = 0;
break;
}
}
else if (nd100 < nConcealed)
{
nHit = 0;
break;
}
else break;
}
eConcealment = GetNextEffect(oFoe);
}
}
else if ((nD20 >= nCritRange) && ((nD20 + nAB) >= nFoeAC) && ((nd20 + nAB + nCritConfirmBonus) >= nFoeAC) && (GetIsImmune(oFoe, IMMUNITY_TYPE_CRITICAL_HIT) == TRUE))
{
nHit = 1;
}
else if ((nD20 >= nCritRange) && ((nD20 + nAB) >= nFoeAC) && ((nd20 + nAB + nCritConfirmBonus) >= nFoeAC))
{
nHit = 2;
}
else if ((nD20 >= nCritRange) && ((nD20 + nAB) >= nFoeAC) && ((nd20 + nAB + nCritConfirmBonus) < nFoeAC))
{
nHit = 1;
}
else if ((nD20 < nCritRange) && ((nD20 + nAB) >= nFoeAC))
{
nHit = 1;
}
else nHit = 0;
return nHit;
}
Last edited by Drammel; 04-10-2009 at 03:37 AM. Reason: debugging |
|
#2
|
||||
|
||||
|
Let's move on to actual weapon damage. A lot of these are modified versions of Kaedrin's cmi_ginc_wpns and sneakattack files. It'll also incorperate my GetIsFlankValid function for determining sneak attacks. I apologize now if I'm forgetting some include files. I'm trying to post by type of functions here for convienience. Also, as a footnote, I'm using Sunjammer's itemproperty fixes to make the damamge vs "" functions work properly. They have some major bugs
. Edit: After talking a little with Sunjammer it appears that his itemproperty fixes were not responsible for my functions coming back to life. At the moment I'm still unsure what I did, but so long as the bug doesn't return I'm happy. For sneak attacks: Code:
// Checks a Player's current class levels to determine sneak attack and death attack dice.
int GetSneakAttackDice(object oSneakAttacker = OBJECT_SELF)
{
/* Drammel's note: Removed Kaedrin's classes not because they aren't excelent work,
but simply because they weren't intended for use in the Tome of Battle and I have
no idea how they would function if I attempted to integrate them with my scripts.
I am adapting these scripts for use in a way they were never intended so a
level of caution seems like a good plan.
Also, Assassin's Stance will run as a damage bonus effect and therefore should be
picked up by GenerateAttackEffect. No need to include it here. */
int nDice = 0;
int nClassLevel = 0;
nClassLevel = GetLevelByClass(CLASS_TYPE_ARCANETRICKSTER, oSneakAttacker);
if (nClassLevel > 1)
{
nDice = nDice + nClassLevel / 2;
}
nClassLevel = GetLevelByClass(CLASS_TYPE_ASSASSIN, oSneakAttacker);
if (nClassLevel > 0)
{
nDice = nDice + (nClassLevel + 1) / 2;
}
nClassLevel = GetLevelByClass(CLASS_TYPE_BLACKGUARD, oSneakAttacker);
if (nClassLevel > 3)
{
nDice = nDice + (nClassLevel - 1) / 3;
}
if (GetLevelByClass(CLASS_NWNINE_WARDER, oSneakAttacker) > 2)
{
nDice = nDice + 2;
}
nClassLevel = GetLevelByClass(CLASS_TYPE_ROGUE, oSneakAttacker);
if (nClassLevel > 0)
{
nDice = nDice + (nClassLevel + 1) / 2;
}
nClassLevel = GetLevelByClass(CLASS_TYPE_SHADOWTHIEFOFAMN, oSneakAttacker);
if (nClassLevel > 0)
{
nDice = nDice + (nClassLevel + 1) / 2;
}
if (GetHasFeat(FEAT_EPIC_IMPROVED_SNEAK_ATTACK_10))
{
nDice += 10;
}
else if (GetHasFeat(FEAT_EPIC_IMPROVED_SNEAK_ATTACK_9))
{
nDice += 9;
}
else if (GetHasFeat(FEAT_EPIC_IMPROVED_SNEAK_ATTACK_8))
{
nDice += 8;
}
else if (GetHasFeat(FEAT_EPIC_IMPROVED_SNEAK_ATTACK_7))
{
nDice += 7;
}
else if (GetHasFeat(FEAT_EPIC_IMPROVED_SNEAK_ATTACK_6))
{
nDice += 6;
}
else if (GetHasFeat(FEAT_EPIC_IMPROVED_SNEAK_ATTACK_5))
{
nDice += 5;
}
else if (GetHasFeat(FEAT_EPIC_IMPROVED_SNEAK_ATTACK_4))
{
nDice += 4;
}
else if (GetHasFeat(FEAT_EPIC_IMPROVED_SNEAK_ATTACK_3))
{
nDice += 3;
}
else if (GetHasFeat(FEAT_EPIC_IMPROVED_SNEAK_ATTACK_2))
{
nDice += 2;
}
else if (GetHasFeat(FEAT_EPIC_IMPROVED_SNEAK_ATTACK_1))
{
nDice += 1;
}
return nDice;
}
// Returns the number of levels oTarget has in a class that can sneak attack.
int GetSneakLevels(object oTarget)
{
int nClassLevel = 0;
int nSneakLevels = 0;
nClassLevel = GetLevelByClass(CLASS_TYPE_ARCANETRICKSTER, oTarget);
if (nClassLevel > 1)
{
nSneakLevels = nSneakLevels + nClassLevel;
}
nClassLevel = GetLevelByClass(CLASS_TYPE_ASSASSIN, oTarget);
if (nClassLevel > 0)
{
nSneakLevels = nSneakLevels + nClassLevel;
}
nClassLevel = GetLevelByClass(CLASS_TYPE_BLACKGUARD, oTarget);
if (nClassLevel > 3)
{
nSneakLevels = nSneakLevels + nClassLevel;
}
if (GetLevelByClass(CLASS_NWNINE_WARDER, oTarget) > 2)
{
nSneakLevels = nSneakLevels + nClassLevel;
}
nClassLevel = GetLevelByClass(CLASS_TYPE_ROGUE, oTarget);
if (nClassLevel > 0)
{
nSneakLevels = nSneakLevels + nClassLevel;
}
nClassLevel = GetLevelByClass(CLASS_TYPE_SHADOWTHIEFOFAMN, oTarget);
if (nClassLevel > 0)
{
nSneakLevels = nSneakLevels + nClassLevel;
}
return nSneakLevels;
}
// Determines if oTarget has concealment from oSneakAttacker.
int IsTargetConcealed(object oTarget, object oSneakAttacker)
{
int bIsConcealed = FALSE;
int bAttackerHasTrueSight = GetHasEffect(EFFECT_TYPE_TRUESEEING, oSneakAttacker);
int bAttackerCanSeeInvisble = GetHasEffect(EFFECT_TYPE_SEEINVISIBLE, oSneakAttacker);
int bAttackerUltraVision = GetHasEffect(EFFECT_TYPE_ULTRAVISION, oSneakAttacker);
if(GetHasFeat(FEAT_EPIC_SELF_CONCEALMENT_50, oTarget))
bIsConcealed = TRUE;
else if(GetHasFeat(FEAT_EPIC_SELF_CONCEALMENT_40, oTarget))
bIsConcealed = TRUE;
else if(GetHasFeat(FEAT_EPIC_SELF_CONCEALMENT_30, oTarget))
bIsConcealed = TRUE;
else if(GetHasFeat(FEAT_EPIC_SELF_CONCEALMENT_20, oTarget))
bIsConcealed = TRUE;
else if(GetHasFeat(FEAT_EPIC_SELF_CONCEALMENT_10, oTarget))
bIsConcealed = TRUE;
else if(!GetObjectSeen(oTarget, oSneakAttacker)) // Removed the mode check because initiating a strike seems to jump out of Stealth before the check is made.
bIsConcealed = TRUE;
else if(GetHasEffect(EFFECT_TYPE_SANCTUARY, oTarget) && !bAttackerHasTrueSight)
bIsConcealed = TRUE;
else if(GetHasEffect(EFFECT_TYPE_INVISIBILITY, oTarget) && !bAttackerHasTrueSight && !bAttackerCanSeeInvisble)
bIsConcealed = TRUE;
else if(GetHasEffect(EFFECT_TYPE_DARKNESS, oTarget) && !bAttackerHasTrueSight && !bAttackerUltraVision)
bIsConcealed = TRUE;
else if(GetHasFeatEffect(FEAT_EMPTY_BODY, oTarget))
bIsConcealed = TRUE;
else if(GetHasEffect(EFFECT_TYPE_ETHEREAL, oTarget) && !bAttackerHasTrueSight && !bAttackerCanSeeInvisble)
bIsConcealed = TRUE;
else if(GetHasEffect(EFFECT_TYPE_CONCEALMENT, oTarget) && !bAttackerHasTrueSight)
bIsConcealed = TRUE;
if (GetHasEffect(EFFECT_TYPE_CONCEALMENT_NEGATED, oTarget))
{
bIsConcealed = FALSE;
}
else if ((GetHasFeat(2031, oSneakAttacker) == TRUE) && (GetIsSpirit(oTarget) == TRUE)) // Ghost Warrior
{
bIsConcealed = FALSE;
}
return bIsConcealed;
}
// Sneak Attack can't be used against targets with concealment
int IsTargetValidForSneakAttack(object oTarget, object oSneakAttacker)
{
object oAttackedByTarget = GetAttackTarget(oTarget);
int nSneakLevels = GetSneakLevels(oSneakAttacker);
//Don't bother if the target is out of range
if (GetDistanceBetween(oSneakAttacker, oTarget) < FeetToMeters(30.0f))
{
//Don't bother if the target is concealed
if (IsTargetConcealed(oTarget, oSneakAttacker))
{
return FALSE;
}
if (GetHasFeat(FEAT_IMPROVED_UNCANNY_DODGE, oTarget, TRUE))
{
if (nSneakLevels > (GetSneakLevels(oTarget) + 3) ) // Need to be >= Target Dice + 4
{
return FALSE;
}
}
if (oAttackedByTarget == oSneakAttacker) //Head to Head requires the target be unable to defend themself
{
if (GetHasEffect(EFFECT_TYPE_STUNNED, oTarget) || GetHasEffect(EFFECT_TYPE_BLINDNESS, oTarget)
|| GetHasEffect(EFFECT_TYPE_PARALYZE, oTarget) || GetHasEffect(EFFECT_TYPE_SLEEP, oTarget)
|| GetHasEffect(EFFECT_TYPE_PETRIFY, oTarget) || GetHasEffect(EFFECT_TYPE_CUTSCENE_PARALYZE, oTarget))
{
return TRUE;
}
else return FALSE;
}
else if (IsTargetConcealed(oSneakAttacker, oTarget) == TRUE) // Sudden Strike is based on this incidentally.
{
return TRUE;
}
else if (IsFlankValid(oSneakAttacker, oTarget) == TRUE) //Listed as 'else if' because if we're already a target the flank doesn't matter.
{
return TRUE;
}
} // end distance check
return FALSE;
}
// Applies Sneak Attack Damage
effect SneakAttack(object oWeapon, object oPC, object oFoe)
{
string sMartialJournal = GetFirstName(oPC) + "martial_journal";
object oMartialJournal = GetObjectByTag(sMartialJournal);
int nBaseItemType = GetBaseItemType(oWeapon);
int nWeaponType = GetWeaponType(oWeapon);
int nSub = GetSubRace(oFoe);
int nDice = GetSneakAttackDice(oPC);
int nSneakAttack;
int nSlash;
int nPierce;
int nBlunt;
effect eSneakAttack;
nSneakAttack = d6(nDice);
// Get immuntiy and exceptions to immunity.
if (GetIsImmune(oFoe, IMMUNITY_TYPE_SNEAK_ATTACK, oPC) || GetIsImmune(oFoe, IMMUNITY_TYPE_CRITICAL_HIT, oPC))
{
if ((nSub == RACIAL_SUBTYPE_UNDEAD) && (GetHasFeat(2129, oPC) == TRUE)) // Death's Ruin
{
nSneakAttack = nSneakAttack / 2;
}
else if ((nSub == RACIAL_SUBTYPE_ELEMENTAL) && (GetHasFeat(2130, oPC) == TRUE)) // Elemental's Ruin
{
nSneakAttack = nSneakAttack / 2;
}
else if ((nSub == RACIAL_SUBTYPE_PLANT) && (GetHasFeat(2131, oPC) == TRUE)) // Nature's Ruin
{
nSneakAttack = nSneakAttack / 2;
}
else if ((GetIsSpirit(oFoe) == TRUE) && (GetHasFeat(2132, oPC) == TRUE)) // Spirit's Ruin
{
nSneakAttack = nSneakAttack / 2;
}
else if ((nSub == RACIAL_SUBTYPE_CONSTRUCT) && (GetHasFeat(2133, oPC) == TRUE)) // Builder's Ruin
{
nSneakAttack = nSneakAttack / 2;
}
else if (GetHasFeat(2128, oPC) == TRUE) // Epic Precision
{
nSneakAttack = nSneakAttack / 2;
}
else nSneakAttack = 0;
}
if (nSneakAttack > 0)
{
FloatingTextStringOnCreature("*Sneak Attack!*", oPC, TRUE, 3.0f, COLOR_GREY, COLOR_BLACK);
SetLocalInt(oMartialJournal, "SneakHasHit", 1);
DelayCommand(3.0f, SetLocalInt(oMartialJournal, "SneakHasHit", 0));
if (nWeaponType == WEAPON_TYPE_SLASHING || nWeaponType == WEAPON_TYPE_PIERCING_AND_SLASHING)
{
nSlash += nSneakAttack;
}
else if (nWeaponType == WEAPON_TYPE_PIERCING)
{
nPierce += nSneakAttack;
}
else nBlunt += nSneakAttack;
}
eSneakAttack = EffectDamage(nPierce, DAMAGE_TYPE_PIERCING);
if (nSlash > 0)
{
effect eDmg = EffectDamage(nSlash, DAMAGE_TYPE_SLASHING);
eSneakAttack = EffectLinkEffects(eDmg, eSneakAttack);
}
if (nBlunt > 0)
{
effect eDmg;
if ((GetLevelByClass(CLASS_TYPE_MONK, oPC) > 3) && (!GetIsObjectValid(oWeapon)))
{
eDmg = EffectDamage(nBlunt, DAMAGE_TYPE_MAGICAL);
}
else eDmg = EffectDamage(nBlunt, DAMAGE_TYPE_BLUDGEONING);
eSneakAttack = EffectLinkEffects(eDmg, eSneakAttack);
}
return eSneakAttack;
}
Code:
#include "x2_inc_itemprop"
int GetDamageByIPConstDamageBonus(int nDamageBonus)
{
switch (nDamageBonus)
{
case IP_CONST_DAMAGEBONUS_1: return 1; break;
case IP_CONST_DAMAGEBONUS_10: return 10; break;
case IP_CONST_DAMAGEBONUS_1d10: return d10(1); break;
case IP_CONST_DAMAGEBONUS_1d12: return d12(1); break;
case IP_CONST_DAMAGEBONUS_1d4: return d4(1); break;
case IP_CONST_DAMAGEBONUS_1d6: return d6(1); break;
case IP_CONST_DAMAGEBONUS_1d8: return d8(1); break;
case IP_CONST_DAMAGEBONUS_2: return 2; break;
case IP_CONST_DAMAGEBONUS_2d10: return d10(2); break;
case IP_CONST_DAMAGEBONUS_2d12: return d12(2); break;
case IP_CONST_DAMAGEBONUS_2d4: return d4(2); break;
case IP_CONST_DAMAGEBONUS_2d6: return d6(2); break;
case IP_CONST_DAMAGEBONUS_2d8: return d8(2); break;
case IP_CONST_DAMAGEBONUS_3: return 3; break;
case IP_CONST_DAMAGEBONUS_3d10: return d10(3); break;
case IP_CONST_DAMAGEBONUS_3d12: return d12(3); break;
case IP_CONST_DAMAGEBONUS_3d6: return d6(3); break;
case IP_CONST_DAMAGEBONUS_4: return 4; break;
case IP_CONST_DAMAGEBONUS_4d10: return d10(4); break;
case IP_CONST_DAMAGEBONUS_4d12: return d12(4); break;
case IP_CONST_DAMAGEBONUS_4d6: return d6(4); break;
case IP_CONST_DAMAGEBONUS_4d8: return d8(4); break;
case IP_CONST_DAMAGEBONUS_5: return 5; break;
case IP_CONST_DAMAGEBONUS_5d12: return d12(5); break;
case IP_CONST_DAMAGEBONUS_5d6: return d6(5); break;
case IP_CONST_DAMAGEBONUS_6: return 6; break;
case IP_CONST_DAMAGEBONUS_6d12: return d12(6); break;
case IP_CONST_DAMAGEBONUS_6d6: return d6(6); break;
case IP_CONST_DAMAGEBONUS_7: return 7; break;
case IP_CONST_DAMAGEBONUS_8: return 8; break;
case IP_CONST_DAMAGEBONUS_9: return 9; break;
case IP_CONST_DAMAGEBONUS_11: return 11; break;
case IP_CONST_DAMAGEBONUS_12: return 12; break;
case IP_CONST_DAMAGEBONUS_13: return 13; break;
case IP_CONST_DAMAGEBONUS_14: return 14; break;
case IP_CONST_DAMAGEBONUS_15: return 15; break;
case IP_CONST_DAMAGEBONUS_16: return 16; break;
case IP_CONST_DAMAGEBONUS_17: return 17; break;
case IP_CONST_DAMAGEBONUS_18: return 18; break;
case IP_CONST_DAMAGEBONUS_19: return 19; break;
case IP_CONST_DAMAGEBONUS_20: return 20; break;
case IP_CONST_DAMAGEBONUS_21: return 21; break;
case IP_CONST_DAMAGEBONUS_22: return 22; break;
case IP_CONST_DAMAGEBONUS_23: return 23; break;
case IP_CONST_DAMAGEBONUS_24: return 24; break;
case IP_CONST_DAMAGEBONUS_25: return 25; break;
case IP_CONST_DAMAGEBONUS_26: return 26; break;
case IP_CONST_DAMAGEBONUS_27: return 27; break;
case IP_CONST_DAMAGEBONUS_28: return 28; break;
case IP_CONST_DAMAGEBONUS_29: return 29; break;
case IP_CONST_DAMAGEBONUS_30: return 30; break;
case IP_CONST_DAMAGEBONUS_31: return 31; break;
case IP_CONST_DAMAGEBONUS_32: return 32; break;
case IP_CONST_DAMAGEBONUS_33: return 33; break;
case IP_CONST_DAMAGEBONUS_34: return 34; break;
case IP_CONST_DAMAGEBONUS_35: return 35; break;
case IP_CONST_DAMAGEBONUS_36: return 36; break;
case IP_CONST_DAMAGEBONUS_37: return 37; break;
case IP_CONST_DAMAGEBONUS_38: return 38; break;
case IP_CONST_DAMAGEBONUS_39: return 39; break;
case IP_CONST_DAMAGEBONUS_40: return 40; break;
default: return 1; break;
}
return 1;
}
int GetDamageByDamageBonus(int nDamageBonus)
{
switch (nDamageBonus)
{
case DAMAGE_BONUS_1: return 1; break;
case DAMAGE_BONUS_10: return 10; break;
case DAMAGE_BONUS_11: return 11; break;
case DAMAGE_BONUS_12: return 12; break;
case DAMAGE_BONUS_13: return 13; break;
case DAMAGE_BONUS_14: return 14; break;
case DAMAGE_BONUS_15: return 15; break;
case DAMAGE_BONUS_16: return 16; break;
case DAMAGE_BONUS_17: return 17; break;
case DAMAGE_BONUS_18: return 18; break;
case DAMAGE_BONUS_19: return 19; break;
case DAMAGE_BONUS_1d10: return d10(1); break;
case DAMAGE_BONUS_1d12: return d12(1); break;
case DAMAGE_BONUS_1d4: return d4(1); break;
case DAMAGE_BONUS_1d6: return d6(1); break;
case DAMAGE_BONUS_1d8: return d8(1); break;
case DAMAGE_BONUS_2: return 2; break;
case DAMAGE_BONUS_20: return 20; break;
case DAMAGE_BONUS_21: return 21; break;
case DAMAGE_BONUS_22: return 22; break;
case DAMAGE_BONUS_23: return 23; break;
case DAMAGE_BONUS_24: return 24; break;
case DAMAGE_BONUS_25: return 25; break;
case DAMAGE_BONUS_26: return 26; break;
case DAMAGE_BONUS_27: return 27; break;
case DAMAGE_BONUS_28: return 28; break;
case DAMAGE_BONUS_29: return 29; break;
case DAMAGE_BONUS_2d10: return d10(2); break;
case DAMAGE_BONUS_2d12: return d12(2); break;
case DAMAGE_BONUS_2d4: return d4(2); break;
case DAMAGE_BONUS_2d6: return d6(2); break;
case DAMAGE_BONUS_2d8: return d8(2); break;
case DAMAGE_BONUS_3: return 3; break;
case DAMAGE_BONUS_30: return 30; break;
case DAMAGE_BONUS_31: return 31; break;
case DAMAGE_BONUS_32: return 32; break;
case DAMAGE_BONUS_33: return 33; break;
case DAMAGE_BONUS_34: return 34; break;
case DAMAGE_BONUS_35: return 35; break;
case DAMAGE_BONUS_36: return 36; break;
case DAMAGE_BONUS_37: return 37; break;
case DAMAGE_BONUS_38: return 38; break;
case DAMAGE_BONUS_39: return 39; break;
case DAMAGE_BONUS_4: return 4; break;
case DAMAGE_BONUS_40: return 40; break;
case DAMAGE_BONUS_5: return 5; break;
case DAMAGE_BONUS_6: return 6; break;
case DAMAGE_BONUS_7: return 7; break;
case DAMAGE_BONUS_8: return 8; break;
case DAMAGE_BONUS_9: return 9; break;
default: return 1; break;
}
return 1;
}
int GetDamageByDice(int nDice, int nNum)
{
int nDamage;
switch (nDice)
{
case 2: nDamage = d2(nNum); break;
case 3: nDamage = d3(nNum); break;
case 4: nDamage = d4(nNum); break;
case 6: nDamage = d6(nNum); break;
case 8: nDamage = d8(nNum); break;
case 10:nDamage = d10(nNum);break;
case 12:nDamage = d12(nNum);break;
default:nDamage = 1; break;
}
return nDamage;
}
// The main weapon damage effect function.
effect GenerateAttackEffect(object oPC, object oWeapon, object oTarget)
{
string sMartialJournal = GetFirstName(oPC) + "martial_journal";
object oMartialJournal = GetObjectByTag(sMartialJournal);
object oLeftHand = GetItemInSlot(INVENTORY_SLOT_LEFTHAND);
int nBaseItemType = GetBaseItemType(oWeapon);
int nIsRanged = GetWeaponRanged(oWeapon);
int nBasedice = StringToInt(Get2DAString("baseitems", "DieToRoll", nBaseItemType));
int nDiceNum = StringToInt( Get2DAString("baseitems", "NumDice", nBaseItemType) );
int nBaseDamage = GetDamageByDice(nBasedice, nDiceNum);
int nWeaponType = GetWeaponType(oWeapon);
int nSlash = 0;
int nBlunt = 0;
int nPierce = 0;
int nAcid = 0;
int nCold = 0;
int nElec = 0;
int nFire = 0;
int nSonic = 0;
int nDivine = 0;
int nMagic = 0;
int nPosit = 0;
int nNegat = 0;
int nStrMod = GetAbilityModifier(ABILITY_STRENGTH, oPC);
int nIntMod = GetAbilityModifier(ABILITY_INTELLIGENCE, oPC);
/* Drammel's Note: Split up GenerateAttackEffect into GenerateAttackEffect
and GenerateItemProperties to better simulate critical hit rules. Only
enchantment bonuses have been left in this function.*/
// Apply Feat damage.
if ((GetHasFeat(1957, oPC)) && (nIntMod > nStrMod))//Combat Insight
{
if (!nIsRanged)
{
if (!GetIsObjectValid(oLeftHand))
{
//Two-Handed
nStrMod = nStrMod + (((nIntMod - nStrMod)*3)/2);
}
else
{
//One-Handed
nStrMod = nStrMod + (nIntMod - nStrMod);
}
}
}
if ((nIsRanged == TRUE) && (GetHasFeat(FEAT_POINT_BLANK_SHOT, oPC) == TRUE))
{
float fDist = GetDistanceToObject(oTarget);
if (fDist <= FeetToMeters(15.0f))
{
nStrMod += 1;
}
}
if ((GetHasFeat(2141, oPC) == TRUE) && (GetIsImmune(oTarget, IMMUNITY_TYPE_CRITICAL_HIT) == FALSE)) //Swashbuckler's Insightful Strike
{
object oArmor = GetItemInSlot(INVENTORY_SLOT_CHEST, oPC);
if ((GetArmorRank(oArmor) == ARMOR_RANK_LIGHT) || (GetArmorRank(oArmor) == ARMOR_RANK_NONE))
{
if (GetIsLightWeapon(oWeapon, oPC) == TRUE)
{
nStrMod += nIntMod;
}
}
}
if (GetIsFavoredEnemy(oPC, oTarget)) // Favored Enemy
{
int nLevel = GetLevelByClass(CLASS_TYPE_RANGER, oPC);
if (nLevel > 29)
{
nStrMod += 7;
}
else if (nLevel > 24)
{
nStrMod += 6;
}
else if (nLevel > 19)
{
nStrMod += 5;
}
else if (nLevel > 14)
{
nStrMod += 4;
}
else if (nLevel > 9)
{
nStrMod += 3;
}
else if (nLevel > 4)
{
nStrMod += 2;
}
else nStrMod += 1;
if (GetIsImpFavoredEnemy(oPC, oTarget) == TRUE) // Improved Favored Enemy
{
nStrMod += 3;
}
if (GetHasFeat(FEAT_EPIC_BANE_OF_ENEMIES, oPC) == TRUE)
{
nStrMod += d6(2);
}
}
if (GetActionMode(oPC, ACTION_MODE_POWER_ATTACK) == TRUE)
{
if (GetHasFeat(FEAT_ENHANCED_POWER_ATTACK) == TRUE)
{
if ((GetIsFavoredEnemyPA(oPC, oTarget) == TRUE) && (!GetIsObjectValid(oLeftHand)))
{
nStrMod += 15;
}
else if (GetIsFavoredEnemyPA(oPC, oTarget) == TRUE)
{
nStrMod += 10;
}
else nStrMod += 5;
}
else if (GetHasFeat(FEAT_SUPREME_POWER_ATTACK) == TRUE)
{
if ((GetIsFavoredEnemyPA(oPC, oTarget) == TRUE) && (!GetIsObjectValid(oLeftHand)))
{
nStrMod += 18;
}
else if (GetIsFavoredEnemyPA(oPC, oTarget) == TRUE)
{
nStrMod += 12;
}
else nStrMod += 6;
}
else if ((GetIsFavoredEnemyPA(oPC, oTarget) == TRUE) && (!GetIsObjectValid(oLeftHand)))
{
nStrMod += 9;
}
else if (GetIsFavoredEnemyPA(oPC, oTarget) == TRUE)
{
nStrMod += 6;
}
else nStrMod += 3;
}
else if (GetActionMode(oPC, ACTION_MODE_IMPROVED_POWER_ATTACK) == TRUE)
{
if (GetHasFeat(FEAT_ENHANCED_POWER_ATTACK) == TRUE)
{
if ((GetIsFavoredEnemyPA(oPC, oTarget) == TRUE) && (!GetIsObjectValid(oLeftHand)))
{
nStrMod += 30;
}
else if (GetIsFavoredEnemyPA(oPC, oTarget) == TRUE)
{
nStrMod += 20;
}
else nStrMod += 10;
}
else if (GetHasFeat(FEAT_SUPREME_POWER_ATTACK) == TRUE)
{
if ((GetIsFavoredEnemyPA(oPC, oTarget) == TRUE) && (!GetIsObjectValid(oLeftHand)))
{
nStrMod += 36;
}
else if (GetIsFavoredEnemyPA(oPC, oTarget))
{
nStrMod += 24;
}
else nStrMod += 12;
}
else if ((GetIsFavoredEnemyPA(oPC, oTarget) == TRUE) && (!GetIsObjectValid(oLeftHand)))
{
nStrMod += 18;
}
else if (GetIsFavoredEnemyPA(oPC, oTarget) == TRUE)
{
nStrMod += 12;
}
else nStrMod += 6;
}
if (GetHasFeat(FEAT_EPIC_PROWESS, oPC) == TRUE)
{
nStrMod += 1;
}
// Wpn Spec, Epic Wpn Spec
if (GetIsObjectValid(oWeapon) == TRUE)
{
int iWeapon = GetBaseItemType(oWeapon);
int nWSFeat = StringToInt(Get2DAString("baseitems", "FEATWpnSpec", iWeapon));
int nEWSFeat = StringToInt(Get2DAString("baseitems", "FEATEpicWpnSpec", iWeapon));
if (GetHasFeat(nEWSFeat, oPC))
{
nStrMod += 6; //Operating under the asumption that Epic and normal Weapon Spec stack.
}
else if (GetHasFeat(nWSFeat, oPC))
{
nStrMod += 2;
}
}
else if (GetHasFeat(FEAT_EPIC_WEAPON_SPECIALIZATION_UNARMED, oPC))
{
nStrMod += 6;
}
else if (GetHasFeat(FEAT_WEAPON_SPECIALIZATION_UNARMED_STRIKE, oPC))
{
nStrMod += 2;
}
if ((GetHasFeat(FEAT_TW_CIRCLE_OF_BLADES) == TRUE) && (IsFlankValid(oPC, oTarget) == TRUE))
{
nStrMod += 2;
}
if ((GetHasFeat(FEAT_BLADE_MEDITATION_DW, oPC) == TRUE) && (GetLocalInt(oMartialJournal, "DesertWindStrike") == 1))
{
nStrMod += 1;
}
if ((GetHasFeat(FEAT_BLADE_MEDITATION_DS, oPC) == TRUE) && (GetLocalInt(oMartialJournal, "DevotedSpiritStrike") == 1))
{
nStrMod += 1;
}
if ((GetHasFeat(FEAT_BLADE_MEDITATION_DM, oPC) == TRUE) && (GetLocalInt(oMartialJournal, "DiamondMindStrike") == 1))
{
nStrMod += 1;
}
if ((GetHasFeat(FEAT_BLADE_MEDITATION_IH, oPC) == TRUE) && (GetLocalInt(oMartialJournal, "IronHeartStrike") == 1))
{
nStrMod += 1;
}
if ((GetHasFeat(FEAT_BLADE_MEDITATION_SS, oPC) == TRUE) && (GetLocalInt(oMartialJournal, "SettingSunStrike") == 1))
{
nStrMod += 1;
}
if ((GetHasFeat(FEAT_BLADE_MEDITATION_SH, oPC) == TRUE) && (GetLocalInt(oMartialJournal, "ShadowHandStrike") == 1))
{
nStrMod += 1;
}
if ((GetHasFeat(FEAT_BLADE_MEDITATION_SD, oPC) == TRUE) && (GetLocalInt(oMartialJournal, "StoneDragonStrike") == 1))
{
nStrMod += 1;
}
if ((GetHasFeat(FEAT_BLADE_MEDITATION_TC, oPC) == TRUE) && (GetLocalInt(oMartialJournal, "TigerClawStrike") == 1))
{
nStrMod += 1;
}
if ((GetHasFeat(FEAT_BLADE_MEDITATION_WR, oPC) == TRUE) && (GetLocalInt(oMartialJournal, "WhiteRavenStrike") == 1))
{
nStrMod += 1;
}
nStrMod += nBaseDamage;
if (GetHasFeat(FEAT_PRECISE_STRIKE, oPC)) //FEAT_PRECISE_STRIKE
{
object oLeftHand = GetItemInSlot(INVENTORY_SLOT_LEFTHAND);
if (!GetIsObjectValid(oLeftHand))
{
//Nothing in the left hand
if (nWeaponType == WEAPON_TYPE_PIERCING || nWeaponType == WEAPON_TYPE_PIERCING_AND_SLASHING)
{
//Valid Precise Strike weapon
if (GetLevelByClass(CLASS_TYPE_DUELIST, oPC) == 10)
nPierce += d6(2);
else
nPierce += d6(1);
}
}
}
// Apply weapon modifiying damage.
if (nWeaponType == WEAPON_TYPE_SLASHING || nWeaponType == WEAPON_TYPE_PIERCING_AND_SLASHING)
{
nSlash += nStrMod;
}
else if (nWeaponType == WEAPON_TYPE_PIERCING)
{
nPierce += nStrMod;
}
else nBlunt += nStrMod;
// Apply effect damage.
effect eEffect = GetFirstEffect(oPC);
while (GetIsEffectValid(eEffect))
{
int nType = GetEffectType(eEffect);
if (nType == EFFECT_TYPE_DAMAGE_INCREASE)
{
// int i0 = GetEffectInteger(eEffect, 0); //DamageBonus
// int i1 = GetEffectInteger(eEffect, 1); //DamageType
int nDamage = GetDamageByDamageBonus(GetEffectInteger(eEffect, 0)); //DamageBonus
switch (GetEffectInteger(eEffect, 1)) //DamageType
{
case DAMAGE_TYPE_ACID: nAcid += nDamage; break;
case DAMAGE_TYPE_BLUDGEONING: nBlunt += nDamage; break;
case DAMAGE_TYPE_COLD: nCold += nDamage; break;
case DAMAGE_TYPE_DIVINE: nDivine += nDamage; break;
case DAMAGE_TYPE_ELECTRICAL: nElec += nDamage; break;
case DAMAGE_TYPE_FIRE: nFire += nDamage; break;
case DAMAGE_TYPE_MAGICAL: nMagic += nDamage; break;
case DAMAGE_TYPE_NEGATIVE: nNegat += nDamage; break;
case DAMAGE_TYPE_PIERCING: nPierce += nDamage; break;
case DAMAGE_TYPE_POSITIVE: nPosit += nDamage; break;
case DAMAGE_TYPE_SLASHING: nSlash += nDamage; break;
case DAMAGE_TYPE_SONIC: nSonic += nDamage; break;
}
}
else if (nType == EFFECT_TYPE_DAMAGE_DECREASE)
{
int nDamage = GetDamageByDamageBonus(GetEffectInteger(eEffect, 0)); //DamageBonus
switch (GetEffectInteger(eEffect, 1)) //DamageType
{
case DAMAGE_TYPE_ACID: nAcid -= nDamage; break;
case DAMAGE_TYPE_BLUDGEONING: nBlunt -= nDamage; break;
case DAMAGE_TYPE_COLD: nCold -= nDamage; break;
case DAMAGE_TYPE_DIVINE: nDivine -= nDamage; break;
case DAMAGE_TYPE_ELECTRICAL: nElec -= nDamage; break;
case DAMAGE_TYPE_FIRE: nFire -= nDamage; break;
case DAMAGE_TYPE_MAGICAL: nMagic -= nDamage; break;
case DAMAGE_TYPE_NEGATIVE: nNegat -= nDamage; break;
case DAMAGE_TYPE_PIERCING: nPierce -= nDamage; break;
case DAMAGE_TYPE_POSITIVE: nPosit -= nDamage; break;
case DAMAGE_TYPE_SLASHING: nSlash -= nDamage; break;
case DAMAGE_TYPE_SONIC: nSonic -= nDamage; break;
}
}
eEffect = GetNextEffect(oPC);
}
int nEnhance = 0;
itemproperty iProp;
if (GetIsObjectValid(oWeapon) == TRUE)
{
iProp = GetFirstItemProperty(oWeapon);
}
else iProp = GetFirstItemProperty(GetItemInSlot(INVENTORY_SLOT_ARMS, oPC)); // Love for monks.
while (GetIsItemPropertyValid(iProp))
{
if (GetItemPropertyType(iProp) == ITEM_PROPERTY_ENHANCEMENT_BONUS)
{
int nItemEnhance = GetItemPropertyCostTableValue(iProp); //Enhance bonus
if (nItemEnhance > nEnhance)
nEnhance = nItemEnhance;
}
else if (GetItemPropertyType(iProp) == ITEM_PROPERTY_ENHANCEMENT_BONUS_VS_ALIGNMENT_GROUP)
{
int nGoodEvil = GetAlignmentGoodEvil(oTarget);
int nLawChaos = GetAlignmentLawChaos(oTarget);
if ((GetItemPropertySubType(iProp) == nGoodEvil) || (GetItemPropertySubType(iProp) == nLawChaos))
{
int nDamage = GetDamageByIPConstDamageBonus(GetItemPropertyCostTableValue(iProp));
nEnhance += nDamage;
}
}
else if (GetItemPropertyType(iProp) == ITEM_PROPERTY_ENHANCEMENT_BONUS_VS_RACIAL_GROUP)
{
int nTargetRace = GetRacialType(oTarget);
if (GetItemPropertySubType(iProp) == nTargetRace)
{
int nDamage = GetDamageByIPConstDamageBonus(GetItemPropertyCostTableValue(iProp));
nEnhance += nDamage;
}
}
else if (GetItemPropertyType(iProp) == ITEM_PROPERTY_ENHANCEMENT_BONUS_VS_SPECIFIC_ALIGNEMENT)
{
int nAlignment = GetAlignment(oTarget);
if (GetItemPropertySubType(iProp) == nAlignment)
{
int nDamage = GetDamageByIPConstDamageBonus(GetItemPropertyCostTableValue(iProp));
nEnhance += nDamage;
}
}
else if (GetItemPropertyType(iProp) == ITEM_PROPERTY_DECREASED_DAMAGE || GetItemPropertyType(iProp) == ITEM_PROPERTY_DECREASED_ENHANCEMENT_MODIFIER)
{
int nPenalty = GetItemPropertyCostTableValue(iProp);
if (nPenalty < nEnhance)
{
nEnhance -= nPenalty;
}
}
iProp = GetNextItemProperty(oWeapon);
}
if (nWeaponType == WEAPON_TYPE_SLASHING || nWeaponType == WEAPON_TYPE_PIERCING_AND_SLASHING)
nSlash += nEnhance;
else
if (nWeaponType == WEAPON_TYPE_PIERCING)
nPierce += nEnhance;
else
if (nWeaponType == WEAPON_TYPE_BLUDGEONING)
nBlunt += nEnhance;
if ( nIsRanged ) // Gets bonuses from ammo as well as the bow, if it was called by the last set of routines.
{
int nBaseType = GetBaseItemType(oWeapon);
int nEnhance = 0;
object oAmmo;
if (nBaseType == BASE_ITEM_LIGHTCROSSBOW || nBaseType == BASE_ITEM_HEAVYCROSSBOW)
oAmmo = GetItemInSlot(INVENTORY_SLOT_BOLTS);
if (nBaseType == BASE_ITEM_LONGBOW || nBaseType == BASE_ITEM_SHORTBOW)
oAmmo = GetItemInSlot(INVENTORY_SLOT_ARROWS);
if (nBaseType == BASE_ITEM_SLING)
oAmmo = GetItemInSlot(INVENTORY_SLOT_BULLETS);
itemproperty iProp = GetFirstItemProperty(oAmmo);
while (GetIsItemPropertyValid(iProp))
{
if (GetItemPropertyType(iProp) == ITEM_PROPERTY_ENHANCEMENT_BONUS)
{
int nItemEnhance = GetItemPropertyCostTableValue(iProp); //Enhance bonus
if (nItemEnhance > nEnhance)
nEnhance = nItemEnhance;
}
iProp = GetNextItemProperty(oAmmo);
}
if (nWeaponType == WEAPON_TYPE_SLASHING || nWeaponType == WEAPON_TYPE_PIERCING_AND_SLASHING)
nSlash += nEnhance;
else
if (nWeaponType == WEAPON_TYPE_PIERCING)
nPierce += nEnhance;
else
if (nWeaponType == WEAPON_TYPE_BLUDGEONING)
nBlunt += nEnhance;
}
//Time to build a mega damage event
effect eLink = EffectDamage(nPierce, DAMAGE_TYPE_PIERCING);
if (!GetIsObjectValid(oWeapon))
{
effect eDmg = SnapKickDamage(); // Fortunately, Snap Kick will get apporpiate unarmed damage and runs a check for Superior Unarmed Strike.
eLink = EffectLinkEffects(eDmg, eLink);
}
if (nAcid > 0)
{
effect eDmg = EffectDamage(nAcid, DAMAGE_TYPE_ACID);
eLink = EffectLinkEffects(eDmg, eLink);
}
if (nSlash > 0)
{
effect eDmg = EffectDamage(nSlash, DAMAGE_TYPE_SLASHING);
eLink = EffectLinkEffects(eDmg, eLink);
}
if (nBlunt > 0)
{
effect eDmg;
if ((GetLevelByClass(CLASS_TYPE_MONK, oPC) > 3) && (!GetIsObjectValid(oWeapon)))
{
eDmg = EffectDamage(nBlunt, DAMAGE_TYPE_MAGICAL);
}
else eDmg = EffectDamage(nBlunt, DAMAGE_TYPE_BLUDGEONING);
eLink = EffectLinkEffects(eDmg, eLink);
}
if (nCold > 0)
{
effect eDmg = EffectDamage(nCold, DAMAGE_TYPE_COLD);
eLink = EffectLinkEffects(eDmg, eLink);
}
if (nElec > 0)
{
effect eDmg = EffectDamage(nElec, DAMAGE_TYPE_ELECTRICAL);
eLink = EffectLinkEffects(eDmg, eLink);
}
if (nFire > 0)
{
effect eDmg = EffectDamage(nFire, DAMAGE_TYPE_FIRE);
eLink = EffectLinkEffects(eDmg, eLink);
}
if (nSonic > 0)
{
effect eDmg = EffectDamage(nSonic, DAMAGE_TYPE_SONIC);
eLink = EffectLinkEffects(eDmg, eLink);
}
if (nDivine > 0)
{
effect eDmg = EffectDamage(nDivine, DAMAGE_TYPE_DIVINE);
eLink = EffectLinkEffects(eDmg, eLink);
}
if (nMagic > 0)
{
effect eDmg = EffectDamage(nMagic, DAMAGE_TYPE_MAGICAL);
eLink = EffectLinkEffects(eDmg, eLink);
}
if (nPosit > 0)
{
effect eDmg = EffectDamage(nPosit, DAMAGE_TYPE_POSITIVE);
eLink = EffectLinkEffects(eDmg, eLink);
}
if (nNegat > 0)
{
effect eDmg = EffectDamage(nNegat, DAMAGE_TYPE_NEGATIVE);
eLink = EffectLinkEffects(eDmg, eLink);
}
return eLink;
}
// Generates effects from item properties.
effect GenerateItemProperties(object oPC, object oWeapon, object oTarget)
{
int nBaseItemType = GetBaseItemType(oWeapon);
int nIsRanged = GetWeaponRanged(oWeapon);
int nSlash = 0;
int nBlunt = 0;
int nPierce = 0;
int nAcid = 0;
int nCold = 0;
int nElec = 0;
int nFire = 0;
int nSonic = 0;
int nDivine = 0;
int nMagic = 0;
int nPosit = 0;
int nNegat = 0;
itemproperty iProp;
iProp = GetFirstItemProperty(oWeapon);
while (GetIsItemPropertyValid(iProp))
{
if (GetItemPropertyType(iProp) == ITEM_PROPERTY_DAMAGE_BONUS)
{
int nDamage = GetDamageByIPConstDamageBonus(GetItemPropertyCostTableValue(iProp));
switch (GetItemPropertySubType(iProp)) //DamageType
{
case IP_CONST_DAMAGETYPE_ACID: nAcid += nDamage; break;
case IP_CONST_DAMAGETYPE_BLUDGEONING: nBlunt += nDamage; break;
case IP_CONST_DAMAGETYPE_COLD: nCold += nDamage; break;
case IP_CONST_DAMAGETYPE_DIVINE: nDivine += nDamage; break;
case IP_CONST_DAMAGETYPE_ELECTRICAL: nElec += nDamage; break;
case IP_CONST_DAMAGETYPE_FIRE: nFire += nDamage; break;
case IP_CONST_DAMAGETYPE_MAGICAL: nMagic += nDamage; break;
case IP_CONST_DAMAGETYPE_NEGATIVE: nNegat += nDamage; break;
case IP_CONST_DAMAGETYPE_PHYSICAL: nSlash += nDamage; break;
case IP_CONST_DAMAGETYPE_PIERCING: nPierce += nDamage; break;
case IP_CONST_DAMAGETYPE_POSITIVE: nPosit += nDamage; break;
case IP_CONST_DAMAGETYPE_SLASHING: nSlash += nDamage; break;
case IP_CONST_DAMAGETYPE_SONIC: nSonic += nDamage; break;
}
}
else if (GetItemPropertyType(iProp) == ITEM_PROPERTY_DAMAGE_BONUS_VS_ALIGNMENT_GROUP)
{
int nGoodEvil = GetAlignmentGoodEvil(oTarget);
int nLawChaos = GetAlignmentLawChaos(oTarget);
if ((GetItemPropertySubType(iProp) == nGoodEvil) || (GetItemPropertySubType(iProp) == nLawChaos))
{
int nDamage = GetDamageByIPConstDamageBonus(GetItemPropertyCostTableValue(iProp));
nMagic += nDamage;
}
}
else if (GetItemPropertyType(iProp) == ITEM_PROPERTY_DAMAGE_BONUS_VS_RACIAL_GROUP)
{
int nTargetRace = GetRacialType(oTarget);
if (GetItemPropertySubType(iProp) == nTargetRace)
{
int nDamage = GetDamageByIPConstDamageBonus(GetItemPropertyCostTableValue(iProp));
nMagic += nDamage;
}
}
else if (GetItemPropertyType(iProp) == ITEM_PROPERTY_DAMAGE_BONUS_VS_SPECIFIC_ALIGNMENT)
{
int nAlignment = GetAlignment(oTarget);
if (GetItemPropertySubType(iProp) == nAlignment)
{
int nDamage = GetDamageByIPConstDamageBonus(GetItemPropertyCostTableValue(iProp));
nMagic += nDamage;
}
}
iProp = GetNextItemProperty(oWeapon);
}
if (nIsRanged == TRUE) // Gets bonuses from ammo as well as the bow, if it was called by the last set of routines.
{
int nBaseType = GetBaseItemType(oWeapon);
object oAmmo;
if (nBaseType == BASE_ITEM_LIGHTCROSSBOW || nBaseType == BASE_ITEM_HEAVYCROSSBOW)
oAmmo = GetItemInSlot(INVENTORY_SLOT_BOLTS);
if (nBaseType == BASE_ITEM_LONGBOW || nBaseType == BASE_ITEM_SHORTBOW)
oAmmo = GetItemInSlot(INVENTORY_SLOT_ARROWS);
if (nBaseType == BASE_ITEM_SLING)
oAmmo = GetItemInSlot(INVENTORY_SLOT_BULLETS);
itemproperty iProp = GetFirstItemProperty(oAmmo);
while (GetIsItemPropertyValid(iProp))
{
if (GetItemPropertyType(iProp )== ITEM_PROPERTY_DAMAGE_BONUS)
{
GetItemPropertyCostTableValue(iProp); //IP_CONST_DAMAGEBONUS
GetItemPropertySubType(iProp); //IP_CONST_DAMAGETYPE
int nDamage = GetDamageByIPConstDamageBonus(GetItemPropertyCostTableValue(iProp));
switch (GetItemPropertySubType(iProp)) //DamageType
{
case IP_CONST_DAMAGETYPE_ACID: nAcid += nDamage; break;
case IP_CONST_DAMAGETYPE_BLUDGEONING: nBlunt += nDamage; break;
case IP_CONST_DAMAGETYPE_COLD: nCold += nDamage; break;
case IP_CONST_DAMAGETYPE_DIVINE: nDivine += nDamage; break;
case IP_CONST_DAMAGETYPE_ELECTRICAL: nElec += nDamage; break;
case IP_CONST_DAMAGETYPE_FIRE: nFire += nDamage; break;
case IP_CONST_DAMAGETYPE_MAGICAL: nMagic += nDamage; break;
case IP_CONST_DAMAGETYPE_NEGATIVE: nNegat += nDamage; break;
case IP_CONST_DAMAGETYPE_PHYSICAL: nSlash += nDamage; break;
case IP_CONST_DAMAGETYPE_PIERCING: nPierce += nDamage; break;
case IP_CONST_DAMAGETYPE_POSITIVE: nPosit += nDamage; break;
case IP_CONST_DAMAGETYPE_SLASHING: nSlash += nDamage; break;
case IP_CONST_DAMAGETYPE_SONIC: nSonic += nDamage; break;
}
}
else if (GetItemPropertyType(iProp) == ITEM_PROPERTY_DAMAGE_BONUS_VS_ALIGNMENT_GROUP)
{
int nGoodEvil = GetAlignmentGoodEvil(oTarget);
int nLawChaos = GetAlignmentLawChaos(oTarget);
if ((GetItemPropertySubType(iProp) == nGoodEvil) || (GetItemPropertySubType(iProp) == nLawChaos))
{
int nDamage = GetDamageByIPConstDamageBonus(GetItemPropertyCostTableValue(iProp));
nMagic += nDamage;
}
}
else if (GetItemPropertyType(iProp) == ITEM_PROPERTY_DAMAGE_BONUS_VS_RACIAL_GROUP)
{
int nTargetRace = GetRacialType(oTarget);
if (GetItemPropertySubType(iProp) == nTargetRace)
{
int nDamage = GetDamageByIPConstDamageBonus(GetItemPropertyCostTableValue(iProp));
nMagic += nDamage;
}
}
else if (GetItemPropertyType(iProp) == ITEM_PROPERTY_DAMAGE_BONUS_VS_SPECIFIC_ALIGNMENT)
{
int nAlignment = GetAlignment(oTarget);
if (GetItemPropertySubType(iProp) == nAlignment)
{
int nDamage = GetDamageByIPConstDamageBonus(GetItemPropertyCostTableValue(iProp));
nMagic += nDamage;
}
}
iProp = GetNextItemProperty(oAmmo);
}
}
if (!GetIsObjectValid(oWeapon)) // love for monks
{
object oArms = GetItemInSlot(INVENTORY_SLOT_ARMS);
itemproperty iArm = GetFirstItemProperty(oArms);
while (GetIsItemPropertyValid(iArm))
{
if (GetItemPropertyType(iArm) == ITEM_PROPERTY_DAMAGE_BONUS)
{
int nDamage = GetDamageByIPConstDamageBonus(GetItemPropertyCostTableValue(iArm));
switch (GetItemPropertySubType(iArm)) //DamageType
{
case IP_CONST_DAMAGETYPE_ACID: nAcid += nDamage; break;
case IP_CONST_DAMAGETYPE_BLUDGEONING: nBlunt += nDamage; break;
case IP_CONST_DAMAGETYPE_COLD: nCold += nDamage; break;
case IP_CONST_DAMAGETYPE_DIVINE: nDivine += nDamage; break;
case IP_CONST_DAMAGETYPE_ELECTRICAL: nElec += nDamage; break;
case IP_CONST_DAMAGETYPE_FIRE: nFire += nDamage; break;
case IP_CONST_DAMAGETYPE_MAGICAL: nMagic += nDamage; break;
case IP_CONST_DAMAGETYPE_NEGATIVE: nNegat += nDamage; break;
case IP_CONST_DAMAGETYPE_PHYSICAL: nSlash += nDamage; break;
case IP_CONST_DAMAGETYPE_PIERCING: nPierce += nDamage; break;
case IP_CONST_DAMAGETYPE_POSITIVE: nPosit += nDamage; break;
case IP_CONST_DAMAGETYPE_SLASHING: nSlash += nDamage; break;
case IP_CONST_DAMAGETYPE_SONIC: nSonic += nDamage; break;
}
}
else if (GetItemPropertyType(iArm) == ITEM_PROPERTY_DAMAGE_BONUS_VS_ALIGNMENT_GROUP)
{
int nGoodEvil = GetAlignmentGoodEvil(oTarget);
int nLawChaos = GetAlignmentLawChaos(oTarget);
if ((GetItemPropertySubType(iArm) == nGoodEvil) || (GetItemPropertySubType(iArm) == nLawChaos))
{
int nDamage = GetDamageByIPConstDamageBonus(GetItemPropertyCostTableValue(iArm));
nMagic += nDamage;
}
}
else if (GetItemPropertyType(iArm) == ITEM_PROPERTY_DAMAGE_BONUS_VS_RACIAL_GROUP)
{
int nTargetRace = GetRacialType(oTarget);
if (GetItemPropertySubType(iProp) == nTargetRace)
{
int nDamage = GetDamageByIPConstDamageBonus(GetItemPropertyCostTableValue(iArm));
nMagic += nDamage;
}
}
else if (GetItemPropertyType(iArm) == ITEM_PROPERTY_DAMAGE_BONUS_VS_SPECIFIC_ALIGNMENT)
{
int nAlignment = GetAlignment(oTarget);
if (GetItemPropertySubType(iArm) == nAlignment)
{
int nDamage = GetDamageByIPConstDamageBonus(GetItemPropertyCostTableValue(iArm));
nMagic += nDamage;
}
}
iArm = GetNextItemProperty(oArms);
}
}
//Time to build a mega damage event
effect eLink = EffectDamage(nPierce, DAMAGE_TYPE_PIERCING);
if (!GetIsObjectValid(oWeapon))
{
effect eDmg = SnapKickDamage(); // Fortunately, Snap Kick will get apporpiate unarmed damage and runs a check for Superior Unarmed Strike.
eLink = EffectLinkEffects(eDmg, eLink);
}
if (nAcid > 0)
{
effect eDmg = EffectDamage(nAcid, DAMAGE_TYPE_ACID);
eLink = EffectLinkEffects(eDmg, eLink);
}
if (nSlash > 0)
{
effect eDmg = EffectDamage(nSlash, DAMAGE_TYPE_SLASHING);
eLink = EffectLinkEffects(eDmg, eLink);
}
if (nBlunt > 0)
{
effect eDmg;
if ((GetLevelByClass(CLASS_TYPE_MONK, oPC) > 3) && (!GetIsObjectValid(oWeapon)))
{
eDmg = EffectDamage(nBlunt, DAMAGE_TYPE_MAGICAL);
}
else eDmg = EffectDamage(nBlunt, DAMAGE_TYPE_BLUDGEONING);
eLink = EffectLinkEffects(eDmg, eLink);
}
if (nCold > 0)
{
effect eDmg = EffectDamage(nCold, DAMAGE_TYPE_COLD);
eLink = EffectLinkEffects(eDmg, eLink);
}
if (nElec > 0)
{
effect eDmg = EffectDamage(nElec, DAMAGE_TYPE_ELECTRICAL);
eLink = EffectLinkEffects(eDmg, eLink);
}
if (nFire > 0)
{
effect eDmg = EffectDamage(nFire, DAMAGE_TYPE_FIRE);
eLink = EffectLinkEffects(eDmg, eLink);
}
if (nSonic > 0)
{
effect eDmg = EffectDamage(nSonic, DAMAGE_TYPE_SONIC);
eLink = EffectLinkEffects(eDmg, eLink);
}
if (nDivine > 0)
{
effect eDmg = EffectDamage(nDivine, DAMAGE_TYPE_DIVINE);
eLink = EffectLinkEffects(eDmg, eLink);
}
if (nMagic > 0)
{
effect eDmg = EffectDamage(nMagic, DAMAGE_TYPE_MAGICAL);
eLink = EffectLinkEffects(eDmg, eLink);
}
if (nPosit > 0)
{
effect eDmg = EffectDamage(nPosit, DAMAGE_TYPE_POSITIVE);
eLink = EffectLinkEffects(eDmg, eLink);
}
if (nNegat > 0)
{
effect eDmg = EffectDamage(nNegat, DAMAGE_TYPE_NEGATIVE);
eLink = EffectLinkEffects(eDmg, eLink);
}
return eLink;
}
Code:
// Applies instant critical hit damage effects.
effect StrikeCriticalEffect(object oPC, object oWeapon, object oTarget)
{
string sMartialJournal = GetFirstName(oPC) + "martial_journal";
object oMartialJournal = GetObjectByTag(sMartialJournal);
int nWeapon = GetWeaponType(oWeapon);
int nBaseWeapon = GetBaseItemType(oWeapon);
int nOCFeat = StringToInt(Get2DAString("baseitems", "FEATOverWhCrit", nBaseWeapon));
int nCritMult = GetCriticalMultiplier(oWeapon);
int nDamage;
int nPierce;
int nSlash;
int nBlunt;
int nSonic;
itemproperty iProp = GetFirstItemProperty(oWeapon);
while (GetIsItemPropertyValid(iProp))
{
if (GetItemPropertyType(iProp) == ITEM_PROPERTY_MASSIVE_CRITICALS)
{
int nMassive = GetDamageByIPConstDamageBonus(GetItemPropertyCostTableValue(iProp));
switch (nWeapon) //DamageType
{
case WEAPON_TYPE_PIERCING_AND_SLASHING: nPierce += nMassive; break;
case WEAPON_TYPE_PIERCING: nPierce += nMassive; break;
case WEAPON_TYPE_SLASHING: nSlash += nMassive; break;
case WEAPON_TYPE_BLUDGEONING: nBlunt += nMassive; break;
}
}
iProp=GetNextItemProperty(oWeapon);
}
if ((GetHasFeat(FEAT_BLADE_MEDITATION_DW, oPC) == TRUE) && (GetLocalInt(oMartialJournal, "DesertWindStrike") == 1))
{
nDamage += 1;
}
if ((GetHasFeat(FEAT_BLADE_MEDITATION_DS, oPC) == TRUE) && (GetLocalInt(oMartialJournal, "DevotedSpiritStrike") == 1))
{
nDamage += 1;
}
if ((GetHasFeat(FEAT_BLADE_MEDITATION_DM, oPC) == TRUE) && (GetLocalInt(oMartialJournal, "DiamondMindStrike") == 1))
{
nDamage += 1;
}
if ((GetHasFeat(FEAT_BLADE_MEDITATION_IH, oPC) == TRUE) && (GetLocalInt(oMartialJournal, "IronHeartStrike") == 1))
{
nDamage += 1;
}
if ((GetHasFeat(FEAT_BLADE_MEDITATION_SS, oPC) == TRUE) && (GetLocalInt(oMartialJournal, "SettingSunStrike") == 1))
{
nDamage += 1;
}
if ((GetHasFeat(FEAT_BLADE_MEDITATION_SH, oPC) == TRUE) && (GetLocalInt(oMartialJournal, "ShadowHandStrike") == 1))
{
nDamage += 1;
}
if ((GetHasFeat(FEAT_BLADE_MEDITATION_SD, oPC) == TRUE) && (GetLocalInt(oMartialJournal, "StoneDragonStrike") == 1))
{
nDamage += 1;
}
if ((GetHasFeat(FEAT_BLADE_MEDITATION_TC, oPC) == TRUE) && (GetLocalInt(oMartialJournal, "TigerClawStrike") == 1))
{
nDamage += 1;
}
if ((GetHasFeat(FEAT_BLADE_MEDITATION_WR, oPC) == TRUE) && (GetLocalInt(oMartialJournal, "WhiteRavenStrike") == 1))
{
nDamage += 1;
}
if ((GetHasFeat(nOCFeat, oPC)) && (GetIsImmune(oTarget, IMMUNITY_TYPE_CRITICAL_HIT) == FALSE)) // Overwhelming Critical
{
if (nCritMult == 2)
{
nDamage += d6(1);
}
else if (nCritMult == 3)
{
nDamage += d6(2);
}
else if (nCritMult == 4)
{
nDamage += d6(3);
}
else if (nCritMult > 4)
{
nDamage += d6(4);
}
}
if (nWeapon == WEAPON_TYPE_PIERCING_AND_SLASHING || nWeapon == WEAPON_TYPE_PIERCING)
{
nPierce += nDamage;
}
else if (nWeapon == WEAPON_TYPE_SLASHING)
{
nSlash += nDamage;
}
else nBlunt += nDamage;
if ((GetHasFeat(FEAT_EPIC_THUNDERING_RAGE, oPC) == TRUE) && (GetIsRaging(oPC) == TRUE))
{
if (nCritMult == 2)
{
nSonic += d8(1);
}
else if (nCritMult == 3)
{
nSonic += d8(2);
}
else if (nCritMult == 4)
{
nSonic += d8(3);
}
else if (nCritMult > 4)
{
nSonic += d8(4);
}
}
effect eLink = EffectDamage(nPierce, DAMAGE_TYPE_PIERCING);
if (nSlash > 0)
{
effect eDmg = EffectDamage(nSlash, DAMAGE_TYPE_SLASHING);
eLink = EffectLinkEffects(eDmg, eLink);
}
if (nSonic > 0)
{
effect eDmg = EffectDamage(nSlash, DAMAGE_TYPE_SONIC);
eLink = EffectLinkEffects(eDmg, eLink);
}
if (nBlunt > 0)
{
effect eDmg;
if ((GetLevelByClass(CLASS_TYPE_MONK, oPC) > 3) && (!GetIsObjectValid(oWeapon)))
{
eDmg = EffectDamage(nBlunt, DAMAGE_TYPE_MAGICAL);
}
else eDmg = EffectDamage(nBlunt, DAMAGE_TYPE_BLUDGEONING);
eLink = EffectLinkEffects(eDmg, eLink);
}
return eLink;
}
Code:
// Temporary Effects. Each Needs to be applied seperately to get the proper durations.
// Simulates the effects of Invisible Blade's Bleeding Wound.
// Only meant for use in conjunction with effect SneakAttack.
effect IBBleedingWound()
{
object oPC = OBJECT_SELF;
effect eBlW;
if (GetHasFeat(2054, oPC) == TRUE) //Bleeding Wound 3
{
eBlW = EffectDamageOverTime(6, 6.0f, DAMAGE_TYPE_MAGICAL, TRUE);
}
else if (GetHasFeat(2053, oPC) == TRUE) //Bleeding Wound 2
{
eBlW = EffectDamageOverTime(4, 6.0f, DAMAGE_TYPE_MAGICAL, TRUE);
}
else if (GetHasFeat(2052, oPC) == TRUE) //Bleeding Wound
{
eBlW = EffectDamageOverTime(2, 6.0f, DAMAGE_TYPE_MAGICAL, TRUE);
}
return eBlW;
}
// Debuffs the Target's AC for one round.
effect MissileVolley(object oPC, object oWeapon)
{
effect eVolley = EffectACDecrease(1, AC_DODGE_BONUS, DAMAGE_TYPE_SLASHING);
return eVolley;
}
Last edited by Drammel; 04-21-2009 at 07:16 PM. Reason: fine tuning |
|
#3
|
||||
|
||||
|
Now for the mundane functions that duplicate combat animations and OnHit damage sound effects. I'll mention it now; the 'sound creatures' are my method of getting around a limitation of the PlaySound function. That limit being that it only plays when no actions are enqueued, a huge pain. So my thinking was this: if sounds are only played when a creature has no action, a creature I create at a target's location with "Script Hidden = True" and "Disable AI While Hidden = False" that has all it's scripts removed except for one that plays my sound and then destroys itself would look exactly like a normal sound was playing on hit. Sure enough it does.
Code:
// Wrapper function for the PlayCustomAnimation Function (duh)
void WrapperPlayCustomAnimation(object oPC, string sAnimation, int nLoop)
{
PlayCustomAnimation(oPC, sAnimation, nLoop);
}
// Plays a basic attack animation with oWeapon.
void BasicAttackAnimation(object oWeapon)
{
object oPC = OBJECT_SELF;
string sBow;
string sAttack;
if (GetWeaponRanged(oWeapon) == TRUE)
{
int nD2 = d2(1);
switch (nD2)
{
case 1: sBow = "*1attack01"; break;
case 2: sBow = "*1attack02"; break;
}
WrapperPlayCustomAnimation(oPC, sBow, 0);
}
else
{
int nD4 = d4(1);
switch (nD4)
{
case 1: sAttack = "*1attack01"; break;
case 2: sAttack = "*1attack02"; break;
case 3: sAttack = "*1attack03"; break;
case 4: sAttack = "*1attack04"; break;
}
WrapperPlayCustomAnimation(oPC, sAttack, 0);
}
}
// Wrapper for CreateObject.
void WrapperCreateObject(int nObjectType, string sTemplate, location lLocation, int bUseAppearAnimation=FALSE, string sNewTag="")
{
CreateObject(nObjectType, sTemplate, lLocation, bUseAppearAnimation, sNewTag);
}
// Returns an interger for oWeapon coresponding to the sound type it makes.
int GetWeaponSoundType(object oWeapon)
{
int nWeapon = GetBaseItemType(oWeapon);
int nSound;
switch (nWeapon)
{
case BASE_ITEM_ALLUSE_SWORD: nSound = SOUND_TYPE_BLADE; break;
case BASE_ITEM_BASTARDSWORD: nSound = SOUND_TYPE_BLADE; break;
case BASE_ITEM_BATTLEAXE: nSound = SOUND_TYPE_BLADE; break;
case BASE_ITEM_DOUBLEAXE: nSound = SOUND_TYPE_BLADE; break;
case BASE_ITEM_DWARVENWARAXE: nSound = SOUND_TYPE_BLADE; break;
case BASE_ITEM_FALCHION: nSound = SOUND_TYPE_BLADE; break;
case BASE_ITEM_GREATAXE: nSound = SOUND_TYPE_BLADE; break;
case BASE_ITEM_GREATSWORD: nSound = SOUND_TYPE_BLADE; break;
case BASE_ITEM_HALBERD: nSound = SOUND_TYPE_BLADE; break;
case BASE_ITEM_HANDAXE: nSound = SOUND_TYPE_BLADE; break;
case BASE_ITEM_KAMA: nSound = SOUND_TYPE_BLADE; break;
case BASE_ITEM_KATANA: nSound = SOUND_TYPE_BLADE; break;
case BASE_ITEM_LONGSWORD: nSound = SOUND_TYPE_BLADE; break;
case BASE_ITEM_RAPIER: nSound = SOUND_TYPE_BLADE; break;
case BASE_ITEM_SCIMITAR: nSound = SOUND_TYPE_BLADE; break;
case BASE_ITEM_SCYTHE: nSound = SOUND_TYPE_BLADE; break;
case BASE_ITEM_SHORTSPEAR: nSound = SOUND_TYPE_BLADE; break;
case BASE_ITEM_SHORTSWORD: nSound = SOUND_TYPE_BLADE; break;
case BASE_ITEM_SICKLE: nSound = SOUND_TYPE_BLADE; break;
case BASE_ITEM_SPEAR: nSound = SOUND_TYPE_BLADE; break;
case BASE_ITEM_TWOBLADEDSWORD: nSound = SOUND_TYPE_BLADE; break;
case BASE_ITEM_CLUB: nSound = SOUND_TYPE_BLUNT; break;
case BASE_ITEM_DIREMACE: nSound = SOUND_TYPE_BLUNT; break;
case BASE_ITEM_GREATCLUB: nSound = SOUND_TYPE_BLUNT; break;
case BASE_ITEM_LIGHTHAMMER: nSound = SOUND_TYPE_BLUNT; break;
case BASE_ITEM_LIGHTMACE: nSound = SOUND_TYPE_BLUNT; break;
case BASE_ITEM_MACE: nSound = SOUND_TYPE_BLUNT; break;
case BASE_ITEM_MAGICROD: nSound = SOUND_TYPE_BLUNT; break;
case BASE_ITEM_MAGICSTAFF: nSound = SOUND_TYPE_BLUNT; break;
case BASE_ITEM_MORNINGSTAR: nSound = SOUND_TYPE_BLUNT; break;
case BASE_ITEM_QUARTERSTAFF: nSound = SOUND_TYPE_BLUNT; break;
case BASE_ITEM_TRAINING_CLUB: nSound = SOUND_TYPE_BLUNT; break;
case BASE_ITEM_WARHAMMER: nSound = SOUND_TYPE_BLUNT; break;
case BASE_ITEM_WARMACE: nSound = SOUND_TYPE_BLUNT; break;
case BASE_ITEM_DART: nSound = SOUND_TYPE_RANGED; break;
case BASE_ITEM_GRENADE: nSound = SOUND_TYPE_RANGED; break;
case BASE_ITEM_HEAVYCROSSBOW: nSound = SOUND_TYPE_RANGED; break;
case BASE_ITEM_LIGHTCROSSBOW: nSound = SOUND_TYPE_RANGED; break;
case BASE_ITEM_LONGBOW: nSound = SOUND_TYPE_RANGED; break;
case BASE_ITEM_SHORTBOW: nSound = SOUND_TYPE_RANGED; break;
case BASE_ITEM_SHURIKEN: nSound = SOUND_TYPE_RANGED; break;
case BASE_ITEM_SLING: nSound = SOUND_TYPE_RANGED; break;
case BASE_ITEM_THROWINGAXE: nSound = SOUND_TYPE_RANGED; break;
case BASE_ITEM_DAGGER: nSound = SOUND_TYPE_DAGGER; break;
case BASE_ITEM_KUKRI: nSound = SOUND_TYPE_DAGGER; break;
case BASE_ITEM_WHIP: nSound = SOUND_TYPE_WHIP; break;
default: nSound = SOUND_TYPE_INVALID;break;
}
return nSound;
}
// Returns the material sound of oWeapon if GetWeaponSoundType returns SOUND_TYPE_BLUNT.
int GetBluntWeaponSound(object oWeapon)
{
int nWeapon = GetBaseItemType(oWeapon);
int nSound;
switch (nWeapon)
{
case BASE_ITEM_DIREMACE: nSound = SOUND_TYPE_METAL; break;
case BASE_ITEM_LIGHTHAMMER: nSound = SOUND_TYPE_METAL; break;
case BASE_ITEM_LIGHTMACE: nSound = SOUND_TYPE_METAL; break;
case BASE_ITEM_MACE: nSound = SOUND_TYPE_METAL; break;
case BASE_ITEM_MAGICROD: nSound = SOUND_TYPE_METAL; break;
case BASE_ITEM_MORNINGSTAR: nSound = SOUND_TYPE_METAL; break;
case BASE_ITEM_WARHAMMER: nSound = SOUND_TYPE_METAL; break;
case BASE_ITEM_WARMACE: nSound = SOUND_TYPE_METAL; break;
case BASE_ITEM_CLUB: nSound = SOUND_TYPE_WOOD; break;
case BASE_ITEM_GREATCLUB: nSound = SOUND_TYPE_WOOD; break;
case BASE_ITEM_MAGICSTAFF: nSound = SOUND_TYPE_WOOD; break;
case BASE_ITEM_QUARTERSTAFF: nSound = SOUND_TYPE_WOOD; break;
case BASE_ITEM_TRAINING_CLUB: nSound = SOUND_TYPE_WOOD; break;
default: nSound = SOUND_TYPE_INVALID;break;
}
return nSound;
}
// Plays an OnHit sound corresponding to the appropriate item property.
// Unlike weapon damage sounds these can be played simultaneously.
// -oWeapon: The item we're getting properties from.
// -oFoe: Deterimines where the sound will be played.
void StrikeItemPropSound(object oWeapon, object oFoe)
{
object oPC = OBJECT_SELF;
location lFoe = GetLocation(oFoe);
itemproperty iProp = GetFirstItemProperty(oWeapon);
while (GetIsItemPropertyValid(iProp))
{
if (GetItemPropertyType(iProp) == ITEM_PROPERTY_DAMAGE_BONUS)
{
switch (GetItemPropertySubType(iProp))
{
case IP_CONST_DAMAGETYPE_ACID: WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_i_acid", lFoe); break;
case IP_CONST_DAMAGETYPE_COLD: WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_i_cold", lFoe); break;
case IP_CONST_DAMAGETYPE_DIVINE: WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_i_holy", lFoe); break;
case IP_CONST_DAMAGETYPE_ELECTRICAL: WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_i_elec", lFoe); break;
case IP_CONST_DAMAGETYPE_FIRE: WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_i_fire", lFoe); break;
case IP_CONST_DAMAGETYPE_NEGATIVE: WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_i_dark", lFoe); break;
case IP_CONST_DAMAGETYPE_POSITIVE: WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_i_holy", lFoe); break;
case IP_CONST_DAMAGETYPE_SONIC: WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_i_holy", lFoe); break;
}
}
/* else if (GetItemPropertyType(iProp) == ITEM_PROPERTY_ON_HIT_PROPERTIES) //Commented out until I can make these sounds only active when the effect beats the DC.
{
switch (GetItemPropertySubType(iProp))
{
case IP_CONST_ONHIT_ABILITYDRAIN: WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_i_dark", lFoe); break;
case IP_CONST_ONHIT_BLINDNESS: WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_i_dark", lFoe); break;
case IP_CONST_ONHIT_CONFUSION: WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_i_dark", lFoe); break;
case IP_CONST_ONHIT_DAZE: WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_i_dark", lFoe); break;
case IP_CONST_ONHIT_DEAFNESS: WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_i_dark", lFoe); break;
case IP_CONST_ONHIT_DISEASE: WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_i_acid", lFoe); break;
case IP_CONST_ONHIT_DISPELMAGIC: WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_i_dis", lFoe); break;
case IP_CONST_ONHIT_DOOM: WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_i_dark", lFoe); break;
case IP_CONST_ONHIT_FEAR: WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_i_dark", lFoe); break;
case IP_CONST_ONHIT_GREATERDISPEL: WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_i_dis", lFoe); break;
case IP_CONST_ONHIT_HOLD: WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_i_dark", lFoe); break;
case IP_CONST_ONHIT_ITEMPOISON: WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_i_acid", lFoe); break;
case IP_CONST_ONHIT_KNOCK: WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_i_dis", lFoe); break;
case IP_CONST_ONHIT_LESSERDISPEL: WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_i_dis", lFoe); break;
case IP_CONST_ONHIT_LEVELDRAIN: WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_i_dark", lFoe); break;
case IP_CONST_ONHIT_MORDSDISJUNCTION: WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_i_dis", lFoe); break;
case IP_CONST_ONHIT_SILENCE: WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_i_dark", lFoe); break;
case IP_CONST_ONHIT_SLEEP: WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_i_dark", lFoe); break;
case IP_CONST_ONHIT_SLOW: WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_i_dark", lFoe); break;
case IP_CONST_ONHIT_STUN: WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_i_dark", lFoe); break;
case IP_CONST_ONHIT_VORPAL: WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_i_dark", lFoe); break;
case IP_CONST_ONHIT_WOUNDING: WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_i_dark", lFoe); break;
}
}*/
if (GetItemPropertyType(iProp) == ITEM_PROPERTY_HOLY_AVENGER)
{
WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_i_holy", lFoe);
}
if (GetItemPropertyType(iProp) == ITEM_PROPERTY_REGENERATION_VAMPIRIC)
{
WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_i_dark", lFoe);
}
iProp = GetNextItemProperty(oWeapon);
}
}
// Plays a sound based on the results of StrikeAttackRoll.
// -oWeapon: Weapon in right or left hand.
// -oTarget: Creature where we want to play the hit or miss sound.
// -nHit: Either a miss, hit, or critical hit. 0, 1, or 2.
// -fDelay: Amount of time to delay the sound effect by.
// There is a minimum 0.1 delay while the sound creature is created.
// -nAttackCry: Plays the character's attacking grunt sound while set to TRUE.
// Set it to FALSE if you wish to use another sound or none at all when attacking.
void StrikeAttackSound(object oWeapon, object oTarget, int nHit, float fDelay = 0.0f, int bAttackCry = TRUE)
{
object oPC = OBJECT_SELF;
int nWeapon = GetBaseItemType(oWeapon);
int nSoundCategory = GetWeaponSoundType(oWeapon);
int nWooden = GetBluntWeaponSound(oWeapon);
int nFoe = GetObjectType(oTarget);
int nFoeSkin = GetSubRace(oTarget);
int nFoeArmor = GetArmorRank(GetItemInSlot(INVENTORY_SLOT_CHEST, oTarget));
location lTarget = GetLocation(oTarget);
if (bAttackCry == TRUE)
{
int nD3 = d3(1);
switch (nD3)
{
case 1: PlayVoiceChat(VOICE_CHAT_GATTACK1, oPC); break;
case 2: PlayVoiceChat(VOICE_CHAT_GATTACK2, oPC); break;
case 3: PlayVoiceChat(VOICE_CHAT_GATTACK3, oPC); break;
}
}
if (nHit == 2)
{
DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_crit", lTarget));
DelayCommand(fDelay + 0.1f, StrikeItemPropSound(oWeapon, oTarget));
}
else if (nHit == 0)
{
if (nWeapon == BASE_ITEM_FLAIL)
{
DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_missflail", lTarget));
}
else if (nWeapon == BASE_ITEM_HEAVYFLAIL)
{
DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_missflail", lTarget));
}
else if (nWeapon == BASE_ITEM_LIGHTFLAIL)
{
DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_missflail", lTarget));
}
else if (nWeapon == BASE_ITEM_WHIP)
{
DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_misswhip", lTarget));
}
else if (nSoundCategory == SOUND_TYPE_BLADE)
{
DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_missbld", lTarget));
}
else if (nSoundCategory == SOUND_TYPE_BLUNT)
{
if (nWooden == SOUND_TYPE_WOOD)
{
DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_misswood", lTarget));
}
else DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_missblnt", lTarget));
}
else if (nSoundCategory == SOUND_TYPE_RANGED)
{
if (nWeapon == BASE_ITEM_HEAVYCROSSBOW)
{
DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_missxbow", lTarget));
}
else if (nWeapon == BASE_ITEM_LIGHTCROSSBOW)
{
DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_missxbow", lTarget));
}
else DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_missbow", lTarget));
}
else if (nSoundCategory == SOUND_TYPE_DAGGER)
{
DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_missdgr", lTarget));
}
else DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_missua", lTarget));
}
else if (nHit == 1)
{
DelayCommand(fDelay + 0.1f, StrikeItemPropSound(oWeapon, oTarget));
if (nFoe != OBJECT_TYPE_CREATURE)
{
if (nSoundCategory != SOUND_TYPE_BLUNT)
{
switch (nSoundCategory)
{
case SOUND_TYPE_BLADE: DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_bld2st", lTarget)); break;
case SOUND_TYPE_DAGGER: DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_d2st", lTarget)); break;
case SOUND_TYPE_RANGED: DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_arrow", lTarget)); break;
case SOUND_TYPE_WHIP: DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_wp2st", lTarget)); break;
case SOUND_TYPE_INVALID:DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_f2st", lTarget)); break;
}
}
else if (nSoundCategory == SOUND_TYPE_BLUNT)
{
if (nWooden == SOUND_TYPE_WOOD)
{
DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_w2st", lTarget));
}
else DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_m2st", lTarget));
}
}
else if (nFoeSkin == RACIAL_SUBTYPE_OOZE || nFoeSkin == RACIAL_SUBTYPE_INCORPOREAL)
{
DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_eth", lTarget));
}
else if (nFoeSkin == RACIAL_SUBTYPE_DRAGON || nFoeSkin == RACIAL_SUBTYPE_HUMANOID_REPTILIAN || nFoeSkin == RACIAL_SUBTYPE_YUANTI)
{
DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_f2sc", lTarget));
}
else if (nFoeSkin == RACIAL_SUBTYPE_PLANT)
{
if (nSoundCategory != SOUND_TYPE_BLUNT)
{
switch (nSoundCategory)
{
case SOUND_TYPE_BLADE: DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_bld2w", lTarget)); break;
case SOUND_TYPE_DAGGER: DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_d2w", lTarget)); break;
case SOUND_TYPE_RANGED: DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_arrow", lTarget)); break;
case SOUND_TYPE_WHIP: DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_wp2w", lTarget)); break;
case SOUND_TYPE_INVALID:DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_f2w", lTarget)); break;
}
}
else if (nSoundCategory == SOUND_TYPE_BLUNT)
{
if (nWooden == SOUND_TYPE_WOOD)
{
DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_w2w", lTarget));
}
else DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_m2w", lTarget));
}
}
else if (nFoeSkin == RACIAL_SUBTYPE_CONSTRUCT)
{
if (nSoundCategory != SOUND_TYPE_BLUNT)
{
switch (nSoundCategory)
{
case SOUND_TYPE_BLADE: DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_bld2st", lTarget)); break;
case SOUND_TYPE_DAGGER: DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_d2st", lTarget)); break;
case SOUND_TYPE_RANGED: DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_arrow", lTarget)); break;
case SOUND_TYPE_WHIP: DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_wp2st", lTarget)); break;
case SOUND_TYPE_INVALID:DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_f2st", lTarget)); break;
}
}
else if (nSoundCategory == SOUND_TYPE_BLUNT)
{
if (nWooden == SOUND_TYPE_WOOD)
{
DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_w2st", lTarget));
}
else DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_m2st", lTarget));
}
}
else if (nFoeArmor == ARMOR_RANK_LIGHT)
{
if (nSoundCategory != SOUND_TYPE_BLUNT)
{
switch (nSoundCategory)
{
case SOUND_TYPE_BLADE: DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_bld2l", lTarget)); break;
case SOUND_TYPE_DAGGER: DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_d2l", lTarget)); break;
case SOUND_TYPE_RANGED: DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_arrow", lTarget)); break;
case SOUND_TYPE_WHIP: DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_wp2l", lTarget)); break;
case SOUND_TYPE_INVALID:DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_f2l", lTarget)); break;
}
}
else if (nSoundCategory == SOUND_TYPE_BLUNT)
{
if (nWooden == SOUND_TYPE_WOOD)
{
DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_w2l", lTarget));
}
else DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_m2l", lTarget));
}
}
else if (nFoeArmor == ARMOR_RANK_MEDIUM)
{
if (nSoundCategory != SOUND_TYPE_BLUNT)
{
switch (nSoundCategory)
{
case SOUND_TYPE_BLADE: DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_bld2ch", lTarget)); break;
case SOUND_TYPE_DAGGER: DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_d2ch", lTarget)); break;
case SOUND_TYPE_RANGED: DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_arrow", lTarget)); break;
case SOUND_TYPE_WHIP: DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_wp2ch", lTarget)); break;
case SOUND_TYPE_INVALID:DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_f2ch", lTarget)); break;
}
}
else if (nSoundCategory == SOUND_TYPE_BLUNT)
{
if (nWooden == SOUND_TYPE_WOOD)
{
DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_w2ch", lTarget));
}
else DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_m2ch", lTarget));
}
}
else if (nFoeArmor == ARMOR_RANK_HEAVY)
{
if (nSoundCategory != SOUND_TYPE_BLUNT)
{
switch (nSoundCategory)
{
case SOUND_TYPE_BLADE: DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_bld2p", lTarget)); break;
case SOUND_TYPE_DAGGER: DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_d2p", lTarget)); break;
case SOUND_TYPE_RANGED: DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_arrow", lTarget)); break;
case SOUND_TYPE_WHIP: DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_wp2p", lTarget)); break;
case SOUND_TYPE_INVALID:DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_f2p", lTarget)); break;
}
}
else if (nSoundCategory == SOUND_TYPE_BLUNT)
{
if (nWooden == SOUND_TYPE_WOOD)
{
DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_w2p", lTarget));
}
else DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_m2p", lTarget));
}
}
else if (nFoeArmor == ARMOR_RANK_NONE)
{
if (nSoundCategory != SOUND_TYPE_BLUNT)
{
switch (nSoundCategory)
{
case SOUND_TYPE_BLADE: DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_bld2l", lTarget)); break;
case SOUND_TYPE_DAGGER: DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_d2l", lTarget)); break;
case SOUND_TYPE_RANGED: DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_arrow", lTarget)); break;
case SOUND_TYPE_WHIP: DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_wp2l", lTarget)); break;
case SOUND_TYPE_INVALID:DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_f2l", lTarget)); break;
}
}
else if (nSoundCategory == SOUND_TYPE_BLUNT)
{
if (nWooden == SOUND_TYPE_WOOD)
{
DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_w2l", lTarget));
}
else DelayCommand(fDelay, WrapperCreateObject(OBJECT_TYPE_CREATURE, "c_soundfx_m2l", lTarget));
}
}
}
}
:Code:
// Returns TRUE if oWeapon is vaild for Weapon Finesse and similar feats.
int GetIsLightWeapon(object oWeapon, object oPC)
{
int nReturn;
int nWeapon = GetBaseItemType(oWeapon);
if (GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC) == OBJECT_INVALID)
{
nReturn = TRUE; // No base item const for unarmed strikes, but this is a close aproximation.
}
else
{
switch (nWeapon)
{
case BASE_ITEM_RAPIER: nReturn = TRUE; break;
case BASE_ITEM_WHIP: nReturn = TRUE; break;
case BASE_ITEM_DAGGER: nReturn = TRUE; break;
case BASE_ITEM_SICKLE: nReturn = TRUE; break;
case BASE_ITEM_LIGHTHAMMER: nReturn = TRUE; break;
case BASE_ITEM_THROWINGAXE: nReturn = TRUE; break;
case BASE_ITEM_HANDAXE: nReturn = TRUE; break;
case BASE_ITEM_KUKRI: nReturn = TRUE; break;
case BASE_ITEM_SHORTSWORD: nReturn = TRUE; break;
case BASE_ITEM_KAMA: nReturn = TRUE; break;
default: nReturn = FALSE; break;
}
}
return nReturn;
}
// Returns TRUE if oTarget is a favored enemy of oPC.
int GetIsFavoredEnemy(object oPC, object oTarget)
{
int nRace = GetRacialType(oTarget);
int nSubRace = GetSubRace(oTarget);
int bFEnemy;
switch (nRace)
{
case RACIAL_TYPE_DWARF: bFEnemy = GetHasFeat(261, oPC, TRUE); break;
case RACIAL_TYPE_ELF: bFEnemy = GetHasFeat(262, oPC, TRUE); break;
case RACIAL_TYPE_GNOME: bFEnemy = GetHasFeat(263, oPC, TRUE); break;
case RACIAL_TYPE_HALFLING: bFEnemy = GetHasFeat(264, oPC, TRUE); break;
case RACIAL_TYPE_HALFELF: bFEnemy = GetHasFeat(265, oPC, TRUE); break;
case RACIAL_TYPE_HALFORC: bFEnemy = GetHasFeat(266, oPC, TRUE); break;
case RACIAL_TYPE_HUMAN: bFEnemy = GetHasFeat(267, oPC, TRUE); break;
case RACIAL_TYPE_ABERRATION: bFEnemy = GetHasFeat(268, oPC, TRUE); break;
case RACIAL_TYPE_ANIMAL: bFEnemy = GetHasFeat(269, oPC, TRUE); break;
case RACIAL_TYPE_BEAST: bFEnemy = GetHasFeat(270, oPC, TRUE); break;
case RACIAL_TYPE_CONSTRUCT: bFEnemy = GetHasFeat(271, oPC, TRUE); break;
case RACIAL_TYPE_DRAGON: bFEnemy = GetHasFeat(272, oPC, TRUE); break;
case RACIAL_TYPE_HUMANOID_GOBLINOID: bFEnemy = GetHasFeat(273, oPC, TRUE); break;
case RACIAL_TYPE_HUMANOID_MONSTROUS: bFEnemy = GetHasFeat(274, oPC, TRUE); break;
case RACIAL_TYPE_HUMANOID_ORC: bFEnemy = GetHasFeat(275, oPC, TRUE); break;
case RACIAL_TYPE_HUMANOID_REPTILIAN: bFEnemy = GetHasFeat(276, oPC, TRUE); break;
case RACIAL_TYPE_ELEMENTAL: bFEnemy = GetHasFeat(277, oPC, TRUE); break;
case RACIAL_TYPE_FEY: bFEnemy = GetHasFeat(278, oPC, TRUE); break;
case RACIAL_TYPE_GIANT: bFEnemy = GetHasFeat(279, oPC, TRUE); break;
case RACIAL_TYPE_MAGICAL_BEAST: bFEnemy = GetHasFeat(280, oPC, TRUE); break;
case RACIAL_TYPE_OUTSIDER: bFEnemy = GetHasFeat(281, oPC, TRUE); break;
case RACIAL_TYPE_SHAPECHANGER: bFEnemy = GetHasFeat(284, oPC, TRUE); break;
case RACIAL_TYPE_UNDEAD: bFEnemy = GetHasFeat(285, oPC, TRUE); break;
case RACIAL_TYPE_VERMIN: bFEnemy = GetHasFeat(286, oPC, TRUE); break;
default: bFEnemy = FALSE; break;
}
if ((GetHasFeat(282, oPC, TRUE) == TRUE) && (nSubRace == RACIAL_SUBTYPE_PLANT)) // Plants have a subtype but not a race.
{
bFEnemy = TRUE;
}
return bFEnemy;
}
// Returns TRUE if oPC has Improved Favored Enemy for oTarget.
int GetIsImpFavoredEnemy(object oPC, object oTarget)
{
int nRace = GetRacialType(oTarget);
int nSubRace = GetSubRace(oTarget);
int bFEnemy;
switch (nRace)
{
case RACIAL_TYPE_DWARF: bFEnemy = GetHasFeat(1198, oPC, TRUE); break;
case RACIAL_TYPE_ELF: bFEnemy = GetHasFeat(1199, oPC, TRUE); break;
case RACIAL_TYPE_GNOME: bFEnemy = GetHasFeat(1200, oPC, TRUE); break;
case RACIAL_TYPE_HALFLING: bFEnemy = GetHasFeat(1201, oPC, TRUE); break;
case RACIAL_TYPE_HALFELF: bFEnemy = GetHasFeat(1202, oPC, TRUE); break;
case RACIAL_TYPE_HALFORC: bFEnemy = GetHasFeat(1203, oPC, TRUE); break;
case RACIAL_TYPE_HUMAN: bFEnemy = GetHasFeat(1204, oPC, TRUE); break;
case RACIAL_TYPE_ABERRATION: bFEnemy = GetHasFeat(1205, oPC, TRUE); break;
case RACIAL_TYPE_ANIMAL: bFEnemy = GetHasFeat(1206, oPC, TRUE); break;
case RACIAL_TYPE_BEAST: bFEnemy = GetHasFeat(1207, oPC, TRUE); break;
case RACIAL_TYPE_CONSTRUCT: bFEnemy = GetHasFeat(1208, oPC, TRUE); break;
case RACIAL_TYPE_DRAGON: bFEnemy = GetHasFeat(1209, oPC, TRUE); break;
case RACIAL_TYPE_HUMANOID_GOBLINOID: bFEnemy = GetHasFeat(1210, oPC, TRUE); break;
case RACIAL_TYPE_HUMANOID_MONSTROUS: bFEnemy = GetHasFeat(1211, oPC, TRUE); break;
case RACIAL_TYPE_HUMANOID_ORC: bFEnemy = GetHasFeat(1212, oPC, TRUE); break;
case RACIAL_TYPE_HUMANOID_REPTILIAN: bFEnemy = GetHasFeat(1213, oPC, TRUE); break;
case RACIAL_TYPE_ELEMENTAL: bFEnemy = GetHasFeat(1214, oPC, TRUE); break;
case RACIAL_TYPE_FEY: bFEnemy = GetHasFeat(1215, oPC, TRUE); break;
case RACIAL_TYPE_GIANT: bFEnemy = GetHasFeat(1216, oPC, TRUE); break;
case RACIAL_TYPE_MAGICAL_BEAST: bFEnemy = GetHasFeat(1217, oPC, TRUE); break;
case RACIAL_TYPE_OUTSIDER: bFEnemy = GetHasFeat(1218, oPC, TRUE); break;
case RACIAL_TYPE_SHAPECHANGER: bFEnemy = GetHasFeat(1219, oPC, TRUE); break;
case RACIAL_TYPE_UNDEAD: bFEnemy = GetHasFeat(1220, oPC, TRUE); break;
case RACIAL_TYPE_VERMIN: bFEnemy = GetHasFeat(1221, oPC, TRUE); break;
default: bFEnemy = FALSE; break;
}
if ((GetHasFeat(2055, oPC, TRUE) == TRUE) && (nSubRace == RACIAL_SUBTYPE_PLANT)) // Plants have a subtype but not a race.
{
bFEnemy = TRUE;
}
return bFEnemy;
}
// Returns TRUE if oPC has Power Attack Favored Enemy for oTarget.
int GetIsFavoredEnemyPA(object oPC, object oTarget)
{
int nRace = GetRacialType(oTarget);
int nSubRace = GetSubRace(oTarget);
int bFEnemy;
switch (nRace)
{
case RACIAL_TYPE_DWARF: bFEnemy = GetHasFeat(1222, oPC, TRUE); break;
case RACIAL_TYPE_ELF: bFEnemy = GetHasFeat(1223, oPC, TRUE); break;
case RACIAL_TYPE_GNOME: bFEnemy = GetHasFeat(1223, oPC, TRUE); break;
case RACIAL_TYPE_HALFLING: bFEnemy = GetHasFeat(1224, oPC, TRUE); break;
case RACIAL_TYPE_HALFELF: bFEnemy = GetHasFeat(1225, oPC, TRUE); break;
case RACIAL_TYPE_HALFORC: bFEnemy = GetHasFeat(1226, oPC, TRUE); break;
case RACIAL_TYPE_HUMAN: bFEnemy = GetHasFeat(1227, oPC, TRUE); break;
case RACIAL_TYPE_ABERRATION: bFEnemy = GetHasFeat(1228, oPC, TRUE); break;
case RACIAL_TYPE_ANIMAL: bFEnemy = GetHasFeat(1229, oPC, TRUE); break;
case RACIAL_TYPE_BEAST: bFEnemy = GetHasFeat(1230, oPC, TRUE); break;
case RACIAL_TYPE_CONSTRUCT: bFEnemy = GetHasFeat(1231, oPC, TRUE); break;
case RACIAL_TYPE_DRAGON: bFEnemy = GetHasFeat(1232, oPC, TRUE); break;
case RACIAL_TYPE_HUMANOID_GOBLINOID: bFEnemy = GetHasFeat(1233, oPC, TRUE); break;
case RACIAL_TYPE_HUMANOID_MONSTROUS: bFEnemy = GetHasFeat(1234, oPC, TRUE); break;
case RACIAL_TYPE_HUMANOID_ORC: bFEnemy = GetHasFeat(1235, oPC, TRUE); break;
case RACIAL_TYPE_HUMANOID_REPTILIAN: bFEnemy = GetHasFeat(1236, oPC, TRUE); break;
case RACIAL_TYPE_ELEMENTAL: bFEnemy = GetHasFeat(1237, oPC, TRUE); break;
case RACIAL_TYPE_FEY: bFEnemy = GetHasFeat(1238, oPC, TRUE); break;
case RACIAL_TYPE_GIANT: bFEnemy = GetHasFeat(1239, oPC, TRUE); break;
case RACIAL_TYPE_MAGICAL_BEAST: bFEnemy = GetHasFeat(1240, oPC, TRUE); break;
case RACIAL_TYPE_OUTSIDER: bFEnemy = GetHasFeat(1241, oPC, TRUE); break;
case RACIAL_TYPE_SHAPECHANGER: bFEnemy = GetHasFeat(1242, oPC, TRUE); break;
case RACIAL_TYPE_UNDEAD: bFEnemy = GetHasFeat(1243, oPC, TRUE); break;
case RACIAL_TYPE_VERMIN: bFEnemy = GetHasFeat(1244, oPC, TRUE); break;
default: bFEnemy = FALSE; break;
}
if ((GetHasFeat(2089, oPC, TRUE) == TRUE) && (nSubRace == RACIAL_SUBTYPE_PLANT)) // Plants have a subtype but not a race.
{
bFEnemy = TRUE;
}
return bFEnemy;
}
// Returns a specific ALIGNMENT constant for oTarget.
int GetAlignment(object oTarget)
{
int nGoodEvil = GetAlignmentGoodEvil(oTarget);
int nLawChaos = GetAlignmentLawChaos(oTarget);
int nAlignment;
if ((nGoodEvil == ALIGNMENT_GOOD) && (nLawChaos == ALIGNMENT_LAWFUL))
{
nAlignment = TYPE_ALIGNMENT_LG;
}
else if ((nGoodEvil == ALIGNMENT_GOOD) && (nLawChaos == ALIGNMENT_NEUTRAL) || (nLawChaos == ALIGNMENT_ALL))
{
nAlignment = TYPE_ALIGNMENT_NG;
}
else if ((nGoodEvil == ALIGNMENT_GOOD) && (nLawChaos == ALIGNMENT_CHAOTIC))
{
nAlignment = TYPE_ALIGNMENT_CG;
}
else if ((nGoodEvil == ALIGNMENT_NEUTRAL) || (nGoodEvil == ALIGNMENT_ALL) && (nLawChaos == ALIGNMENT_LAWFUL))
{
nAlignment = TYPE_ALIGNMENT_LN;
}
else if ((nGoodEvil == ALIGNMENT_NEUTRAL) || (nGoodEvil == ALIGNMENT_ALL) && (nLawChaos == ALIGNMENT_NEUTRAL) || (nLawChaos == ALIGNMENT_ALL))
{
nAlignment = TYPE_ALIGNMENT_TN;
}
else if ((nGoodEvil == ALIGNMENT_NEUTRAL) || (nGoodEvil == ALIGNMENT_ALL) && (nLawChaos == ALIGNMENT_CHAOTIC))
{
nAlignment = TYPE_ALIGNMENT_CN;
}
else if ((nGoodEvil == ALIGNMENT_EVIL) && (nLawChaos == ALIGNMENT_LAWFUL))
{
nAlignment = TYPE_ALIGNMENT_LE;
}
else if ((nGoodEvil == ALIGNMENT_EVIL) && (nLawChaos == ALIGNMENT_NEUTRAL) || (nLawChaos == ALIGNMENT_ALL))
{
nAlignment = TYPE_ALIGNMENT_NE;
}
else if ((nGoodEvil == ALIGNMENT_EVIL) && (nLawChaos == ALIGNMENT_CHAOTIC))
{
nAlignment = TYPE_ALIGNMENT_CE;
}
return nAlignment;
}
// Returns TRUE if oPC is Raging.
int GetIsRaging(object oPC)
{
int nReturn = FALSE;
if (GetHasSpellEffect(SPELLABILITY_BARBARIAN_RAGE, oPC) == TRUE)
{
return TRUE;
}
else if (GetHasSpellEffect(SPELLABILITY_EPIC_MIGHTY_RAGE, oPC) == TRUE)
{
return TRUE;
}
else if (GetHasSpellEffect(SPELLABILITY_RAGE_3, oPC) == TRUE)
{
return TRUE;
}
else if (GetHasSpellEffect(SPELLABILITY_RAGE_4, oPC) == TRUE)
{
return TRUE;
}
else if (GetHasSpellEffect(SPELLABILITY_RAGE_5, oPC) == TRUE)
{
return TRUE;
}
return nReturn;
}
// Returns the Z position of a vector as a float.
float GetZ(vector vPos)
{
float fReturn = vPos.z;
return fReturn;
}
// Returns an itemproperty from an item based on a desired itemproperty constant.
// nSubType by default ignores subtypes until a constant is entered as its value.
itemproperty GetItemPropertyByConst(int nItemProp, object oItem, int nSubType = -1)
{
itemproperty iNull = ItemPropertyNoDamage();
itemproperty ip = GetFirstItemProperty(oItem);
int nSub = GetItemPropertySubType(ip);
while (GetIsItemPropertyValid(ip))
{
if (GetItemPropertyType(ip) == nItemProp)
{
if (nSubType == -1 || nSub == nSubType)
{
return ip;
}
}
ip = GetNextItemProperty(oItem);
nSub = GetItemPropertySubType(ip);
}
return iNull; //47, No combat damage property.
}
//Returns the integer value of nSubType if it matches the subtype of the test item.
int GetItemPropertySubTypeByConst(int nItemProp, object oItem, int nSubType = -1)
{
itemproperty ip = GetFirstItemProperty(oItem);
int nSub = GetItemPropertySubType(ip);
while (GetIsItemPropertyValid(ip))
{
if (GetItemPropertyType(ip) == nItemProp)
{
if (nSubType == -1 || nSub == nSubType)
{
return nSubType;
}
}
ip = GetNextItemProperty(oItem);
nSub = GetItemPropertySubType(ip);
}
return -1; // Nothing should have this subtype.
}
// Returns a constant from an item based on a desired itemproperty constant.
// nSubType by default ignores subtypes until a constant is entered as its value.
int GetItemPropertyConst(itemproperty ip, int nItemProp, object oItem, int nSubType = -1)
{
int nSub = GetItemPropertySubType(ip);
if (GetItemPropertyType(ip) == nItemProp)
{
if (nSubType == -1 || nSub == nSubType)
{
return nItemProp;
}
}
return -1;
}
// Makes the caller of the function constantly turn to face oTarget.
void WatchOpponent(object oTarget, object oPC = OBJECT_SELF)
{
if (GetCurrentHitPoints(oTarget) > 0)
{
if (GetCurrentHitPoints(oPC) > 0)
{
TurnToFaceObject(oTarget, oPC);
}
}
else
{
object oNext = GetNearestCreature(CREATURE_TYPE_IS_ALIVE, REPUTATION_TYPE_ENEMY);
TurnToFaceObject(oNext, oPC);
}
}
Code:
const int IP_CONST_DAMAGEBONUS_11 = 21; const int IP_CONST_DAMAGEBONUS_12 = 22; const int IP_CONST_DAMAGEBONUS_13 = 23; const int IP_CONST_DAMAGEBONUS_14 = 24; const int IP_CONST_DAMAGEBONUS_15 = 25; const int IP_CONST_DAMAGEBONUS_16 = 26; const int IP_CONST_DAMAGEBONUS_17 = 27; const int IP_CONST_DAMAGEBONUS_18 = 28; const int IP_CONST_DAMAGEBONUS_19 = 29; const int IP_CONST_DAMAGEBONUS_20 = 30; const int IP_CONST_DAMAGEBONUS_21 = 31; const int IP_CONST_DAMAGEBONUS_22 = 32; const int IP_CONST_DAMAGEBONUS_23 = 33; const int IP_CONST_DAMAGEBONUS_24 = 34; const int IP_CONST_DAMAGEBONUS_25 = 35; const int IP_CONST_DAMAGEBONUS_26 = 36; const int IP_CONST_DAMAGEBONUS_27 = 37; const int IP_CONST_DAMAGEBONUS_28 = 38; const int IP_CONST_DAMAGEBONUS_29 = 39; const int IP_CONST_DAMAGEBONUS_30 = 40; const int IP_CONST_DAMAGEBONUS_31 = 41; const int IP_CONST_DAMAGEBONUS_32 = 42; const int IP_CONST_DAMAGEBONUS_33 = 43; const int IP_CONST_DAMAGEBONUS_34 = 44; const int IP_CONST_DAMAGEBONUS_35 = 45; const int IP_CONST_DAMAGEBONUS_36 = 46; const int IP_CONST_DAMAGEBONUS_37 = 47; const int IP_CONST_DAMAGEBONUS_38 = 48; const int IP_CONST_DAMAGEBONUS_39 = 49; const int IP_CONST_DAMAGEBONUS_40 = 50; // Alignment const int TYPE_ALIGNMENT_CE = 8; const int TYPE_ALIGNMENT_CG = 6; const int TYPE_ALIGNMENT_CN = 7; const int TYPE_ALIGNMENT_LE = 2; const int TYPE_ALIGNMENT_LG = 0; const int TYPE_ALIGNMENT_LN = 1; const int TYPE_ALIGNMENT_NE = 5; const int TYPE_ALIGNMENT_NG = 3; const int TYPE_ALIGNMENT_TN = 4; // Weapon Size const int WEAPON_SIZE_INVALID = 0; const int WEAPON_SIZE_TINY = 1; const int WEAPON_SIZE_SMALL = 2; const int WEAPON_SIZE_MEDIUM = 3; const int WEAPON_SIZE_LARGE = 4; // Sound Types const int SOUND_TYPE_INVALID = 0; const int SOUND_TYPE_BLADE = 1; const int SOUND_TYPE_BLUNT = 2; const int SOUND_TYPE_METAL = 3; const int SOUND_TYPE_WOOD = 4; const int SOUND_TYPE_RANGED = 5; const int SOUND_TYPE_DAGGER = 6; const int SOUND_TYPE_WHIP = 7; Last edited by Drammel; 04-05-2009 at 05:41 AM. |
|
#4
|
||||
|
||||
|
Okay now it's time to wrap everything up and put a pretty bow on it:
Code:
/* Note to self: Many of the feat constants in MotB and SoZ aren't listed
in nwscript and therefore are not listed in the toolset. Be sure to
check the manuals and feat.2da for any modifiers to these scripts. These
feats must be listed as their number from feat.2da rather than as a
constant. */
// Applies base weapon damage, visual effects and critical hit damage based on
// the results of StrikeAttackRoll. 0 for miss, 1 for hit, 2 for critical hit.
// -oWeapon: The weapon we're generating attack damage for.
// -nHit: The type of hit or miss we're generating a visual effect for.
// nHit also will apply critical hit damage if it equals 2.
// -oFoe: Our target gets chances to defend against certain effects!
effect BaseStrikeDamage(object oWeapon, int nHit, object oFoe)
{
object oPC = OBJECT_SELF;
string sMartialJournal = GetFirstName(oPC) + "martial_journal";
object oMartialJournal = GetObjectByTag(sMartialJournal);
effect eDamage = GenerateAttackEffect(oPC, oWeapon, oFoe);
effect eWeapon = GenerateItemProperties(oPC, oWeapon, oFoe);
effect eLink;
/* A Note on critical damage: The Stormlord PrC has a Shocking Busrt effect
listed in the MotB manual, but looking at the actual code one can see this is
erroneous. The actual effect is massive critical and even then it doesn't
scale with crit multiplier as described in the manual. Keep an eye out
for similar problems.*/
if (nHit == 1)
{
eLink = EffectLinkEffects(eDamage, eWeapon);
StrikeVFXDamage(oWeapon, nHit, oFoe);
if ((GetSneakLevels(oPC) > 0) && (IsTargetValidForSneakAttack(oFoe, oPC) == TRUE))
{
effect eSneak = SneakAttack(oWeapon, oPC, oFoe);
eLink = EffectLinkEffects(eLink, eSneak);
}
}
else if (nHit == 2)
{
effect eCrit = GenerateAttackEffect(oPC, oWeapon, oFoe);
eLink = EffectLinkEffects(eDamage, eWeapon);
eLink = EffectLinkEffects(eLink, eCrit);
effect eCritEffects = StrikeCriticalEffect(oPC, oWeapon, oFoe);
eLink = EffectLinkEffects(eLink, eCritEffects);
StrikeVFXDamage(oWeapon, nHit, oFoe);
if (GetCriticalMultiplier(oWeapon) > 2)
{
effect eCrit3 = GenerateAttackEffect(oPC, oWeapon, oFoe);
eLink = EffectLinkEffects(eLink, eCrit3);
}
if (GetCriticalMultiplier(oWeapon) > 3)
{
effect eCrit4 = GenerateAttackEffect(oPC, oWeapon, oFoe);
eLink = EffectLinkEffects(eLink, eCrit4);
}
if (GetCriticalMultiplier(oWeapon) > 4)
{
effect eCrit5 = GenerateAttackEffect(oPC, oWeapon, oFoe);
eLink = EffectLinkEffects(eLink, eCrit5);
}
if ((GetSneakLevels(oPC) > 0) && (IsTargetValidForSneakAttack(oFoe, oPC) == TRUE))
{
effect eSneak = SneakAttack(oWeapon, oPC, oFoe);
eLink = EffectLinkEffects(eLink, eSneak);
}
}
return eLink;
}
// Applies misc permanent effects to a strike and must be applied seperately from BaseStrikeDamage
effect StrikePermanentEffects(object oWeapon, int nHit, object oFoe)
{
object oPC = OBJECT_SELF;
string sMartialJournal = GetFirstName(oPC) + "martial_journal";
object oMartialJournal = GetObjectByTag(sMartialJournal);
effect eLink;
if (nHit == 1)
{
if ((GetHasFeat(FEAT_CRIPPLING_STRIKE, oPC) == TRUE) && (GetIsImmune(oFoe, IMMUNITY_TYPE_CRITICAL_HIT) == FALSE) && (GetLocalInt(oMartialJournal, "SneakHasHit") == 1))
{
effect eCrippling = EffectAbilityDecrease(ABILITY_STRENGTH, 2);
eLink = EffectLinkEffects(eCrippling, eLink);
}
}
// Critical Hit only.
if (nHit == 2)
{
if ((GetIsImmune(oFoe, IMMUNITY_TYPE_CRITICAL_HIT) == FALSE) && (GetHasFeat(2150, oPC) == TRUE)) //Weakening Critical
{
effect eWeakeningCrit = EffectAbilityDecrease(ABILITY_STRENGTH, 2);
eLink = EffectLinkEffects(eLink, eWeakeningCrit);
}
if ((GetIsImmune(oFoe, IMMUNITY_TYPE_CRITICAL_HIT) == FALSE) && (GetHasFeat(2151, oPC) == TRUE)) //Wounding Critical
{
effect eWoundingCrit = EffectAbilityDecrease(ABILITY_CONSTITUTION, 2);
eLink = EffectLinkEffects(eLink, eWoundingCrit);
}
}
return eLink;
}
// Applies the results of weapon and feat modifiers on a martial strike.
// -oWeapon: Either right or left hand are vaild. (GetItemInSlot returning
// OBJECT_INVALID should return unarmed damage.
// -nHit: 0 for miss, 1 for hit, 2 for critical hit.
// -oFoe: The target of the strike.
void StrikeWeaponDamage(object oWeapon, int nHit, object oFoe)
{
object oPC = OBJECT_SELF;
effect eBase = BaseStrikeDamage(oWeapon, nHit, oFoe);
effect ePerm = StrikePermanentEffects(oWeapon, nHit, oFoe);
StrikeTrailEffect(oWeapon, nHit);
WatchOpponent(oFoe, oPC);
DelayCommand(0.5f, WatchOpponent(oFoe, oPC));
DelayCommand(1.5f, WatchOpponent(oFoe, oPC));
DelayCommand(2.5f, WatchOpponent(oFoe, oPC));
DelayCommand(3.5f, WatchOpponent(oFoe, oPC));
DelayCommand(4.5f, WatchOpponent(oFoe, oPC));
DelayCommand(5.5f, WatchOpponent(oFoe, oPC));
if (nHit == 0)
{
SendMessageToPC(oPC, "<color=paleturquoise>" + GetName(oPC) + "</color>" + "<color=chocolate> misses the " + GetName(oFoe) + ".</color>");
return;
}
else if (nHit == 2)
{
FloatingTextStringOnCreature("<color=red>*Critical Hit!*</color>", oPC, TRUE, 3.0f, COLOR_RED, COLOR_RED_DARK);
}
if (nHit > 0)
{
if (GetItemHasItemProperty(oWeapon, ITEM_PROPERTY_REGENERATION_VAMPIRIC) == TRUE)
{
itemproperty iVamp = GetFirstItemProperty(oWeapon);
while (GetIsItemPropertyValid(iVamp))
{
if (GetItemPropertyType(iVamp) == ITEM_PROPERTY_REGENERATION_VAMPIRIC)
{
int nVamp = GetDamageByIPConstDamageBonus(GetItemPropertyCostTableValue(iVamp));
effect eVamp = EffectHeal(nVamp);
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVamp, oPC);
break;
}
iVamp = GetNextItemProperty(oWeapon);
}
}
if (GetWeaponRanged(oWeapon) == TRUE)
{
int nBaseType = GetBaseItemType(oWeapon);
object oAmmo;
if (nBaseType == BASE_ITEM_LIGHTCROSSBOW || nBaseType == BASE_ITEM_HEAVYCROSSBOW)
oAmmo = GetItemInSlot(INVENTORY_SLOT_BOLTS);
if (nBaseType == BASE_ITEM_LONGBOW || nBaseType == BASE_ITEM_SHORTBOW)
oAmmo = GetItemInSlot(INVENTORY_SLOT_ARROWS);
if (nBaseType == BASE_ITEM_SLING)
oAmmo = GetItemInSlot(INVENTORY_SLOT_BULLETS);
itemproperty iVamp = GetFirstItemProperty(oAmmo);
while (GetIsItemPropertyValid(iVamp))
{
if (GetItemPropertyType(iVamp)== ITEM_PROPERTY_REGENERATION_VAMPIRIC)
{
int nVamp = GetDamageByIPConstDamageBonus(GetItemPropertyCostTableValue(iVamp));
effect eVamp = EffectHeal(nVamp);
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVamp, oPC);
break;
}
iVamp = GetNextItemProperty(oWeapon);
}
}
}
ApplyEffectToObject(DURATION_TYPE_INSTANT, eBase, oFoe);
ApplyEffectToObject(DURATION_TYPE_PERMANENT, ePerm, oFoe);
if ((GetHasFeat(2054, oPC) == TRUE) || (GetHasFeat(2053, oPC) == TRUE) || (GetHasFeat(2052, oPC) == TRUE)) //Bleeding Wound 1-3
{
effect eBlW = IBBleedingWound();
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eBlW, oFoe, 18.0f);
}
if ((GetWeaponRanged(oWeapon) == TRUE) && (GetHasFeat(FEAT_TW_MISSILE_VOLLEYS, oPC) == TRUE))
{
effect eVolley = MissileVolley(oPC, oWeapon);
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eVolley, oFoe, 6.0f);
}
}
Code:
//////////////////////////////////////////////
// Author: Drammel //
// Date: 2/9/2009 //
// Title: gui_st_stnbones //
// Description: Standard Action; On a //
// successful hit with this maneuver, gain //
// DR 5/adamantine. //
//////////////////////////////////////////////
#include "bot9s_inc_maneuvers"
void main()
{
object oPC = OBJECT_SELF;
string sMartialJournal = GetFirstName(oPC) + "martial_journal";
object oMartialJournal = GetObjectByTag(sMartialJournal);
object oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC);
SetLocalInt(oMartialJournal, "StoneDragonStrike", 1);
DelayCommand(6.0f, SetLocalInt(oMartialJournal, "StoneDragonStrike", 0));
NotMyFoe("StoneBones");
object oTarget = IntToObject(GetLocalInt(oMartialJournal, "StoneBones"));
int nHit = StrikeAttackRoll(oWeapon, oTarget);
if (GetIsInMeleeRange(oTarget, oPC) == TRUE)
{
StrikeAttackSound(oWeapon, oTarget, nHit, 0.2f);
BasicAttackAnimation(oWeapon);
DelayCommand(0.3f, StrikeWeaponDamage(oWeapon, nHit, oTarget));
if (nHit == 1 || nHit == 2)
{
effect eVis = EffectVisualEffect(VFX_STRIKE_STONE_BONES);
effect eDR = EffectDamageReduction(5, DR_TYPE_NONE, 0, GMATERIAL_METAL_ADAMANTINE);
effect eLink = EffectLinkEffects(eVis, eDR);
eLink = ExtraordinaryEffect(eLink);
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oPC, 6.0f);
}
}
else SendMessageToPC(oPC, "You are not in melee range.");
}
)
Last edited by Drammel; 04-21-2009 at 07:20 PM. Reason: more vfx |
|
#5
|
||||
|
||||
|
Hey, for someone who just picked up scripting, you seem to be doing an admirable job!
Good stuff there.
|
|
#6
|
|||
|
|||
|
Wow!
My eyes glazed over. One thing I am sure of, though, is you're seemingly extremely thorough. I may have some ideas I'd like to bounce off your head once you're through converting the Tome of Battle to NWN2. Almost all of it non-combat related. Between you and pain, I might actually start to really understand this stuff. best regards, dunniteowl
__________________
Simple does not mean easy. Easy does not mean without value. Value is not always measured with money. Money isn't class. Class is not superiority. Superiority is not being better than something or somebody. We are all somebody. |
|
#7
|
|||
|
|||
|
Woo Hoo! Lotta goodies in there!
|
|
#8
|
|||
|
|||
|
Well all i can say is, i'd like to merge this in with the common scripting library.
Tome of battle is one of the best things ever done for D&D and i hear instant feats will be possible very soon. Some of it is duplicated, some of it is really cool things being added, but it all fits under the Combat include really. Mainly the supporting functions ( like the constants ) which hopefully means the finished product is easier to maintain. But i'd really like to have the tome of battle features implemented. You also should look up the PRC codebase and pull from that. They have a lot of combat related functions already implemented. ( Ladydesire maintains it ). My goal with the common scripting library is to make it a central script library which has all those difficult functions in the center, from which many diverse projects can pull as needed, but when an update to the game is made ( new expansion or patch ) the central library being updated is all you need to update your scripts for the new version. Last edited by pain; 04-06-2009 at 11:50 PM. |
|
#9
|
||||
|
||||
|
Wow, instant feats. Funny you mention that, I'm currently setting up to do my first crop of those, if by instant you mean 'click it and something happens without the engine throwing a fit over the action queue'. Can't post anything yet because I'm in the middle of a major overhaul of my original framework. Right now I'm here, slacking off because a UIGrid is being a bit of a pain and I'm not quite mentally ready to tackle it again. Good news is that it's easier than I thought it would be to change up. I suppose last time I had no idea how I was going to get from point A to B. Coming from B and back again does make a difference.
The framework I've mocked up will have same functionality, but it's much cleaner and easier to edit. Now that I'm on the cusp of seriously writing out the maneuvers, editing that framework has become more and more important as weird little nuances of the maneuvers crop up. I still have no idea what I'm going to do for things like the one stance that lets you walk on walls, for example. Translating stuff like that into NWN2 is just going to have to take a DM-style judgment call. Good news is that in the framework's new form it'll be easier for other people to adapt it to their heart's content. Less learning curve more use (y'know in a perfect world). It's kinda scary how much I've learned since January looking at my first bunch of scripts. I suppose I should mention how this rig works. Essentially, I'm using the new recipe bags from SoZ as a spellbook (or maneuverbook or whatever). Items representing maneuvers go in (and incidentally, cannot go out again unless script destroys them), custom gui is clicked, scripts do indexing based on what's in the container, icons appear on a few menus, and clicking them selects and/or executes maneuvers. That's the quick and dirty way to describe it. Perhaps, not the best method ever, but it does allow me to do a few things such as implement those instant style feats, swift actions (of which, about half of all maneuvers are), and stuff like Smite Evil or Charge. I think that's worth a tiny bit wonkyness. By the way, thanks for the kind words, I really wasn't sure how much of this would be useful, but you've encouraged me to quit slacking and jump back into the frey. Here I come UIGrid! |
|
#10
|
|||
|
|||
|
Please don't stop.
Instant feats will happen soon, officially. Don't kill your self over it. Rumor has it they are on the drawing board. And you should review the PRC, you will find they've already done a lot of what you are looking at. The critical hits and sneak routines came from there originally i believe. Get on IRC and bug Kemo, and sunjammer about the UIGrid, Grinning fool kind of knows it too. There are very few folks who can actually code the UI to do what they want. Which is why you are having trouble i imagine. |
![]() |
| Thread Tools | |
| Display Modes | |
|
|