PDA

View Full Version : Double Attack change


Congdar
09-26-2008, 06:31 PM
I think the Client::CheckDoubleAttack() method needs some modifications. Here it is currently:

bool Client::CheckDoubleAttack(bool AAadd, bool Triple) {
int skill = 0;
if (Triple)
{
if(!HasSkill(DOUBLE_ATTACK))
return(false);

if (GetClass() == MONK || GetClass() == WARRIOR || GetClass() == RANGER || GetClass() == BERSERKER)
{
skill = GetSkill(DOUBLE_ATTACK)/2;
} else {
return(false);
}
}
else
{

//should these stack with skill, or does that ever even happen?
int aaskill = GetAA(aaBestialFrenzy)*25 + GetAA(aaHarmoniousAttack)*25
+ GetAA(aaKnightsAdvantage)*25 + GetAA(aaFerocity)*25;

if (!aaskill && !HasSkill(DOUBLE_ATTACK))
{
return false;
}
skill = GetSkill(DOUBLE_ATTACK) + aaskill;

//discipline effects
skill += (spellbonuses.DoubleAttackChance + itembonuses.DoubleAttackChance) * 3;

if(skill < 300) //only gain if we arnt garunteed
CheckIncreaseSkill(DOUBLE_ATTACK);
}
if(MakeRandomInt(0, 299) < skill)
{
return true;
}
return false;
}

The first thing needing changes is the first argument bool AAadd, it doesn't get used anywhere in the method.
Next is the aa bonus *25 is too high. Max double attack skill for a 65 warrior is 255. In the following check if(skill < 300) if a warrior had only 225 skill + all 3 Ferocity AA's, the warrior would never skill up past 225 to max but would always double attack anyway in the random check below that. The magic number 299 is used there. If max skill and max ferocity, the warrior would always double attack. I think with the bonuses you should get real close to always, but not 100%. Rogue and Bards get a discipline that gives the a 10000% bonus so that's the only guarantee I know of.

Here's how I've rewritten the mentod. What do you think?

bool Client::CheckDoubleAttack(bool TripleAttack) {

// If you don't have the double attack skill, return
if(!HasSkill(DOUBLE_ATTACK))
return false;

// You start with no chance of double attacking
int chance = 0;

// Used for maxSkill and triple attack calcs
int class = GetClass();

// The current skill level
int skill = GetSkill(DOUBLE_ATTACK);

// Discipline bonuses give you 100% chance to double attack
int buffs = (spellbonuses.DoubleAttackChance + itembonuses.DoubleAttackChance) * 3;

// The maximum value for the Class based on the server rule of MaxLevel
int maxSkill = MaxSkill(DOUBLE_ATTACK, class, RuleI(Character, MaxLevel));

// AA bonuses for the melee classes
int aaBonus = GetAA(aaBestialFrenzy)*10 +
GetAA(aaHarmoniousAttack)*10 +
GetAA(aaKnightsAdvantage)*10 +
GetAA(aaFerocity)*10 +
GetAA(aaDanceofBlades)*10;


// Half of Double Attack Skill used to check chance for Triple Attack
if(TripleAttack) {
// Only some Double Attack classes get Triple Attack
if(class == MONK || class == WARRIOR || class == RANGER || class == BERSERKER) {
// We only get half the skill, but should get all the bonuses
chance = (skill/2) + buffs + aaBonus;
}
else {
return false;
}
}
else {
// This is the actual Double Attack chance
chance = skill + buffs + aaBonus;

// You can gain skill even if you don't successfully double attack,
// but put it here so you don't skill up on triple attacks
CheckIncreaseSkill(DOUBLE_ATTACK);
}

// If your chance is greater than the RNG you are successful!
if(chance > MakeRandomInt(0, maxSkill*.92)) {
return true;
}

return false;
}

AndMetal
09-26-2008, 07:12 PM
// If your chance is greater than the RNG you are successful!
if(chance > MakeRandomInt(0, maxSkill*.92)) {
return true;
}


Just to make sure I'm understanding correctly, that means the last 8% of skill-ups before the max cap would always land, since chance will equal at least the skill level of the character, not including any mods, right?

If that's the case, I think we may want to rethink this, especially in the scenario of newer levels. For example, a Monk on a progression server levels up to 50, so their max skill would be 240, so they would start double attacking 100% of the time after 220.8 (so starting at 221) skill. Say the player stops playing & the level cap has been raised to 65 (PoP I think?). They may have 240 skill, but the minimum to double attack 100% of the time (max being 265) is now 243.8 (so have to have 244+). The character hasn't changed, the rules of the server haven't changed, just the max level, but they won't be hitting like before. Granted, in that scenario, it's only a difference of about 9.5%, but that can still be significant.

Imo, I think it should be a static value, possibly set as a Rule. If it was set as a rule, would allow us to have a default value, similar to Live (which 300 sounds about right), but if you want to tune it for Progression-type servers, etc, you can.

Thoughts?

ChaosSlayer
09-26-2008, 07:16 PM
AndMetal is right, value should be static, otherwise everytime max cap increses - your char sudenly becomes weaker out of the blue
make sure it will also work beyond lev 80 :D

Congdar
09-26-2008, 07:22 PM
heh, right after I posted that I saw the *.92 I used to test and knew it wasn't right.

Congdar
09-26-2008, 07:35 PM
Imo, I think it should be a static value, possibly set as a Rule. If it was set as a rule, would allow us to have a default value, similar to Live (which 300 sounds about right), but if you want to tune it for Progression-type servers, etc, you can.
Thoughts?

300 isn't the right number either. Once Tribute goes in the warrior will have scores of up to 310 I think it was. I was hoping somebody would get the math right for me ;) but I think it needs to scale with the rule for max level as it is now but maybe add in the bonus to maxSkill too? Just a guess:

if(chance > MakeRandomInt(0, maxSkill + itembonuses.DoubleAttackChance + aaBonus)) {


This line is a bit off too. The Rogue and Bard disciplines adds 10000 to spellbonuses so then *3 + itembonuses is overkill in the calcs.

int buffs = (spellbonuses.DoubleAttackChance + itembonuses.DoubleAttackChance) * 3;

ChaosSlayer
09-26-2008, 07:41 PM
two words: diminishing returns

let say with 300 you have 90% chance
next +10 gives you +1%
next +10 give you +0.5%
next +10 give you +0.25%
etc
or whatever numbers you want to use.

BUT at the very end leave soem sort of gap so there is NEVER a 100% chance even if your level is 200 and skill is 1k+

Congdar
09-26-2008, 08:03 PM
so lets work up a calculation. if it should be a static value.. no static % then lets say you can never get more than 95% chance to double attack through bonuses. That means you always have a 5% chance to fail no matter how good you are. So if the best skill value available is a result of maxSkill + aaBonus + itembonuses.DoubleAttackChance then

if(chance > ((maxSkill + aaBonus + itembonuses.DoubleAttackChance)*1.05))

because you could only get 5% less than what is needed for max.

Is 95% the right number?

Congdar
09-26-2008, 09:15 PM
almost forgot the change needed for client.h

bool CheckDoubleAttack(bool TripleAttack = false);

Congdar
09-26-2008, 09:21 PM
I totally missed the makerandom part


if(chance > MakeRandomInt(0, ((maxSkill + aaBonus + itembonuses.DoubleAttackChance)*1.05))

Congdar
09-28-2008, 09:09 PM
To help with cut/paste:

find client.h line 645

bool CheckDoubleAttack(bool AAadd = false, bool Triple = false);

change to

bool CheckDoubleAttack(bool tripleAttack = false);

find client_process.cpp lines 288-291

//triple attack: rangers, monks, warriors, berserkers over level 60
if((((GetClass() == MONK || GetClass() == WARRIOR || GetClass() == RANGER || GetClass() == BERSERKER)
&& GetLevel() >= 60) || SpecAttacks[SPECATK_TRIPLE])
&& CheckDoubleAttack(false,true))

change to

//triple attack: rangers, monks, warriors, berserkers over level 60
if((((GetClass() == MONK || GetClass() == WARRIOR || GetClass() == RANGER || GetClass() == BERSERKER)
&& GetLevel() >= 60) || SpecAttacks[SPECATK_TRIPLE])
&& CheckDoubleAttack(true))

find client_process.cpp lines 297-298

//quad attack, does this belong here??
if(SpecAttacks[SPECATK_QUAD] && CheckDoubleAttack(false,true))

change to

//quad attack, does this belong here??
if(SpecAttacks[SPECATK_QUAD] && CheckDoubleAttack(true))

find attack.cpp line 2716 Delete the entire method Client::CheckDoubleAttack() and replace with this, it is completely rewritten.

bool Client::CheckDoubleAttack(bool tripleAttack) {

// If you don't have the double attack skill, return
if(!HasSkill(DOUBLE_ATTACK))
return false;

// You start with no chance of double attacking
int chance = 0;

// Used for maxSkill and triple attack calcs
int classtype = GetClass();

// The current skill level
int skill = GetSkill(DOUBLE_ATTACK);

// Discipline bonuses give you 100% chance to double attack
int buffs = (spellbonuses.DoubleAttackChance + itembonuses.DoubleAttackChance) * 3;

// The maximum value for the Class based on the database entry for level
int maxSkill = MaxSkill(DOUBLE_ATTACK, classtype, GetLevel());

// AA bonuses for the melee classes
int aaBonus =
(GetAA(aaBestialFrenzy)*10) +
(GetAA(aaHarmoniousAttack)*10) +
(GetAA(aaKnightsAdvantage)*10) +
(GetAA(aaFerocity)*10) +
(GetAA(aaDanceofBlades)*10);

// Half of Double Attack Skill used to check chance for Triple Attack
if(tripleAttack) {
// Only some Double Attack classes get Triple Attack
if((classtype == MONK) || (classtype == WARRIOR) || (classtype == RANGER) || (classtype == BERSERKER)) {
// We only get half the skill, but should get all the bonuses
chance = (skill/2) + buffs + aaBonus;
}
else {
return false;
}
}
else {
// This is the actual Double Attack chance
chance = skill + buffs + aaBonus;

// You can gain skill even if you don't successfully double attack,
// but put it here so you don't skill up on triple attacks
CheckIncreaseSkill(DOUBLE_ATTACK);
}

// If your chance is greater than the RNG you are successful! Always have a 5% chance to fail.
if(chance > MakeRandomInt(0, ((maxSkill + itembonuses.DoubleAttackChance + aaBonus)*1.05))) {
return true;
}

return false;
}

Congdar
09-29-2008, 12:30 PM
Can you move this to Submissions forum Trev, Cave?

AndMetal
09-29-2008, 02:54 PM
Done. I'll merge it into SVN so everyone can start testing it out & comment out the old stuff just in case some want to utilize the older code.