mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-16 01:01:30 +00:00
Implemented SE_Assassinate, SE_AssassinateLevel - Defines assassinate damage and level requirements.
Revised Assassinate mechanic so damage now receives all backstab bonuses, proc chance can be set to either (lives new Proc Per minute system, or flat chance based on dex (formula updated). Assassinate can now proc from THROW if behind target, various other adjustments. Required SQL for AA updates
This commit is contained in:
parent
8a92fada5a
commit
70f10782b0
@ -12,8 +12,11 @@ Kayen: Update SE_AETaunt - Base value will now determine AE taunt range (This wi
|
||||
Kayen: Udpated SE_ReclaimPet - Correct forumla for mana returned to properly return 75% of actual pet spell mana cost.
|
||||
Kayen: Implemented SE_ImprovedReclaimEnergy - Modifies % mana returned from SE_ReclaimPet.
|
||||
Kayen: Implemented SE_HeadShot, SE_HeadShotLevel - Defines headshot damage and level requirements.
|
||||
Revised HeadShot mechanic so damage now recieves all archery bonuses, proc chance can be set to either (lives new Proc Per minute
|
||||
Revised HeadShot mechanic so damage now receives all archery bonuses, proc chance can be set to either (lives new Proc Per minute
|
||||
system, or flat chance based on dex (formula updated).
|
||||
Kayen: Implemented SE_Assassinate, SE_AssassinateLevel - Defines assassinate damage and level requirements.
|
||||
Revised Assassinate mechanic so damage now receives all backstab bonuses, proc chance can be set to either (lives new Proc Per minute
|
||||
system, or flat chance based on dex (formula updated). Assassinate can now proc from THROW if behind target, various other adjustments.
|
||||
|
||||
Required SQL: utils/sql/git/required/2014_06_25_AA_Update.sql
|
||||
Optional SQL: utils/sql/git/optiional/2014_06_29_HeadShotRules.sql
|
||||
|
||||
@ -13,5 +13,11 @@ INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (
|
||||
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('644', '1', '217', '0', '32000');
|
||||
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('644', '2', '346', '46', '0');
|
||||
|
||||
-- spells_new update
|
||||
ALTER TABLE `spells_new` CHANGE `field175` `numhits_type` INT(11) NOT NULL DEFAULT '0';
|
||||
-- AA Anatomy (Rogue Assassinate)
|
||||
INSERT INTO `altadv_vars` (`skill_id`, `name`, `cost`, `max_level`, `hotkey_sid`, `hotkey_sid2`, `title_sid`, `desc_sid`, `type`, `spellid`, `prereq_skill`, `prereq_minpoints`, `spell_type`, `spell_refresh`, `classes`, `berserker`, `class_type`, `cost_inc`, `aa_expansion`, `special_category`, `sof_type`, `sof_cost_inc`, `sof_max_level`, `sof_next_skill`, `clientver`, `account_time_required`, `sof_current_level`,`sof_next_id`,`level_inc`) VALUES ('1604', 'Anatomy', '5', '3', '4294967295', '4294967295', '1604', '1604', '1', '4294967295', '0', '0', '0', '0', '512', '0', '60', '1', '10', '4294967295', '3', '0', '3', '1604', '1', '0', '0', '0', '0');
|
||||
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('1604', '1', '439', '0', '32000');
|
||||
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('1604', '2', '345', '48', '0');
|
||||
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('1605', '1', '439', '0', '32000');
|
||||
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('1605', '2', '345', '51', '0');
|
||||
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('1606', '1', '439', '0', '32000');
|
||||
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('1606', '2', '345', '53', '0');
|
||||
@ -1296,6 +1296,22 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon)
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_Assassinate:
|
||||
{
|
||||
if(newbon->Assassinate[1] < base2){
|
||||
newbon->Assassinate[0] = base1;
|
||||
newbon->Assassinate[1] = base2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_AssassinateLevel:
|
||||
{
|
||||
if(newbon->AssassinateLevel < base1)
|
||||
newbon->AssassinateLevel = base1;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -423,9 +423,9 @@ struct StatBonuses {
|
||||
int8 IncreaseChanceMemwipe; // increases chance to memory wipe
|
||||
int8 CriticalMend; // chance critical monk mend
|
||||
int16 ImprovedReclaimEnergy; // Modifies amount of mana returned from reclaim energy
|
||||
int32 HeadShot[2]; // Headshot AA (Massive dmg vs humaniod w/ archery) 0= ? 1= Dmg
|
||||
uint32 HeadShot[2]; // Headshot AA (Massive dmg vs humaniod w/ archery) 0= ? 1= Dmg
|
||||
uint8 HSLevel; // Max Level Headshot will be effective at.
|
||||
int32 Assassinate[2]; // Assassinate AA (Massive dmg vs humaniod w/ assassinate) 0= ? 1= Dmg
|
||||
uint32 Assassinate[2]; // Assassinate AA (Massive dmg vs humaniod w/ assassinate) 0= ? 1= Dmg
|
||||
uint8 AssassinateLevel; // Max Level Assassinate will be effective at.
|
||||
|
||||
};
|
||||
|
||||
@ -142,6 +142,7 @@ public:
|
||||
void TryPetCriticalHit(Mob *defender, uint16 skill, int32 &damage);
|
||||
virtual bool TryFinishingBlow(Mob *defender, SkillUseTypes skillinuse);
|
||||
uint32 TryHeadShot(Mob* defender, SkillUseTypes skillInUse);
|
||||
uint32 TryAssassinate(Mob* defender, SkillUseTypes skillInUse, uint16 ReuseTime);
|
||||
virtual void DoRiposte(Mob* defender);
|
||||
void ApplyMeleeDamageBonus(uint16 skill, int32 &damage);
|
||||
virtual void MeleeMitigation(Mob *attacker, int32 &damage, int32 minhit, ExtraAttackOptions *opts = nullptr);
|
||||
@ -694,7 +695,7 @@ public:
|
||||
int32 AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTic, Mob* attacker);
|
||||
int32 ReduceAllDamage(int32 damage);
|
||||
|
||||
virtual void DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, int32 min_damage = 1, int32 hate_override = -1, int ReuseTime = 10, bool HitChance=false);
|
||||
virtual void DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, int32 min_damage = 1, int32 hate_override = -1, int ReuseTime = 10, bool HitChance=false, bool CanAvoid=true);
|
||||
virtual void DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon=nullptr, const Item_Struct* item=nullptr, uint16 weapon_damage=0, int16 chance_mod=0,int16 focus=0);
|
||||
virtual void DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes skillinuse, int16 chance_mod=0, int16 focus=0, bool CanRiposte=false);
|
||||
virtual void DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon=nullptr, const ItemInst* Ammo=nullptr, uint16 weapon_damage=0, int16 chance_mod=0, int16 focus=0);
|
||||
@ -991,7 +992,8 @@ protected:
|
||||
void ExecWeaponProc(const ItemInst* weapon, uint16 spell_id, Mob *on);
|
||||
virtual float GetProcChances(float ProcBonus, uint16 weapon_speed = 30, uint16 hand = 13);
|
||||
virtual float GetDefensiveProcChances(float &ProcBonus, float &ProcChance, uint16 weapon_speed = 30, uint16 hand = 13);
|
||||
virtual float GetSpecialProcChances(uint16 hand = 13);
|
||||
virtual float GetSpecialProcChances(uint16 hand);
|
||||
virtual float GetAssassinateProcChances(uint16 ReuseTime);
|
||||
int GetWeaponDamage(Mob *against, const Item_Struct *weapon_item);
|
||||
int GetWeaponDamage(Mob *against, const ItemInst *weapon_item, uint32 *hate = nullptr);
|
||||
int GetKickDamage();
|
||||
|
||||
@ -100,7 +100,8 @@ void Mob::ApplySpecialAttackMod(SkillUseTypes skill, int32 &dmg, int32 &mindmg)
|
||||
}
|
||||
}
|
||||
|
||||
void Mob::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, int32 min_damage, int32 hate_override,int ReuseTime, bool HitChance) {
|
||||
void Mob::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, int32 min_damage, int32 hate_override,int ReuseTime,
|
||||
bool HitChance, bool CanAvoid) {
|
||||
//this really should go through the same code as normal melee damage to
|
||||
//pick up all the special behavior there
|
||||
|
||||
@ -135,7 +136,9 @@ void Mob::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage,
|
||||
if(skill == SkillThrowing || skill == SkillArchery) // changed from '&&'
|
||||
CanRiposte = false;
|
||||
|
||||
who->AvoidDamage(this, max_damage, CanRiposte);
|
||||
if (CanAvoid)
|
||||
who->AvoidDamage(this, max_damage, CanRiposte);
|
||||
|
||||
who->MeleeMitigation(this, max_damage, min_damage);
|
||||
|
||||
if(max_damage > 0) {
|
||||
@ -373,8 +376,8 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) {
|
||||
if (ca_atk->m_atk != 100 || ca_atk->m_skill != SkillBackstab) {
|
||||
break;
|
||||
}
|
||||
TryBackstab(GetTarget(), ReuseTime);
|
||||
ReuseTime = BackstabReuseTime-1 - skill_reduction;
|
||||
TryBackstab(GetTarget(), ReuseTime);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -527,64 +530,47 @@ void Mob::TryBackstab(Mob *other, int ReuseTime) {
|
||||
if (FrontalBSChance && (FrontalBSChance > MakeRandomInt(0, 100)))
|
||||
bCanFrontalBS = true;
|
||||
}
|
||||
|
||||
|
||||
if (bIsBehind || bCanFrontalBS){ // Player is behind other OR can do Frontal Backstab
|
||||
|
||||
if (bCanFrontalBS) {
|
||||
if (bCanFrontalBS)
|
||||
CastToClient()->Message(0,"Your fierce attack is executed with such grace, your target did not see it coming!");
|
||||
}
|
||||
|
||||
RogueBackstab(other,false,ReuseTime);
|
||||
if (level > 54) {
|
||||
|
||||
// solar - chance to assassinate
|
||||
int chance = 10 + (GetDEX()/10) + (itembonuses.HeroicDEX/10); //18.5% chance at 85 dex 40% chance at 300 dex
|
||||
if(
|
||||
level >= 60 && // player is 60 or higher
|
||||
other->GetLevel() <= 45 && // mob 45 or under
|
||||
!other->CastToNPC()->IsEngaged() && // not aggro
|
||||
other->GetHP()<=32000
|
||||
&& other->IsNPC()
|
||||
&& MakeRandomFloat(0, 99) < chance // chance
|
||||
) {
|
||||
entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, ASSASSINATES, GetName());
|
||||
if(IsClient())
|
||||
CastToClient()->CheckIncreaseSkill(SkillBackstab, other, 10);
|
||||
RogueAssassinate(other);
|
||||
}
|
||||
else {
|
||||
RogueBackstab(other);
|
||||
if (level > 54) {
|
||||
float DoubleAttackProbability = (GetSkill(SkillDoubleAttack) + GetLevel()) / 500.0f; // 62.4 max
|
||||
// Check for double attack with main hand assuming maxed DA Skill (MS)
|
||||
if(IsClient() && CastToClient()->CheckDoubleAttack(false))
|
||||
{
|
||||
if(other->GetHP() > 0)
|
||||
RogueBackstab(other,false,ReuseTime);
|
||||
|
||||
if(MakeRandomFloat(0, 1) < DoubleAttackProbability) // Max 62.4 % chance of DA
|
||||
{
|
||||
if(other->GetHP() > 0)
|
||||
RogueBackstab(other,false,ReuseTime);
|
||||
|
||||
if (tripleChance && other->GetHP() > 0 && tripleChance > MakeRandomInt(0, 100))
|
||||
RogueBackstab(other,false,ReuseTime);
|
||||
}
|
||||
if (tripleChance && other->GetHP() > 0 && tripleChance > MakeRandomInt(0, 100))
|
||||
RogueBackstab(other,false,ReuseTime);
|
||||
}
|
||||
if(IsClient())
|
||||
CastToClient()->CheckIncreaseSkill(SkillBackstab, other, 10);
|
||||
}
|
||||
|
||||
if(IsClient())
|
||||
CastToClient()->CheckIncreaseSkill(SkillBackstab, other, 10);
|
||||
|
||||
}
|
||||
//Live AA - Chaotic Backstab
|
||||
else if(aabonuses.FrontalBackstabMinDmg || itembonuses.FrontalBackstabMinDmg || spellbonuses.FrontalBackstabMinDmg) {
|
||||
|
||||
//we can stab from any angle, we do min damage though.
|
||||
RogueBackstab(other, true);
|
||||
RogueBackstab(other, true, ReuseTime);
|
||||
if (level > 54) {
|
||||
float DoubleAttackProbability = (GetSkill(SkillDoubleAttack) + GetLevel()) / 500.0f; // 62.4 max
|
||||
if(IsClient())
|
||||
CastToClient()->CheckIncreaseSkill(SkillBackstab, other, 10);
|
||||
|
||||
// Check for double attack with main hand assuming maxed DA Skill (MS)
|
||||
if(MakeRandomFloat(0, 1) < DoubleAttackProbability) // Max 62.4 % chance of DA
|
||||
if(IsClient() && CastToClient()->CheckDoubleAttack(false))
|
||||
if(other->GetHP() > 0)
|
||||
RogueBackstab(other,true, ReuseTime);
|
||||
|
||||
if (tripleChance && other->GetHP() > 0 && tripleChance > MakeRandomInt(0, 100))
|
||||
RogueBackstab(other,false,ReuseTime);
|
||||
}
|
||||
|
||||
if(IsClient())
|
||||
CastToClient()->CheckIncreaseSkill(SkillBackstab, other, 10);
|
||||
}
|
||||
else { //We do a single regular attack if we attack from the front without chaotic stab
|
||||
Attack(other, 13);
|
||||
@ -594,6 +580,9 @@ void Mob::TryBackstab(Mob *other, int ReuseTime) {
|
||||
//heko: backstab
|
||||
void Mob::RogueBackstab(Mob* other, bool min_damage, int ReuseTime)
|
||||
{
|
||||
if (!other)
|
||||
return;
|
||||
|
||||
int32 ndamage = 0;
|
||||
int32 max_hit = 0;
|
||||
int32 min_hit = 0;
|
||||
@ -668,12 +657,20 @@ void Mob::RogueBackstab(Mob* other, bool min_damage, int ReuseTime)
|
||||
}
|
||||
|
||||
ndamage = mod_backstab_damage(ndamage);
|
||||
|
||||
uint32 Assassinate_Dmg = 0;
|
||||
Assassinate_Dmg = TryAssassinate(other, SkillBackstab, ReuseTime);
|
||||
|
||||
if (Assassinate_Dmg) {
|
||||
ndamage = Assassinate_Dmg;
|
||||
entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, ASSASSINATES, GetName());
|
||||
}
|
||||
|
||||
DoSpecialAttackDamage(other, SkillBackstab, ndamage, min_hit, hate, ReuseTime);
|
||||
DoSpecialAttackDamage(other, SkillBackstab, ndamage, min_hit, hate, ReuseTime, false, false);
|
||||
DoAnim(animPiercing);
|
||||
}
|
||||
|
||||
// solar - assassinate
|
||||
// solar - assassinate [Kayen: No longer used for regular assassinate 6-29-14]
|
||||
void Mob::RogueAssassinate(Mob* other)
|
||||
{
|
||||
//can you dodge, parry, etc.. an assassinate??
|
||||
@ -1276,13 +1273,24 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite
|
||||
|
||||
int32 TotalDmg = 0;
|
||||
|
||||
uint32 Assassinate_Dmg = 0;
|
||||
if (GetClass() == ROGUE && (BehindMob(other, GetX(), GetY())))
|
||||
Assassinate_Dmg = TryAssassinate(other, SkillThrowing, ranged_timer.GetDuration());
|
||||
|
||||
if(WDmg > 0)
|
||||
{
|
||||
int minDmg = 1;
|
||||
uint16 MaxDmg = GetThrownDamage(WDmg, TotalDmg, minDmg);
|
||||
|
||||
if (Assassinate_Dmg) {
|
||||
TotalDmg = Assassinate_Dmg;
|
||||
entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, ASSASSINATES, GetName());
|
||||
}
|
||||
|
||||
mlog(COMBAT__RANGED, "Item DMG %d. Max Damage %d. Hit for damage %d", WDmg, MaxDmg, TotalDmg);
|
||||
other->AvoidDamage(this, TotalDmg, false); //CanRiposte=false - Can not riposte throw attacks.
|
||||
if (!Assassinate_Dmg)
|
||||
other->AvoidDamage(this, TotalDmg, false); //CanRiposte=false - Can not riposte throw attacks.
|
||||
|
||||
other->MeleeMitigation(this, TotalDmg, minDmg);
|
||||
if(TotalDmg > 0)
|
||||
{
|
||||
@ -1866,92 +1874,6 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
void Mob::Taunt(NPC* who, bool always_succeed, float chance_bonus) {
|
||||
|
||||
if (who == nullptr)
|
||||
return;
|
||||
|
||||
if(DivineAura())
|
||||
return;
|
||||
|
||||
if(!CombatRange(who))
|
||||
return;
|
||||
|
||||
if(!always_succeed && IsClient())
|
||||
CastToClient()->CheckIncreaseSkill(TAUNT, who, 10);
|
||||
|
||||
int level = GetLevel();
|
||||
Mob *hate_top = who->GetHateMost();
|
||||
|
||||
// Check to see if we're already at the top of the target's hate list
|
||||
// a mob will not be taunted if its target's health is below 20%
|
||||
if ((hate_top != this)
|
||||
&& (who->GetLevel() < level)
|
||||
&& (hate_top == nullptr || hate_top->GetHPRatio() >= 20) ) {
|
||||
int32 newhate, tauntvalue;
|
||||
|
||||
float tauntchance;
|
||||
if(always_succeed) {
|
||||
tauntchance = 101;
|
||||
} else {
|
||||
|
||||
// no idea how taunt success is actually calculated
|
||||
// TODO: chance for level 50+ mobs should be lower
|
||||
int level_difference = level - who->GetLevel();
|
||||
if (level_difference <= 5) {
|
||||
tauntchance = 25.0; // minimum
|
||||
tauntchance += tauntchance * (float)GetSkill(TAUNT) / 200.0; // skill modifier
|
||||
if (tauntchance > 65.0)
|
||||
tauntchance = 65.0;
|
||||
}
|
||||
else if (level_difference <= 10) {
|
||||
tauntchance = 30.0; // minimum
|
||||
tauntchance += tauntchance * (float)GetSkill(TAUNT) / 200.0; // skill modifier
|
||||
if (tauntchance > 85.0)
|
||||
tauntchance = 85.0;
|
||||
}
|
||||
else if (level_difference <= 15) {
|
||||
tauntchance = 40.0; // minimum
|
||||
tauntchance += tauntchance * (float)GetSkill(TAUNT) / 200.0; // skill modifier
|
||||
if (tauntchance > 90.0)
|
||||
tauntchance = 90.0;
|
||||
}
|
||||
else {
|
||||
tauntchance = 50.0; // minimum
|
||||
tauntchance += tauntchance * (float)GetSkill(TAUNT) / 200.0; // skill modifier
|
||||
if (tauntchance > 95.0)
|
||||
tauntchance = 95.0;
|
||||
}
|
||||
}
|
||||
|
||||
if (chance_bonus)
|
||||
tauntchance = tauntchance + (tauntchance*chance_bonus/100.0f);
|
||||
|
||||
if (tauntchance > MakeRandomFloat(0, 100)) {
|
||||
// this is the max additional hate added per succesfull taunt
|
||||
tauntvalue = (MakeRandomInt(2, 4) * level);
|
||||
//tauntvalue = (int32) ((float)level * 10.0 * (float)rand()/(float)RAND_MAX + 1);
|
||||
// new hate: find diff of player's hate and whoever's at top of list, add that plus tauntvalue to players hate
|
||||
newhate = who->GetNPCHate(hate_top) - who->GetNPCHate(this) + tauntvalue;
|
||||
// add the hate
|
||||
who->CastToNPC()->AddToHateList(this, newhate);
|
||||
}
|
||||
else{
|
||||
//generate at least some hate reguardless of the outcome.
|
||||
who->CastToNPC()->AddToHateList(this, (MakeRandomInt(2, 4)*level));
|
||||
}
|
||||
}
|
||||
|
||||
//generate at least some hate reguardless of the outcome.
|
||||
who->CastToNPC()->AddToHateList(this, (MakeRandomInt(2, 4)*level));
|
||||
if (HasSkillProcs()){
|
||||
float chance = (float)TauntReuseTime*RuleR(Combat, AvgProcsPerMinute)/60000.0f;
|
||||
TrySkillProc(who, TAUNT, chance);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
void Mob::Taunt(NPC* who, bool always_succeed, float chance_bonus) {
|
||||
|
||||
if (who == nullptr)
|
||||
@ -2089,9 +2011,10 @@ void Mob::InstillDoubt(Mob *who) {
|
||||
uint32 Mob::TryHeadShot(Mob* defender, SkillUseTypes skillInUse) {
|
||||
|
||||
//Only works on YOUR target.
|
||||
if(defender && (skillInUse == SkillArchery) && (GetTarget() == defender)) {
|
||||
if(defender && (defender->GetBodyType() == BT_Humanoid) && !defender->IsClient()
|
||||
&& (skillInUse == SkillArchery) && (GetTarget() == defender)) {
|
||||
|
||||
int32 HeadShot_Dmg = aabonuses.HeadShot[1] + spellbonuses.HeadShot[1] + itembonuses.HeadShot[1];
|
||||
uint32 HeadShot_Dmg = aabonuses.HeadShot[1] + spellbonuses.HeadShot[1] + itembonuses.HeadShot[1];
|
||||
|
||||
uint8 HeadShot_Level = 0; //Get Highest Headshot Level
|
||||
HeadShot_Level = aabonuses.HSLevel;
|
||||
@ -2100,14 +2023,11 @@ uint32 Mob::TryHeadShot(Mob* defender, SkillUseTypes skillInUse) {
|
||||
else if (HeadShot_Level < itembonuses.HSLevel)
|
||||
HeadShot_Level = itembonuses.HSLevel;
|
||||
|
||||
if(HeadShot_Dmg && defender->GetBodyType() == BT_Humanoid) {
|
||||
if(HeadShot_Level && (defender->GetLevel() <= HeadShot_Level) && !defender->IsClient()){
|
||||
if(HeadShot_Dmg && HeadShot_Level && (defender->GetLevel() <= HeadShot_Level)){
|
||||
|
||||
float ProcChance = GetSpecialProcChances(11);
|
||||
if(ProcChance > MakeRandomFloat(0,1))
|
||||
return HeadShot_Dmg;
|
||||
|
||||
}
|
||||
float ProcChance = GetSpecialProcChances(11);
|
||||
if(ProcChance > MakeRandomFloat(0,1))
|
||||
return HeadShot_Dmg;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2119,7 +2039,7 @@ float Mob::GetSpecialProcChances(uint16 hand)
|
||||
int mydex = GetDEX();
|
||||
|
||||
if (mydex > 255)
|
||||
mydex = 255;
|
||||
mydex = 255;
|
||||
|
||||
uint16 weapon_speed;
|
||||
float ProcChance = 0.0f;
|
||||
@ -2155,6 +2075,69 @@ float Mob::GetSpecialProcChances(uint16 hand)
|
||||
return ProcChance;
|
||||
}
|
||||
|
||||
uint32 Mob::TryAssassinate(Mob* defender, SkillUseTypes skillInUse, uint16 ReuseTime) {
|
||||
|
||||
if(defender && (defender->GetBodyType() == BT_Humanoid) && !defender->IsClient() &&
|
||||
(skillInUse == SkillBackstab || skillInUse == SkillThrowing)) {
|
||||
|
||||
uint32 Assassinate_Dmg = aabonuses.Assassinate[1] + spellbonuses.Assassinate[1] + itembonuses.Assassinate[1];
|
||||
|
||||
uint8 Assassinate_Level = 0; //Get Highest Headshot Level
|
||||
Assassinate_Level = aabonuses.AssassinateLevel;
|
||||
if (Assassinate_Level < spellbonuses.AssassinateLevel)
|
||||
Assassinate_Level = spellbonuses.AssassinateLevel;
|
||||
else if (Assassinate_Level < itembonuses.AssassinateLevel)
|
||||
Assassinate_Level = itembonuses.AssassinateLevel;
|
||||
|
||||
if (GetLevel() >= 60){ //Innate Assassinate Ability if client as no bonuses.
|
||||
if (!Assassinate_Level)
|
||||
Assassinate_Level = 45;
|
||||
|
||||
if (!Assassinate_Dmg)
|
||||
Assassinate_Dmg = 32000;
|
||||
}
|
||||
|
||||
if(Assassinate_Dmg && Assassinate_Level && (defender->GetLevel() <= Assassinate_Level)){
|
||||
float ProcChance = 0.0f;
|
||||
|
||||
if (skillInUse == SkillThrowing)
|
||||
ProcChance = GetSpecialProcChances(11);
|
||||
else
|
||||
ProcChance = GetAssassinateProcChances(ReuseTime);
|
||||
|
||||
if(ProcChance > MakeRandomFloat(0,1))
|
||||
return Assassinate_Dmg;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
float Mob::GetAssassinateProcChances(uint16 ReuseTime)
|
||||
{
|
||||
int mydex = GetDEX();
|
||||
|
||||
if (mydex > 255)
|
||||
mydex = 255;
|
||||
|
||||
float ProcChance = 0.0f;
|
||||
float ProcBonus = 0.0f;
|
||||
|
||||
if (RuleB(Combat, AdjustSpecialProcPerMinute)) {
|
||||
ProcChance = (static_cast<float>(ReuseTime*1000) *
|
||||
RuleR(Combat, AvgSpecialProcsPerMinute) / 60000.0f);
|
||||
ProcBonus += (10 + (static_cast<float>(mydex/10) + static_cast<float>(itembonuses.HeroicDEX /10)))/100.0f;
|
||||
ProcChance += ProcChance * ProcBonus / 100.0f;
|
||||
|
||||
} else {
|
||||
/*Kayen: Unable to find data on old proc rate of assassinate, no idea if our formula is real or made up.*/
|
||||
ProcChance = (10 + (static_cast<float>(mydex/10) + static_cast<float>(itembonuses.HeroicDEX /10)))/100.0f;
|
||||
|
||||
}
|
||||
|
||||
return ProcChance;
|
||||
}
|
||||
|
||||
void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes skillinuse, int16 chance_mod, int16 focus, bool CanRiposte)
|
||||
{
|
||||
if (!CanDoSpecialAttack(other))
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user