EQEmulator Forums

EQEmulator Forums (https://www.eqemulator.org/forums/index.php)
-   Support::Windows Servers (https://www.eqemulator.org/forums/forumdisplay.php?f=587)
-   -   Acceptable/efficient syntax (https://www.eqemulator.org/forums/showthread.php?t=40039)

AdrianD 09-22-2015 04:45 PM

Acceptable/efficient syntax
 
I made a small change to remove max lvl 1 starting skills in client.cpp.

It appears to work after logging in but, I want to be certain the syntax is correct and if it could be done better.

My comments inside:

Code:

void Client::SetClassStartingSkills(PlayerProfile_Struct *pp)
{
        for (uint32 i = 0; i <= HIGHEST_SKILL; ++i) {
                if (pp->skills[i] == 0); /* added ; just before this comment  commented out 9-22-15 to test starting skills (I do not want max skills at lvl 1)
                                                                {
                        // Skip specialized, tradeskills (fishing excluded), Alcohol Tolerance, and Bind Wound
                        if (EQEmu::IsSpecializedSkill((SkillUseTypes)i) ||
                                        (EQEmu::IsTradeskill((SkillUseTypes)i) && i != SkillFishing) ||
                                        i == SkillAlcoholTolerance || i == SkillBindWound)
                                continue;

                        pp->skills[i] = database.GetSkillCap(pp->class_, (SkillUseTypes)i, 1);
                } */
        }
}

Thank you.

EDIT: I notice the client shows skills with values > 0 but the DB does not. I suppose the addition of quite a few more lines of code will be needed to account for the removal of the segment above to make accurate.

If this doesn't belong here please move it, thanks.

Shendare 09-22-2015 05:09 PM

The client will often display hard-coded level 1 starting stats no matter what you code into the server and enter into the database. I haven't tested to see if it corrects to what the server tells it at level two.

I'd say the very easiest thing to do in that method would simply be to add a return statement after the very first opening brace. Hehe.

Code:

void Client::SetClassStartingSkills(PlayerProfile_Struct *pp)
{
        return;
        for (uint32 i = 0; i <= HIGHEST_SKILL; ++i) {
                if (pp->skills[i] == 0) {
                        // Skip specialized, tradeskills (fishing excluded), Alcohol Tolerance, and Bind Wound
                        if (EQEmu::IsSpecializedSkill((SkillUseTypes)i) ||
                                        (EQEmu::IsTradeskill((SkillUseTypes)i) && i != SkillFishing) ||
                                        i == SkillAlcoholTolerance || i == SkillBindWound)
                                continue;

                        pp->skills[i] = database.GetSkillCap(pp->class_, (SkillUseTypes)i, 1);
                }
        }
}

But that's assuming you're okay with getting 1359 compilation warnings instead of 1358. :P

AdrianD 09-22-2015 05:15 PM

Superb! Thank you.

I'll have to add something that states something along the lines of: set 1hb = 5 if class = a,b,c,d... and set 1hs = 5 if class = e,f..

I'll have to look at similar to see what the syntax would look like.

Thanks again.

Shendare 09-22-2015 05:25 PM

In the C++ code they have a couple of shortcuts so you don't have to go by individual classes, too.

IsWarriorClass() returns true for WAR, ROG, MNK, PAL, SHD, RNG, BST, BER, BRD.

GetArchectype() returns ARCHETYPE_MELEE, _CASTER, or _HYBRID depending on the class. If you aren't clear on who is and isn't a hybrid, you can see the full list in zone/mob.cpp around line 862.

AdrianD 09-22-2015 05:26 PM

Grateful for that, thank you Shendare.

Kingly_Krab 09-22-2015 06:26 PM

Likely, this would be easier done in Perl because it would be done as soon as the player logged in, rather than being handled by something that may or may not be hard-coded client-side, such as start skills and stuff like that.

Secrets 09-22-2015 07:06 PM

Quote:

Originally Posted by Kingly_Krab (Post 243423)
Likely, this would be easier done in Perl because it would be done as soon as the player logged in, rather than being handled by something that may or may not be hard-coded client-side, such as start skills and stuff like that.

Easier, yes, but efficient, no. Perl loops are horrible for performance as it locks the entire zone thread in what's basically a VM to a C++ interface.

Kingly_Krab 09-22-2015 07:18 PM

Quote:

Originally Posted by Secrets (Post 243427)
Easier, yes, but efficient, no. Perl loops are horrible for performance as it locks the entire zone thread in what's basically a VM to a C++ interface.

Yeah, super fun to lock a zone thread by creating a endless loop when using a 'while' loop. But I'm sure this could be simplified in C++ and added to the level up code by creating a client method like Client::MaxSkills or something.

Shendare 09-22-2015 07:21 PM

Or a couple of rules.

Character:MaxSkillsOnCharCreate (true)
Character:MaxSkillsOnLevelUp (false)

Secrets 09-22-2015 10:32 PM

Quote:

Originally Posted by Kingly_Krab (Post 243430)
Yeah, super fun to lock a zone thread by creating a endless loop when using a 'while' loop. But I'm sure this could be simplified in C++ and added to the level up code by creating a client method like Client::MaxSkills or something.

No; The loop wouldn't be endless, it would end, but freeze the entire zone while it is processing. This is unacceptable by anyone's standards.

Note clients would still receive data as that's handled in another thread entirely.

The point I was making is it'd be faster to make a method in C++ that you can call from Perl as opposed from looping in Perl.

AdrianD 09-23-2015 08:56 PM

Below are the changes I made, it seems to work but, curious if everything looks right.

Also, I couldn't figure out how to do this using <GetArchectype>. If someone could throw me a bone, I'd appreciate it.

Code:

void Client::SetClassStartingSkills(PlayerProfile_Struct *pp)
{
       
                        switch (pp->class_)       
                        {
                        case WARRIOR:
                                {
                                pp->skills[Skill1HSlashing] = 5;
                                break;
                                }
                        case PALADIN:
                                {
                                pp->skills[Skill1HSlashing] = 5;
                                break;
                                }
                        case RANGER:
                                {
                                pp->skills[Skill1HSlashing] = 5;
                                break;
                                }
                        case SHADOWKNIGHT:
                                {
                                pp->skills[Skill1HSlashing] = 5;
                                break;
                                }
                        case BARD:
                                {
                                pp->skills[Skill1HSlashing] = 5;
                                break;
                                }
                        case CLERIC:
                                {
                                pp->skills[Skill1HBlunt] = 5;
                                break;
                                }
                        case DRUID:
                                {
                                pp->skills[Skill1HBlunt] = 5;
                                break;
                                }
                        case MONK:
                                {
                                pp->skills[Skill1HBlunt] = 5;
                                pp->skills[SkillHandtoHand] = 5;
                                break;
                                }
                        case SHAMAN:
                                {
                                pp->skills[Skill1HBlunt] = 5;
                                break;
                                }
                        case ROGUE:
                                {
                                pp->skills[Skill1HPiercing] = 5;
                                break;
                                }
                        case NECROMANCER:
                                {
                                pp->skills[Skill1HPiercing] = 5;
                                break;
                                }
                        case WIZARD:
                                {
                                pp->skills[Skill1HPiercing] = 5;
                                break;
                                }
                        case MAGICIAN:
                                {
                                pp->skills[Skill1HPiercing] = 5;
                                break;
                                }
                        case ENCHANTER:
                                {
                                pp->skills[Skill1HPiercing] = 5;
                                break;
                                }
                        case BERSERKER:
                                {
                                pp->skills[Skill2HSlashing] = 5;
                                break;
                                }
                        }
}

Is it necessary to have <break;> or <continue;> at the end?

Thanks

Shendare 09-23-2015 09:02 PM

Do you anticipate that you'll want to make changes on a per-class level later?

If not, you could group them together to clean it up a tad.

Code:

void Client::SetClassStartingSkills(PlayerProfile_Struct *pp)
{
        switch (pp->class_)       
        {
                case WARRIOR:
                case PALADIN:
                case RANGER:
                case SHADOWKNIGHT:
                case BARD:
                        pp->skills[Skill1HSlashing] = 5;
                        break;
                case CLERIC:
                case DRUID:
                case SHAMAN:
                        pp->skills[Skill1HBlunt] = 5;
                        break;
                case MONK:
                        pp->skills[Skill1HBlunt] = 5;
                        pp->skills[SkillHandtoHand] = 5;
                        break;
                case ROGUE:
                case NECROMANCER:
                case WIZARD:
                case MAGICIAN:
                case ENCHANTER:
                        pp->skills[Skill1HPiercing] = 5;
                        break;
                case BERSERKER:
                        pp->skills[Skill2HSlashing] = 5;
                        break;
        }
}


Shendare 09-23-2015 09:03 PM

Also, you're missing Beastlords. If that wasn't intended, they'd probably be grouped with Monks.

AdrianD 09-23-2015 09:47 PM

BST - oversight, thanks (and clarifying starting skill)

Quote:

Do you anticipate that you'll want to make changes on a per-class level later?
No, I desire <easy-mode eq: off> and I think, as far as starting skills go, this accomplishes that.

I appreciate your help =)

EDIT: I understand the implications of the corrections, for the most part. I am most thankful for that.

Uleat 09-23-2015 10:04 PM

Yes, Shendare's method is more efficient!


Switch statements essentially create a jump table entry (per case value) and code paths for each entry listed in the machine code.

If no exit clause is specified, the code path will 'fall-through' every line of code until it reaches the default exit clause..meaning that every case between case entry and
default exit will be processed as true.


The fall-through behavior can be very useful for grouping like singular and progressive-compound methodologies..but, it can also be a trap if that behavior is not desired.


All times are GMT -4. The time now is 06:15 AM.

Powered by vBulletin®, Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.