View Full Version : New Server, Couple of Small Issues
haggzor
12-24-2013, 07:35 PM
Hi Guys,
I got my server up and running (Windows 7, 64-bit) with minimal difficulty (thanks very much for the great Windows CMake guide!), but I'm running into a couple of questions that I just haven't been able to solve on my own by rummaging around in the db.
1.) Which settings do I use to adjust the multipliers for XP gain? The ones in Variables ("EXPMod") or the one in Rule_Values (1, "Character:ExpMultiplier")? I set both to 3.0 for standard XP gain (a little less than 5 times the normal 0.65 that it defaults to), but after restarting the server it seems as though XP gain is the exact same. Am I missing a switch somewhere?
2.) Does the Expansions value in Variables work? How about the (1, World:ExpansionSettings) value in Rules_Values? Do they differ? I set both to 7 (Classic (0), Kunark (1), Velious (2) and Luclin(4)). I would really like to limit as many server / map (ie PoK tomes) and client features (Map display) as possible. Does anyone know if these are implemented yet? Do they just restrict access to zones, or is it more than that?
3.) I'm seeing that Harm Touch (and I'm guessing Lay on Hands) are not working. They are doing nothing and then giving giving me a message saying interrupted. I saw in an old thread, something about that being a stopgap until the issue was fixed. I have the newest code checkout from GIT and the db build from 12-23-2013. Is this still an issue or am I just missing something?
4.) HP and Mana regen. One of the things that I'm adjusting is that I'm upping the standard HP and Mana regen by about 25% (timesaver for casual play). Is this just the setting in Rules_Values for (1, Character:HPRegenMultiplier) or is there something more that I need to do. It doesn't seem as though it's changed.
Any help with any of these numerous (and I'm sure annoying) questions would be incredibly helpful. I spent a few hours googling and pouring over the forums, but I didn't really feel as though I found what I needed.
On an unrelated note, great job on the Install Guide, Global Settings, Schema and Server Command documentation. They have been immensely helpful!
haggzor
12-25-2013, 01:47 AM
1.) Which settings do I use to adjust the multipliers for XP gain? The ones in Variables ("EXPMod") or the one in Rule_Values (1, "Character:ExpMultiplier")? I set both to 3.0 for standard XP gain (a little less than 5 times the normal 0.65 that it defaults to), but after restarting the server it seems as though XP gain is the exact same. Am I missing a switch somewhere?
I figured this one out. The "EXPMod" value in the Variables table doesn't appear to do anything (that I've been able to see). I've tested it fairly well. The "Character:ExpMultiplier" value in the Rule_Values table does work, you just need to make sure that you are setting it for the Rule_Set ID that's associated with the zone that you are currently in. Any changes to this value also requires a server restart. That must be the step that I missed when I was doing my initial experimentation. ONE DOWN!
Akkadius
12-25-2013, 01:55 AM
I figured this one out. The "EXPMod" value in the Variables table doesn't appear to do anything (that I've been able to see). I've tested it fairly well. The "Character:ExpMultiplier" value in the Rule_Values table does work, you just need to make sure that you are setting it for the Rule_Set ID that's associated with the zone that you are currently in. Any changes to this value also requires a server restart. ONE DOWN!
You can reload a zones rules on the fly for testing using #reload rules
Another thing with EXP Mods, the rule you found will affect things globally, however you can adjust EXP mods per level by using the table:
mysql> select * from level_exp_mods order by level;
+-------+---------+------------+
| level | exp_mod | aa_exp_mod |
+-------+---------+------------+
| 1 | 6 | 8 |
| 2 | 6 | 8 |
| 3 | 6 | 8 |
| 4 | 6 | 8 |
| 5 | 6 | 8 |
| 6 | 6 | 8 |
| 7 | 6 | 8 |
| 8 | 6 | 8 |
| 9 | 6 | 8 |
| 10 | 6 | 8 |
| 11 | 6 | 8 |
| 12 | 6 | 8 |
| 13 | 6 | 8 |
| 14 | 6 | 8 |
| 15 | 6 | 8 |
| 16 | 6 | 8 |
| 17 | 6 | 8 |
| 18 | 6 | 8 |
| 19 | 6 | 8 |
| 20 | 6 | 8 |
| 21 | 6 | 8 |
| 22 | 6 | 8 |
| 23 | 6 | 8 |
| 24 | 6 | 8 |
| 25 | 6 | 8 |
| 26 | 6 | 8 |
| 27 | 6 | 8 |
| 28 | 6 | 8 |
| 29 | 6 | 8 |
| 30 | 6 | 8 |
| 31 | 6 | 8 |
| 32 | 6 | 8 |
| 33 | 6 | 8 |
| 34 | 6 | 8 |
| 35 | 6 | 8 |
| 36 | 6 | 8 |
| 37 | 6 | 8 |
| 38 | 6 | 8 |
| 39 | 6 | 8 |
| 40 | 6 | 8 |
| 41 | 6 | 8 |
| 42 | 6 | 8 |
| 43 | 6 | 8 |
| 44 | 6 | 8 |
| 45 | 6 | 8 |
| 46 | 6 | 8 |
| 47 | 6 | 8 |
| 48 | 6 | 8 |
| 49 | 6 | 8 |
| 50 | 6 | 8 |
| 51 | 6 | 8 |
| 52 | 6 | 8 |
| 53 | 6 | 8 |
| 54 | 6 | 8 |
| 55 | 6 | 8 |
| 56 | 6 | 8 |
| 57 | 6 | 8 |
| 58 | 6 | 8 |
| 59 | 6 | 8 |
| 60 | 6 | 8 |
| 61 | 6 | 8 |
| 62 | 6 | 8 |
| 63 | 6 | 8 |
| 64 | 6 | 8 |
| 65 | 6 | 8 |
| 66 | 6 | 8 |
| 67 | 6 | 8 |
| 68 | 6 | 8 |
| 69 | 6 | 8 |
| 70 | 6 | 8 |
| 71 | 6 | 8 |
| 72 | 6 | 8 |
| 73 | 6 | 8 |
| 74 | 6 | 8 |
| 75 | 6 | 8 |
| 76 | 6 | 8 |
| 77 | 6 | 8 |
| 78 | 6 | 8 |
| 79 | 6 | 8 |
| 80 | 6 | 8 |
| 81 | 6 | 8 |
| 82 | 6 | 8 |
| 83 | 6 | 8 |
| 84 | 6 | 8 |
| 85 | 6 | 8 |
| 86 | 6 | 8 |
| 87 | 6 | 8 |
| 88 | 6 | 8 |
| 89 | 6 | 8 |
| 90 | 6 | 8 |
| 91 | 6 | 8 |
| 92 | 6 | 8 |
| 93 | 6 | 8 |
| 94 | 6 | 8 |
| 95 | 6 | 8 |
| 96 | 6 | 8 |
| 97 | 6 | 8 |
| 98 | 6 | 8 |
| 99 | 6 | 8 |
| 100 | 6 | 7 |
Your table may not look the same, it is probably all 1's. This table multiplies base experience per level. So if you wanted to slow things down you could put for example .3 at level 80 and above for regular experience. You can also adjust AA experience rate all in the same.
Make sure that this rule is set to true in order for this to work:
Zone:LevelBasedEXPMods true
haggzor
12-25-2013, 02:11 AM
2.) Does the Expansions value in Variables work? How about the (1, World:ExpansionSettings) value in Rules_Values? Do they differ? I set both to 7 (Classic (0), Kunark (1), Velious (2) and Luclin(4)). I would really like to limit as many server / map (ie PoK tomes) and client features (Map display) as possible. Does anyone know if these are implemented yet? Do they just restrict access to zones, or is it more than that?
http://www.eqemulator.org/forums/showthread.php?t=36925
I found an article on this, however it dates back to June. Is this still the best way to accomplish this? It would seem they are suggesting that rather than relying on a setting like the Expansions value in Variables work and the World:ExpansionSettings value in Rules_Values, you should just lock people out of those individual zones using status.
Is that still the best way?
Thanks!
EDIT:
Also found http://www.eqemulator.org/forums/showthread.php?t=34814&highlight=remove which speaks to removing PoK book functionality. Nice!
haggzor
12-25-2013, 02:15 AM
You can reload a zones rules on the fly for testing using #reload rules
Another thing with EXP Mods, the rule you found will affect things globally, however you can adjust EXP mods per level by using the table:
mysql> select * from level_exp_mods order by level;
+-------+---------+------------+
| level | exp_mod | aa_exp_mod |
+-------+---------+------------+
| 1 | 6 | 8 |
| 2 | 6 | 8 |
| 3 | 6 | 8 |
| 4 | 6 | 8 |
| 5 | 6 | 8 |
| 6 | 6 | 8 |
| 7 | 6 | 8 |
| 8 | 6 | 8 |
| 9 | 6 | 8 |
| 10 | 6 | 8 |
| 11 | 6 | 8 |
| 12 | 6 | 8 |
| 13 | 6 | 8 |
| 14 | 6 | 8 |
| 15 | 6 | 8 |
| 16 | 6 | 8 |
| 17 | 6 | 8 |
| 18 | 6 | 8 |
| 19 | 6 | 8 |
| 20 | 6 | 8 |
| 21 | 6 | 8 |
| 22 | 6 | 8 |
| 23 | 6 | 8 |
| 24 | 6 | 8 |
| 25 | 6 | 8 |
| 26 | 6 | 8 |
| 27 | 6 | 8 |
| 28 | 6 | 8 |
| 29 | 6 | 8 |
| 30 | 6 | 8 |
| 31 | 6 | 8 |
| 32 | 6 | 8 |
| 33 | 6 | 8 |
| 34 | 6 | 8 |
| 35 | 6 | 8 |
| 36 | 6 | 8 |
| 37 | 6 | 8 |
| 38 | 6 | 8 |
| 39 | 6 | 8 |
| 40 | 6 | 8 |
| 41 | 6 | 8 |
| 42 | 6 | 8 |
| 43 | 6 | 8 |
| 44 | 6 | 8 |
| 45 | 6 | 8 |
| 46 | 6 | 8 |
| 47 | 6 | 8 |
| 48 | 6 | 8 |
| 49 | 6 | 8 |
| 50 | 6 | 8 |
| 51 | 6 | 8 |
| 52 | 6 | 8 |
| 53 | 6 | 8 |
| 54 | 6 | 8 |
| 55 | 6 | 8 |
| 56 | 6 | 8 |
| 57 | 6 | 8 |
| 58 | 6 | 8 |
| 59 | 6 | 8 |
| 60 | 6 | 8 |
| 61 | 6 | 8 |
| 62 | 6 | 8 |
| 63 | 6 | 8 |
| 64 | 6 | 8 |
| 65 | 6 | 8 |
| 66 | 6 | 8 |
| 67 | 6 | 8 |
| 68 | 6 | 8 |
| 69 | 6 | 8 |
| 70 | 6 | 8 |
| 71 | 6 | 8 |
| 72 | 6 | 8 |
| 73 | 6 | 8 |
| 74 | 6 | 8 |
| 75 | 6 | 8 |
| 76 | 6 | 8 |
| 77 | 6 | 8 |
| 78 | 6 | 8 |
| 79 | 6 | 8 |
| 80 | 6 | 8 |
| 81 | 6 | 8 |
| 82 | 6 | 8 |
| 83 | 6 | 8 |
| 84 | 6 | 8 |
| 85 | 6 | 8 |
| 86 | 6 | 8 |
| 87 | 6 | 8 |
| 88 | 6 | 8 |
| 89 | 6 | 8 |
| 90 | 6 | 8 |
| 91 | 6 | 8 |
| 92 | 6 | 8 |
| 93 | 6 | 8 |
| 94 | 6 | 8 |
| 95 | 6 | 8 |
| 96 | 6 | 8 |
| 97 | 6 | 8 |
| 98 | 6 | 8 |
| 99 | 6 | 8 |
| 100 | 6 | 7 |
Your table may not look the same, it is probably all 1's. This table multiplies base experience per level. So if you wanted to slow things down you could put for example .3 at level 80 and above for regular experience. You can also adjust AA experience rate all in the same.
Make sure that this rule is set to true in order for this to work:
Zone:LevelBasedEXPMods true
Awesome! Thanks! That's really useful.
If I decide to define "hell levels", will those values override the Rule_Value setting or vice versa? It sounded like you said that the Rule_Value setting will trump anything in the level_exp_mods table. If that's the case, then I'm probably better off just manually setting each level to what I want and leaving the Rule_Value setting (Character:ExpMultiplier and it's ilk) at the default.
On a side note, do you know why the default is 0.65 instead of 1.00?
Akkadius
12-25-2013, 02:15 AM
http://www.eqemulator.org/forums/showthread.php?t=36925
I found an article on this, however it dates back to June. Is this still the best way to accomplish this? It would seem they are suggesting that rather than relying on a setting like the Expansions value in Variables work and the World:ExpansionSettings value in Rules_Values, you should just lock people out of those zones using status.
Is that still the best way?
Thanks!
Yes, this info is here:
http://www.eqemulator.net/wiki/wikka.php?wakka=ServerVariables
Expansions
Default: 511
Accessible expansions for all players.
0 - Classic
1 - Ruins of Kunark
2 - Scars of Velious
4 - Shadows of Luclin
8 - Planes of Power
16 - Legacy of Ykesha
32 - Lost Dungeons of Norrath
64 - Gates of Discord
128 - Omens of War
256 - Dragons of Norrath
512 - Depths of Darkhallow
1024 - Prophecy of Ro
2048 - Serpent's Spine
4096 - The Burried Sea
8192 - Secrets of Faydwer
To really put a block on it, using the status column can be most effective because it simply requires that status number to traverse.
haggzor
12-25-2013, 02:28 AM
To really put a block on it, using the status column can be most effective because it simply requires that status number to traverse.
Great! Thanks! I'll do both, then. I currently have both set to 7 (Classic (0), Kunark (1), Velious (2) and Luclin(4)), so now I'll just manually status block out all of the zones that are associated with later expansions. This should be relatively easy on account of the fact that they use a different rule_set ID for PoP+.
haggzor
12-25-2013, 03:10 AM
3.) I'm seeing that Harm Touch (and I'm guessing Lay on Hands) are not working. They are doing nothing and then giving giving me a message saying interrupted. I saw in an old thread, something about that being a stopgap until the issue was fixed. I have the newest code checkout from GIT and the db build from 12-23-2013. Is this still an issue or am I just missing something?
Pretty much everything else is working now (except I still haven't figured out how to turn off access to the client map). This is really the last major thing that I wanted to investigate. Does anyone happen to know the status of Lay on Hands and Harm Touch? Is it just me or is anyone still having this issue?
demonstar55
12-25-2013, 03:59 AM
Pretty much everything else is working now (except I still haven't figured out how to turn off access to the client map). This is really the last major thing that I wanted to investigate. Does anyone happen to know the status of Lay on Hands and Harm Touch? Is it just me or is anyone still having this issue?
They both work fine on Underfoot for me. The maps thing you kind of have to do some client side hackery to get done I think?
haggzor
12-25-2013, 12:35 PM
They both work fine on Underfoot for me. The maps thing you kind of have to do some client side hackery to get done I think?
I noticed in the data that in the Spells_New table, "Harm Touch" is set to ID 88. When I try and use Harm Touch in the game, it creates a row in the Timers table referencing type 89. Is it possible that this issue that I'm experiencing is an ID mapping problem from a constant in the code (I know exactly zero C, so I'm just guessing)? I'd imagine that since I have the newest data model, perhaps others aren't having this issue because they have an older data set?
haggzor
12-25-2013, 12:53 PM
//some spell IDs which will prolly change, but are needed
#define SPELL_LEECH_TOUCH 2766
#define SPELL_LAY_ON_HANDS 87
#define SPELL_HARM_TOUCH 88
#define SPELL_HARM_TOUCH2 2821
#define SPELL_IMP_HARM_TOUCH 2774
#define SPELL_NPC_HARM_TOUCH 929
I found this in spdat.h. Could that ID mismatch be my problem?
Township EQ
12-25-2013, 01:03 PM
Haggzor.. I've noticed that at least on Underfoot restricting expansions broke my LoH/HT. Just a suggestion cause I'm not as knowledgeable about this stuff as demonstar or Akka, but have you tried un restricting your expansions and then trying it? might have something to do with it.
haggzor
12-25-2013, 01:22 PM
I have not tried that! I'll give it a shot and see what it does.
haggzor
12-25-2013, 01:30 PM
I'm going to guess that the expansion level probably determines whether you are using the standard Harm Touch or the IMP (improved?) Harm Touch. Since IMP Harm Touch is correctly mapped, that's probably why it works. I'm going to try updating the ID for the old harm touch and recompiling. We'll see if that works. =D
haggzor
12-26-2013, 01:14 PM
I reset all of my expansion variables back to 16383 but still no luck with Harm Touch. Nothing is showing in the logs, so I'm sort of at a loss. The entry in the timer table says 89, which still leads me to believe that there is something out of sync between the client and the skill lookup (88 in the spells_new table).
Uleat
12-26-2013, 07:04 PM
Please read both pages of this thread and re-ask your question after doing so:
http://www.eqemulator.org/forums/showthread.php?t=36768&highlight=spellid
haggzor
12-27-2013, 12:25 AM
Alright, well I figured out one thing. This is the line of code that's causing Harm Touch to fail (client_packet.cpp line 4623, Handle_OP_CastSpell method):
if(castspell->slot < MAX_PP_MEMSPELL)
{
LogFile->write(EQEMuLog::Debug, "Slot [%d] is less than MAX_PP_MEMSPELL [%d]", castspell->slot, MAX_PP_MEMSPELL);
spell_to_cast = m_pp.mem_spells[castspell->slot];
if(spell_to_cast != castspell->spell_id)
{
LogFile->write(EQEMuLog::Debug, "Code thinks I'm a cheater because [%d] does not equal [%d]", spell_to_cast, castspell->spell_id);
InterruptSpell(castspell->spell_id); //CHEATER!!!
return;
}
}
else {
LogFile->write(EQEMuLog::Debug, "Slot [%d] is greater than or equal to MAX_PP_MEMSPELL [%d]", castspell->slot, MAX_PP_MEMSPELL);
InterruptSpell();
return;
}
In eq_packet_structs, you can see that MAX_PP_MEMSPELL is set to 9.
static const uint32 MAX_PP_MEMSPELL = 9;
In the comments for Harm Touch and LoH it mentions that it's assuming that the spell slot is going to be 8, which is not correct in the Titanium client. LoH and Harm Touch are spell slot 9 (ABILITY_SLOT).
Does anyone know what the MAX_PP_MEMSPELL represents? I haven't been able to figure that one out yet. My assumption is that it represents a separation between memorized spells and ability/discipline/item spells (which are all handled individually).
Basically, as long as that value is set to 9 and Harm Touch is coming in on spell slot 9, it automatically goes to interruptSpell, which is why it's not working. My guess is that this block needs an additional elseif specifically for Abilities that are being processed as spells, such as LoH and Harm Touch.
Any input would be wonderful!
haggzor
12-27-2013, 01:23 AM
Alrighty, that fixed it. Basically I added a flag in the existing special SK and Paladin portion of the code to bypass the spell slot evaluation and memorized spell check that was breaking Harm Touch and Lay on Hands.
client_packet.cpp(line 4581)
uint16 spell_to_cast = 0;
// flag to bypass memorized spell check
bool isKnightAbility = false;
//current client seems to send LH in slot 8 now...
if(castspell->slot == ABILITY_SPELL_SLOT &&
castspell->spell_id == SPELL_LAY_ON_HANDS && GetClass() == PALADIN) {
if(!p_timers.Expired(&database, pTimerLayHands)) {
Message(13,"Ability recovery time not yet met.");
InterruptSpell(castspell->spell_id);
return;
}
spell_to_cast = SPELL_LAY_ON_HANDS;
isKnightAbility = true;
p_timers.Start(pTimerLayHands, LayOnHandsReuseTime);
} else if(castspell->slot == ABILITY_SPELL_SLOT &&
(castspell->spell_id == SPELL_HARM_TOUCH
|| castspell->spell_id == SPELL_HARM_TOUCH2
) && GetClass() == SHADOWKNIGHT) {
if(!p_timers.Expired(&database, pTimerHarmTouch)) {
Message(13,"Ability recovery time not yet met.");
InterruptSpell(castspell->spell_id);
return;
}
if(GetLevel() < 40)
spell_to_cast = SPELL_HARM_TOUCH;
else
spell_to_cast = SPELL_HARM_TOUCH2;
LogFile->write(EQEMuLog::Debug, "Harm Touch Spell to Cast: %d (based on lvl [%d])... starting recast timer.", spell_to_cast, GetLevel());
isKnightAbility = true;
p_timers.Start(pTimerHarmTouch, HarmTouchReuseTime);
}
//handle disciplines, OLD, they keep changing this
if(castspell->slot == DISCIPLINE_SPELL_SLOT) {
if(!UseDiscipline(castspell->spell_id, castspell->target_id)) {
printf("Unknown ability being used by %s, spell being cast is: %i\n",GetName(),castspell->spell_id);
InterruptSpell(castspell->spell_id);
}
return;
}
if(castspell->slot < MAX_PP_MEMSPELL)
{
LogFile->write(EQEMuLog::Debug, "Slot [%d] is less than MAX_PP_MEMSPELL [%d]", castspell->slot, MAX_PP_MEMSPELL);
spell_to_cast = m_pp.mem_spells[castspell->slot];
if(spell_to_cast != castspell->spell_id)
{
LogFile->write(EQEMuLog::Debug, "Code thinks I'm a cheater because [%d] does not equal [%d]", spell_to_cast, castspell->spell_id);
InterruptSpell(castspell->spell_id); //CHEATER!!!
return;
}
}
else if (castspell->slot >= MAX_PP_MEMSPELL && !isKnightAbility) {
LogFile->write(EQEMuLog::Debug, "Slot [%d] is greater than or equal to MAX_PP_MEMSPELL [%d]", castspell->slot, MAX_PP_MEMSPELL);
InterruptSpell();
return;
}
LogFile->write(EQEMuLog::Debug, "Casting Spell: [%i] on target [%d]", spell_to_cast, castspell->target_id);
CastSpell(spell_to_cast, castspell->target_id, castspell->slot);
provocating
12-27-2013, 07:01 PM
So will this go into the GIT source as a fix soon? Please !
I just compiled this fix and everything seems to work.
demonstar55
12-27-2013, 07:51 PM
Well, you can do it without an extra flag and its not in a format I feel like dealing with. (Either pull requests on github or a unified diff posted on the code submission forums, note pull requests are preferred because its easier, unless you don't know how to use git that is ...)
haggzor
12-27-2013, 08:21 PM
Yeah, this isn't the prettiest fix in the world. =)
I just posted it in this format because I wanted to show where the problem was located. I had sort of assumed that the development team didn't want random people doing code submissions and that they would fix it in whatever way they see as best. If you would like, I'd be happy to pretty it up some, remove some of the extraneous logging that I added and submit it. I apologize, I'm pretty new to this community. I set up this account a few years ago but never actually got as far as installing anything until this week. Heh.
demonstar55
12-27-2013, 08:27 PM
Its an open source project, any submissions are welcome, but not guaranteed to be accepted of course.
I would recommend submitting pull requests on GitHub since it's much easier on people with access to pull them.
haggzor
12-27-2013, 09:21 PM
Admittedly, I'm new to Git. I've always used SVN. I assume that since Git doesn't have a single master repo that I can access, I'm safe to just commit my updated changes? How do I then submit the commit for review (I'm reading about Git as I'm writing this)?
demonstar55
12-27-2013, 09:30 PM
Basically, fork the main repo, commit your changes to the fork, make a pull request to your fork. Its recommended that you push your changes to a branch on your fork.
This thread might help, I'm sure github has some better docs in their support http://eqemulator.org/forums/showthread.php?t=36515
haggzor
12-27-2013, 09:38 PM
Perfect, thanks!
demonstar55
12-27-2013, 11:26 PM
http://bpaste.net/show/162354/ if someone wants to test this patch (I can't right now), I think it should be better. (Plus I think it was the original intent of the code ...)
haggzor
12-27-2013, 11:42 PM
Code committed in a branch and pull request completed:
https://github.com/EQEmu/Server/pull/102
I'm going to put a copy of the fix on here so that others might have a stopgap measure until if / when it's approved.
Updates to zone/client_packet.cpp (line 4476)
void Client::Handle_OP_CastSpell(const EQApplicationPacket *app)
{
if (app->size != sizeof(CastSpell_Struct)) {
std::cout << "Wrong size: OP_CastSpell, size=" << app->size << ", expected " << sizeof(CastSpell_Struct) << std::endl;
return;
}
if (IsAIControlled()) {
this->Message_StringID(13, NOT_IN_CONTROL);
//Message(13, "You cant cast right now, you arent in control of yourself!");
return;
}
CastSpell_Struct* castspell = (CastSpell_Struct*)app->pBuffer;
#ifdef _EQDEBUG
LogFile->write(EQEMuLog::Debug, "cs_unknown2: %u %i", (uint8)castspell->cs_unknown[0], castspell->cs_unknown[0]);
LogFile->write(EQEMuLog::Debug, "cs_unknown2: %u %i", (uint8)castspell->cs_unknown[1], castspell->cs_unknown[1]);
LogFile->write(EQEMuLog::Debug, "cs_unknown2: %u %i", (uint8)castspell->cs_unknown[2], castspell->cs_unknown[2]);
LogFile->write(EQEMuLog::Debug, "cs_unknown2: %u %i", (uint8)castspell->cs_unknown[3], castspell->cs_unknown[3]);
LogFile->write(EQEMuLog::Debug, "cs_unknown2: 32 %p %u", &castspell->cs_unknown, *(uint32*) castspell->cs_unknown );
LogFile->write(EQEMuLog::Debug, "cs_unknown2: 32 %p %i", &castspell->cs_unknown, *(uint32*) castspell->cs_unknown );
LogFile->write(EQEMuLog::Debug, "cs_unknown2: 16 %p %u %u", &castspell->cs_unknown, *(uint16*) castspell->cs_unknown, *(uint16*) castspell->cs_unknown+sizeof(uint16) );
LogFile->write(EQEMuLog::Debug, "cs_unknown2: 16 %p %i %i", &castspell->cs_unknown, *(uint16*) castspell->cs_unknown, *(uint16*) castspell->cs_unknown+sizeof(uint16) );
#endif
LogFile->write(EQEMuLog::Debug, "OP CastSpell: slot=%d, spell=%d, target=%d, inv=%lx", castspell->slot, castspell->spell_id, castspell->target_id, (unsigned long)castspell->inventoryslot);
if ((castspell->slot == USE_ITEM_SPELL_SLOT) || (castspell->slot == POTION_BELT_SPELL_SLOT)) // ITEM or POTION cast
{
//discipline, using the item spell slot
if (castspell->inventoryslot == 0xFFFFFFFF) {
if (!UseDiscipline(castspell->spell_id, castspell->target_id)) {
LogFile->write(EQEMuLog::Debug, "Unknown ability being used by %s, spell being cast is: %i\n", GetName(), castspell->spell_id);
InterruptSpell(castspell->spell_id);
}
return;
}
else if ((castspell->inventoryslot < 30) || (castspell->slot == POTION_BELT_SPELL_SLOT)) // sanity check
{
const ItemInst* inst = m_inv[castspell->inventoryslot]; //slot values are int16, need to check packet on this field
//bool cancast = true;
if (inst && inst->IsType(ItemClassCommon))
{
const Item_Struct* item = inst->GetItem();
if (item->Click.Effect != (uint32)castspell->spell_id)
{
database.SetMQDetectionFlag(account_name, name, "OP_CastSpell with item, tried to cast a different spell.", zone->GetShortName());
InterruptSpell(castspell->spell_id); //CHEATER!!
return;
}
if ((item->Click.Type == ET_ClickEffect) || (item->Click.Type == ET_Expendable) || (item->Click.Type == ET_EquipClick) || (item->Click.Type == ET_ClickEffect2))
{
if (item->Click.Level2 > 0)
{
if (GetLevel() >= item->Click.Level2)
{
ItemInst* p_inst = (ItemInst*)inst;
int i = parse->EventItem(EVENT_ITEM_CLICK_CAST, this, p_inst, nullptr, "", castspell->inventoryslot);
if (i == 0) {
CastSpell(item->Click.Effect, castspell->target_id, castspell->slot, item->CastTime, 0, 0, castspell->inventoryslot);
}
else {
InterruptSpell(castspell->spell_id);
return;
}
}
else
{
database.SetMQDetectionFlag(account_name, name, "OP_CastSpell with item, did not meet req level.", zone->GetShortName());
Message(0, "Error: level not high enough.", castspell->inventoryslot);
InterruptSpell(castspell->spell_id);
}
}
else
{
ItemInst* p_inst = (ItemInst*)inst;
int i = parse->EventItem(EVENT_ITEM_CLICK_CAST, this, p_inst, nullptr, "", castspell->inventoryslot);
if (i == 0) {
CastSpell(item->Click.Effect, castspell->target_id, castspell->slot, item->CastTime, 0, 0, castspell->inventoryslot);
}
else {
InterruptSpell(castspell->spell_id);
return;
}
}
}
else
{
Message(0, "Error: unknown item->Click.Type (0x%02x)", item->Click.Type);
}
}
else
{
Message(0, "Error: item not found in inventory slot #%i", castspell->inventoryslot);
InterruptSpell(castspell->spell_id);
}
}
else
{
Message(0, "Error: castspell->inventoryslot >= 30 (0x%04x)", castspell->inventoryslot);
InterruptSpell(castspell->spell_id);
}
}
else if (castspell->slot == DISCIPLINE_SPELL_SLOT) { // DISCIPLINE cast
if (!UseDiscipline(castspell->spell_id, castspell->target_id)) {
printf("Unknown ability being used by %s, spell being cast is: %i\n", GetName(), castspell->spell_id);
InterruptSpell(castspell->spell_id);
return;
}
}
else if (castspell->slot == ABILITY_SPELL_SLOT) { // ABILITY cast (LoH and Harm Touch)
uint16 spell_to_cast = 0;
if (castspell->spell_id == SPELL_LAY_ON_HANDS && GetClass() == PALADIN) {
if (!p_timers.Expired(&database, pTimerLayHands)) {
Message(13, "Ability recovery time not yet met.");
InterruptSpell(castspell->spell_id);
return;
}
spell_to_cast = SPELL_LAY_ON_HANDS;
p_timers.Start(pTimerLayHands, LayOnHandsReuseTime);
}
else if ((castspell->spell_id == SPELL_HARM_TOUCH
|| castspell->spell_id == SPELL_HARM_TOUCH2) && GetClass() == SHADOWKNIGHT) {
if (!p_timers.Expired(&database, pTimerHarmTouch)) {
Message(13, "Ability recovery time not yet met.");
InterruptSpell(castspell->spell_id);
return;
}
// determine which version of HT we are casting based on level
if (GetLevel() < 40)
spell_to_cast = SPELL_HARM_TOUCH;
else
spell_to_cast = SPELL_HARM_TOUCH2;
p_timers.Start(pTimerHarmTouch, HarmTouchReuseTime);
}
if (spell_to_cast > 0) // if we've matched LoH or HT, cast now
CastSpell(spell_to_cast, castspell->target_id, castspell->slot);
}
else // MEMORIZED SPELL (first confirm that it's a valid memmed spell slot, then validate that the spell is currently memorized)
{
uint16 spell_to_cast = 0;
if(castspell->slot < MAX_PP_MEMSPELL)
{
spell_to_cast = m_pp.mem_spells[castspell->slot];
if(spell_to_cast != castspell->spell_id)
{
InterruptSpell(castspell->spell_id); //CHEATER!!!
return;
}
}
else if (castspell->slot >= MAX_PP_MEMSPELL) {
InterruptSpell();
return;
}
CastSpell(spell_to_cast, castspell->target_id, castspell->slot);
}
return;
}
haggzor
12-27-2013, 11:50 PM
BTW, thanks to demonstar55 for the great Git tutorial. Helped a lot.
haggzor
12-28-2013, 01:29 AM
@Provocating
The bug fix has been approved and merged. It should be available soon in Git.
provocating
12-28-2013, 01:29 PM
And it worked perfectly, thanks much!
vBulletin® v3.8.11, Copyright ©2000-2025, vBulletin Solutions Inc.