129 lines
4.7 KiB
Plaintext
129 lines
4.7 KiB
Plaintext
#include "color_inc"
|
|
|
|
|
|
void main()
|
|
{
|
|
object oTarget = OBJECT_SELF;
|
|
object oAttacker = GetLastAttacker(oTarget);
|
|
object oWeapon = GetLastWeaponUsed(oAttacker);
|
|
|
|
// Sanity check - Ranged weapon?
|
|
if(!GetWeaponRanged(oWeapon)) return;
|
|
|
|
// d20 roll as base, apply penalties/bonuses to this:
|
|
int nRoll = d20();
|
|
|
|
// Critical Miss.
|
|
if(nRoll == 1)
|
|
{
|
|
SpeakString(color_ConvertString("[missed]", "700"));
|
|
return;
|
|
}
|
|
|
|
// Critical hit. Rather than automatic hit, just a nice bonus
|
|
if(nRoll == 20) nRoll += 5;
|
|
|
|
|
|
//Base Attack Bonus
|
|
nRoll += GetBaseAttackBonus(oAttacker);
|
|
//Dexterity Bonus
|
|
nRoll += GetAbilityModifier(ABILITY_DEXTERITY, oAttacker);
|
|
|
|
// +3 bonus for called shot
|
|
nRoll += 3 * GetHasFeat(FEAT_CALLED_SHOT, oAttacker);
|
|
|
|
|
|
// Weapon focus/specialization and Improved Critical all add +1 bonus.
|
|
switch(GetBaseItemType(oWeapon))
|
|
{
|
|
case BASE_ITEM_DART:
|
|
nRoll += GetHasFeat(FEAT_WEAPON_FOCUS_DART, oAttacker);
|
|
nRoll += GetHasFeat(FEAT_WEAPON_SPECIALIZATION_DART, oAttacker);
|
|
nRoll += GetHasFeat(FEAT_IMPROVED_CRITICAL_DART, oAttacker);
|
|
break;
|
|
|
|
case BASE_ITEM_HEAVYCROSSBOW:
|
|
nRoll += GetHasFeat(FEAT_WEAPON_FOCUS_HEAVY_CROSSBOW, oAttacker);
|
|
nRoll += GetHasFeat(FEAT_WEAPON_SPECIALIZATION_HEAVY_CROSSBOW, oAttacker);
|
|
nRoll += GetHasFeat(FEAT_IMPROVED_CRITICAL_HEAVY_CROSSBOW, oAttacker);
|
|
break;
|
|
|
|
case BASE_ITEM_LIGHTCROSSBOW:
|
|
nRoll += GetHasFeat(FEAT_WEAPON_FOCUS_LIGHT_CROSSBOW, oAttacker);
|
|
nRoll += GetHasFeat(FEAT_WEAPON_SPECIALIZATION_LIGHT_CROSSBOW, oAttacker);
|
|
nRoll += GetHasFeat(FEAT_IMPROVED_CRITICAL_LIGHT_CROSSBOW, oAttacker);
|
|
break;
|
|
|
|
case BASE_ITEM_LONGBOW:
|
|
nRoll += GetHasFeat(FEAT_WEAPON_FOCUS_LONGBOW, oAttacker);
|
|
nRoll += GetHasFeat(FEAT_WEAPON_SPECIALIZATION_LONGBOW, oAttacker);
|
|
nRoll += GetHasFeat(FEAT_IMPROVED_CRITICAL_LONGBOW, oAttacker);
|
|
break;
|
|
|
|
case BASE_ITEM_SHORTBOW:
|
|
nRoll += GetHasFeat(FEAT_WEAPON_FOCUS_SHORTBOW, oAttacker);
|
|
nRoll += GetHasFeat(FEAT_WEAPON_SPECIALIZATION_SHORTBOW, oAttacker);
|
|
nRoll += GetHasFeat(FEAT_IMPROVED_CRITICAL_SHORTBOW, oAttacker);
|
|
break;
|
|
|
|
case BASE_ITEM_SHURIKEN:
|
|
nRoll += GetHasFeat(FEAT_WEAPON_FOCUS_SHURIKEN, oAttacker);
|
|
nRoll += GetHasFeat(FEAT_WEAPON_SPECIALIZATION_SHURIKEN, oAttacker);
|
|
nRoll += GetHasFeat(FEAT_IMPROVED_CRITICAL_SHURIKEN, oAttacker);
|
|
break;
|
|
|
|
case BASE_ITEM_SLING:
|
|
nRoll += GetHasFeat(FEAT_WEAPON_FOCUS_SLING, oAttacker);
|
|
nRoll += GetHasFeat(FEAT_WEAPON_SPECIALIZATION_SLING, oAttacker);
|
|
nRoll += GetHasFeat(FEAT_IMPROVED_CRITICAL_SLING, oAttacker);
|
|
break;
|
|
|
|
case BASE_ITEM_THROWINGAXE:
|
|
nRoll += GetHasFeat(FEAT_WEAPON_FOCUS_THROWING_AXE, oAttacker);
|
|
nRoll += GetHasFeat(FEAT_WEAPON_SPECIALIZATION_THROWING_AXE, oAttacker);
|
|
nRoll += GetHasFeat(FEAT_IMPROVED_CRITICAL_THROWING_AXE, oAttacker);
|
|
break;
|
|
}
|
|
|
|
// Distance penalty is double the number of meters to the target
|
|
float fDistance = GetDistanceBetween(oAttacker, oTarget);
|
|
nRoll -= 2 * FloatToInt(fDistance);
|
|
|
|
|
|
// Find out where it hit.
|
|
int nHit;
|
|
|
|
if (nRoll < 2) nHit = 0;
|
|
else if (nRoll < 4) nHit = 1;
|
|
else if (nRoll < 6) nHit = 2;
|
|
else if (nRoll < 8) nHit = 3;
|
|
else if (nRoll < 10) nHit = 4;
|
|
else if (nRoll < 12) nHit = 5;
|
|
else if (nRoll < 14) nHit = 6;
|
|
else if (nRoll < 16) nHit = 7;
|
|
else if (nRoll < 18) nHit = 8;
|
|
else if (nRoll < 20) nHit = 9;
|
|
else nHit = 10;
|
|
|
|
// Notify the players
|
|
string sMessage;
|
|
|
|
switch (nHit)
|
|
{
|
|
case 0: sMessage = color_ConvertString("[missed]", "700"); break;
|
|
case 1: sMessage = color_ConvertString("[1]", "720"); break;
|
|
case 2: sMessage = color_ConvertString("[2]", "740"); break;
|
|
case 3: sMessage = color_ConvertString("[3]", "750"); break;
|
|
case 4: sMessage = color_ConvertString("[4]", "760"); break;
|
|
case 5: sMessage = color_ConvertString("[5]", "770"); break;
|
|
case 6: sMessage = color_ConvertString("[6]", "670"); break;
|
|
case 7: sMessage = color_ConvertString("[7]", "570"); break;
|
|
case 8: sMessage = color_ConvertString("[8]", "470"); break;
|
|
case 9: sMessage = color_ConvertString("[9]", "270"); break;
|
|
case 10: sMessage = color_ConvertString("[BULLSEYE]", "070"); break;
|
|
}
|
|
|
|
SpeakString(sMessage);
|
|
|
|
}
|