#include ConsoleWrite(";; Klanhaboru fun by ChesTeRcs@2023" & @CRLF & @CRLF) #Region === Configurations AutoItSetOption("SendKeyDelay", 1) AutoItSetOption("SendKeyDownDelay", 1) AutoItSetOption("WinTitleMatchMode", 2) AutoItSetOption("TrayAutoPause" ,0) Global $toggleRestoreLastWindow = false ; dont change Global $browser = IniRead(@ScriptDir & "/config.ini", "Options", "browser", "Google Chrome") Global $gameTitle = IniRead(@ScriptDir & "/config.ini", "Options", "gameTitle", "Klánháború") Global $server = IniRead(@ScriptDir & "/config.ini", "Options", "server", "hu83") ; get it from game url Global $villageId = IniRead(@ScriptDir & "/config.ini", "Options", "villageId", "1") ; get it from game url Global $scavengeMode = IniRead(@ScriptDir & "/config.ini", "Options", "scavengeMode", "2") ; Mode 0-3 (0-Lusta gyűjtögetők, 1-Szerény gyűjtögetők, 2-Okos gyűjtögetők, 3-Kiváló gyűjtögetők) Global $traytip = IniRead(@ScriptDir & "/config.ini", "Options", "trayTip", true) Global $debug = IniRead(@ScriptDir & "/config.ini", "Options", "debug", false) Global $gyujtogetesEventTimer = eventStart(0) ; delay task after bot started with seconds (default: 0) Global $gyujtogetesEventTimer2 = eventStart(0) ; delay task after bot started with seconds (default: 0) Global $trainUnitsEventTimer = eventStart(3600) ; delay task after bot started with seconds (default: 0) Global $trainLovassagEventTimer = eventStart(3600) ; delay task after bot started with seconds (default: 0) Global $trainMachinesEventTimer = eventStart(3600) ; delay task after bot started with seconds (default: 0) Global $epitesEventTimer = eventStart(0) ; delay task after bot started with seconds (default: 0) Global $trainKnightEventTimer = eventStart(0) ; delay task after bot started with seconds (default: 0) Global $sendAttackEventTimer = eventStart(0) ; delay task after bot started with seconds (default: 0) Global $diamondGatheringEventTimer = eventStart(0) ; delay task after bot started with seconds (default: 0) Global $pageLoadTime = 400 ; inMs Global $sleepTimesInEndOfTasks = 2200 ; inMs #EndRegion While loopEnd() ;;;;;;;;;;;;;;;;;;;;;;;;;;; Gyűjtögetés ;;;;;;;;;;;;;;;;;;;;;;;;;;; sendAll, mode, landzsas, kardforgato, bardos, ijasz, konnyulovas, lovasijasz, nehezlovas, lovag (-1 meant to send all unit button) $gyujtogetesEventTimer2 = gyujtogetes(false, 2, -1, 0, 0, 0, -1, -1, -1, 0, $gyujtogetesEventTimer2) $gyujtogetesEventTimer = gyujtogetes(false, 3, 0, 0, 0, 0, -1, -1, -1, 0, $gyujtogetesEventTimer) ;;;;;;;;;;;;;;;;;;;;;;;;;;; Train Units $trainUnitsEventTimer = trainUnits( 0, 10, 0, 0, 7200, $trainUnitsEventTimer) ;;;;;;;;;;;;;;;;;;;;;;;;;;; Train Lovassag ;;;;;;;;;;;;;;;;;;;;;;;;;;; kem, konnyulovas, lovasijasz, nehezlovas (can be -1 what is meant to all unit button) $trainLovassagEventTimer = trainLovassag( 0, 0, 0, 0, 3600, $trainLovassagEventTimer) ;;;;;;;;;;;;;;;;;;;;;;;;;;; Train Machinery ;;;;;;;;;;;;;;;;;;;;;;;;;;; kos, katapult (can be -1 what is meant to all unit button) $trainMachinesEventTimer = trainMachines( 0, 0, 3600, $trainMachinesEventTimer) ;;;;;;;;;;;;;;;;;;;;;;;;;;; Építés ;;;;;;;;;;;;;;;;;;;;;;;;;;; Options: main, barracks, stable, watchtower, smith, place, statue, market, wood, stone, iron, farm, storage, hide, wall $epitesEventTimer = epites( "stone", 3600, $epitesEventTimer) ;;;;;;;;;;;;;;;;;;;;;;;;;;; Train Knight ;;;;;;;;;;;;;;;;;;;;;;;;;;; ;$trainKnightEventTimer = trainKnight( 9000, $trainKnightEventTimer) ;;;;;;;;;;;;;;;;;;;;;;;;;;; Send Attack ;;;;;;;;;;;;;;;;;;;;;;;;;;; $x, $y, $landzsas, $kardforgato, $bardos, $ijasz, $kem, $konnyulovas, $lovasijasz, $nehezlovas, $kos, $katapult, $lovag, $nemes, $eventTimer $sendAttackEventTimer = sendAttack(490, 562, 0, 250, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 3750, $sendAttackEventTimer) ; 10800 - 3h ;;;;;;;;;;;;;;;;;;;;;;;;;;; Diamon Gathering event ;;;;;;;;;;;;;;;;;;;;;;;;;;; $diamondGatheringEventTimer = diamondGatheringEvent( $diamondGatheringEventTimer) WEnd #Region === Functions Func loopEnd() TrayTipGG("") Sleep(1000) If ($debug == true) Then ConsoleWrite("should alt tab: " & $toggleRestoreLastWindow & @CRLF) If ($toggleRestoreLastWindow == true) Then Send("!{TAB}") $toggleRestoreLastWindow = false EndIf return true EndFunc Func diamondGatheringEvent($eventTimer) If (Not eventTriggered($eventTimer)) Then Return $eventTimer TraytipGG("Diamong gathering started!" & @CRLF) openNewTab() navigateUrl(getGameUrl("event_mine"), false) sendJsClickById("minecart_action_free") Sleep($pageLoadTime) $seconds = parseTimeToSeconds(getDataWithJs("document.getElementById('next_round_countdown').children[0]")) If ($seconds > 0) Then $eventTimer = eventStart($seconds) endTask("Diamong gathering done, next event: " & @CRLF & $eventTimer) Return $eventTimer EndIf endTask("Diamong gathering ERROR!", 3) Return $eventTimer EndFunc Func gyujtogetes($sendAll, $mode, $landzsas, $kardforgato, $bardos, $ijasz, $konnyulovas, $lovasijasz, $nehezlovas, $lovag, $eventTimer) ;Mode 0-3 (0-Lusta gyűjtögetők, 1-Szerény gyűjtögetők, 2-Okos gyűjtögetők, 3-Kiváló gyűjtögetők) If ($sendAll = false and $landzsas = 0 and $kardforgato = 0 and $bardos = 0 and $ijasz = 0 and $konnyulovas = 0 and $lovasijasz = 0 and $nehezlovas = 0 and $lovag = 0) Then Return $eventTimer If (Not eventTriggered($eventTimer)) Then Return $eventTimer TraytipGG("Gyüjtögetés started!" & @CRLF) openNewTab() navigateUrl(getGameUrl("place", "scavenge"), false) $seconds = parseTimeToSeconds(getDataWithJs("document.getElementsByClassName('scavenge-option')[" & $mode & "].getElementsByClassName('return-countdown')[0]")) If ($seconds > 0) Then $eventTimer = eventStart($seconds) endTask("Gyüjtögetés in progress, next event: " & @CRLF & $eventTimer) Return $eventTimer EndIf If ($sendAll) Then sendJsClickByClass("fill-all") Else sendUnits($landzsas, $kardforgato, $bardos, $ijasz) sendLovassag(0, $konnyulovas, $lovasijasz, $nehezlovas) sendRoyalties($lovag, 0) EndIf jsExecutor("document.getElementsByClassName('scavenge-option')[" & $mode & "].getElementsByClassName('btn-default')[0].click();") Sleep($pageLoadTime) $seconds = parseTimeToSeconds(getDataWithJs("document.getElementsByClassName('scavenge-option')[" & $mode & "].getElementsByClassName('return-countdown')[0]")) If ($seconds > 0) Then $eventTimer = eventStart($seconds) endTask("Gyüjtögetés done, next event: " & @CRLF & $eventTimer) Return $eventTimer EndIf endTask("Gyüjtögetés ERROR!", 3) Return $eventTimer EndFunc Func trainUnits($landzsas, $kardforgato, $bardos, $ijasz, $repeatTimer, $eventTimer) If ($landzsas = 0 and $kardforgato = 0 and $bardos = 0 and $ijasz = 0) Then Return $eventTimer If (Not eventTriggered($trainUnitsEventTimer)) Then Return $eventTimer TraytipGG("Train Units started!" & @CRLF) openNewTab() navigateUrl(getGameUrl("barracks"), false) sendUnits($landzsas, $kardforgato, $bardos, $ijasz) sendJsClickByClass("btn-recruit") $eventTimer = eventStart($repeatTimer) endTask("Train Units done, next event: " & @CRLF & $eventTimer) Return $eventTimer EndFunc Func trainLovassag($kem, $konnyulovas, $lovasijasz, $nehezlovas, $repeatTimer, $eventTimer) If ($kem = 0 and $konnyulovas = 0 and $lovasijasz = 0 and $nehezlovas = 0) Then Return $eventTimer If (Not eventTriggered($trainLovassagEventTimer)) Then Return $eventTimer TraytipGG("Train Lovassag started!" & @CRLF) openNewTab() navigateUrl(getGameUrl("stable"), false) sendLovassag($kem, $konnyulovas, $lovasijasz, $nehezlovas) sendJsClickByClass("btn-recruit") $eventTimer = eventStart($repeatTimer) endTask("Train Lovassag done, next event: " & @CRLF & $eventTimer) Return $eventTimer EndFunc Func trainMachines($kos, $katapult, $repeatTimer, $eventTimer) If ($kos = 0 and $katapult = 0) Then Return $eventTimer If (Not eventTriggered($trainMachinesEventTimer)) Then Return $eventTimer TraytipGG("Train Machines started!" & @CRLF) openNewTab() navigateUrl(getGameUrl("garage"), false) sendMachines($kos, $katapult) sendJsClickByClass("btn-recruit") $eventTimer = eventStart($repeatTimer) endTask("Train Machines done, next event: " & @CRLF & $eventTimer) Return $eventTimer EndFunc Func epites($buildingId, $repeatTimer, $eventTimer) ;Options: main, barracks, stable, watchtower, smith, place, statue, market, wood, stone, iron, farm, storage, hide, wall If (Not eventTriggered($epitesEventTimer)) Then Return $eventTimer TraytipGG("Epites started: " & $buildingId & @CRLF) openNewTab() navigateUrl(getGameUrl("main"), false) jsExecutor("document.querySelector('{#}main_buildrow_" & $buildingId & "').querySelector('a.btn-build').click();") $eventTimer = eventStart($repeatTimer) endTask("Epites done, next event: " & @CRLF & $eventTimer) Return $eventTimer EndFunc Func trainKnight($repeatTimer, $eventTimer) If (Not eventTriggered($trainKnightEventTimer)) Then Return $eventTimer TraytipGG("Train Knight started! " & @CRLF) openNewTab() navigateUrl(getGameUrl("statue"), false) sendJsClickByClass("knight_train_launch") Sleep($pageLoadTime) sendJsClickByClass("knight_regimen_confirm") $eventTimer = eventStart($repeatTimer) endTask("Train Knight, next event: " & @CRLF & $eventTimer & @CRLF) Return $eventTimer EndFunc Func sendAttack($x, $y, $landzsas, $kardforgato, $bardos, $ijasz, $kem, $konnyulovas, $lovasijasz, $nehezlovas, $kos, $katapult, $lovag, $nemes, $repeatTimer, $eventTimer) If ($landzsas = 0 and $kardforgato = 0 and $bardos = 0 and $ijasz = 0 and $kem = 0 and $konnyulovas = 0 and $lovasijasz = 0 and $nehezlovas = 0 and $kos = 0 and $katapult = 0 and $lovag = 0 and $nemes = 0) Then Return $eventTimer If (Not eventTriggered($sendAttackEventTimer)) Then Return $eventTimer If ($x = null or $y = null) Then Return $eventTimer TraytipGG("Send Attack started!" & @CRLF) openNewTab() navigateUrl(getGameUrl("place", "command"), false) sendUnits($landzsas, $kardforgato, $bardos, $ijasz) sendLovassag($kem, $konnyulovas, $lovasijasz, $nehezlovas) sendMachines($kos, $katapult) sendRoyalties($lovag, $nemes) jsExecutor("document.getElementsByClassName('target-input-field')[0].value = '" & $x & "|" & $y & "'") sendJsClickById("target_attack") Sleep($pageLoadTime) sendJsClickById("troop_confirm_submit") $eventTimer = eventStart($repeatTimer) endTask("Send Attack done, next event: " & @CRLF & $eventTimer) Return $eventTimer EndFunc Func sendUnits($landzsas, $kardforgato, $bardos, $ijasz) If ($landzsas > 0) Then jsExecutor("{$}('input[name=spear]').val('" & $landzsas & "').trigger('keyup');") If ($kardforgato > 0) Then jsExecutor("{$}('input[name=sword]').val('" & $kardforgato & "').trigger('keyup');") If ($bardos > 0) Then jsExecutor("{$}('input[name=axe]').val('" & $bardos & "').trigger('keyup');") If ($ijasz > 0) Then jsExecutor("{$}('input[name=archer]').val('" & $ijasz & "').trigger('keyup');") If ($landzsas < 0) Then jsExecutor("document.getElementsByName('spear')[0].parentElement.lastElementChild.click();") If ($kardforgato < 0) Then jsExecutor("document.getElementsByName('sword')[0].parentElement.lastElementChild.click();") If ($bardos < 0) Then jsExecutor("document.getElementsByName('axe')[0].parentElement.lastElementChild.click();") If ($ijasz < 0) Then jsExecutor("document.getElementsByName('archer')[0].parentElement.lastElementChild.click();") EndFunc Func sendLovassag($kem, $konnyulovas, $lovasijasz, $nehezlovas) If ($kem > 0) Then jsExecutor("{$}('input[name=spy]').val('" & $kem & "').trigger('keyup');") If ($konnyulovas > 0) Then jsExecutor("{$}('input[name=light]').val('" & $konnyulovas & "').trigger('keyup');") If ($lovasijasz > 0) Then jsExecutor("{$}('input[name=marcher]').val('" & $lovasijasz & "').trigger('keyup');") If ($nehezlovas > 0) Then jsExecutor("{$}('input[name=heavy]').val('" & $nehezlovas & "').trigger('keyup');") If ($kem < 0) Then jsExecutor("document.getElementsByName('spy')[0].parentElement.lastElementChild.click();") If ($konnyulovas < 0) Then jsExecutor("document.getElementsByName('light')[0].parentElement.lastElementChild.click();") If ($lovasijasz < 0) Then jsExecutor("document.getElementsByName('marcher')[0].parentElement.lastElementChild.click();") If ($nehezlovas < 0) Then jsExecutor("document.getElementsByName('heavy')[0].parentElement.lastElementChild.click();") EndFunc Func sendMachines($kos, $katapult) If ($kos > 0) Then jsExecutor("{$}('input[name=ram]').val('" & $kos & "').trigger('keyup');") If ($katapult > 0) Then jsExecutor("{$}('input[name=catapult]').val('" & $katapult & "').trigger('keyup');") If ($kos < 0) Then jsExecutor("document.getElementsByName('ram')[0].parentElement.lastElementChild.click();") If ($katapult < 0) Then jsExecutor("document.getElementsByName('catapult')[0].parentElement.lastElementChild.click();") EndFunc Func sendRoyalties($lovag, $nemes) If ($lovag > 0) Then jsExecutor("{$}('input[name=knight]').val('" & $lovag & "').trigger('keyup');") If ($nemes > 0) Then jsExecutor("{$}('input[name=snob]').val('" & $nemes & "').trigger('keyup');") If ($lovag < 0) Then jsExecutor("document.getElementsByName('knight')[0].parentElement.lastElementChild.click();") If ($nemes < 0) Then jsExecutor("document.getElementsByName('snob')[0].parentElement.lastElementChild.click();") EndFunc #EndRegion #Region === Helper Functions Func openNewTab() $hWnd = WinGetHandle("[active]") $hWndBrowser = WinGetHandle($browser) if ($hWnd <> $hWndBrowser) Then $toggleRestoreLastWindow = true WinActivate($browser) Sleep(10) Send("^t") Sleep(10) EndFunc Func closeTab() WinActivate($browser) Sleep(10) Send("^w") Sleep(10) EndFunc Func getGameUrl($screen, $mode = "") $url = "https://" & $server & ".klanhaboru.hu/game.php?village=" & $villageId & "&screen=" & $screen If (Not ($mode = "")) Then $url &= "&mode=" & $mode return $url EndFunc Func sendJsClickById($elementId) jsExecutor("document.getElementById('" & $elementId & "').click();") EndFunc Func sendJsClickByClass($classId) jsExecutor("document.getElementsByClassName('" & $classId & "')[0].click();") EndFunc Func jsExecutor($code) navigateUrl("javascript:(function(){{}" & $code & "{}})();") EndFunc Func navigateUrl($url, $waitForGame = true) WinWaitActive($browser) If ($debug == true) Then TraytipGG($url & @CRLF) If ($waitForGame) Then WinWaitActive($gameTitle) Send("^l") Sleep(10) Send("^a") Sleep(10) Send($url) Send("{ENTER}") WinWaitActive($gameTitle) ; now pageLoadTime can be 0 EndFunc Func getDataWithJs($jsSelector) $clipBoardCache = ClipGet() jsExecutor("window.location = '{#}'{+}" & $jsSelector & ".innerHTML") Send("^l") Sleep(10) Send("^a") Sleep(10) Send("^c") Sleep(100) $data = ClipGet() ClipPut($clipBoardCache) $data = StringSplit( $data, "#") If ($data[0] < 2) Then If ($debug == true) Then TraytipGG("getDataWithJs error!" & $data & " Expected array size 2, actual: " & $data[0] & @CRLF, 3) If ($debug == true) Then Sleep(2000) return "" EndIf TraytipGG("Data: " & $data[2] & @CRLF) return $data[2] EndFunc Func parseTimeToSeconds($string) $parsedString = StringSplit( $string, ":") If ($parsedString[0] < 3) Then If ($debug == true) Then TraytipGG("parseTimeToSeconds error! Expected array size 3, actual: " & $parsedString[0] & @CRLF, 3) If ($debug == true) Then Sleep(2000) return 0 EndIf $hours = $parsedString[1] $minutes = $parsedString[2] $seconds = $parsedString[3] return ($hours*3600+$minutes*60+$seconds) EndFunc Func TraytipGG($text, $icon = 1, $console = true) If ($traytip == true) then ToolTip($text, 150, 75, $gameTitle & " - " & $server & " - " & $villageId, $icon) If ($console == true) then ConsoleWrite($text) EndFunc Func endTask($logText, $icon = 1) TraytipGG($logText & @CRLF, $icon) ConsoleWrite(@CRLF) Sleep($sleepTimesInEndOfTasks) closeTab() TrayTipGG("") return true EndFunc #EndRegion #Region === EventHandlers Func eventStart($secondsToWait = 3, $mode = "s") return _DateAdd($mode, $secondsToWait, _NowCalc()) EndFunc Func eventCountDown($targetDate, $mode = "s") return _DateDiff($mode, _NowCalc(), $targetDate) EndFunc Func eventTimePassed($startDate, $targetDate = _NowCalc(), $mode = "s") return _DateDiff($mode, $startDate, $targetDate) EndFunc Func eventTimeCompare($startDate, $targetDate, $mode = "s") return _DateDiff($mode, $startDate, $targetDate) EndFunc Func eventTriggered($targetDate, $mode = "s") return eventCountDown($targetDate, $mode) <= 0 EndFunc Func compareTimeEventFormatted($startTime, $endTime = _NowCalc()) $seconds = StringFormat("%02i", Mod(eventTimeCompare($startTime, $endTime, "s"), 60)) $minutes = StringFormat("%02i", Mod(eventTimeCompare($startTime, $endTime, "n"), 60)) $hours = StringFormat("%01i", eventTimeCompare($startTime, $endTime, "h")) If ($hours <> -1 and $minutes <> -1 and $seconds <> -1) then return $hours &":" &$minutes &":" &$seconds Else EndIf return "" EndFunc Func countdownTimeEventFormatted($endTime) $seconds = StringFormat("%02i", Mod(eventCountDown($endTime, "s"), 60)) $minutes = StringFormat("%02i", Mod(eventCountDown($endTime, "n"), 60)) $hours = StringFormat("%01i", eventCountDown($endTime, "h")) If ($hours <> -1 and $minutes <> -1 and $seconds <> -1) then return $hours &":" &$minutes &":" &$seconds Else return "" EndIf EndFunc Func passedTimeEventFormatted($startTime, $endTime = _NowCalc()) $seconds = StringFormat("%02i", Mod(eventTimePassed($startTime, $endTime, "s"), 60)) $minutes = StringFormat("%02i", Mod(eventTimePassed($startTime, $endTime, "n"), 60)) $hours = StringFormat("%01i", eventTimePassed($startTime, $endTime, "h")) If ($hours <> -1 and $minutes <> -1 and $seconds <> -1) then return $hours &":" &$minutes &":" &$seconds Else return "" EndIf EndFunc #EndRegion