Unlink Tiger Claw from other monk skills for RoF2+

Tiger Claw has its own reuse now, which the client expects

pTimerCombatAbility2 should be able to be used if they do something
similar for other classes.
This commit is contained in:
Michael Cook (mackal) 2015-05-21 18:15:34 -04:00
parent ea44b4b3b1
commit 9cbda0f81b
2 changed files with 60 additions and 54 deletions

View File

@ -39,7 +39,8 @@ enum { //values for pTimerType
pTimerDisciplineReuseStart = 14,
pTimerDisciplineReuseEnd = 24,
pTimerCombatAbility = 25,
pTimerBeggingPickPocket = 26,
pTimerCombatAbility2 = 26, // RoF2+ Tiger Claw is unlinked from other monk skills, generic in case other classes ever need it
pTimerBeggingPickPocket = 27,
pTimerLayHands = 87, //these IDs are used by client too
pTimerHarmTouch = 89, //so dont change them

View File

@ -95,7 +95,7 @@ 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,
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
@ -181,6 +181,11 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) {
return;
CombatAbility_Struct* ca_atk = (CombatAbility_Struct*) app->pBuffer;
pTimerType timer = pTimerCombatAbility;
// RoF2+ Tiger Claw is unlinked from other monk skills, if they ever do that for other classes there will need
// to be more checks here
if (GetClientVersion() >= ClientVersion::RoF2 && ca_atk->m_skill == SkillTigerClaw)
timer = pTimerCombatAbility2;
/* Check to see if actually have skill */
if (!MaxSkill(static_cast<SkillUseTypes>(ca_atk->m_skill)))
@ -218,7 +223,7 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) {
if(!CombatRange(GetTarget()))
return;
if(!p_timers.Expired(&database, pTimerCombatAbility, false)) {
if(!p_timers.Expired(&database, timer, false)) {
Message(13,"Ability recovery time not yet met.");
return;
}
@ -268,7 +273,7 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) {
DoSpecialAttackDamage(GetTarget(), SkillBash, dmg, 1, ht, ReuseTime);
if(ReuseTime > 0)
{
p_timers.Start(pTimerCombatAbility, ReuseTime);
p_timers.Start(timer, ReuseTime);
}
}
return;
@ -304,7 +309,7 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) {
}
if(ReuseTime > 0) {
p_timers.Start(pTimerCombatAbility, ReuseTime);
p_timers.Start(timer, ReuseTime);
}
return;
}
@ -390,7 +395,7 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) {
ReuseTime = (ReuseTime*HasteMod)/100;
if(ReuseTime > 0){
p_timers.Start(pTimerCombatAbility, ReuseTime);
p_timers.Start(timer, ReuseTime);
}
}
@ -558,7 +563,7 @@ void Mob::TryBackstab(Mob *other, int ReuseTime) {
if (level > 54) {
// Check for double attack with main hand assuming maxed DA Skill (MS)
if(IsClient() && CastToClient()->CheckDoubleAttack(false))
if(IsClient() && CastToClient()->CheckDoubleAttack(false))
if(other->GetHP() > 0)
RogueBackstab(other,true, ReuseTime);
@ -650,10 +655,10 @@ 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());
@ -797,26 +802,26 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) {
//EndlessQuiver AA base1 = 100% Chance to avoid consumption arrow.
int ChanceAvoidConsume = aabonuses.ConsumeProjectile + itembonuses.ConsumeProjectile + spellbonuses.ConsumeProjectile;
if (!ChanceAvoidConsume || (ChanceAvoidConsume < 100 && zone->random.Int(0,99) > ChanceAvoidConsume)){
if (!ChanceAvoidConsume || (ChanceAvoidConsume < 100 && zone->random.Int(0,99) > ChanceAvoidConsume)){
DeleteItemInInventory(ammo_slot, 1, true);
Log.Out(Logs::Detail, Logs::Combat, "Consumed one arrow from slot %d", ammo_slot);
} else {
Log.Out(Logs::Detail, Logs::Combat, "Endless Quiver prevented ammo consumption.");
}
CheckIncreaseSkill(SkillArchery, GetTarget(), -15);
CheckIncreaseSkill(SkillArchery, GetTarget(), -15);
CommonBreakInvisible();
}
void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const ItemInst* Ammo, uint16 weapon_damage, int16 chance_mod, int16 focus, int ReuseTime,
void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const ItemInst* Ammo, uint16 weapon_damage, int16 chance_mod, int16 focus, int ReuseTime,
uint32 range_id, uint32 ammo_id, const Item_Struct *AmmoItem, int AmmoSlot, float speed) {
if ((other == nullptr ||
((IsClient() && CastToClient()->dead) ||
(other->IsClient() && other->CastToClient()->dead)) ||
HasDied() ||
if ((other == nullptr ||
((IsClient() && CastToClient()->dead) ||
(other->IsClient() && other->CastToClient()->dead)) ||
HasDied() ||
(!IsAttackAllowed(other)) ||
(other->GetInvul() ||
(other->GetInvul() ||
other->GetSpecialAbility(IMMUNE_MELEE))))
{
return;
@ -841,12 +846,12 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite
LaunchProjectile = true;
else{
/*
Item sync check on projectile landing.
Item sync check on projectile landing.
Weapon damage is already calculated so this only affects procs!
Ammo proc check will use database to find proc if you used up your last ammo.
If you change range item mid projectile flight, you loose your chance to proc from bow (Deal with it!).
*/
if (!RangeWeapon && !Ammo && range_id && ammo_id){
ProjectileImpact = true;
@ -858,8 +863,8 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite
_RangeWeapon = CastToClient()->m_inv[MainRange];
if (_RangeWeapon && _RangeWeapon->GetItem() && _RangeWeapon->GetItem()->ID == range_id)
RangeWeapon = _RangeWeapon;
RangeWeapon = _RangeWeapon;
_Ammo = CastToClient()->m_inv[AmmoSlot];
if (_Ammo && _Ammo->GetItem() && _Ammo->GetItem()->ID == ammo_id)
Ammo = _Ammo;
@ -985,7 +990,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite
other->AddToHateList(this, hate, 0, false);
other->Damage(this, TotalDmg, SPELL_UNKNOWN, SkillArchery);
//Skill Proc Success
if (TotalDmg > 0 && HasSkillProcSuccess() && other && !other->HasDied()){
if (ReuseTime)
@ -1047,10 +1052,10 @@ bool Mob::TryProjectileAttack(Mob* other, const Item_Struct *item, SkillUseTypes
ProjectileAtk[slot].origin_x = GetX();
ProjectileAtk[slot].origin_y = GetY();
ProjectileAtk[slot].origin_z = GetZ();
if (RangeWeapon && RangeWeapon->GetItem())
ProjectileAtk[slot].ranged_id = RangeWeapon->GetItem()->ID;
if (Ammo && Ammo->GetItem())
ProjectileAtk[slot].ammo_id = Ammo->GetItem()->ID;
@ -1085,7 +1090,7 @@ void Mob::ProjectileAttack()
disable = false;
Mob* target = entity_list.GetMobID(ProjectileAtk[i].target_id);
if (target && target->IsMoving()){ //Only recalculate hit increment if target moving
//Due to frequency that we need to check increment the targets position variables may not be updated even if moving. Do a simple check before calculating distance.
if (ProjectileAtk[i].tlast_x != target->GetX() || ProjectileAtk[i].tlast_y != target->GetY()){
@ -1109,7 +1114,7 @@ void Mob::ProjectileAttack()
else
CastToNPC()->DoRangedAttackDmg(target, false, ProjectileAtk[i].wpn_dmg,0, static_cast<SkillUseTypes>(ProjectileAtk[i].skill));
}
else
{
if (ProjectileAtk[i].skill == SkillArchery)
@ -1120,7 +1125,7 @@ void Mob::ProjectileAttack()
SpellOnTarget(ProjectileAtk[i].wpn_dmg, target, false, true, spells[ProjectileAtk[i].wpn_dmg].ResistDiff, true);
}
}
ProjectileAtk[i].increment = 0;
ProjectileAtk[i].target_id = 0;
ProjectileAtk[i].wpn_dmg = 0;
@ -1180,7 +1185,7 @@ float Mob::GetRangeDistTargetSizeMod(Mob* other)
mod = 42.0f + (5.8f * (tsize - 15.0f));
else
mod = 75.0f;
return (mod + 2.0f); //Add 2.0f as buffer to prevent any chance of failures, client enforce range check regardless.
}
@ -1210,7 +1215,7 @@ void NPC::RangedAttack(Mob* other)
float min_range = static_cast<float>(RuleI(Combat, MinRangedAttackDist));
float max_range = 250; // needs to be longer than 200(most spells)
if (sa_max_range)
max_range = static_cast<float>(sa_max_range);
@ -1242,12 +1247,12 @@ void NPC::RangedAttack(Mob* other)
}
void NPC::DoRangedAttackDmg(Mob* other, bool Launch, int16 damage_mod, int16 chance_mod, SkillUseTypes skill, float speed, const char *IDFile) {
if ((other == nullptr ||
(other->HasDied())) ||
HasDied() ||
if ((other == nullptr ||
(other->HasDied())) ||
HasDied() ||
(!IsAttackAllowed(other)) ||
(other->GetInvul() ||
(other->GetInvul() ||
other->GetSpecialAbility(IMMUNE_MELEE)))
{
return;
@ -1268,7 +1273,7 @@ void NPC::DoRangedAttackDmg(Mob* other, bool Launch, int16 damage_mod, int16 cha
ammo = GetAmmoIDfile();
ProjectileAnimation(other, 0,false,speed,0,0,0,ammo,skillInUse);
if (RuleB(Combat, ProjectileDmgOnImpact))
{
TryProjectileAttack(other, nullptr, skillInUse, damage_mod, nullptr, nullptr, 0, speed);
@ -1276,7 +1281,7 @@ void NPC::DoRangedAttackDmg(Mob* other, bool Launch, int16 damage_mod, int16 cha
}
}
if (!chance_mod)
if (!chance_mod)
chance_mod = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 2);
if (!other->CheckHitChance(this, skillInUse, MainRange, chance_mod))
@ -1298,11 +1303,11 @@ void NPC::DoRangedAttackDmg(Mob* other, bool Launch, int16 damage_mod, int16 cha
if (!damage_mod)
damage_mod = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 3);//Damage modifier
TotalDmg += TotalDmg * damage_mod / 100;
TotalDmg += TotalDmg * damage_mod / 100;
other->AvoidDamage(this, TotalDmg, false);
other->MeleeMitigation(this, TotalDmg, MinDmg);
if (TotalDmg > 0)
CommonOutgoingHitSuccess(other, TotalDmg, skillInUse);
else if (TotalDmg < -4)
@ -1432,18 +1437,18 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51
//consume ammo
DeleteItemInInventory(ammo_slot, 1, true);
CheckIncreaseSkill(SkillThrowing, GetTarget());
CheckIncreaseSkill(SkillThrowing, GetTarget());
CommonBreakInvisible();
}
void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Item_Struct* AmmoItem, uint16 weapon_damage, int16 chance_mod,int16 focus, int ReuseTime, uint32 range_id, int AmmoSlot, float speed)
{
if ((other == nullptr ||
((IsClient() && CastToClient()->dead) ||
(other->IsClient() && other->CastToClient()->dead)) ||
HasDied() ||
if ((other == nullptr ||
((IsClient() && CastToClient()->dead) ||
(other->IsClient() && other->CastToClient()->dead)) ||
HasDied() ||
(!IsAttackAllowed(other)) ||
(other->GetInvul() ||
(other->GetInvul() ||
other->GetSpecialAbility(IMMUNE_MELEE))))
{
return;
@ -1511,7 +1516,7 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite
return;
}
}
else
else
WDmg = weapon_damage;
if (focus) //From FcBaseEffects
@ -1535,7 +1540,7 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite
Log.Out(Logs::Detail, Logs::Combat, "Item DMG %d. Max Damage %d. Hit for damage %d", WDmg, MaxDmg, TotalDmg);
if (!Assassinate_Dmg)
other->AvoidDamage(this, TotalDmg, false); //CanRiposte=false - Can not riposte throw attacks.
other->MeleeMitigation(this, TotalDmg, minDmg);
if(TotalDmg > 0)
CommonOutgoingHitSuccess(other, TotalDmg, SkillThrowing);
@ -1620,7 +1625,7 @@ void Mob::SendItemAnimation(Mob *to, const Item_Struct *item, SkillUseTypes skil
safe_delete(outapp);
}
void Mob::ProjectileAnimation(Mob* to, int item_id, bool IsArrow, float speed, float angle, float tilt, float arc, const char *IDFile, SkillUseTypes skillInUse) {
void Mob::ProjectileAnimation(Mob* to, int item_id, bool IsArrow, float speed, float angle, float tilt, float arc, const char *IDFile, SkillUseTypes skillInUse) {
if (!to)
return;
@ -2092,7 +2097,7 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte)
}
ReuseTime = ReuseTime / HasteMod;
if(ReuseTime > 0 && !IsRiposte){
if(ReuseTime > 0 && !IsRiposte){
p_timers.Start(pTimerCombatAbility, ReuseTime);
}
}
@ -2270,7 +2275,7 @@ float Mob::GetSpecialProcChances(uint16 hand)
if (RuleB(Combat, AdjustSpecialProcPerMinute)) {
ProcChance = (static_cast<float>(weapon_speed) *
RuleR(Combat, AvgSpecialProcsPerMinute) / 60000.0f);
RuleR(Combat, AvgSpecialProcsPerMinute) / 60000.0f);
ProcBonus += static_cast<float>(mydex/35) + static_cast<float>(itembonuses.HeroicDEX / 25);
ProcChance += ProcChance * ProcBonus / 100.0f;
} else {
@ -2363,7 +2368,7 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes
int Hand = MainPrimary;
if (hate == 0 && weapon_damage > 1) hate = weapon_damage;
if(weapon_damage > 0){
if(weapon_damage > 0){
if (focus) //From FcBaseEffects
weapon_damage += weapon_damage*focus/100;
@ -2376,7 +2381,7 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes
int32 max_hit = (2 * weapon_damage*GetDamageTable(skillinuse)) / 100;
if(GetLevel() >= 28 && IsWarriorClass() ) {
int ucDamageBonus = GetWeaponDamageBonus((const Item_Struct*) nullptr );
int ucDamageBonus = GetWeaponDamageBonus((const Item_Struct*) nullptr );
min_hit += (int) ucDamageBonus;
max_hit += (int) ucDamageBonus;
hate += ucDamageBonus;
@ -2411,7 +2416,7 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes
} else {
other->AvoidDamage(this, damage, CanRiposte);
other->MeleeMitigation(this, damage, min_hit);
if(damage > 0)
if(damage > 0)
CommonOutgoingHitSuccess(other, damage, skillinuse);
}
@ -2449,7 +2454,7 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes
if (CanSkillProc && HasSkillProcs())
TrySkillProc(other, skillinuse, ReuseTime);
if (CanSkillProc && (damage > 0) && HasSkillProcSuccess())
TrySkillProc(other, skillinuse, ReuseTime, true);
}