Finally, I found the way of casting aoe spells by programming
I think this may be useful, so share it.
delphi code :
const
ptrSendPacket = $00584450; //function address(currentconnection_sendpacket)
pDataStore1 = $0092DB38; // first parameter (for normal)
pDataStore2 = $0092EE40; // first parameter (for warden)
ptrNextCastCount = $012E8541;//it's a counter, looping from 1 to FF
//each casting packet will increase this value
CMSG_CAST_SPELL = $12E; //OpCode for cast spell
type
//datastore structure
PDataStore = ^TDataStore;
TDataStore = record
ptrDataStore : DWord; // pDataStore1,pDataStore2
ptrPacketData : DWord; //pointer to packet data
UnKnown1 : DWord; //always 0
MayType : DWord; // 0x100 for normal, 0x300 for warden
PacketLen : DWord; //data length
UnKnown3: DWord; //always 0
end;
//packet data structure for cast spell with no target
PCastSpell = ^TCastSpell;
TCastSpell = packed record
OpCode : DWord;
Count : Byte; //
SpellID : Word;
Zero1 : Byte;
Zero2 : Byte;
Zero3 : Byte;
SpellType : DWord;
end;
//packet data structure for cast spell with target
PCastSpellTarget = ^TCastSpellTarget;
TCastSpellTarget = packed record
OpCode : DWord;
Count : Byte;
SpellID : Word;
Zero : Array[1..3] of Byte;
SpellType : DWord;
Target : TGUID;
end;
//packet data structure for cast spell with postion
PCastSpellAOE = ^TCastSpellAOE;
TCastSpellAOE = packed record
OpCode : DWord;
Count : Byte;
SpellID : Word;
Zero1 : Byte;
Zero2 : Byte;
Zero3 : Byte;
SpellType : DWord; //$40
X : Single;
Y : Single;
Z : Single;
end;
var
MyCastSpellAOE : TCastSpellAOE;
PMyCastSpellAOE : PCastSpellAOE = @MyCastSpellAOE;
procedure CastSpellAOE_Target(SpellID : Word);
implementation
//it's an example for casting aoe spells, centerd with target
procedure CastSpellAOE_Target(SpellID : Word);
var
count : Byte;
ptrTarget : DWord;
PTargetObj : PWOWObject;
begin
try
//get target object
ptrTarget := GetTargetPointer;
if ptrTarget=0 then
exit;
PTargetObj := PWOWObject(ptrTarget);
//get current counter
count := 0;
ReadProcessMemory(ProcessHandle, Pointer(ptrNextCastCount), @count, 1, dwSize);
//prepare casting packet data
PMyCastSpellAOE^.OpCode := CMSG_CAST_SPELL;
PMyCastSpellAOE^.Count := Byte(count);
PMyCastSpellAOE^.SpellID := Word(SpellID);
PMyCastSpellAOE^.Zero1 := Byte(0);
PMyCastSpellAOE^.Zero2 := Byte(0);
PMyCastSpellAOE^.Zero3 := Byte(0);
PMyCastSpellAOE^.SpellType := $40;
PMyCastSpellAOE^.X := PTargetObj^.X;
PMyCastSpellAOE^.Y := PTargetObj^.Y;
PMyCastSpellAOE^.Z := PTargetObj^.Z;
//prepare datastore to send
PMyDataStore^.ptrDataStore := pDataStore1;
PMyDataStore^.ptrPacketData := LongWord(PMyCastSpellAOE);
PMyDataStore^.UnKnown1 := 0;
PMyDataStore^.MayType := $100;
PMyDataStore^.PacketLen := $1A;
PMyDataStore^.UnKnown3 := 0;
//call sendpacket
asm
mov ecx,[ptrCurrentConnection]
push PMyDataStore
mov ebx,ptrSendPacket
call ebx
end;
//increase counter by 1
count := count+1;
WriteProcessMemory(ProcessHandle, Pointer(ptrNextCastCount), @count, 1, dwSize);
except
LogInfo('Cast aoe Error!');
end;
end;