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

Development::Bug Reports Post detailed bug reports and what you would like to see next in the emu here.

Reply
 
Thread Tools Display Modes
  #1  
Old 11-10-2008, 03:45 AM
trevius's Avatar
trevius
Developer
 
Join Date: Aug 2006
Location: USA
Posts: 5,946
Default

Thanks again KLS. So, that is basically just sending a level update to the client. I understand much better now
__________________
Trevazar/Trevius Owner of: Storm Haven
Everquest Emulator FAQ (Frequently Asked Questions) - Read It!
Reply With Quote
  #2  
Old 11-10-2008, 08:27 AM
trevius's Avatar
trevius
Developer
 
Join Date: Aug 2006
Location: USA
Posts: 5,946
Default

Well, I got this tested, and had to adjust how it was written slightly to make sure it included the logging.

Code:
void Client::SetLevel(int8 set_level, bool command)
{
	#ifdef GUILDWARS
		if(set_level > SETLEVEL) {
			Message(0,"You cannot exceed level %i on a GuildWars Server.",SETLEVEL);
			return;
		}
	#endif

	if (GetEXPForLevel(set_level) == 0xFFFFFFFF) {
		LogFile->write(EQEMuLog::Error,"Client::SetLevel() GetEXPForLevel(%i) = 0xFFFFFFFF", set_level);
		return;
	}

	EQApplicationPacket* outapp = new EQApplicationPacket(OP_LevelUpdate, sizeof(LevelUpdate_Struct));
	LevelUpdate_Struct* lu = (LevelUpdate_Struct*)outapp->pBuffer;
	lu->level = set_level;
	lu->level_old = level;
	level = set_level;

	if(IsRaidGrouped())
	{
		Raid *r = this->GetRaid();
		if(r){
			r->UpdateLevel(GetName(), set_level);
		}
	}

	if (set_level > m_pp.level2) {
		m_pp.points += 5 * (set_level - m_pp.level2);
		m_pp.level2 = set_level;

#ifdef EMBPERL
		((PerlembParser*)parse)->Event(EVENT_LEVEL_UP, 0, "", (NPC*)NULL, this);
#endif
	}

	m_pp.level = set_level;
	if (command){
		m_pp.exp = GetEXPForLevel(set_level);
		Message(15, "Welcome to level %i!", set_level);
		lu->exp = 0;
	}
	else {
		float tmpxp = (float) ( (float) m_pp.exp - GetEXPForLevel( GetLevel() )) /
						( (float) GetEXPForLevel(GetLevel()+1) - GetEXPForLevel(GetLevel()));
		lu->exp =  (int32)(330.0f * tmpxp);
    }
	QueuePacket(outapp);
	safe_delete(outapp);
	this->SendAppearancePacket(AT_WhoLevel, set_level); // who level change

    LogFile->write(EQEMuLog::Normal,"Setting Level for %s to %i", GetName(), set_level);

	CalcBonuses();
	if(!RuleB(Character, HealOnLevel))
	{
		int mhp = CalcMaxHP();
		if(GetHP() > mhp)
			SetHP(mhp);
	}
	else
	{
		SetHP(CalcMaxHP());		// Why not, lets give them a free heal
	}

	SendHPUpdate();
	SetMana(CalcMaxMana());
	UpdateWho();
	Save();
}
But, it still doesn't seem to be working, so I am guessing that level2 is either being updated somewhere else to match current level, or the points are being added elsewhere.
__________________
Trevazar/Trevius Owner of: Storm Haven
Everquest Emulator FAQ (Frequently Asked Questions) - Read It!
Reply With Quote
  #3  
Old 11-10-2008, 09:18 AM
Derision
Developer
 
Join Date: Feb 2004
Location: UK
Posts: 1,540
Default

You need to check if m_pp.level2 is zero, which it will be for any character created before this change, otherwise you will give existing characters lots of extra skill points. The code below works for me, however if you try and train skills after levelling, without zoning, the client will show an extra 5 points, however if you zone first, it seems to display correctly.

Code:
        if(set_level > m_pp.level2)
        {
                printf("m_pp.level2 is %i\n", m_pp.level2); fflush(stdout);
                if(m_pp.level2 == 0)
                        m_pp.points += 5;
                else
                        m_pp.points += (5 * (set_level - m_pp.level2));

                m_pp.level2 = set_level;
        }
        if(set_level > m_pp.level) { // Yes I am aware that you could delevel yourself and relevel this is just to test!

#ifdef EMBPERL
                ((PerlembParser*)parse)->Event(EVENT_LEVEL_UP, 0, "", (NPC*)NULL, this);
#endif
        }

        m_pp.level = set_level;
Reply With Quote
  #4  
Old 11-10-2008, 09:55 AM
Derision
Developer
 
Join Date: Feb 2004
Location: UK
Posts: 1,540
Default

I've just had a look at the client disassembly and it is comparing lu->level with lu->level_old and adding 5 skill points if lu->level > lu_level_old, so in fact lu->level_old should be set to the max level the player has previously reached (m_pp.level2). This seems to work:

Code:
void Client::SetLevel(int8 set_level, bool command)
{
        #ifdef GUILDWARS
                if(set_level > SETLEVEL) {
                        Message(0,"You cannot exceed level %i on a GuildWars Server.",SETLEVEL);
                        return;
                }
        #endif

        if (GetEXPForLevel(set_level) == 0xFFFFFFFF) {
                LogFile->write(EQEMuLog::Error,"Client::SetLevel() GetEXPForLevel(%i) = 0xFFFFFFFF", set_level);
                return;
        }

        EQApplicationPacket* outapp = new EQApplicationPacket(OP_LevelUpdate, sizeof(LevelUpdate_Struct));
        LevelUpdate_Struct* lu = (LevelUpdate_Struct*)outapp->pBuffer;
        lu->level = set_level;
        if(m_pp.level2 != 0)
                lu->level_old = m_pp.level2;
        else
                lu->level_old = level;

        level = set_level;

        if(IsRaidGrouped())
        {
                Raid *r = this->GetRaid();
                if(r){
                        r->UpdateLevel(GetName(), set_level);
                }
        }
        if(set_level > m_pp.level2)
        {
                if(m_pp.level2 == 0)
                        m_pp.points += 5;
                else
                        m_pp.points += (5 * (set_level - m_pp.level2));

                m_pp.level2 = set_level;
        }
        if(set_level > m_pp.level) { // Yes I am aware that you could delevel yourself and relevel this is just to test!

#ifdef EMBPERL
                ((PerlembParser*)parse)->Event(EVENT_LEVEL_UP, 0, "", (NPC*)NULL, this);
#endif
        }

        m_pp.level = set_level;
        if (command){
                m_pp.exp = GetEXPForLevel(set_level);
                Message(15, "Welcome to level %i!", set_level);
                lu->exp = 0;
        }
        else {
                float tmpxp = (float) ( (float) m_pp.exp - GetEXPForLevel( GetLevel() )) /
                                                ( (float) GetEXPForLevel(GetLevel()+1) - GetEXPForLevel(GetLevel()));
                lu->exp =  (int32)(330.0f * tmpxp);
    }
        QueuePacket(outapp);
        safe_delete(outapp);
        this->SendAppearancePacket(AT_WhoLevel, set_level); // who level change

    LogFile->write(EQEMuLog::Normal,"Setting Level for %s to %i", GetName(), set_level);

        CalcBonuses();
        if(!RuleB(Character, HealOnLevel))
        {
                int mhp = CalcMaxHP();
                if(GetHP() > mhp)
                        SetHP(mhp);
        }
        else
        {
                SetHP(CalcMaxHP());             // Why not, lets give them a free heal
        }

        SendHPUpdate();
        SetMana(CalcMaxMana());
        UpdateWho();
        Save();
}
Reply With Quote
  #5  
Old 11-10-2008, 10:24 AM
trevius's Avatar
trevius
Developer
 
Join Date: Aug 2006
Location: USA
Posts: 5,946
Default

Nice work, Derision! So, basically, if I understand correctly, the packet structure should say level2 instead of level_old? Not that it actually requires it to say that for this to work, but in reality, I am thinking level_old is really level2. I think that would make everything match up perfectly and finally make actual sense of the level2 field.

I am going to test this now.
__________________
Trevazar/Trevius Owner of: Storm Haven
Everquest Emulator FAQ (Frequently Asked Questions) - Read It!
Reply With Quote
  #6  
Old 11-10-2008, 10:34 AM
Derision
Developer
 
Join Date: Feb 2004
Location: UK
Posts: 1,540
Default

Well, both old_level and m.pp_level2 should probably both be renamed to MaxLevelReached, or something like that.
Reply With Quote
  #7  
Old 11-10-2008, 10:49 AM
trevius's Avatar
trevius
Developer
 
Join Date: Aug 2006
Location: USA
Posts: 5,946
Default

YES! Tested and it worked perfectly! When you train skills, it will even update the current number of points showing properly thanks to your finding that level_old is actually used for the client to update points.

The only case where it doesn't update properly is if you #level more than 1 level at a time. But, this isn't really an issue. And, it is easily resolved by just zoning.

Excellent fix. If someone else doesn't get this on the SVN before tonight, I will do it later
__________________
Trevazar/Trevius Owner of: Storm Haven
Everquest Emulator FAQ (Frequently Asked Questions) - Read It!
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 10:52 AM.


 

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