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.

AdrianD 09-24-2015 05:49 AM

Thanks Uleat.

I understand the concept but the vocab is still a little beyond me.

I figured to add to this thread with a different snippet since the same question applies. It appears to work with 12 > SkillMeditate > 0 in game.

Both #showstats and watching ticks are accurate although client mana# jumps around. Not sure when it normalizes but, a level 50 at max meditate (235) shows the ticks perfectly for a titanium client.

Does this look right/could it be better?

Comments within the code below:
Code:

int32 Client::CalcBaseManaRegen()
{
        uint8 clevel = GetLevel();
        int32 regen = 0;
        if (IsSitting() || (GetHorseId() != 0)) {
                if (HasSkill(SkillMeditate) && GetSkill(SkillMeditate) > 11) { // added GetSkill(SkillMeditate) > 11 so obtaining meditate isn't an immediate detriment at low levels
                        regen = ((GetSkill(SkillMeditate) / 12)) + 1; // changed equation
                }
                else {
                        regen = 2;
                }
        }
        else {
                regen = 1; // changed to 1 from 2
        }
        return regen;
}

int32 Client::CalcManaRegen()
{
        uint8 clevel = GetLevel();
        int32 regen = 0;
        //this should be changed so we dont med while camping, etc...
        if (IsSitting() || (GetHorseId() != 0)) {
                BuffFadeBySitModifier();
                if (HasSkill(SkillMeditate) && GetSkill(SkillMeditate) > 11) { // added GetSkill(SkillMeditate) > 11 so obtaining meditate isn't an immediate detriment at low levels
                        regen = ((GetSkill(SkillMeditate) / 12)) + 1;  // changed equation
                        regen += spellbonuses.ManaRegen + itembonuses.ManaRegen;
                        CheckIncreaseSkill(SkillMeditate, nullptr, -5);
                }
                else {
                        regen = 2 + spellbonuses.ManaRegen + itembonuses.ManaRegen;
                }
        }
        else {
                this->medding = false;
                regen = 1 + spellbonuses.ManaRegen + itembonuses.ManaRegen; // changed to 1 from 2
        }
        //AAs
        regen += aabonuses.ManaRegen;
        return (regen * RuleI(Character, ManaRegenMultiplier) / 100);
}

I'm open to all critique.

Thanks

image 09-24-2015 07:50 AM

I mean is this new formula another guestimation? Since the client has its own idea of regen we should be able to pull the math from there I would think..

AdrianD 09-24-2015 08:17 AM

I have noticed client mana# jumping around on my titanium client for quite some time. I did not take note of it until a few months ago. This occurred at times on live when I played but, probably for different reasons. I never thought much of it.

Prior to making this change, I had changed rule_values regarding mana regen. I noticed mana regen was +2 standing and this was introduced well after classic and possibly after Titanium was relesed, I don't recall. I wanted to fix this so, I changed the rule_values associated with mana regen. This change was not perfect. I knew I would need to alter the source at some point to actually fix it the way I wanted.

As far as guestimating a new formula: This is partially why I posted this. If there is a more accurate formula for mana regen that was in use from classic to OoW or around there, I'd like to hear it.

I played the most on live between SoL and DoN and I do not recall standing mana regen giving +2. In addition, I recall mana regen as a linear function of the meditate skill and never dependant on caster level during the time I played the most. I could be mistaken as I had no reason to actually create a formula.

PS. Your sarcasm is not lost on me ;)

image 09-24-2015 08:39 AM

Wasn't sarcasm honestly, I just think if you want things to work the client and server have to be matching on the functions. I know in the past we had some concerns that our timing of the regen packets and the frequency were possibly a problem.

AdrianD 09-24-2015 08:50 AM

False assumption.

There seems to be quite a few differences between clients. Titanium and others? having certain things hardcoded making customization more difficult.

P99 codes for the same client and I have noticed a little mana# jumping there, as well. Again, I never thought of it much because "on tick" was the real amount, if off by a couple.

This is very noticeable when medding for longer periods and watching HP regen. I'm sure many know what I am talking about.

I'm curious to know how both of these, hp and mana, if different between client/server, could be detrimental.
EDIT: hp and mana regen

Thanks

image 09-24-2015 08:56 AM

Using HP for example while sitting down, it seems the client gets its update and then tries to make another jump just a few second after which then the server corrects back downward. Client is also trying to give 6 hp per tick more than the server wants to in this scenario.

http://i.imgur.com/zVexaQ6.png

AdrianD 09-24-2015 08:59 AM

Aye, this is what I noticed with mana regen but maybe the other way around. The client says +1 because it's titanium, and the server says, nu-uh +2 and adds 1. I was getting 1+1 mana regen on most ticks (always 2 per full tick).

This was the main reason for my fix. I figured to learn a bit and change manaregen to something I thought was more classic-y.

image 09-24-2015 09:04 AM

yea id like to see it fixed also. Plus the scenario in which people fall unconscious before they lose all their HP... if you get hit serious enough you fall over for a moment until for whatever reason it lets you back up as if nothing happened.

AdrianD 09-24-2015 09:12 AM

That stopped happening to me after I recompiled on 7/29/15 and changed some rules. Unsure what it was exactly.

Before that, I would have very brief "double hits".

Check out post #3 - 7 in the thread below. Unsure if it will work for you or if you have done this but, I was very pleased it went away.

http://www.eqemulator.org/forums/showthread.php?t=39907

Shendare 09-24-2015 11:15 AM

FYI, the HP and Mana jumping forward and then back to what it's supposed to be while regenerating? Happened on Live, too. For yeeeeears. Wouldn't be surprised if it still does.

Uleat 09-24-2015 12:26 PM

Character:SoDClientUseSoDHPManaEnd, perchance?

That doesn't solve the entire issue..but, it may have been a rule you changed.


I know that item scaling/stats is also an issue with some clients..but, I think demonstar55 did some work to fix that, or at least alleviate some of the problem.

When the client tries to calculate regen bonuses based on item stats, they really need to be inline with what the client expects..not what the server is necessarily using.

There's still a lot of tweaking that needs to be done in this area.

AdrianD 09-24-2015 12:35 PM

Quote:

Character:SoDClientUseSoDHPManaEnd, perchance?
That was the last thing I did before it went away, changed the rule to false.

Quote:

When the client tries to calculate regen bonuses based on item stats, they really need to be inline with what the client expects..not what the server is necessarily using.
I don't foresee it affecting me but, does this mean changing <Character:HPRegenMultiplier> or similar is not the best idea?

AdrianD 09-26-2015 12:30 PM

I'm trying to replace the `CheckIncreaseSkill` equation in `zone\client.cpp( ~2268 )`. After a bit of testing, I found something that will only require changing one line. I don't like the coefficients for some skills. The solution I found mitigates a bit of my distaste for them.

To be replaced:

Code:

int32 Chance = 10 + chancemodi + ((252 - skillval) / 20);
I would like some assistance with properly writing the new equation. Below is my attempt to describe it:

Quote:

I had to graph this as a function of x - f(x) - otherwise I would have done it differently.
Instead of y = x^3 it needed to be x = y^3, I think. It's been many years since I've done any of this.

c = chancemodi
x = skillval

This is directly from the graphing program: (-root(3, 9.61x)1.5 + 22)

The best I can do to write it out: <-root(3, ((|15 + c|^1.1) * 0.4 + 1.75) * x ) * 1.5 + 22 + (2c/3)>

The parts <(-root(3,>, <(|15 + c|^1.1)> I do not know how to write out in C++
This is as far as I got:

Code:

int32 Chance = 22 + (chancemodi * 1.5) + 1.5 * (-root (3, (((abs(15 + chancemodi))^1.1 * 0.4 + 1.75) * skillval)))

or

int32 Chance = 22 + (chancemodi * 1.5) + 1.5 * (-cube root of (((abs(15 + chancemodi))^1.1) * 0.4 + 1.75) * skillval))

If you are interested in seeing it graphed with a few comparisons to current skill increase rates:

http://prntscr.com/8kpm36

AdrianD 09-26-2015 05:34 PM

C'mon you programming wizards! With all the traffic today I can't imagine noone can throw me a bone!

Please tell me how to write - (cube root), absolute value and x^n in C++.

Uleat 09-26-2015 06:58 PM

A good place to start: http://www.cplusplus.com/reference/cmath/

Code:

cbrt(x)
abs(x)
pow(x, e)


AdrianD 09-26-2015 07:05 PM

Thanks. Knowing how to put them in the lines was my main concern (syntax).

I can reference the functions anytime I forget something, which is often.

Regardless, I got it to work and according to the logsys, it's working as intended, just as the graph shows.

EDIT: btw Uleat, that's the exact page I used to figure it out =)

AdrianD 09-26-2015 08:01 PM

Never said it was pretty:

Code:

double param, result;
                param = ((pow ((std::abs(15 + chancemodi)), 1.1) * 0.4 + 1.75) * skillval);
                result = cbrt (param);
        int32 Chance = (-((result)* 1.5) + 22 + (chancemodi / 1.5));

If it could be better, please let me know.

AdrianD 09-27-2015 08:04 PM

I removed the Spellshield and the "cast on other" messages which appear when attacking an npc with a rune. The Spellshield message seemed correct but, the "cast on other" message displays the damage shield "cast on other" each time the npc hits the client. This only occurs if the client has a DS and the NPC has a rune. The "was pierced by thorns" message also appears, as normal.

My main concern is if the second line I commented out will affect anything else. I tested this by casting a rune on myself and having an npc attack and dispel the rune. It appears to work normal. I left larger spaces between lines to accentuate the lines I commented out.

Code:

\zone\attack.cpp(3548 - 3571)

//see if any runes want to reduce this damage
if(spell_id == SPELL_UNKNOWN) {
        damage = ReduceDamage(damage);
        Log.Out(Logs::Detail, Logs::Combat, "Melee Damage reduced to %d", damage);
        damage = ReduceAllDamage(damage);
        TryTriggerThreshHold(damage, SE_TriggerMeleeThreshold, attacker);

        if (skill_used)
                CheckNumHitsRemaining(NumHit::IncomingHitSuccess);

} else {
        int32 origdmg = damage;
       
       
//        damage = AffectMagicalDamage(damage, spell_id, iBuffTic, attacker); <--- commented out second


/*        if (origdmg != damage && attacker && attacker->IsClient()) {  <---
                if(attacker->CastToClient()->GetFilter(FilterDamageShields) != FilterHide)  <--- commented out first
                        attacker->Message(15, "The Spellshield absorbed %d of %d points of damage", origdmg - damage, origdmg);  <---
        } */
                       
                       
        if (damage == 0 && attacker && origdmg != damage && IsClient()) {
                //Kayen: Probably need to add a filter for this - Not sure if this msg is correct but there should be a message for spell negate/runes.
                Message(263, "%s tries to cast on YOU, but YOUR magical skin absorbs the spell.",attacker->GetCleanName());
        }
        damage = ReduceAllDamage(damage);
        TryTriggerThreshHold(damage, SE_TriggerSpellThreshold, attacker);
}

I was trying to find the relationship in this portion with other portions that would tell me why it would make the reference to `cast_on_other` but, couldn't figure it out.

Thanks

AdrianD 09-29-2015 02:52 AM

It's been about a week since I started making changes to my server code. I'm very green in this aspect but, I learn quickly and understand concepts more than syntax. I also understand the implications of things. Not everything though!

I want to thank those that have given assistance if I haven't already.

My question/issue at the bottom.

I've added a few lines to <\zone\zonedb.cpp(3177)> and created a couple rules <\common\ruletypes.h(151) - RULE_CATEGORY(Pets)>.

It works as I expected.

Below is what I added:
ruletypes.h
Code:

RULE_BOOL(Pets, PetZonePersistence, true) //  if true, pets will zone with players
RULE_BOOL(Pets, PetLogPersistence, true) //  if false, pets will poof 30 minutes after logging character out (PetZonePersistence must be true)

zonedb.cpp
Code:

void ZoneDatabase::LoadPetInfo(Client *client)
{
// added this part 9/28/15       
                if (!RuleB(Pets, PetZonePersistence)) {

                        std::string query = StringFormat("DELETE FROM `character_pet_info` WHERE EXISTS (SELECT * FROM `character_data` WHERE character_pet_info.char_id = character_data.id AND `char_id` = %u AND character_pet_info.pet = 0)", client->CharacterID());
                        auto results = database.QueryDatabase(query);
                        if (!results.Success())
                                return;

                        query = StringFormat("DELETE FROM `character_pet_buffs` WHERE EXISTS (SELECT * FROM `character_data` WHERE character_pet_buffs.char_id = character_data.id AND `char_id` = %u AND character_pet_buffs.pet = 0)", client->CharacterID());
                        results = database.QueryDatabase(query);
                        if (!results.Success())
                                return;

                        query = StringFormat("DELETE FROM `character_pet_inventory` WHERE EXISTS (SELECT * FROM `character_data` WHERE character_pet_inventory.char_id = character_data.id AND `char_id` = %u AND character_pet_inventory.pet = 0)", client->CharacterID());
                        results = database.QueryDatabase(query);
                        if (!results.Success())
                                return;
                }
                else if (!RuleB(Pets, PetLogPersistence)) {

                        std::string query = StringFormat("DELETE FROM `character_pet_info` WHERE EXISTS (SELECT * FROM `character_data` WHERE character_pet_info.char_id = character_data.id AND `char_id` = %u AND(UNIX_TIMESTAMP(NOW()) - `last_login` > 1800) AND character_pet_info.pet = 0)", client->CharacterID());
                        auto results = database.QueryDatabase(query);
                        if (!results.Success())
                                return;

                        query = StringFormat("DELETE FROM `character_pet_buffs` WHERE EXISTS (SELECT * FROM `character_data` WHERE character_pet_buffs.char_id = character_data.id AND `char_id` = %u AND (UNIX_TIMESTAMP(NOW()) - `last_login` > 1800) AND character_pet_buffs.pet = 0)", client->CharacterID());
                        results = database.QueryDatabase(query);
                        if (!results.Success())
                                return;

                        query = StringFormat("DELETE FROM `character_pet_inventory` WHERE EXISTS (SELECT * FROM `character_data` WHERE character_pet_inventory.char_id = character_data.id AND `char_id` = %u AND (UNIX_TIMESTAMP(NOW()) - `last_login` > 1800) AND character_pet_inventory.pet = 0)", client->CharacterID());
                        results = database.QueryDatabase(query);
                        if (!results.Success())
                                return;
                }
// above added 9/28/15 and a few small changes below       
       
        // Load current pet and suspended pet
        PetInfo *petinfo = client->GetPetInfo(0);
        PetInfo *suspended = client->GetPetInfo(1);

        memset(petinfo, 0, sizeof(PetInfo));
        memset(suspended, 0, sizeof(PetInfo));

        std::string query = StringFormat("SELECT `pet`, `petname`, `petpower`, `spell_id`, "
                                        "`hp`, `mana`, `size` FROM `character_pet_info` "
                                        "WHERE `char_id` = %u",
                                        client->CharacterID());
        auto results = database.QueryDatabase(query);
        if (!results.Success()) {
                return;
        }

My notes during the process:
Code:

Added lines to remove pet persistence after 30 minutes when logged off - `ZoneDatabase::LoadPetInfo` - \zone\zonedb.cpp(3177)
        - it appears to work but, I am unsure if there is a better way
        - this may also delete the entries if zoning after 30 min from `last_login` timestamp (if this timestamp is what I presume)
                - it references `last_login` similar to norent although norent items are only loaded once through inventory.cpp, I think
                - the solution may be to add the new lines where inventory.cpp is called for norent items
                - nevermind, `last_login` appears to be an update timestamp which eliminates this as a possible issue
        - create a rule for it to easily switch off for later expansions - done
       
ToDo: remove pet persistence between zones and create a rule for it - \zone\zonedb.cpp(3177)
        - likely need an "if" statement in the same code as above; it seems to call for those lines after each zone switch
        - possible solution is to simply use the added lines but, without the timestamp part and add a rule
        - added more lines and rules linked to these lines
        - it appears to work although I notice the rules need some time to catch up after #rules reload with these added rules
                - I'm guessing it has to do with zonedb periodic updates
        - issue remains on logging out and keeping pet for 30 min if `PetZonePersistence` is false - currently pets poof when logging back
                - possible solution is to reference the DB `character_data` for zoneid prior to overwriting this data when logging in
                - unsure the order in which the data is currently read and then overwritten

My implied question:
Code:

- issue remains on logging out and keeping pet for 30 min if `PetZonePersistence` is false
        - currently pets poof when logging back
        - possible solution is to reference the DB `character_data` for zoneid prior to overwriting this data when logging in
        - unsure the order in which the data is currently read and then overwritten

The other issue is the running of the above queries and deleting of DB rows each time a player zones. I'd like to make this a little more efficient, if possible. (such as skipping the query if certain values don't exist, which requires another query ofc but, I seek efficiency)

I am open to suggestions.

Thanks

Uleat 09-29-2015 01:08 PM

Check out where this is being called: https://github.com/EQEmu/Server/blob...ocess.cpp#L757 ..

.. in this function: https://github.com/EQEmu/Server/blob...cket.cpp#L1685


Very similar methodology for norent (temporary) items.

AdrianD 09-29-2015 03:33 PM

I pored over NoRentExpired, bool deletenorent and some other areas until I came to zonedb and saw some things I was familiar with. As this is all so foreign to me, knowing what to search for and then processing it consumes much more time than actually changing it to something different.

I was thinking of trying to work it in with the norent code but, my concern was with keeping suspended pets suspended. My intention was to cover as many possibilities as I could think of with that.

The difference with no rent items and what I'm trying to do is the additional option of having pets poof when zoning (a la classic) while not having them go away like norent items when logging for under 30 minutes.

It really isn't a big deal as far as the game goes. I enjoy trying to solve the problem.

Thanks for the response, it got me thinking about it a little different.

Uleat 09-29-2015 04:02 PM

Adding that methodology to LoadPets will cause that to be processed every time that LoadPets is called..as in zone changes.

You may need to split the methodology up to have one portion processed on zone entry, and the other on zone change.


You could create handlers for the actions that you want to process in Database(SharedDatabase?) (ref: https://github.com/EQEmu/Server/comm...5353f5ed8d8044)

.. and handle the returns appropriately.


I know it's a pain to figure out what does what, where and why..but, it comes with exposure.

AdrianD 09-29-2015 05:01 PM

Yes! That's exactly what I was thinking (in regards to splitting it up) but didn't understand and still having a hard time understanding. I'll probably get it a little with, like you said, more exposure.

Uleat 09-29-2015 05:16 PM

I am extremely slow when it comes to picking up new material...

Intellisense has been my friend since day one!

AdrianD 09-29-2015 06:47 PM

I have to say that feature is wonderful, really helps in learning it.

Compiling the new code now. Hopefully it works.


All times are GMT -4. The time now is 09:58 PM.

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