EQEmulator Forums

EQEmulator Forums (https://www.eqemulator.org/forums/index.php)
-   Development::Development (https://www.eqemulator.org/forums/forumdisplay.php?f=590)
-   -   Proc spells don't work after zoning (https://www.eqemulator.org/forums/showthread.php?t=26307)

AndMetal 08-21-2008 01:34 PM

Proc spells don't work after zoning
 
I noticed this on Storm Haven. I cast the spell Call of Sky (ID 1461) on a Monk (clickie) while in Nexus. I then zone to another zone to kill stuff, and the spell NEVER goes off. If I recast the spell, it procs like mad (w/ 255 dex).

trevius 08-21-2008 07:47 PM

Hmm, I have heard some reports of some proc buffs not working, or not working all of the time. That might explain it!

AndMetal 08-22-2008 12:26 AM

Here's what I've been able to find in the source as far as procs go:
zone/attack.cpp
Code:

1077        ////////////////////////////////////////////////////////////
 1078        ////////  PROC CODE
 1079        ////////  Kaiyodo - Check for proc on weapon based on DEX
 1080        ///////////////////////////////////////////////////////////
 1081        if(other->GetHP() > -10 && !bRiposte && !IsDead()) {
 1082                TryWeaponProc(weapon, other);
 1083        }

and further down, in Mob::TryWeaponProc
Code:

2596        uint32 i;
 2597        for(i = 0; i < MAX_PROCS; i++) {
 2598                if (PermaProcs[i].spellID != SPELL_UNKNOWN) {
 2599                        if(MakeRandomInt(0, 100) < PermaProcs[i].chance) {
 2600                                mlog(COMBAT__PROCS, "Permanent proc %d procing spell %d (%d percent chance)", i, PermaProcs[i].spellID, PermaProcs[i].chance);
 2601                                ExecWeaponProc(PermaProcs[i].spellID, on);
 2602                        } else {
 2603                                mlog(COMBAT__PROCS, "Permanent proc %d failed to proc %d (%d percent chance)", i, PermaProcs[i].spellID, PermaProcs[i].chance);
 2604                        }
 2605                }
 2606                if (SpellProcs[i].spellID != SPELL_UNKNOWN) {
 2607                        int chance = ProcChance + SpellProcs[i].chance;
 2608                        if(MakeRandomInt(0, 100) < chance) {
 2609                                mlog(COMBAT__PROCS, "Spell proc %d procing spell %d (%d percent chance)", i, SpellProcs[i].spellID, chance);
 2610                                ExecWeaponProc(SpellProcs[i].spellID, on);
 2611                        } else {
 2612                                mlog(COMBAT__PROCS, "Spell proc %d failed to proc %d (%d percent chance)", i, SpellProcs[i].spellID, chance);
 2613                        }
 2614                }
 2615        }

I'm wondering if SpellProcs is only set in the zone process itself, and not carried from zone-to-zone. That could explain why it happens when you cast it in the same zone. And since weapons are checked pretty much every hit, on-weapon procs are fine.

However, if that's the problem, I'm not really sure what the best fix would be... Maybe adding a hack somewhere to check & see if it's defined?

trevius 08-22-2008 04:11 AM

Maybe it has something to do with the unhandled weapon equiping opcodes that come in every time people zone. I always wondered what those might be for.

KLS 08-22-2008 04:12 AM

There's a section of code in client_packet.cpp where it finishes connecting. Search for SE_Illusion, it basically reapplies spells that have specific effects that aren't passive stats when you zone in, think illusion, levitate, etc. It sounds like they're not being reapplied correctly and that's where I'd look first.

AndMetal 08-22-2008 06:00 AM

Discussion: http://eqemulator.net/forums/showthread.php?t=26307

Quote:

Originally Posted by KLS (Post 154586)
There's a section of code in client_packet.cpp where it finishes connecting. Search for SE_Illusion, it basically reapplies spells that have specific effects that aren't passive stats when you zone in, think illusion, levitate, etc. It sounds like they're not being reapplied correctly and that's where I'd look first.

It looks like this is the snippet you're talking about:
zone/client_packet.cpp
Code:

6702        //reapply some buffs
 6703        for (uint32 j1=0; j1 < BUFF_COUNT; j1++) {
 6704                if (buffs[j1].spellid > (int32)SPDAT_RECORDS)
 6705                        continue;
 6706
 6707                const SPDat_Spell_Struct &spell = spells[buffs[j1].spellid];
 6708
 6709                for (int x1=0; x1 < EFFECT_COUNT; x1++) {
 6710                        switch (spell.effectid[x1]) {
 6711                                case SE_Illusion: {
 6712                                        if (spell.base[x1] == -1) {
 6713                                                if (gender == 1)
 6714                                                        gender = 0;
 6715                                                else if (gender == 0)
 6716                                                        gender = 1;
 6717                                                SendIllusionPacket(GetRace(), gender, 0xFFFF, 0xFFFF);
 6718                                        }
 6719                                        else if (spell.base[x1] == -2)
 6720                                        {
 6721                                                if (GetRace() == 128 || GetRace() == 130 || GetRace() <= 12)
 6722                                                        SendIllusionPacket(GetRace(), GetGender(), spell.max[x1], spell.max[x1]);
 6723                                        }
 6724                                        else if (spell.max[x1] > 0)
 6725                                        {
 6726                                                SendIllusionPacket(spell.base[x1], 0xFF, spell.max[x1], spell.max[x1]);
 6727                                        }
 6728                                        else
 6729                                        {
 6730                                                SendIllusionPacket(spell.base[x1], 0xFF, 0xFFFF, 0xFFFF);
 6731                                        }
 6732                                        switch(spell.base[x1]){
 6733                                                case OGRE:
 6734                                                        SendAppearancePacket(AT_Size, 9);
 6735                                                        break;
 6736                                                case TROLL:
 6737                                                        SendAppearancePacket(AT_Size, 8);
 6738                                                        break;
 6739                                                case VAHSHIR:
 6740                                                case FROGLOK:
 6741                                                case BARBARIAN:
 6742                                                        SendAppearancePacket(AT_Size, 7);
 6743                                                        break;
 6744                                                case HALF_ELF:
 6745                                                case WOOD_ELF:
 6746                                                case DARK_ELF:
 6747                                                        SendAppearancePacket(AT_Size, 5);
 6748                                                        break;
 6749                                                case DWARF:
 6750                                                        SendAppearancePacket(AT_Size, 4);
 6751                                                        break;
 6752                                                case HALFLING:
 6753                                                case GNOME:
 6754                                                        SendAppearancePacket(AT_Size, 3);
 6755                                                        break;
 6756                                                default:
 6757                                                        SendAppearancePacket(AT_Size, 6);
 6758                                                        break;
 6759                                        }
 6760                                        break;
 6761                                }
 6762                                case SE_SummonHorse: {
 6763                                        SummonHorse(buffs[j1].spellid);
 6764                                        //hasmount = true;        //this was false, is that the correct thing?
 6765                                        break;
 6766                                }
 6767                                case SE_Silence:
 6768                                        {
 6769                                                Silence(true);
 6770                                                break;
 6771                                        }
 6772                                case SE_DivineAura:
 6773                                        {
 6774                                        invulnerable = true;
 6775                                        break;
 6776                                        }
 6777                                case SE_Invisibility2:
 6778                                case SE_Invisibility:
 6779                                        {
 6780                                        invisible = true;
 6781                                        SendAppearancePacket(AT_Invis, 1);
 6782                                        break;
 6783                                        }
 6784                                case SE_Levitate:
 6785                                        {
 6786                        if( !zone->CanLevitate() )
 6787                        {
 6788                            if(!GetGM())
 6789                            {
 6790                                SendAppearancePacket(AT_Levitate, 0);
 6791                                BuffFadeByEffect(SE_Levitate);
 6792                                Message(13, "You can't levitate in this zone.");
 6793                            }
 6794                        }else{
 6795                            SendAppearancePacket(AT_Levitate, 2);
 6796                        }
 6797                                        break;
 6798                                        }
 6799                                case SE_InvisVsUndead2:
 6800                                case SE_InvisVsUndead:
 6801                                        {
 6802                                        invisible_undead = true;
 6803                                        break;
 6804                                        }
 6805                                case SE_InvisVsAnimals:
 6806                                        {
 6807                                        invisible_animals = true;
 6808                                        break;
 6809                                        }
 6810                        }
 6811                }
 6812        }

There isn't one currently there for proc types. Then again, I can't really think why we would want to put it there, since zone should be able to read through the buffs, see if there is currently one with a proc effect.

Digging deeper, there is a spell effect SE_WeaponProc defined in zone/spell_effects.cpp:
Code:

  52 bool Mob::SpellEffect(Mob* caster, int16 spell_id, float partial)
  53 {

 1297                        case SE_WeaponProc:
 1298                        {
 1299                                uint16 procid = GetProcID(spell_id, i);
 1300 #ifdef SPELL_EFFECT_SPAM
 1301                                snprintf(effect_desc, _EDLEN, "Weapon Proc: %s (id %d)", spells[effect_value].name, procid);
 1302 #endif
 1303
 1304                                AddProcToWeapon(procid);
 1305                                break;
 1306                        }

 2406 }


 2810 void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses)
 2811 {

 2830                        case SE_WeaponProc:
 2831                        {
 2832                                uint16 procid = GetProcID(buffs[slot].spellid, i);
 2833                                RemoveProcFromWeapon(procid, false);
 2834                                break;
 2835                        }

 3031 }

And seeing as how most of client_packet.cpp is the same as spell_effects.cpp, depending on what's being done, I would assume we could do this:
zone/client_packet.cpp
Code:

                                case SE_InvisVsAnimals:
                                        {
                                        invisible_animals = true;
                                        break;
                                        }                                       
                                case SE_WeaponProc:
                                        {
                                        AddProcToWeapon(GetProcID(buffs[j1].spellid, x1));
                                        break;
                                        }

Does that sound about right?

AndMetal 09-07-2008 05:00 AM

I finally had a chance to test this out and verified that this does work as expected. Looks like this is another one for the submission section :D

While I was at it, I was looking over some more of the Spell Effects, and it looks like there might be 1 more change that could help in the long run:
zone/client_packet.cpp
Code:

                for (int x1=0; x1 < EFFECT_COUNT; x1++) {
                        switch (spell.effectid[x1]) {
                                case SE_IllusionCopy:
                                case SE_Illusion: {

Nothing major, but could be an issue for some spells.


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

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