mirror of
https://github.com/EQEmu/Server.git
synced 2026-04-12 01:32:25 +00:00
[Combat] Adjustments to Crippling Blows/Slay Undead and Confirmed Critical Code (#4354)
* Adjustments to Crippling Blows/Slay Undead and Confirmed Critical Code * Adjustments per comments
This commit is contained in:
parent
b044d8533e
commit
0d888268a8
@ -615,6 +615,8 @@ RULE_INT(Combat, PCAccuracyAvoidanceMod2Scale, 100, "Scale Factor for PC Accurac
|
|||||||
RULE_BOOL(Combat, AllowRaidTargetBlind, false, "Toggle to allow raid targets to be blinded, default is false (Live-like)")
|
RULE_BOOL(Combat, AllowRaidTargetBlind, false, "Toggle to allow raid targets to be blinded, default is false (Live-like)")
|
||||||
RULE_BOOL(Combat, RogueBackstabHasteCorrection, false, "Toggle to enable correction for Haste impacting Backstab DPS too much. DEFAULT: false")
|
RULE_BOOL(Combat, RogueBackstabHasteCorrection, false, "Toggle to enable correction for Haste impacting Backstab DPS too much. DEFAULT: false")
|
||||||
RULE_BOOL(Combat, LegacyComputeDefense, false, "Trim AGI Scaling of defense mostly for lower levels to help compensate for the newer agi based defense system. Default: False")
|
RULE_BOOL(Combat, LegacyComputeDefense, false, "Trim AGI Scaling of defense mostly for lower levels to help compensate for the newer agi based defense system. Default: False")
|
||||||
|
RULE_REAL(Combat, SlayDamageAdjustment, 0.5, "Slay Damage Adjustment - Multiply final slay damage by this value. Default: 0.5")
|
||||||
|
RULE_INT(Combat, MaximumLevelStunsCripplingBlow, 55, "Maximum level that Crippling Blows will stun a npc. Default: 55")
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
RULE_CATEGORY(NPC)
|
RULE_CATEGORY(NPC)
|
||||||
|
|||||||
324
zone/attack.cpp
324
zone/attack.cpp
@ -5388,6 +5388,101 @@ void Mob::TryPetCriticalHit(Mob *defender, DamageHitInfo &hit)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Mob::RollMeleeCritCheck(Mob *defender, EQ::skills::SkillType skill)
|
||||||
|
{
|
||||||
|
// We either require an innate crit chance or some SPA 169 to crit
|
||||||
|
bool innate_crit = false;
|
||||||
|
int crit_chance = GetCriticalChanceBonus(skill);
|
||||||
|
// Paladin check
|
||||||
|
if (defender->IsUndeadForSlay()) {
|
||||||
|
crit_chance = crit_chance + GetUndeadSlayRate();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetLevel() >= 12) {
|
||||||
|
if (
|
||||||
|
GetClass() == Class::Warrior ||
|
||||||
|
(GetClass() == Class::Ranger && skill == EQ::skills::SkillArchery) ||
|
||||||
|
(GetClass() == Class::Rogue && skill == EQ::skills::SkillThrowing) ||
|
||||||
|
GetClass() == Class::Berserker
|
||||||
|
) {
|
||||||
|
innate_crit = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// we have a chance to crit!
|
||||||
|
if (innate_crit || crit_chance) {
|
||||||
|
int difficulty = 0;
|
||||||
|
|
||||||
|
if (skill == EQ::skills::SkillArchery) {
|
||||||
|
difficulty = RuleI(Combat, ArcheryCritDifficulty);
|
||||||
|
} else if (skill == EQ::skills::SkillThrowing) {
|
||||||
|
difficulty = RuleI(Combat, ThrowingCritDifficulty);
|
||||||
|
} else {
|
||||||
|
difficulty = RuleI(Combat, MeleeCritDifficulty);
|
||||||
|
}
|
||||||
|
|
||||||
|
int roll = zone->random.Int(1, difficulty);
|
||||||
|
|
||||||
|
int dex_bonus = GetDEX();
|
||||||
|
|
||||||
|
if (dex_bonus > 255) {
|
||||||
|
dex_bonus = 255 + ((dex_bonus - 255) / 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
dex_bonus += 45; // chances did not match live without a small boost
|
||||||
|
|
||||||
|
// so if we have an innate crit we have a better chance, except for ber throwing
|
||||||
|
if (!innate_crit || (GetClass() == Class::Berserker && skill == EQ::skills::SkillThrowing)) {
|
||||||
|
dex_bonus = dex_bonus * 3 / 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
LogCombat("Crit Chance: dex_bonus ({}) * crit_chance ({}) / 100", dex_bonus, crit_chance);
|
||||||
|
|
||||||
|
if (crit_chance) {
|
||||||
|
dex_bonus += dex_bonus * crit_chance / 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if we crited
|
||||||
|
LogCombat("Final Roll! Difficulty = [{}] -- Dex_Bonus = [{}] ", difficulty, dex_bonus);
|
||||||
|
return (roll < dex_bonus);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Mob::GetUndeadSlayRate()
|
||||||
|
{
|
||||||
|
return aabonuses.SlayUndead[0] + itembonuses.SlayUndead[0] + spellbonuses.SlayUndead[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mob::DoUndeadSlay(DamageHitInfo &hit, int crit_mod)
|
||||||
|
{
|
||||||
|
|
||||||
|
int slay_damage_bonus = std::max(
|
||||||
|
{ aabonuses.SlayUndead[1], itembonuses.SlayUndead[1], spellbonuses.SlayUndead[1] });
|
||||||
|
|
||||||
|
LogCombatDetail("Slayundead bonus [{}]", slay_damage_bonus);
|
||||||
|
|
||||||
|
hit.damage_done = std::max(hit.damage_done, hit.base_damage) + 5;
|
||||||
|
hit.damage_done = (hit.damage_done * slay_damage_bonus * crit_mod) / 100;
|
||||||
|
hit.damage_done = static_cast<int>(hit.damage_done * RuleR(Combat, SlayDamageAdjustment));
|
||||||
|
|
||||||
|
LogCombatDetail("Slayundead damage [{}]", hit.damage_done);
|
||||||
|
|
||||||
|
int slay_sex = GetGender() == Gender::Female ? FEMALE_SLAYUNDEAD : MALE_SLAYUNDEAD;
|
||||||
|
|
||||||
|
entity_list.FilteredMessageString(
|
||||||
|
this, /* Sender */
|
||||||
|
false, /* Skip Sender */
|
||||||
|
Chat::MeleeCrit, /* Type: 301 */
|
||||||
|
FilterMeleeCrits, /* FilterType: 12 */
|
||||||
|
slay_sex, /* MessageFormat: %1's holy blade cleanses her target!(%2) */
|
||||||
|
GetCleanName(), /* Message1 */
|
||||||
|
itoa(hit.damage_done) /* Message2 */
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// a lot of good info: http://giline.versus.jp/shiden/damage_e.htm, http://giline.versus.jp/shiden/su.htm
|
||||||
void Mob::TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *opts)
|
void Mob::TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *opts)
|
||||||
{
|
{
|
||||||
#ifdef LUA_EQEMU
|
#ifdef LUA_EQEMU
|
||||||
@ -5414,185 +5509,116 @@ void Mob::TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsNPC() && !RuleB(Combat, NPCCanCrit))
|
if (IsNPC() && !RuleB(Combat, NPCCanCrit)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 1: Try Slay Undead
|
// Step 1: Check if we are critting
|
||||||
if (defender->GetBodyType() == BT_Undead || defender->GetBodyType() == BT_SummonedUndead ||
|
if (!RollMeleeCritCheck(defender, hit.skill)) {
|
||||||
defender->GetBodyType() == BT_Vampire) {
|
return;
|
||||||
int SlayRateBonus = aabonuses.SlayUndead[SBIndex::SLAYUNDEAD_RATE_MOD] + itembonuses.SlayUndead[SBIndex::SLAYUNDEAD_RATE_MOD] + spellbonuses.SlayUndead[SBIndex::SLAYUNDEAD_RATE_MOD];
|
}
|
||||||
if (SlayRateBonus) {
|
|
||||||
float slayChance = static_cast<float>(SlayRateBonus) / 10000.0f;
|
|
||||||
if (zone->random.Roll(slayChance)) {
|
|
||||||
int SlayDmgBonus = std::max(
|
|
||||||
{aabonuses.SlayUndead[SBIndex::SLAYUNDEAD_DMG_MOD], itembonuses.SlayUndead[SBIndex::SLAYUNDEAD_DMG_MOD], spellbonuses.SlayUndead[SBIndex::SLAYUNDEAD_DMG_MOD] });
|
|
||||||
hit.damage_done = std::max(hit.damage_done, hit.base_damage) + 5;
|
|
||||||
hit.damage_done = (hit.damage_done * SlayDmgBonus) / 100;
|
|
||||||
|
|
||||||
/* Female */
|
int crit_mod = EQ::ClampLower((170 + GetCritDmgMod(hit.skill)), 100);
|
||||||
if (GetGender() == Gender::Female) {
|
|
||||||
entity_list.FilteredMessageCloseString(
|
// Step 2: Calculate damage
|
||||||
this, /* Sender */
|
hit.damage_done = std::max(hit.damage_done, hit.base_damage) + 5;
|
||||||
false, /* Skip Sender */
|
int og_damage = hit.damage_done;
|
||||||
RuleI(Range, CriticalDamage),
|
hit.damage_done = hit.damage_done * crit_mod / 100;
|
||||||
Chat::MeleeCrit, /* Type: 301 */
|
|
||||||
FilterMeleeCrits, /* FilterType: 12 */
|
LogCombatDetail("Crit info: [{}] scaled from: [{}] - IsUndeadForSlay: [{}]", hit.damage_done, og_damage, IsUndeadForSlay() ? "true" : "false");
|
||||||
FEMALE_SLAYUNDEAD, /* MessageFormat: %1's holy blade cleanses her target!(%2) */
|
|
||||||
0,
|
// Try Slay Undead
|
||||||
GetCleanName(), /* Message1 */
|
if (defender->IsUndeadForSlay()) {
|
||||||
itoa(hit.damage_done + hit.min_damage) /* Message2 */
|
float chance = GetUndeadSlayRate() / 100.0f;
|
||||||
);
|
LogCombatDetail("Trying Undead slay: Chance: [{}]", chance);
|
||||||
}
|
|
||||||
/* Males and Neuter */
|
if(zone->random.Roll(chance)) {
|
||||||
else {
|
DoUndeadSlay(hit, crit_mod);
|
||||||
entity_list.FilteredMessageCloseString(
|
return;
|
||||||
this, /* Sender */
|
|
||||||
false, /* Skip Sender */
|
|
||||||
RuleI(Range, CriticalDamage),
|
|
||||||
Chat::MeleeCrit, /* Type: 301 */
|
|
||||||
FilterMeleeCrits, /* FilterType: 12 */
|
|
||||||
MALE_SLAYUNDEAD, /* MessageFormat: %1's holy blade cleanses his target!(%2) */
|
|
||||||
0,
|
|
||||||
GetCleanName(), /* Message1 */
|
|
||||||
itoa(hit.damage_done + hit.min_damage) /* Message2 */
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2: Try Melee Critical
|
// Step 3: Check deadly strike
|
||||||
// a lot of good info: http://giline.versus.jp/shiden/damage_e.htm, http://giline.versus.jp/shiden/su.htm
|
if (GetClass() == Class::Rogue && hit.skill == EQ::skills::SkillThrowing && BehindMob(defender, GetX(), GetY())) {
|
||||||
|
int chance = GetLevel() * 12;
|
||||||
|
if (zone->random.Int(1, 1000) < chance) {
|
||||||
|
// Check assassinate
|
||||||
|
int assassinate_damage = TryAssassinate(defender, hit.skill);
|
||||||
|
|
||||||
// We either require an innate crit chance or some SPA 169 to crit
|
if (assassinate_damage) {
|
||||||
bool innate_crit = false;
|
hit.damage_done = assassinate_damage;
|
||||||
int crit_chance = GetCriticalChanceBonus(hit.skill);
|
|
||||||
if ((GetClass() == Class::Warrior || GetClass() == Class::Berserker) && GetLevel() >= 12)
|
|
||||||
innate_crit = true;
|
|
||||||
else if (GetClass() == Class::Ranger && GetLevel() >= 12 && hit.skill == EQ::skills::SkillArchery)
|
|
||||||
innate_crit = true;
|
|
||||||
else if (GetClass() == Class::Rogue && GetLevel() >= 12 && hit.skill == EQ::skills::SkillThrowing)
|
|
||||||
innate_crit = true;
|
|
||||||
|
|
||||||
// we have a chance to crit!
|
|
||||||
if (innate_crit || crit_chance) {
|
|
||||||
int difficulty = 0;
|
|
||||||
if (hit.skill == EQ::skills::SkillArchery)
|
|
||||||
difficulty = RuleI(Combat, ArcheryCritDifficulty);
|
|
||||||
else if (hit.skill == EQ::skills::SkillThrowing)
|
|
||||||
difficulty = RuleI(Combat, ThrowingCritDifficulty);
|
|
||||||
else
|
|
||||||
difficulty = RuleI(Combat, MeleeCritDifficulty);
|
|
||||||
int roll = zone->random.Int(1, difficulty);
|
|
||||||
|
|
||||||
int dex_bonus = GetDEX();
|
|
||||||
if (dex_bonus > 255)
|
|
||||||
dex_bonus = 255 + ((dex_bonus - 255) / 5);
|
|
||||||
dex_bonus += 45; // chances did not match live without a small boost
|
|
||||||
|
|
||||||
// so if we have an innate crit we have a better chance, except for ber throwing
|
|
||||||
if (!innate_crit || (GetClass() == Class::Berserker && hit.skill == EQ::skills::SkillThrowing))
|
|
||||||
dex_bonus = dex_bonus * 3 / 5;
|
|
||||||
|
|
||||||
if (crit_chance)
|
|
||||||
dex_bonus += dex_bonus * crit_chance / 100;
|
|
||||||
|
|
||||||
// check if we crited
|
|
||||||
if (roll < dex_bonus) {
|
|
||||||
// step 1: check for finishing blow
|
|
||||||
if (TryFinishingBlow(defender, hit.damage_done))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// step 2: calculate damage
|
|
||||||
hit.damage_done = std::max(hit.damage_done, hit.base_damage) + 5;
|
|
||||||
int og_damage = hit.damage_done;
|
|
||||||
int crit_mod = 170 + GetCritDmgMod(hit.skill);
|
|
||||||
if (crit_mod < 100) {
|
|
||||||
crit_mod = 100;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hit.damage_done = hit.damage_done * crit_mod / 100;
|
hit.damage_done = hit.damage_done * 200 / 100;
|
||||||
LogCombat("Crit success roll [{}] dex chance [{}] og dmg [{}] crit_mod [{}] new dmg [{}]", roll, dex_bonus, og_damage, crit_mod, hit.damage_done);
|
|
||||||
|
|
||||||
// step 3: check deadly strike
|
entity_list.FilteredMessageCloseString(
|
||||||
if (GetClass() == Class::Rogue && hit.skill == EQ::skills::SkillThrowing) {
|
|
||||||
if (BehindMob(defender, GetX(), GetY())) {
|
|
||||||
int chance = GetLevel() * 12;
|
|
||||||
if (zone->random.Int(1, 1000) < chance) {
|
|
||||||
// step 3a: check assassinate
|
|
||||||
int assdmg = TryAssassinate(defender, hit.skill); // I don't think this is right
|
|
||||||
if (assdmg) {
|
|
||||||
hit.damage_done = assdmg;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
hit.damage_done = hit.damage_done * 200 / 100;
|
|
||||||
|
|
||||||
entity_list.FilteredMessageCloseString(
|
|
||||||
this, /* Sender */
|
|
||||||
false, /* Skip Sender */
|
|
||||||
RuleI(Range, CriticalDamage),
|
|
||||||
Chat::MeleeCrit, /* Type: 301 */
|
|
||||||
FilterMeleeCrits, /* FilterType: 12 */
|
|
||||||
DEADLY_STRIKE, /* MessageFormat: %1 scores a Deadly Strike!(%2) */
|
|
||||||
0,
|
|
||||||
GetCleanName(), /* Message1 */
|
|
||||||
itoa(hit.damage_done + hit.min_damage) /* Message2 */
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// step 4: check crips
|
|
||||||
// this SPA was reused on live ...
|
|
||||||
bool berserk = spellbonuses.BerserkSPA || itembonuses.BerserkSPA || aabonuses.BerserkSPA;
|
|
||||||
if (!berserk) {
|
|
||||||
if (zone->random.Roll(GetCrippBlowChance())) {
|
|
||||||
berserk = true;
|
|
||||||
} // TODO: Holyforge is suppose to have an innate extra undead chance? 1/5 which matches the SPA crip though ...
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsBerserk() || berserk) {
|
|
||||||
hit.damage_done += og_damage * 119 / 100;
|
|
||||||
LogCombat("Crip damage [{}]", hit.damage_done);
|
|
||||||
|
|
||||||
entity_list.FilteredMessageCloseString(
|
|
||||||
this, /* Sender */
|
this, /* Sender */
|
||||||
false, /* Skip Sender */
|
false, /* Skip Sender */
|
||||||
RuleI(Range, CriticalDamage),
|
RuleI(Range, CriticalDamage),
|
||||||
Chat::MeleeCrit, /* Type: 301 */
|
Chat::MeleeCrit, /* Type: 301 */
|
||||||
FilterMeleeCrits, /* FilterType: 12 */
|
FilterMeleeCrits, /* FilterType: 12 */
|
||||||
CRIPPLING_BLOW, /* MessageFormat: %1 lands a Crippling Blow!(%2) */
|
DEADLY_STRIKE, /* MessageFormat: %1 scores a Deadly Strike!(%2) */
|
||||||
0,
|
0,
|
||||||
GetCleanName(), /* Message1 */
|
GetCleanName(), /* Message1 */
|
||||||
itoa(hit.damage_done + hit.min_damage) /* Message2 */
|
itoa(hit.damage_done) /* Message2 */
|
||||||
);
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Crippling blows also have a chance to stun
|
// Step 4: check cripple
|
||||||
// Kayen: Crippling Blow would cause a chance to interrupt for npcs < 55, with a
|
bool berserk = spellbonuses.BerserkSPA || itembonuses.BerserkSPA || aabonuses.BerserkSPA;
|
||||||
// staggers message.
|
|
||||||
if (defender->GetLevel() <= 55 && !defender->GetSpecialAbility(UNSTUNABLE)) {
|
|
||||||
defender->Emote("staggers.");
|
|
||||||
defender->Stun(RuleI(Combat, StunDuration));
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Normal Critical hit message */
|
if (!berserk && zone->random.Roll(GetCrippBlowChance())) {
|
||||||
entity_list.FilteredMessageCloseString(
|
berserk = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsBerserk() || berserk) {
|
||||||
|
hit.damage_done += og_damage * 119 / 100;
|
||||||
|
LogCombatDetail("Crippling damage [{}]", hit.damage_done);
|
||||||
|
|
||||||
|
entity_list.FilteredMessageCloseString(
|
||||||
this, /* Sender */
|
this, /* Sender */
|
||||||
false, /* Skip Sender */
|
false, /* Skip Sender */
|
||||||
RuleI(Range, CriticalDamage),
|
RuleI(Range, CriticalDamage),
|
||||||
Chat::MeleeCrit, /* Type: 301 */
|
Chat::MeleeCrit, /* Type: 301 */
|
||||||
FilterMeleeCrits, /* FilterType: 12 */
|
FilterMeleeCrits, /* FilterType: 12 */
|
||||||
CRITICAL_HIT, /* MessageFormat: %1 scores a critical hit! (%2) */
|
CRIPPLING_BLOW, /* MessageFormat: %1 lands a Crippling Blow!(%2) */
|
||||||
0,
|
0,
|
||||||
GetCleanName(), /* Message1 */
|
GetCleanName(), /* Message1 */
|
||||||
itoa(hit.damage_done + hit.min_damage) /* Message2 */
|
itoa(hit.damage_done) /* Message2 */
|
||||||
|
);
|
||||||
|
|
||||||
|
// Crippling blows also have a chance to stun
|
||||||
|
// Kayen: Crippling Blow would cause a chance to interrupt for npcs < 55, with a
|
||||||
|
// staggers message.
|
||||||
|
if (defender->GetLevel() <= RuleI(Combat, MaximumLevelStunsCripplingBlow) && !defender->GetSpecialAbility(UNSTUNABLE)) {
|
||||||
|
entity_list.MessageCloseString(
|
||||||
|
defender,
|
||||||
|
true,
|
||||||
|
RuleI(Range, Emote),
|
||||||
|
Chat::Emote,
|
||||||
|
STAGGERS,
|
||||||
|
GetName()
|
||||||
);
|
);
|
||||||
|
defender->Stun(RuleI(Combat, StunDuration));
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Normal Critical hit message */
|
||||||
|
entity_list.FilteredMessageCloseString(
|
||||||
|
this, /* Sender */
|
||||||
|
false, /* Skip Sender */
|
||||||
|
RuleI(Range, CriticalDamage),
|
||||||
|
Chat::MeleeCrit, /* Type: 301 */
|
||||||
|
FilterMeleeCrits, /* FilterType: 12 */
|
||||||
|
CRITICAL_HIT, /* MessageFormat: %1 scores a critical hit! (%2) */
|
||||||
|
0,
|
||||||
|
GetCleanName(), /* Message1 */
|
||||||
|
itoa(hit.damage_done) /* Message2 */
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Mob::TryFinishingBlow(Mob *defender, int64 &damage)
|
bool Mob::TryFinishingBlow(Mob *defender, int64 &damage)
|
||||||
|
|||||||
@ -236,7 +236,13 @@ public:
|
|||||||
int compute_defense();
|
int compute_defense();
|
||||||
int GetTotalDefense(); // compute_defense + spell bonuses
|
int GetTotalDefense(); // compute_defense + spell bonuses
|
||||||
bool CheckHitChance(Mob* attacker, DamageHitInfo &hit);
|
bool CheckHitChance(Mob* attacker, DamageHitInfo &hit);
|
||||||
|
bool RollMeleeCritCheck(Mob *defender, EQ::skills::SkillType skill);
|
||||||
|
inline bool CanUndeadSlay() { return static_cast<bool>(GetUndeadSlayRate());}
|
||||||
|
inline bool IsUndeadForSlay() { return (GetBodyType() == BT_Undead || GetBodyType() == BT_SummonedUndead || GetBodyType() == BT_Vampire); }
|
||||||
|
int GetUndeadSlayRate();
|
||||||
|
void DoUndeadSlay(DamageHitInfo &hit, int crit_mod);
|
||||||
void TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *opts = nullptr);
|
void TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *opts = nullptr);
|
||||||
|
bool TryUndeadSlay(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *opts = nullptr);
|
||||||
void TryPetCriticalHit(Mob *defender, DamageHitInfo &hit);
|
void TryPetCriticalHit(Mob *defender, DamageHitInfo &hit);
|
||||||
virtual bool TryFinishingBlow(Mob *defender, int64 &damage);
|
virtual bool TryFinishingBlow(Mob *defender, int64 &damage);
|
||||||
int TryHeadShot(Mob* defender, EQ::skills::SkillType skillInUse);
|
int TryHeadShot(Mob* defender, EQ::skills::SkillType skillInUse);
|
||||||
|
|||||||
@ -204,6 +204,7 @@
|
|||||||
#define FINISHING_BLOW 1009 //%1 scores a Finishing Blow!!
|
#define FINISHING_BLOW 1009 //%1 scores a Finishing Blow!!
|
||||||
#define ASSASSINATES 1016 //%1 ASSASSINATES their victim!!
|
#define ASSASSINATES 1016 //%1 ASSASSINATES their victim!!
|
||||||
#define CRIPPLING_BLOW 1021 //%1 lands a Crippling Blow!(%2)
|
#define CRIPPLING_BLOW 1021 //%1 lands a Crippling Blow!(%2)
|
||||||
|
#define STAGGERS 1022 //%1 staggers.
|
||||||
#define CRITICAL_HIT 1023 //%1 scores a critical hit! (%2)
|
#define CRITICAL_HIT 1023 //%1 scores a critical hit! (%2)
|
||||||
#define DEADLY_STRIKE 1024 //%1 scores a Deadly Strike!(%2)
|
#define DEADLY_STRIKE 1024 //%1 scores a Deadly Strike!(%2)
|
||||||
#define RESISTS_URGE 1025 //%1 resists their urge to flee.
|
#define RESISTS_URGE 1025 //%1 resists their urge to flee.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user