-
Notifications
You must be signed in to change notification settings - Fork 17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Macro approach less than ideal #2
Comments
Chronological list of control flow divergence0x6E4D43: Check to prevent error spam when the player is casting the currently-casting spell repeatedly. if ( spellId == s_modalSpellID )
{
SndInterfacePlayInterfaceSound("igPlayerInviteDecline");
return false;
} Solution: Replace 0x6E4DE3: If a modal spell (one which created a cast bar) is underway, report that another spell is in progress. if ( Spell_C_IsModal() )
{
modalSpell = s_modalSpellID < 0 || s_modalSpellID > g_spellDB.m_maxID ? NULL : g_spellDB.m_recordsById[s_modalSpellID];
if ( !(modalSpell->Attributes & (SPELL_ATTR_ON_NEXT_SWING_2|SPELL_ATTR_ON_NEXT_SWING_1)) )
{
Spell_C_SpellFailed(v44->Id, SPELL_FAILED_SPELL_IN_PROGRESS, -1, -1);
return false;
}
} Solution: If we end up being successful at changing when the cast bar appears, this probably wont be necessary to bypass. For now, it can be bypassed by changing Edit: Another benefit to not bypassing this check (if it's true that we don't need to) is that it will reduce spam to the server. |
Error HandlingThis post assumes the two above patches have been made. When a spell is casting, and the same spell is cast again, two different errors are reported: spell not ready, and interrupted (and the original spell cast is interrupted). This interruption comes from if ( !RangeCheckSelected(this, spell, guid, 1) || !CGUnit_C::CheckAndReportSpellInhibitFlags(this, spell, a2) )
{
return false;
} The logic in // is this spell on cooldown?
if ( Spell_C_GetSpellCooldown(spellRec->Id, 0, 0, 0, 0) )
{
repeatId = GetAutoRepeatSpellId();
if ( repeatId >= 0 && repeatId <= g_spellDB.m_maxID )
{
repeatSpell = g_spellDB.m_recordsById[repeatId];
if ( repeatSpell )
{
// should the current cast be cancelled?
if ( repeatSpell->AttributesEx3 & SPELL_ATTR_EX3_REQ_WAND )// <-- bad name
{
pkt.m_buffer = 0;
pkt.m_base = 0;
pkt.m_alloc = 0;
pkt.m_size = 0;
pkt.m_read = -1;
pkt.VMT = (CDataStoreVMT *)CDataStore::`vftable';
CDataStore::Put32(&pkt, 0x12F); // CMSG_CANCEL_CAST
repeatId = GetAutoRepeatSpellId();
CDataStore::Put32(&pkt, repeatId);
pkt.m_read = 0;
ClientServices_Send(&pkt);
Send_CMSG_CANCEL_AUTO_REPEAT_SPELL();
pkt.VMT = (CDataStoreVMT *)CDataStore::`vftable';
if ( pkt.m_alloc != -1 )
CDataStoreVMT_InternalDestroy(&pkt, &pkt.m_buffer, &pkt.m_base, &pkt.m_alloc);
}
}
}
// fail: not ready yet
Spell_C_SpellFailed(spellRec->Id, SPELL_FAILED_NOT_READY, -1, -1);
return false;
} Note that the check for the auto repeating spell is not relevant to our task. I think there is no problem with Solution: Replace At this point, there is no unexpected behavior, but no new behavior either. The next step is to find why EDIT: There is a problem with allowing this message in that if |
Normal Spell CastThis usually comes from a sprite click (specifically, the action bar). Consequently, the spell cast is triggered by
|
Possible Solution 1Hook Spell push-back is controlled by the server (since it most roll for pushback resist mechanics). The client is informed of delays via
|
Possible Solution 2Begin the cast bar when the cast is sent, rather than when it is acknowledged by the server. The cast bar is controlled by the interface files internal to the games MPQ files. Specifically: The
This is not a complete solution in and of itself. In very rare instances, we will have outdated information about our own spell haste. Our haste may be lower than we are aware, and in extremely rare conditions it may be higher than we are aware (although I think this is practically impossible except with extremely high latency, greater than the duration of the global cooldown). In the event that our haste is lower than we are aware, there shouldn't be any problem, as our cast will actually finish before the cast bar does. In the event that our haste is higher than we are aware, there will still be a slight unnecessary delay before the next cast may complete, but this will be left as a future enhancement to resolve (since in reality it will probably never happen). To achieve this solution, the call to |
Hi namreeb, I am quite interested in your progress on this ticket and am wondering how you are tracking with this? Regards |
Hello, @tserafin. Thank you for your interest. I have started writing code for this and testing it in-game, but it is not quite working yet. I don't have an ETA. In fact, I'm still not even certain that this is a viable solution. Initial results are encouraging, though. |
I have just pushed code for version 2.0, which solves this issue. I do not plan to upload binaries for it until I can test it a bit more. |
The approach of requiring the user to make a macro of
/script CastSpellAtTarget(id)
is less than ideal. It would be better if we could reprogram the client's own behavior. The two primary things to accomplish are:I've created this issue to give myself a convenient place to store research into achieving this goal.
The text was updated successfully, but these errors were encountered: