Damage Bonus Functions
First of all, I have to say a big "thank you" to all of the amazingly talented folks who make this project possible!
I've enjoyed playing on EQEmu servers for three years now, so it's way past time that I offered something back. I hope it's alright if I offer some code changes for the senior developers to consider including in the next build! I do work as a software engineer, so my guild leader on PEQ The Grand Creation (Reno) convinced me to take a look at the code used to calculate two-handed weapon damage bonuses. I did, and it's pretty seriously broken, so I hope it's alright that I've put some work into fixing it. Let me first list the current function used to calculate damage bonuses, so that I can point out what needed to be fixed in it. This method starts on line 1935 in the 2008-09-02 version of attack.cpp: Code:
int Mob::GetWeaponDamageBonus(const Item_Struct* Weapon) Here are some of the more major items that needed to be fixed: Code:
int BasicBonus = ((GetLevel() - 25) / 3) + 1; The correct formula for calculating 1H weapon damage bonuses is (GetLevel() - 25) / 3. The "+ 1" is unnecessary, and artificially increases the damage bonus for all weapons. Code:
// If we have no weapon, or only a single handed weapon, just return the default This is the BIGGEST problem with this function. Weapon->ItemClass can have one of three values: ItemClassCommon, ItemClassContainer, or ItemClassBook. Code:
if ((Weapon->ItemType == ItemType1HS) || (Weapon->ItemType == ItemTypePierce) || (Weapon->ItemType == ItemType1HB)) Not that it matters, as the bug mentioned above ensures that we'd never actually evaluate this conditional, but ItemTypeHand2Hand is omitted. So Hand to Hand weapons would have been evaluated using the two-handed formulae, and therefore would have had damage bonuses that were unfairly high. The code for calculating damage bonuses for 2H weapons was a good attempt to approximate the actual formula that Sony/Verant uses. But it's inaccurate in many cases. Before I post the new formula to calculate 2H damage bonuses, let me post my suggestion for re-writing the above Mob::GetWeaponDamageBonus() function: * If you don't like all of my comments, please feel free to remove them! I figure it's better to err on the side of too many comments, rather than too few! Code:
int Mob::GetWeaponDamageBonus(const Item_Struct* Weapon) Now, you'll also need a copy of the new Calculate2HDamageBonus() function. As I warned you, it's long and ugly-looking, but please don't let that fool you into thinking it's inefficient! Code:
// ************************************************** I am sure that it will return accurate damage bonuses for levels 28-65. However, I believe there are a couple slight inaccuracies in the level range 66-80. Janusd and Romai provided me with the raw data for this level range, and Romai is currently working to verify these values. Please don't let that stop you from including this code in the next build. If there are any damage bonus inaccuracies for levels 66-80, they are slight. That means that this function is FAR better than what we currently have! If Romai informs me that there are inaccuracies, I'll correct the tables, and post to let you know to include the updates. Again, I hope that our contributions are welcomed, and that they benefit the project. Also, I do love coding, so I'd be happy to offer my services on other projects, if needed! Have a great day, everyone! -Eric (Cantus) |
It pleases me that as of late so many people have taken interest into submitign new code. =)
Just one minor note - does your code can handle things for levels BEYOND 80? Some of runing servers with max level of 100+ or even higher - would be nice if these things would keep scaling up and don't just become broken at 70 or 80 =) |
Looks interesting hehe. I am getting:
Code:
Error: Calculate2HDamageBonus was not declared in this scope Seems like many people are working on making the 2H damage bonus better lately for some reason lol. Here are some other examples: http://www.eqemulator.net/forums/showthread.php?t=26200 http://www.eqemulator.net/forums/showthread.php?t=26127 And some other combat related ones: http://www.eqemulator.net/forums/showthread.php?t=26099 http://www.eqemulator.net/forums/showthread.php?t=26213 I wonder why the sudden flood of code for this lol. Not complaining, but it is a little weird to see 3 different posts with fixes for 2H bonuses in the past week or 2. |
One of them was my attempt at it. It wasn't working as accurately as I had hoped and Cantus offered to take a look at it. After much discussion on our guild forum, this is where we ended up. It came out very well in the end. My biggest concern was time to parse that much code. The look up table's actually ended up parsing far faster than some of the formula's I was attempting to use. It is a very good solution to our problem.
|
So, where does Calculate2HDamageBonus function go? I can't figure out where to put it and it errors as shown in my previous post if I put it directly in my attack.cpp.
|
ChaosSlayer, you're right... it is great to see people getting more involved with the project! I'm glad that our contributions seem to be well received by the established community and senior developers. I hope that I'll have more opportunities to help in the future!
Trevius, I did see that others were working on this particular problem, as well. I did work along with several of them (such as Reno) to develop what we believe to be the final solution to the problem, as posted above. Unlike the other threads, we're confident saying "it's done; it's fixed" with the code in this thread. Please do review and test, and if you agree, please feel free to throw it into the next build! Quote:
The GetWeaponDamageBonus() is a member of the Mob class, so it's trying to call a Calculate2HDamageBonus() that's also a member of that class. There is none, as Calculate2HDamageBonus() is declared as a global function. The quick fix is to, when Calculate2HDamageBonus() is called, add two colons (the C++ Scope Resolution Operator) before its name to indicate that it's a function that resides in the global namespace, like this: Code:
return ::Calculate2HDamageBonus( GetLevel(), Weapon->Delay ); A better long-term choice would probably be to make the Calculate2HDamageBonus() a member of the Mob class. As this is my first contribution and I'm therefore a very junior contributor, I didn't want to presume to add a new function to someone else's class. But if you want to do it, here's a rough description of how: Sorry that I can't give precise line numbers, as I'm at work, and do not have a copy of the Emu source available. Find the declaration of the Mob class, and add a prototype for the Calculate2HDamageBonus() function. Then add "Mob" and the scope resolution operator before the definition of the function. A third possibility is: You could also rip out the guts of the function and plug it directly into GetWeaponDamageBonus(), but that'll make the GetWeaponDamageBonus() function huge and ugly. I'd recommend keeping Calculate2HDamageBonus() as a function. I'll be happy to post more detail on these changes when I get home from work tonight! Take care, -Eric |
Quote:
I apologize. I've played only on The Grand Creation (level cap 65), so I didn't have an idea of how many other servers there were out there with a higher level cap. Currently, in most cases, this function stops increasing damage bonuses for 2H weapons beyond their value at level 80. That is not ideal for servers with a level cap of 100+. However, it is still FAR better than the way things are currently, so I would recommend not waiting to get these changes added to the next build. That does not prevent us from adding in support for toons level 81+ in the future! I will work on that for you. Just so you know: in this function, I, and the folks that helped me, focused on returning damage bonuses that were exactly what they should be on Live. I can confidently say that it does this for levels 28-65, and that it's very close for 66-80 (it will be exact once Romai finishes verifying the data he gave me). Because Live only goes as high as 80, I only know, for sure, what damage bonuses are up to that level. Sony has proven to us that they often muck around with the formula used to calculate damage bonuses each time they release a new expansion. So there is no guarantee that future expansions will continue to ramp up 2H damage bonuses at the same rate as bonuses ramped up from level 75 to 80. I will add in support for toons levels 81+, but it'll just be a "best guess" at what the damage bonuses really will be once Sony increases the level cap on Live. When they do increase the level cap, we may have to adjust the formula to better track the real servers. Does that sound acceptable? If so, I'll work on it. |
Quote:
On a side note, my previous formula, posted in this forum, should provide what you seek. It will scale up with level beyond level 80. It should be within 1 or 2 damage from levels 50 on up to 100ish, assuming Sony follows a set scale in the future. Under level 50 you will find it becomes less and less accurate as level decreases. We decided on this method as it was 100% accurate whereas every formula I was able to devise was prone to error's due to rounding and other factors. So, you do have another option if you so wish. (Please note, this is NOT tested beyond level 80 so I have no idea how it will turn out, but it should scale well from 50 on up. It isn't 100% but it is close.) |
thank you for replying renoofturks1!
I just want to point out that you should not realy try to keep up with live, since we simply do not have any access to future/curent content anyway , specialy since Aniversary edition will not be supported by eqemu due to its unavalability on market. So a simple scaling feature will work fine. Also, could I request that you also include a RULE to TURN OFF damage bonus complitly? A kind of fail safe if it starts behave badly past lev 80, or 100 or 150 or whatever. At least this way weapons gona stay vanila. thank you =) PS: As i staed before damage bonus was a complitly useless feature to begin with, the soe should have simply upped the ratios on all 2handers compared to 1handers and be done with it, and this is the kind of balancing I am using on my server |
Quote:
What Reno's saying, I believe, is that if future expansions on Live increase the level cap, we can then figure out exactly what 2H weapon damage bonuses will be on Live for higher levels. That has nothing to do with upgrading the server and requiring EQEmu players to purchase a newer client. Rather, it has to do with figuring out whether Sony will change the formulas they use to calculate damage bonuses for levels 81+, as they've done in the past. Quote:
Servers with a level cap of 81+ will not break the damage bonus calculation function that I posted above. For most weapons, the damage bonus will simply stop increasing beyond its value at 80. Reno and I will work together on including a formula that takes a "best guess" as to what damage bonuses for levels 81+ may look like. When Sony eventually increases the level cap, we may find that our guess was off. But that's not a problem! When that happens, we'll simply come back and modify the code. The formula for 81+ will assume that damage bonuses will keep increasing in line with how they increased from level 70 - 80. I think that should be a good, fair solution for servers with a high level cap! Agreed? By the way, I agree with your points about Damage Bonus. But not much we can do about it now ;-). Have a good one, -Eric (Cantus) |
This is without a doubt going into PEQ when it comes back up, along with a slew of other things!
|
Quote:
As for the proper scaling, I have never had a toon over 65 on EQEmu, Does the weapon show the damage bonus as continuing to scale beyond level 80? If so, all the information we would need to extend it into the higher levels is right in front of us. As for my previous formula, it won't break anything beyond level 80, it is only in-accurate under level 50. I can't say if it is scaling improperly above level 80 because I have no idea what properly scaling would be :D |
Cantus, renoofturks1 - Thank you guys for replying =)
My only concern to avoid an issue when weapons till 80 would have a dmg bonus and past 80 it sudenly becomes zero (or starts going backwords or become negative or whatever +) resulting in pre 80 players doing more dps than past 80 with same weapons. If dmg bonus gona scale up using same formula or even stay the same - all fine by me , as long as it does not become chaotic from level to level =) Thanks again! |
Quote:
|
Quote:
The only thing I could ask if you would add Rule: Damage Bonus on/off - so we can have an option to play with DPS only governed by natural weapon stats. Thanks =) |
Discussion: http://eqemulator.net/forums/showthread.php?t=26262
Thanks again for all of your feedback! I've made several of the changes that were suggested, like adding in a simple preprocessor directive that lets a server administrator build a copy of the Emulator that never applies damage bonuses to weapons. I have not yet added calculations for continuing to ramp up 2H damage bonuses for levels 81+, but we'll get that added soon! To make compilation easier and also to speed things up a tiny bit, I've changed the way this function is deployed. ** Please disregard the first post in this thread, and instead follow the following steps to compile and test the proposed fixes ** 1) Open Mob.h, and scroll down to line #646. It should look like the following: Code:
int GetWeaponDamageBonus(const Item_Struct* Weapon); 2) Please change the first word "int" to "int8", as follows: Code:
int8 GetWeaponDamageBonus(const Item_Struct* Weapon); 3) Open Attack.cpp, and scroll down to lines #971 - 976. They should look like: Code:
//if mainhand only, get the bonus damage from level 4) Completely replace those lines with the following: Code:
// *************************************************************** 5) Scroll further down in Attack.cpp to around line #1952 (assuming you added the code in step 4), and look for the function that starts with the line: Code:
int Mob::GetWeaponDamageBonus(const Item_Struct* Weapon) 6) Replace that entire function (it should take up 36 lines, ranging from about line #1952 down to #1988 ) with the following (much larger!) function: Code:
int8 Mob::GetWeaponDamageBonus( const Item_Struct *Weapon ) 7) Compile, and let me know if it works! I'm sorry, but I wound up working late and never got home to actually test this. If there are any errors, please let me know, and I'll fix them ASAP! |
Quote:
|
It's all merged together in that new set he posted. No need to define a new function.
|
if you wanted to add a rule in for damage bonuses, all you should have to do is add:
In attack.cpp Code:
if(RuleB(Combat, UseDamageBonus)){ Then, just add it to the ruletypes.h file like this: Code:
RULE_BOOL ( Combat, UseDamageBonus, true) //default is true to enable damage bonuses Then just add the optional SQL if you want to disable it. But you don't even need the SQL if you want to leave it enabled, since the default is true: Optional SQL: Code:
Insert into rule_values values (0, 'Combat:UseDamageBonus', true); |
Oh and I got the latest submission in this thread compiled and tested on my server. It looks good to me! Definitely better than the current code in the emulator lol.
|
very good Trev! I hope it makes in with the Rule you described 8)
|
Quote:
ChaosSlayer's suggestion of a flag to allow server administrators to turn damage bonuses on and off is already in the code I posted above. It is not implemented as a standard type of rule as Trevius suggests, but there's a reason for that. Please let me explain, but first, here's the code snippet that mentions the change: Code:
#ifndef EQEMU_NO_WEAPON_DAMAGE_BONUS While I understand ChaosSlayer's points that it would be nice to try things out without damage bonuses, and rely entirely upon the native damage/delay of the weapon, the fact is that most servers are not going to choose to disable damage bonuses. If we implemented the check for whether or not the server administrator wants damage bonuses at runtime, using the standard Rule method that Trevius suggests, that means that every time a melee toon lands a hit with a 2H weapon, there's the extra overhead of calling that Rule function. I know, that doesn't seem like a big deal. But keep in mind that if someone Rampages with an Earthshaker, this code could potentially be called hundreds of times in a split second, for example. Or if someone pops a riposte discipline like Furious or Whirlwind with lots of mobs hitting them. Or if a lot of toons are raiding a mob, and they're landing many hits at once (double, triple, quad hits against the target). In all of these cases, this function will be called many times in rapid succession, so even a small difference -- like the function call overhead involved with checking a rule in the traditional way -- may become significant. So, as this is one of the places where we want things to be as efficient as possible, I used a C/C++ preprocessor directive to allow folks like ChaosSlayer to turn on or off damage bonuses. It is not as slick as Trev's suggestion, as it must be done by adding a line of code and then re-compiling the server, vs. making a database change during runtime, but I still think it's in everyone's best interests -- as it does not slow down processing by involving needless function call overhead every time a 2H weapon hits. I may be wrong... that happens a lot! So if you prefer, feel free to make it a rule, or just ask me and I'll do it for you! |
Quote:
It may already be too late, as you've re-built your server using the new code. But if you still have an old build around on a test machine, it'd be neat to run a quick test to make sure things are working as expected. What I'd recommend is either use your GM to twink a toon with a nice, slow 2H weapon like "A Weighted Axe", or just farm one in the Burning Woods. They drop commonly. That's a perfect 2H weapon to test with, as its native ratio sucks, but due to its slow speed, it receives a massive damage bonus. Fight a mob with it on a server compiled with the old code. Watch for the average and maximum hit (or just go all out and parse it). Then re-build that server with the new damage bonus code. Attack a similar mob, and watch the damage output. It should be greatly increased if things are working well. |
Quote:
Out of interest, I compiled zone with VC++ 2008 Express with optimise for speed selected, and used IDA to look at the code it generates when a boolean rule is checked. It is only 4 machine instructions: Code:
mov edx, dword_A48964 ; Load Rule base pointer |
That answer's my question. Thanks!
|
Cantus, your way would work fine for people who compile their own source. But, many people use the win32 binaries if they are running a windows server.
If the rule did have any performance impact at all, I don't think it would be worth making 99% of all servers suffer so 1% could have a special rule for it :P But if there is no performance impact, the rule would be best. If there is, then your way would be best, so there is still an option available if someone absolutely must disable damage bonus for any reason. Again, I am personally against having a rule in place for this. I just don't see a need. Unless you are running a server with 100% custom created weapons, then your weapon balance will be off if you don't have damage bonuses enabled. I only posted the rule, so it could be added if needed. It is a pretty simple option. Though, it would be nice if there was a way to store that weapon bonus calculation and use it over and over instead of having to calculate it with every swing. I know for sure on my server that even before this change, anyone rampaging more than like 20 mobs is risking a zone crash. I haven't had feedback on the new code yet to see if it still causes that, but not many people use 2H weapons on my server due to them sucking in the first place. I don't think it is only damage bonus that is messed up with 2H weapons. I think there seems to be some weird damage capping going on as well which makes them almost pointless. |
All the testing I have done put's the 2 hander's where they should be now. If there are other issue's, bring them up and I'll see about getting them kinked out
|
Derision,
Excellent information there. I apologize that I don't have the code in front of me... are the rule-checking functions inline? In other words, does the ASM that you posted also take into account function call overhead, unwinding the stack, etc. that would result from invoking a non-inline function? Either way, I think you're right: The performance hit for implementing a rule is trivial. Though your point that the rule is queried from the DB only when a zone first boots is important for folks like ChaosSlayer to remember. If you toggle Damage Bonuses on or off in the DB, you'll have to reboot the zone for it to take effect. Trevius, Excellent points, as always! I think the info that Derision provided shows that adding in a rule adds only a tiny amount of overhead to the code, so let's go that route. I'll make the addition of that rule when I also add the code to continue ramping up Damage Bonus for levels 81+. Hopefully should have that posted in a day or two (work's been killing me this week -- very little free time. Sorry.) You make another excellent point here. I may be able to put your fears to rest: Quote:
Here is some data from a test I ran, as posted to our guild messageboard: Quote:
One last point you made: Quote:
Please do give it another shot after compiling a version of the server using the new code in this thread. I bet you'll be a lot more pleased with 2H weapons than before! In fact, troll the Allakhazam pages for some popular 2H weapons to get people's feedback on how hard these weapons hit. Then use a GM to twink a toon out with that same weapon at the same player level, and see if it hits for about the same on EQEmu. I believe Reno already ran this test, and concluded that, with these fixes, 2H weapons perform just like they did on Live. If that's not the case, well then, we'll look at the code more carefully, find the problem, and fix it! Sound good? |
Quote:
Quote:
|
I moved all of the off-topic discussion comments here:
http://www.eqemulator.net/forums/showthread.php?t=26348 Continue the discussion there instead of here, please. |
i created a new level 1 paladin and started leveling today, and i'm hitting things for 250+. Did i merge something wrong or can someone else confirm this?
|
after more testing my paladin using a 1hs damage 4 delay 29 hit for 250+ until level 23 then started hitting for 10-20 (seems more normal) 2hs damage seemed fine tho.
|
i just readded the level check (think you forgot to put it back in after some editing) and eveything works fine again
Code:
if( GetLevel() < 28 || !IsWarriorClass() ) |
Quote:
Please check step #4 in the instructions on how to build these new Damage Bonus changes. The level check is still in there; I just moved it outside of the Damage Bonus function itself (after all, why bother with function calling overhead if you aren't high enough level to receive a damage bonus?) Here are the relevant lines: Code:
if( Hand == 13 && GetLevel() >= 28 && IsWarriorClass() ) Take care! |
All times are GMT -4. The time now is 10:19 AM. |
Powered by vBulletin®, Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.