Go Back   EQEmulator Home > EQEmulator Forums > Development > Development::Server Code Submissions

Reply
 
Thread Tools Display Modes
  #1  
Old 07-23-2008, 08:50 AM
CodeMephit
Fire Beetle
 
Join Date: Oct 2006
Posts: 18
Default

I have now finished the consumption code. It handles small and large races and mounts. Both of which can be turned off by rules in the database.
I made 3 characters on a live server and timed their eating & drinking. I can post the math for anyone interested, but the end result is I have an almost perfect live-like consumption rate (even with the rules turned off). I used unsigned integers which have no decimal place. To achieve a 'true' live-like rate, I would have to change this to use decimals. As it stands, food may only last a few extra seconds (42 to be exact), and I didn't think it was a big enough deal to worry with changing.

For all of this to work, 4 changes must be made. 3 to the code and 1 to the database.

In file \EQEmu-0.7.0-1119\common\ruletypes.h (Line 49) - ADD
Code:
RULE_BOOL( Character, RacialConsumption, true)
RULE_BOOL( Character, MountConsumption, true)
In file \EQEmu-0.7.0-1119\world\client.cpp (Line 957) - ADD
Code:
	pp.hunger_level		= 5000;
	pp.thirst_level		= 5000;
In file \EQEmu-0.7.0-1119\zone\client_packet.cpp (Line 1255 - 1327) - REPLACE
Code:
void Client::Handle_OP_Consume(const EQApplicationPacket *app)
{
//o----------------------------------------------------------------------------
//| Codemephit [2008.07.22] - Rewrote the consuption routine to handle racial
//|   size and mounts.
//|   Two rules were added.  They are both Boolean.
//|		Character:RacialConsumption - Turns on/off the racial size check.
//|		Character:MountConsumption - Turns on/off the mount present check.	
//o----------------------------------------------------------------------------
	//o------------------------------------------------------------------------
	//| Make sure the OP_Consume packet is valid and with no errors.  If it is
	//| not, then log the error and return to calling code.
	//o------------------------------------------------------------------------
	if (app->size != sizeof(Consume_Struct))
	{
		LogFile->write(EQEMuLog::Error, "OP size error: OP_Consume expected:%i got:%i", sizeof(Consume_Struct), app->size);
		return;
	}

	Consume_Struct* pcs = (Consume_Struct*)app->pBuffer;

	// This is the base Consumption Modifier.
	uint16 intBaseConsMod = 107; //<-- This should be 106.5 but uint16 = no decimal.
	// Apply the rule Character::ConsumptionModifier.  We need to keep the base
	// modifier seperate from the actual modifier to prevent compound calculations.
	uint16 intConsMod = intBaseConsMod * RuleI(Character, ConsumptionMultiplier) / 100;

	//o------------------------------------------------------------------------
	//| Update intConsMod for Character Size.  Only small or large characters
	//| need to be updated, as there is no modifier for a medium sized player.
	//o------------------------------------------------------------------------
	if (RuleB(Character, RacialConsumption))
	{
		if (m_pp.race == 8 || m_pp.race == 11 || m_pp.race == 12)
		{
			// Dwarf = 8, Halfling = 11, Gnome = 12
			// Player is a Small Race. (Modifier = +20%)
			intConsMod = intConsMod + (intBaseConsMod * .20);
		}

		if (m_pp.race == 2 || m_pp.race == 9 || m_pp.race == 10 || m_pp.race == 128 || m_pp.race == 130)
		{
			// Barbarian = 2, Troll = 9, Ogre = 10, Iksar = 128, Vha Shir = 130
			// Player is a Large Race.  (Modifier = -20%)
			intConsMod = intConsMod - (intBaseConsMod * .20);
		}
	}

	//o------------------------------------------------------------------------
	//| Update intConsMod for a summoned mount.  Having this check before the
	//| AA Innate Metabolism check will allow a mount to benifit from the AA
	//| as well as the player. We caculate -25% from the 'base' modifer.  This
	//| ensures that mounts will eat the same ammount regardless of what size
	//| thier owner is.
	//o------------------------------------------------------------------------
	if (RuleB(Character, MountConsumption))
	{
		if (GetHorseId() != 0)
		{
			// A mount is currently summoned.
			intConsMod = intConsMod - (intBaseConsMod * .25);
		}
	}

	//o------------------------------------------------------------------------
	//| Update intConsMod for the Innate Metabolism AA.
	//| All of these updates are done against the current modifer.
	//o------------------------------------------------------------------------
	switch(GetAA(aaInnateMetabolism))
	{
		case 1:
			// Player has Innate Metabolism I (10% increase)
			intConsMod = intConsMod + (intConsMod * .10);
			break;
		case 2:
			// Player has Innate Metabolism II (25% increase)
			intConsMod = intConsMod + (intConsMod * .25);
			break;
		case 3:
			// Player has Innate Metabolism III (50% increase)
			intConsMod = intConsMod + (intConsMod * .50);
			break;
		default:
			// Player has no ranks in Innate Metabolism (0% increase)
			break;
	}

	ItemInst *myitem = GetInv().GetItem(pcs->slot);
	if(myitem == NULL)
	{
		LogFile->write(EQEMuLog::Error, "Consuming from empty slot %d", pcs->slot);
		return;
	}
	
	const Item_Struct* eat_item = myitem->GetItem();
	if (pcs->type == 0x01)
	{
		#if EQDEBUG >= 1
			LogFile->write(EQEMuLog::Debug, "Eating from slot:%i", (int)pcs->slot);
		#endif
		m_pp.hunger_level += eat_item->CastTime*intConsMod;
		DeleteItemInInventory(pcs->slot, 1, false);
		
		if(pcs->auto_consumed != 0xffffffff) //no message if the client consumed for us
			entity_list.MessageClose_StringID(this, true, 50, 0, EATING_MESSAGE, GetName(), eat_item->Name);
	}

	else if (pcs->type == 0x02)
	{
		#if EQDEBUG >= 1
			LogFile->write(EQEMuLog::Debug, "Drinking from slot:%i", (int)pcs->slot);
		#endif
		m_pp.thirst_level += eat_item->CastTime*intConsMod;
		DeleteItemInInventory(pcs->slot, 1, false);
		
		if(pcs->auto_consumed != 0xffffffff) //no message if the client consumed for us
			entity_list.MessageClose_StringID(this, true, 50, 0, DRINKING_MESSAGE, GetName(), eat_item->Name);
	}
	else
	{
		LogFile->write(EQEMuLog::Error, "OP_Consume: unknown type, type:%i", (int)pcs->type);
		return;
	}
	if (m_pp.hunger_level > 6000)
		m_pp.hunger_level = 6000;
	if (m_pp.thirst_level > 6000)
		m_pp.thirst_level = 6000;
	EQApplicationPacket *outapp;
	outapp = new EQApplicationPacket(OP_Stamina, sizeof(Stamina_Struct));
	Stamina_Struct* sta = (Stamina_Struct*)outapp->pBuffer;
	sta->food = m_pp.hunger_level;
	sta->water = m_pp.thirst_level;

	QueuePacket(outapp);
	safe_delete(outapp);
	return;
}
Database SQL
Code:
INSERT INTO rule_values (ruleset_id, rule_name, rule_value)
   VALUES (1, 'Character:RacialConsumption', 'true'); 
INSERT INTO rule_values (ruleset_id, rule_name, rule_value)
   VALUES (1, 'Character:MountConsumption', 'true');
With all of this in place, you can set these 2 rules in the database to true or false. This turn on or off the modifiers for race and mounts.

Also for the rule Character:ConsumptionMultiplier:
A value of 100 = Normal rate.
A lower value means faster eating. (ie. 50 would mean twice as fast)
A higher value means slower eating. (ie 200 would mean twice as slow)
Just keep in mind that everything is rounded to the nearest whole number during calculations.

Thanks for all the help and ideas guys =)
-Codemephit
Reply With Quote
  #2  
Old 07-23-2008, 10:11 AM
So_1337
Dragon
 
Join Date: May 2006
Location: Cincinnati, OH
Posts: 689
Default

Great work, and quick, too!

Possibly related, but do the AAs that affect metabolism work currently? And does this code affect them or vice versa?
Reply With Quote
  #3  
Old 07-23-2008, 11:56 AM
CodeMephit
Fire Beetle
 
Join Date: Oct 2006
Posts: 18
Default

There is only 1 AA (Innate Metabolism) that I know of that affects eating or drinking. If there are others, please let me know and I will look into them.

My code takes into account a player having the Innate Metabolism AA and adjusts their consumption by the correct amount. This is assuming that there is support elsewhere in the code for the AA system (I am pretty sure that there is).

I will run a few tests and report back with my findings.

-Codemephit
Reply With Quote
Reply


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 06:48 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 - 2024, Jelsoft Enterprises Ltd.
Template by Bluepearl Design and vBulletin Templates - Ver3.3