Go Back   EQEmulator Home > EQEmulator Forums > Development > Development::Development

Development::Development Forum for development topics and for those interested in EQEMu development. (Not a support forum)

Reply
 
Thread Tools Display Modes
  #1  
Old 10-21-2006, 03:50 PM
KLS
Administrator
 
Join Date: Sep 2006
Posts: 1,348
Default

Another quick change. Did this pretty quickly so tell me if I messed any part of it up.

Dunno if it bothers anyone else as much as it bothers me but the small quickly used timers for the hard coded client skills keep bugging out on me, my sneak is down for the next 11 days according to my database for instance =(

Not sure at all what causes these short timers to bug out so I added a rule here on whether or not to enforce them, I mean do we really need to enforce them? They're hard coded into the client and it's going to be pretty rare that someone hacks into the client to change the timers, most are only a few seconds anyway.

Also threw in another rule that helps server admins modify the endurance regen since there really isn't any way to raise your regen outside of +endurance regen items, and def seems like something admins might want to change, just like an exp modifier.

new rules:

RULE_BOOL( Character, EnforceSkillTimers, false )
RULE_REAL( Character, EnduranceRegenBonus, 1.0 )

http://hmproject.org/files/timers.patch


Also would like to add that I love this rule system, it's a brilliant concept.

Last edited by KLS; 10-21-2006 at 11:53 PM..
Reply With Quote
  #2  
Old 10-21-2006, 04:01 PM
mattmeck
Guest
 
Posts: n/a
Default

People will hack the client for the timers, trust me. Instant Back Stab for instance.

This was added in because of the amount of people that were hacking the client.
Reply With Quote
  #3  
Old 10-21-2006, 04:02 PM
vales
Discordant
 
Join Date: May 2006
Posts: 458
Default

I love you man!

These are some seriously bad-ass fixes. I'm gonna patch up the server and see the changes. Will report back if I see something out of the ordinary.

Keep up the awesome work!
Reply With Quote
  #4  
Old 10-21-2006, 05:18 PM
KLS
Administrator
 
Join Date: Sep 2006
Posts: 1,348
Default

I'll look for what's happening to the shorter timers, I don't notice it happening with any of the longer ones, my disc timers for instance but it's certainly happening with some of the shorter ones kick sneak hide Feign. That's just there till I figure it out.

Edit: Alright, here's something I found with persistant timers, first I misread the timer in my database last time that led me to the rule conclusion it was really set to 0, 0. If a timer is set to duration 0, enable 0 in the database it wont count as expired, and apparently sometimes when removing timers instead of them being removed from the DB they get set to 0, 0 thus that skill is now bugged for that character(gg). Not sure of a fix yet but yeah thanks for not letting me take the lazy way out with my rule I guess.

Last edited by KLS; 10-22-2006 at 01:50 AM.. Reason: Timer stuff
Reply With Quote
  #5  
Old 10-21-2006, 05:55 PM
fathernitwit
Developer
 
Join Date: Jul 2004
Posts: 773
Default

overall the changes look good.

make sure you default any new rules to how they were before you added the rule... aka EnforceSkillTimers to true.

interesting about the item bonuses being counted twice... have you checked #showbuffs to see how it compares?

also in the endurance calculation, what I put in should have matched your original version here:
http://www.eqemulator.net/forums/showthread.php?t=21661
I am assuming that the int() operators in your original code were being used in place of floor()... but in any light, the 0.075 * GetLevel() in your oringinal code was outside the int(), so it should have had the same rounding effects as my code. If you are really not intending to floor() those numbers, than instead of multiplying out each time like you did, just change the variables in that function to be floats and then use max_end += bonus_sum * GetLevel()*0.075; at the end. (converting an int to a float or vise versa is generally a rather computationally expensive operation, and should be minimized)
Reply With Quote
  #6  
Old 10-21-2006, 06:49 PM
KLS
Administrator
 
Join Date: Sep 2006
Posts: 1,348
Default

I think I've found the issues that affect timers. A timer that is not enabled and as a 0 duration will return false on get expired and never be cleared from the database, sometimes they do(I dunno why? but can we put a work around in the expired code?).

Also some of the hard coded combat skills are affected by haste clientside but not taking that into account server side. Ex just timed my backstab clientside with a stopwatch, about 8 seconds without haste 5.5 with.

The issues with get stats is it uses the Mob:: version of stats instead of Client:: we need to be very careful as a result when things can be both for clients and npcs. Get stats for instance uses the mob version and the mob version counts the item and spell bonuses twice for clients because they aren't counted at all for non clients outside of that.

I'm not sure what's with my head and the endurance sorry, I really had documented a major loss in it the other day but just went to go make sure I wasn't crazy and apparently I am, oh no =( I work too late, sorry mate, if I actually find the problem again I'll bring it back to you in excrutiating detail.

I'm editing this post way too much but yeah also I'm gonna go through and see about getting close to the actual times on the client side skills since some seem off, some by a lot(track/forage!).

Last edited by KLS; 10-22-2006 at 03:02 AM..
Reply With Quote
  #7  
Old 10-22-2006, 08:54 AM
KLS
Administrator
 
Join Date: Sep 2006
Posts: 1,348
Default

Alright after being informed last night how common the hackers were I looked into the timers further. Instead of the enforce rule I did this.

Checks to see if the timer is enabled where we check to see if timers are expired ex:
Code:
-	if(!p_timers.Expired(&database, pTimerCombatAbility, false)) {
+	if(p_timers.Enabled(pTimerCombatAbility) && !p_timers.Expired(&database, pTimerCombatAbility, false)) {
If a timer is disabled for whatever reason we'll count it as expired for these situations, while this really shouldn't be happening it has happened a few times to me and made the skill that was timer enforced completely unusable unless I modified the database to fix it.

Also applied haste to the timers for combat, tested it somewhat and seemed to work fine.

http://hmproject.org/files/timers2.patch
Reply With Quote
  #8  
Old 10-22-2006, 02:15 PM
KLS
Administrator
 
Join Date: Sep 2006
Posts: 1,348
Default

Notice you redid some of the special attack code to be more consistant with regular attacks. Looking over it I saw a few things, not really much from what you changed but what was already there in the orig. design.

In avoid damage there are several calls to functions Mob::CanThisClass<Whatever>() that always return false for npcs meaning they never dodge parry riposte except under certain conditions.

Example:
Code:
bool Mob::CanThisClassParry(void) const
{
	// Trumpcard
	switch(GetClass()) // Lets make sure they are the right level! -image
	{
	case WARRIOR:
		{
		if(GetLevel() < 10)
			return false;
		break;
		}
	case ROGUE:
	case BERSERKER:
		{
		if(GetLevel() < 12)
			return false;
		break;
		}
	case BARD:
		{
		if(GetLevel() < 53)
			return false;
		break;
		}
	case RANGER:
		{
		if(GetLevel() < 18)
			return false;
		break;
		}
	case SHADOWKNIGHT:
	case PALADIN:
		{
		if(GetLevel() < 17)
			return false;
		break;
		}
	default:
		{
			return false;
		}
	}

	if (this->IsClient())
		return(this->CastToClient()->GetSkill(PARRY) != 0);	// No skill = no chance
	else
		return false;
}
We return false if it is not the correct level and get past the switch statement if we are, then we check if we are a client and have skill if so we're okay if not we're not a client we get a false return 100% of the time from that last return false which really should be true. Happens in the following functions:
Code:
bool Mob::CanThisClassParry(void) const
bool Mob::CanThisClassDodge(void) const
bool Mob::CanThisClassRiposte(void) const
Also the riposte code is seperate from avoid damage somewhat in that we only do the auto attack in the Attack() functions instead of in the avoid damage, as a result being riposted with special skills wont ever get you hurt because we don't do the counter attack in the special attack code.

I also question how we do the input damage to that code with regards to AC mitigation. What we do now is take a random number from the min and max hit in terms of combat and then throw that into the avoid damage which has a sort of confusing mitigation formula and this gives us an illusion of real AC mitigation with the random numbers being spit out at us. Really though we should be throwing in the max value and the mitigation should be throwing us back a new value that seems random based on our pure AC from items and our attackers str+atk+offense_skill, then checking the out number versus the min hit we can make.

Then there's also critical hits, currently nothing but auto attack can crit, and the code really just makes the attack() function look messy. Special attacks should be able to crit too so what if we had something like this that we could throw in after every time we do anything with melee:
Code:
void Mob::CriticalHit(Mob* defender, int16 skillinuse, sint32 &damage)
{
	if(damage <= 0)
		return;
	//defender isn't used right now but it's nice to have incase we need to use
	//it for the future.
	float critChance = 0.0f
	int critMod = 2;
	if((GetClass() == WARRIOR || GetClass() == BERSERKER) && GetLevel() >= 12 && IsClient()) 
	{
		critChance += 0.03f
		if(CastToClient()->berserk)
		{
			critChance += 0.06f
			critMod = 4;
		}
	}

	switch(GetAA(aaCombatFury))
	{
	case 1:
		critChance += 0.02f;
		break;
	case 2:
		critChance += 0.04f;
		break;
	case 3:
		critChance += 0.07f;
		break;
	default:
		break;
	}

	critChance += ((critChance) * (spellbonuses.CriticalHitChance + itembonuses.CriticalHitChance) / 100.0f); //crit chance is a % increase to your reg chance
	if(critChance > 0)
		if(MakeRandomFloat(0, 1) <= critChance)
		{
			damage = (damage * critMod);
			if(IsClient() && CastToClient()->berserk)
			{
				entity_list.MessageClose(this, false, 200, 10, "%s lands a crippling blow!(%d)", GetCleanName(), damage);
			}
			else
			{
				entity_list.MessageClose(this, false, 200, 10, "%s scores a critical hit!(%d)", GetCleanName(), damage);
			}
		}
}
Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

   

All times are GMT -4. The time now is 02:42 PM.


 

Everquest is a registered trademark of Daybreak Game Company LLC.
EQEmulator is not associated or affiliated in any way with Daybreak Game Company LLC.
Except where otherwise noted, this site is licensed under a Creative Commons License.
       
Powered by vBulletin®, Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Template by Bluepearl Design and vBulletin Templates - Ver3.3