mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-19 16:31:29 +00:00
[Feature] Classic Taunt (Pre 2006) style of taunt (#3942)
* DRAFT - Classic Taunt (Pre 2006) style of taunt RULE: ClassicTauntSystem Completely seperate logic for each system. Could potentially be re-writte to be more inline but there are a good bit of minor differences. * Consolidate Logic Still needs in-game testing * Feedback Request * Updates per feedback
This commit is contained in:
parent
26693992b6
commit
14d4a2610f
@ -529,6 +529,8 @@ RULE_REAL(Combat, DefProcPerMinAgiContrib, 0.075, "How much agility contributes
|
|||||||
RULE_INT(Combat, NPCFlurryChance, 20, "Chance for NPC to flurry")
|
RULE_INT(Combat, NPCFlurryChance, 20, "Chance for NPC to flurry")
|
||||||
RULE_BOOL(Combat, TauntOverLevel, 1, "Allows you to taunt NPC's over warriors level")
|
RULE_BOOL(Combat, TauntOverLevel, 1, "Allows you to taunt NPC's over warriors level")
|
||||||
RULE_INT(Combat, TauntOverAggro, 0, "+ amount over hate_top it will add before any bonus hate.")
|
RULE_INT(Combat, TauntOverAggro, 0, "+ amount over hate_top it will add before any bonus hate.")
|
||||||
|
RULE_INT(Combat, TauntChanceBonus, 0, "Bonus to taunt chance")
|
||||||
|
RULE_BOOL(Combat, ClassicTauntSystem, false, "Enable to use the pre 2006 taunt system.")
|
||||||
RULE_REAL(Combat, TauntSkillFalloff, 0.33, "For every taunt skill point that's not maxed you lose this percentage chance to taunt")
|
RULE_REAL(Combat, TauntSkillFalloff, 0.33, "For every taunt skill point that's not maxed you lose this percentage chance to taunt")
|
||||||
RULE_BOOL(Combat, EXPFromDmgShield, false, "Determine if damage from a damage shield counts for experience gain")
|
RULE_BOOL(Combat, EXPFromDmgShield, false, "Determine if damage from a damage shield counts for experience gain")
|
||||||
RULE_INT(Combat, QuiverHasteCap, 1000, "Quiver haste cap 1000 on live for a while, currently 700 on live")
|
RULE_INT(Combat, QuiverHasteCap, 1000, "Quiver haste cap 1000 on live for a while, currently 700 on live")
|
||||||
|
|||||||
@ -2134,9 +2134,22 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Classic Taunt Methodology
|
||||||
|
* This is not how Sony did it. This is a guess that fits the very limited data available.
|
||||||
|
* Low level players with maxed taunt for their level taunted about 50% on white cons.
|
||||||
|
* A 65 ranger with 150 taunt skill (max) taunted about 50% on level 60 and under NPCs.
|
||||||
|
* A 65 warrior with maxed taunt (230) was taunting around 50% on SSeru NPCs. */
|
||||||
|
|
||||||
|
/* Rashere in 2006: "your taunt skill was irrelevant if you were above level 60 and taunting
|
||||||
|
* something that was also above level 60."
|
||||||
|
* Also: "The chance to taunt an NPC higher level than yourself dropped off at double the rate
|
||||||
|
* if you were above level 60 than if you were below level 60 making it very hard to taunt creature
|
||||||
|
* higher level than yourself if you were above level 60."
|
||||||
|
*
|
||||||
|
* See http://www.elitegamerslounge.com/home/soearchive/viewtopic.php?t=81156 */
|
||||||
void Mob::Taunt(NPC *who, bool always_succeed, int chance_bonus, bool from_spell, int32 bonus_hate)
|
void Mob::Taunt(NPC *who, bool always_succeed, int chance_bonus, bool from_spell, int32 bonus_hate)
|
||||||
{
|
{
|
||||||
if (!who || DivineAura() || (!from_spell && !CombatRange(who))) {
|
if (!who || DivineAura() || (!from_spell && !CombatRange(who)) || (IsNPC() && IsCharmed())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2144,10 +2157,10 @@ void Mob::Taunt(NPC *who, bool always_succeed, int chance_bonus, bool from_spell
|
|||||||
CastToClient()->CheckIncreaseSkill(EQ::skills::SkillTaunt, who, 10);
|
CastToClient()->CheckIncreaseSkill(EQ::skills::SkillTaunt, who, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
Mob *hate_top = who->GetHateMost();
|
Mob *hate_top = who->GetHateMost();
|
||||||
|
|
||||||
int level_difference = GetLevel() - who->GetLevel();
|
int level_difference = GetLevel() - who->GetLevel();
|
||||||
bool success = false;
|
bool success = false;
|
||||||
|
int taunt_chance = 0;
|
||||||
|
|
||||||
// Support for how taunt worked pre 2000 on LIVE - Can not taunt NPC over your level.
|
// Support for how taunt worked pre 2000 on LIVE - Can not taunt NPC over your level.
|
||||||
if (
|
if (
|
||||||
@ -2159,104 +2172,133 @@ void Mob::Taunt(NPC *who, bool always_succeed, int chance_bonus, bool from_spell
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// All values used based on live parses after taunt was updated in 2006.
|
if (always_succeed) {
|
||||||
if (
|
taunt_chance = 100;
|
||||||
(hate_top && hate_top->GetHPRatio() >= 20) ||
|
}
|
||||||
!hate_top ||
|
|
||||||
chance_bonus
|
// Modern Taunt
|
||||||
) {
|
if (!RuleB(Combat, ClassicTauntSystem)) {
|
||||||
// SE_Taunt this is flat chance
|
if (
|
||||||
if (chance_bonus) {
|
(hate_top && hate_top->GetHPRatio() >= 20) ||
|
||||||
success = zone->random.Roll(chance_bonus);
|
!hate_top ||
|
||||||
} else {
|
chance_bonus
|
||||||
float taunt_chance = 50.0f;
|
) {
|
||||||
|
if (chance_bonus) {
|
||||||
if (always_succeed) {
|
taunt_chance = chance_bonus;
|
||||||
taunt_chance = 101.0f;
|
|
||||||
} else {
|
} else {
|
||||||
if (level_difference < 0) {
|
taunt_chance = 50;
|
||||||
taunt_chance += static_cast<float>(level_difference) * 3.0f;
|
}
|
||||||
if (taunt_chance < 20) {
|
} else {
|
||||||
taunt_chance = 20.0f;
|
if (level_difference < 0) {
|
||||||
}
|
taunt_chance += level_difference * 3;
|
||||||
} else {
|
if (taunt_chance < 20) {
|
||||||
taunt_chance += static_cast<float>(level_difference) * 5.0f;
|
taunt_chance = 20;
|
||||||
if (taunt_chance > 65) {
|
}
|
||||||
taunt_chance = 65.0f;
|
} else {
|
||||||
}
|
taunt_chance += level_difference * 5;
|
||||||
|
if (taunt_chance > 65) {
|
||||||
|
taunt_chance = 65;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TauntSkillFalloff rate is not based on any real data. Default of 33% gives a reasonable
|
|
||||||
// result.
|
|
||||||
if (IsClient() && !always_succeed) {
|
if (IsClient() && !always_succeed) {
|
||||||
taunt_chance -= (RuleR(Combat, TauntSkillFalloff) *
|
taunt_chance -= (RuleR(Combat, TauntSkillFalloff) *
|
||||||
(CastToClient()->MaxSkill(EQ::skills::SkillTaunt) -
|
(CastToClient()->MaxSkill(EQ::skills::SkillTaunt) -
|
||||||
GetSkill(EQ::skills::SkillTaunt)));
|
GetSkill(EQ::skills::SkillTaunt)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (taunt_chance < 1) {
|
if (taunt_chance < 1) {
|
||||||
taunt_chance = 1.0f;
|
taunt_chance = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
taunt_chance /= 100.0f;
|
|
||||||
success = taunt_chance > zone->random.Real(0, 1);
|
|
||||||
|
|
||||||
LogHate(
|
|
||||||
"Taunter mob {} target npc {} taunt_chance [{}] success [{}] hate_top [{}]",
|
|
||||||
GetMobDescription(),
|
|
||||||
who->GetMobDescription(),
|
|
||||||
taunt_chance,
|
|
||||||
success ? "true" : "false",
|
|
||||||
hate_top ? hate_top->GetMobDescription() : "not found"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
} else { // Classic Taunt
|
||||||
if (success) {
|
if (GetLevel() >= 60 && level_difference < 0) {
|
||||||
if (hate_top && hate_top != this) {
|
if (level_difference < -5) {
|
||||||
int64 new_hate = (
|
taunt_chance = 0;
|
||||||
(who->GetNPCHate(hate_top) - who->GetNPCHate(this)) +
|
} else if (level_difference == -5) {
|
||||||
bonus_hate +
|
taunt_chance = 10;
|
||||||
RuleI(Combat, TauntOverAggro) +
|
|
||||||
1
|
|
||||||
);
|
|
||||||
|
|
||||||
LogHate(
|
|
||||||
"Not Top Hate - Taunter [{}] Target [{}] Hated Top [{}] Hate Top Amt [{}] This Character Amt [{}] Bonus_Hate Amt [{}] TauntOverAggro Amt [{}] - Total [{}]",
|
|
||||||
GetMobDescription(),
|
|
||||||
who->GetMobDescription(),
|
|
||||||
hate_top->GetMobDescription(),
|
|
||||||
who->GetNPCHate(hate_top),
|
|
||||||
who->GetNPCHate(this),
|
|
||||||
bonus_hate,
|
|
||||||
RuleI(Combat, TauntOverAggro),
|
|
||||||
new_hate
|
|
||||||
);
|
|
||||||
|
|
||||||
who->CastToNPC()->AddToHateList(this, new_hate);
|
|
||||||
success = true;
|
|
||||||
} else {
|
} else {
|
||||||
who->CastToNPC()->AddToHateList(this, 12);
|
taunt_chance = 50 + level_difference * 10;
|
||||||
}
|
|
||||||
|
|
||||||
if (who->CanTalk()) {
|
|
||||||
who->SayString(SUCCESSFUL_TAUNT, GetCleanName());
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
MessageString(Chat::SpellFailure, FAILED_TAUNT);
|
// this will make the skill difference between the tank classes actually affect success rates
|
||||||
|
// but only for NPCs near the player's level. Mid to low blues will start to taunt at 50%
|
||||||
|
// even with lower skill
|
||||||
|
taunt_chance = 50 * GetSkill(EQ::skills::SkillTaunt) / (who->GetLevel() * 5 + 5);
|
||||||
|
taunt_chance += level_difference * 5;
|
||||||
|
|
||||||
|
if (taunt_chance > 50) {
|
||||||
|
taunt_chance = 50;
|
||||||
|
} else if (taunt_chance < 10) {
|
||||||
|
taunt_chance = 10;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Taunt Chance Rule Bonus
|
||||||
|
taunt_chance += RuleI(Combat, TauntChanceBonus);
|
||||||
|
}
|
||||||
|
|
||||||
|
//success roll
|
||||||
|
success = zone->random.Roll(taunt_chance);
|
||||||
|
|
||||||
|
// Log result
|
||||||
|
LogHate(
|
||||||
|
"Taunter mob [{}] target npc [{}] taunt_chance [{}] success [{}] hate_top [{}]",
|
||||||
|
GetMobDescription(),
|
||||||
|
who->GetMobDescription(),
|
||||||
|
taunt_chance,
|
||||||
|
success ? "true" : "false",
|
||||||
|
hate_top ? hate_top->GetMobDescription() : "not found"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Actual Taunting
|
||||||
|
if (success) {
|
||||||
|
if (hate_top && hate_top != this) {
|
||||||
|
int64 new_hate = (
|
||||||
|
(who->GetNPCHate(hate_top) - who->GetNPCHate(this)) +
|
||||||
|
bonus_hate +
|
||||||
|
RuleI(Combat, TauntOverAggro) +
|
||||||
|
1
|
||||||
|
);
|
||||||
|
|
||||||
|
LogHate(
|
||||||
|
"Not Top Hate - Taunter [{}] Target [{}] Hated Top [{}] Hate Top Amt [{}] This Character Amt [{}] Bonus_Hate Amt [{}] TauntOverAggro Amt [{}] - Total [{}]",
|
||||||
|
GetMobDescription(),
|
||||||
|
who->GetMobDescription(),
|
||||||
|
hate_top->GetMobDescription(),
|
||||||
|
who->GetNPCHate(hate_top),
|
||||||
|
who->GetNPCHate(this),
|
||||||
|
bonus_hate,
|
||||||
|
RuleI(Combat, TauntOverAggro),
|
||||||
|
new_hate
|
||||||
|
);
|
||||||
|
|
||||||
|
who->CastToNPC()->AddToHateList(this, new_hate);
|
||||||
|
} else {
|
||||||
|
LogHate("Already Hate Top");
|
||||||
|
who->CastToNPC()->AddToHateList(this, 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (who->CanTalk()) {
|
||||||
|
who->SayString(SUCCESSFUL_TAUNT, GetCleanName());
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageString(Chat::Skills, TAUNT_SUCCESS, who->GetCleanName());
|
||||||
} else {
|
} else {
|
||||||
MessageString(Chat::SpellFailure, FAILED_TAUNT);
|
MessageString(Chat::Skills, FAILED_TAUNT);
|
||||||
}
|
}
|
||||||
|
|
||||||
TryCastOnSkillUse(who, EQ::skills::SkillTaunt);
|
// Modern Abilities
|
||||||
|
if (!RuleB(Combat, ClassicTauntSystem)) {
|
||||||
|
TryCastOnSkillUse(who, EQ::skills::SkillTaunt);
|
||||||
|
|
||||||
if (HasSkillProcs()) {
|
if (HasSkillProcs()) {
|
||||||
TrySkillProc(who, EQ::skills::SkillTaunt, TauntReuseTime * 1000);
|
TrySkillProc(who, EQ::skills::SkillTaunt, TauntReuseTime * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success && HasSkillProcSuccess()) {
|
if (success && HasSkillProcSuccess()) {
|
||||||
TrySkillProc(who, EQ::skills::SkillTaunt, TauntReuseTime * 1000, true);
|
TrySkillProc(who, EQ::skills::SkillTaunt, TauntReuseTime * 1000, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -140,6 +140,7 @@
|
|||||||
#define SONG_NEEDS_BRASS 408 //You need to play a brass instrument for this song
|
#define SONG_NEEDS_BRASS 408 //You need to play a brass instrument for this song
|
||||||
#define AA_GAIN_ABILITY 410 //You have gained the ability "%T1" at a cost of %2 ability %T3.
|
#define AA_GAIN_ABILITY 410 //You have gained the ability "%T1" at a cost of %2 ability %T3.
|
||||||
#define AA_IMPROVE 411 //You have improved %T1 %2 at a cost of %3 ability %T4.
|
#define AA_IMPROVE 411 //You have improved %T1 %2 at a cost of %3 ability %T4.
|
||||||
|
#define TAUNT_SUCCESS 412 //You taunt %1 to ignore others and attack you!
|
||||||
#define AA_REUSE_MSG 413 //You can use the ability %B1(1) again in %2 hour(s) %3 minute(s) %4 seconds.
|
#define AA_REUSE_MSG 413 //You can use the ability %B1(1) again in %2 hour(s) %3 minute(s) %4 seconds.
|
||||||
#define AA_REUSE_MSG2 414 //You can use the ability %B1(1) again in %2 minute(s) %3 seconds.
|
#define AA_REUSE_MSG2 414 //You can use the ability %B1(1) again in %2 minute(s) %3 seconds.
|
||||||
#define YOU_HEALED 419 //%1 has healed you for %2 points of damage.
|
#define YOU_HEALED 419 //%1 has healed you for %2 points of damage.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user