Hello @Droidz,
I would like to propose an improvement to WRobot's spell casting functionality that enhances both evasion capabilities and reliability on servers that implement Lua-based detection mechanisms.
Problem Statement
Several private servers employ Lua hooks on the CastSpellByName function to detect and flag bot activity. The current implementation's reliance on this Lua function creates a detectable pattern that can be exploited for bot identification.
Solution Overview
I have developed two native methods that bypass the Lua layer entirely, thereby reducing the bot's detectable footprint:
Method 1: Direct Spell ID Resolution
The GetSpellIdByName method directly invokes the game's internal GetSpellIdByName function (0x00540200), retrieving both the spell ID and rank without requiring Lua interaction:
public static int GetSpellIdByName(string spellName, out int rank) { rank = 0; try { uint GetSpellIdByNameAddr = 0x00540200; // Allocate space for spell name string var nameBytes = System.Text.Encoding.UTF8.GetBytes(spellName + "\0"); uint nameSpace = wManager.Wow.Memory.WowMemory.AllocData.Get(nameBytes.Length); if (nameSpace <= 0) return 0; // Allocate space for rank (int = 4 bytes) uint rankSpace = wManager.Wow.Memory.WowMemory.AllocData.Get(4); // Allocate space to store the return value (spell ID from eax) uint spellIdSpace = wManager.Wow.Memory.WowMemory.AllocData.Get(4); if (nameSpace <= 0 || rankSpace <= 0 || spellIdSpace <= 0) return 0; // Write spell name to memory wManager.Wow.Memory.WowMemory.Memory.WriteBytes(nameSpace, nameBytes); wManager.Wow.Memory.WowMemory.Memory.WriteInt32(rankSpace, 0); wManager.Wow.Memory.WowMemory.Memory.WriteInt32(spellIdSpace, 0); var asm = new[] { "push " + rankSpace, // Push pointer to rank (2nd arg) "push " + nameSpace, // Push pointer to name (1st arg) "call " + GetSpellIdByNameAddr, "add esp, 8", // Store the spell ID (eax) to spellIdSpace "mov ecx, " + spellIdSpace, "mov [ecx], eax", "retn" }; wManager.Wow.Memory.WowMemory.InjectAndExecute(asm); // Read back the spell ID and rank int spellId = wManager.Wow.Memory.WowMemory.Memory.ReadInt32(spellIdSpace); rank = wManager.Wow.Memory.WowMemory.Memory.ReadInt32(rankSpace); // Free allocated memory wManager.Wow.Memory.WowMemory.AllocData.Free(nameSpace); wManager.Wow.Memory.WowMemory.AllocData.Free(rankSpace); wManager.Wow.Memory.WowMemory.AllocData.Free(spellIdSpace); return spellId; } catch (System.Exception ex) { Logging.WriteError("Error getting spell ID by name: " + ex.Message); return 0; } }
Method 2: Direct Spell Casting with GUID Support
The CastSpell method invokes the native spell casting function (0x080DA40) directly, accepting a GUID parameter to eliminate the need for target selection:
public static void CastSpell(int spellid, ulong guid = 0) { try { uint CastSpell = 0x080DA40; uint guidLow = (uint)(guid & 0xFFFFFFFF); uint guidHigh = (uint)(guid >> 32); var asm = new[] { "push 0", "push " + guidHigh, "push " + guidLow, "push 0", "push " + spellid, "call " + CastSpell, "add esp, 0x14", "retn" }; wManager.Wow.Memory.WowMemory.InjectAndExecute(asm); } catch (System.Exception ex) { Logging.WriteError("Error casting spell: " + ex.Message); } }
Performance Optimization
While repeated calls to GetSpellIdByName could introduce minor latency, this can be mitigated through result caching with cache invalidation upon skill acquisition or update events.
Benefits
-
Eliminates dependency on the Lua
CastSpellByNamefunction, significantly reducing detection risk on Lua-hook protected servers - Supports targeted spell casting without requiring target changes

Recommended Comments
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now