I'll post mine here to get things started. It works most of the time, but sometimes the toon runs past monsters. I am wondering if it's due to the _CoProcSend() stuff that I do (for parallel threads, makes the bot much more efficient).
monster_detection.au3:
Code:
global $monsterList = "Skeleton"
global $monsterBlacklist = "batSwarm_coneA|ZombiePileAndWagon|ArcaneSummon_skeleton|blastWaveDistort|trap|Tree_Knot|Hidden|Static_pose|projectile|demonFlyerExplode|FallenGrunt_C|demonic_forge|LootType|Corpse|demonFlyer_A_bomber|Chest|demonFlyer_C_bomber|graveDiggerCrownScript"
Func findMonster()
local $max = 5
local $result[$max][7]
for $i = 0 to $max - 1
$result[$i][0] = false
$result[$i][1] = false
$result[$i][2] = false
$result[$i][3] = false
$result[$i][4] = false
$result[$i][5] = false
$result[$i][6] = false
next
local $j = 0
Local $objList = IterateObjectList(0)
Dim $monster[11]
For $i = 0 To UBound($objList, 1) - 1 step 1
local $range = $objList[$i][8]
local $guid = $objList[$i][1]
local $name = $objList[$i][2]
If ($guid == 0xFFFFFFFF or $objList[$i][7] == -1) Then
ContinueLoop
EndIf
If ($range > $rangeAtWhichToFightMonsters or $range == "" or $range == false) Then
;_CoProcSend($gi_CoProcParent, "monster_list_out_of_range_" & $name & "_" & $range)
ContinueLoop
EndIf
If (Not checkFromList($monsterList, $name)) Then
;_CoProcSend($gi_CoProcParent, "monster_list_not_wl_" & $name)
ContinueLoop
EndIf
If (checkFromList($monsterBlacklist, $name)) Then
;_CoProcSend($gi_CoProcParent, "monster_list_bl_" & $name)
ContinueLoop
EndIf
if (monsterIsDead($guid, "1")) then
;_CoProcSend($gi_CoProcParent, "monster_list_is_dead_" & $guid)
ContinueLoop
;Else
;_CoProcSend($gi_CoProcParent, "monster_list_alive_" & $guid)
EndIf
;_CoProcSend($gi_CoProcParent, "monster_list_ok_" & $i & "_" & $guid & "_" & $name & "_" & $range)
$result[$j][0] = $objList[$i][9] - $_ObjmanagerStrucSize
$result[$j][1] = $name
$result[$j][2] = $range
$result[$j][3] = $guid
$result[$j][4] = $objList[$i][3]
$result[$j][5] = $objList[$i][4]
$result[$j][6] = $objList[$i][5]
$j = $j + 1
if $j == $max then
ExitLoop
endif
Next
_ArraySort($result, 0, 0, 0, 2)
Return $result
EndFunc
Func attackCoordinatesForMonster($monsterOffset, $guid, $monsterName)
local $guid2 = mr_ptr($monsterOffset + 0x4)
local $data2 = mr_int($monsterOffset + 0x1Cc)
local $name = mr_string($monsterOffset + 0x8)
If ($guid2 == 0xFFFFFFFF) Then
;_CoProcSend($gi_CoProcParent, "monster_list_no_guid")
return True
EndIf
If ($data2 == -1) Then
;_CoProcSend($gi_CoProcParent, "monster_list_no_data2")
return True
EndIf
local $x = mr_float($monsterOffset + 0xB0)
local $y = mr_float($monsterOffset + 0xB4)
local $z = mr_float($monsterOffset + 0xB8)
local $CurrentLoc = GetCurrentPos()
local $xd = $x - $CurrentLoc[0]
local $yd = $y - $CurrentLoc[1]
local $zd = $z - $CurrentLoc[2]
;should be more critical
;If $zd > 20 Then
; $zd *= 3
;EndIf
local $range = Sqrt($xd * $xd + $yd * $yd + $zd * $zd)
If ($range > $rangeAtWhichToFightMonsters) Then
;_CoProcSend($gi_CoProcParent, "monster_list_out_of_range_" & $range)
return True
EndIf
if (monsterIsDead($guid, "2")) then
; _CoProcSend($gi_CoProcParent, "monster_list_2is_dead_" & $guid)
return true
endif
;_CoProcSend($gi_CoProcParent, "monster_list_2alive_" & $guid)
;_CoProcSend($gi_CoProcParent, "monster_list_2_" & $name & "_" & $range)
local $result[3]
$result[0] = $x
$result[1] = $y
$result[2] = $z
Return $result
EndFunc
Func workerScanForMonsters()
initMemoryWorker()
readMemoryOffsets()
global $monsterList = "Skeleton|_A_Unique_"
global $monsterBlacklist = "batSwarm_coneA|ZombiePileAndWagon|ArcaneSummon_skeleton|blastWaveDistort|trap|Tree_Knot|Hidden|Static_pose|projectile|demonFlyerExplode|FallenGrunt_C|demonic_forge|LootType|Corpse|demonFlyer_A_bomber|Chest|demonFlyer_C_bomber|graveDiggerCrownScript"
While 1
Local $r = findMonster()
If ($r[0][0] == false) Then
_CoProcSend($gi_CoProcParent, "monster_coords_0#0#0#0#0")
Sleep(100)
ContinueLoop
EndIf
;_ArraySort($r, 0, 0, 0, 2)
for $i = 0 to Ubound($r, 1) - 1 step 1
local $monsterOffset = $r[$i][0]
if ($monsterOffset == false) Then
ExitLoop
EndIf
local $monsterName = $r[$i][1]
local $monsterRange = $r[$i][2]
local $monsterGuid = $r[$i][3]
local $x = $r[$i][4]
local $y = $r[$i][5]
local $z = $r[$i][6]
_CoProcSend($gi_CoProcParent, "monster_coords_" & $x & "#" & $y & "#" & $z & "#" & $monsterName & "#" & $monsterRange)
Sleep(200)
While 1
local $coords = attackCoordinatesForMonster($monsterOffset, $monsterGuid, $monsterName)
if ($coords) Then
ExitLoop
EndIf
_CoProcSend($gi_CoProcParent, "monster_coords_" & $coords[0] & "#" & $coords[1] & "#" & $coords[2] & "#" & $monsterName & "#" & $monsterRange)
Sleep(200)
WEnd
next
;no more monsters, send stop attack signal
_CoProcSend($gi_CoProcParent, "monster_coords_0#0#0#0#0")
Sleep(100)
WEnd
EndFunc
func monsterIsDead($guid, $prefix)
local $hitpoints = IterateActorAtribs($guid, $Atrib_Hitpoints_Cur)
;_CoProcSend($gi_CoProcParent, "monster_list_hp_" & $prefix & "_" & $guid & "_" & $hitpoints & "_" & ($hitpoints == 0 or $hitpoints == false))
return ($hitpoints < 0.01 or $hitpoints == false)
endfunc
workers.au3:
Code:
Global $monsterX = False
Global $monsterY = False
Func startWorkers()
_CoProc("workerScanForMonsters")
_CoProcReciver("workerReceiver")
EndFunc
Func workerReceiver($param)
If (StringInStr($param, "monster_coords_")) Then
Local $coords = StringSplit(StringReplace($param, "monster_coords_", ""), "#")
if ($coords[1] == 0) Then
$monsterX = false
$monsterY = false
elseif (distanceToPath($coords[1], $coords[2], $coords[3]) <= 100) then
local $c = FromD3ToScreenCoords($coords[1], $coords[2], $coords[3])
$monsterX = $c[0]
$monsterY = $c[1]
EndIf
EndIf
EndFunc
attack.au3 (clearArea() is run after having reached the next path point):
Code:
func clearArea($loot = true)
if ($isDead or $timeIsUp or not $canAttack) Then
Return
endif
if (not $monsterX) then
if ($loot) then
loot()
moveBack()
EndIf
return
endif
DEBUG('CLEAR AREA')
while ($monsterX and not $isDead and $canAttack and not $timeIsUp)
Call($char & "_kill")
Sleep(250)
WEnd
toggleKeyboard()
if ($isDead or not $canAttack) Then
Return
EndIf
if ($loot) then
loot()
moveBack()
EndIf
endfunc
Wizard kill function:
Code:
func wizard_beforeClearArea()
if (not $monsterX) then
return
EndIf
$isAttacking = true
if (not $archonActive) then
if (not hasObjectWithinRange("Wizard_HydraHead", $rangeAtWhichToFightMonsters + 1)) then
hydra($monsterX, $monsterY)
Sleep(200)
endif
endif
EndFunc
func wizard_afterClearArea()
$isAttacking = false
EndFunc
func wizard_kill()
if ($isDead or $timeIsUp or not $canAttack or tooFarAwayFromLeader()) Then
return
endif
if ($archonActive or $archonAvailable) then
MouseDown('right')
$archonActive = true
endif
while 1
if ($isDead or $timeIsUp or not $canAttack or not $monsterX) Then
Send('{SHIFTUP}')
ExitLoop
endif
;have a small chance of prolonging our hydra
if (not $archonActive) then
; dont cast hydra for every new monster we want to kill
if (Random(1, 20, 1) == 1) then
hydra($monsterX, $monsterY)
Sleep(200)
endif
endif
Local $distance = distance($monsterX, $monsterY, $startX, $startY)
if ($archonActive and $distance > 95) then
mouseUp('left')
Send('{SHIFTUP}')
mouseDown('right')
endif
if (not $archonActive or $distance <= 95) then
MouseUp('right')
Send('{SHIFTDOWN}')
MouseDown('left')
endif
moveMouse($monsterX, $monsterY, 2)
Sleep(100)
wend
Send('{SHIFTUP}')
endfunc
Feedback welcome!