import cv2
import numpy as np
import time
import win32gui
import win32con
from PIL import ImageGrab
import win32api
import os
import random
from image_processor import ImageProcessor
from mouse_controller import MouseController
from assist import Assist
class Kaitu:
def __init__(self, assist = None,日志输出=None, settings=None,延时=None):
self.hwnd =assist.hwnd
self.延时 = 延时
self.日志输出 = 日志输出
self.assist = assist
self.kaitudata = {
'kaitu': settings['kaitu'], #开图功能
'tandong': settings['tandong'],#探洞
}
def openyingdi(self):
"""打开营地的操作"""
#print("开始执行打开营地操作")
self.日志输出.info("开始执行打开营地操作")
# 查找ts1或ts2图片
tsimgs = {
'ts1': 'img/ts1.bmp',
'ts2': 'img/ts2.bmp',
'ts3': 'img/ts3.bmp',
}
ts1_location = self.assist.img_processor.find_images(tsimgs,0.75)
if not ts1_location :
self.日志输出.info("未找到探索")
#判断
return 3
# 使用找到的图片位置
target_location = ts1_location if ts1_location else ts2_location if ts2_location else ts3_location
self.日志输出.info("找到探索")
# 计算随机偏移量
offset_x = random.randint(15, 30)
offset_y = random.randint(40, 60)
# 点击位置(带偏移)
#print(f"点击位置偏移: x={offset_x}, y={offset_y}")
self.assist.mouse.click_position(target_location, offset_x, offset_y)
self.延时.delay()
# 查找openyingdi图片
max_attempts = 3
attempt = 0
openyingdi_location = None
while attempt < max_attempts:
#print(f"第{attempt + 1}次尝试查找openyingdi图片...")
self.日志输出.info(f"第{attempt + 1}次尝试查找openyingdi图片...")
openyingdi_location = self.assist.img_processor.find_image('img/openyingdi.bmp', threshold=0.6)
if openyingdi_location:
self.日志输出.info("找到openyingdi图片")
break
print(f"第{attempt + 1}次未找到openyingdi图片")
attempt += 1
if attempt < max_attempts:
wait_time = random.uniform(0.5, 1.0)
self.日志输出.info(f"等待{wait_time:.2f}秒后重试...")
time.sleep(wait_time)
if not openyingdi_location:
self.日志输出.info("多次尝试后仍未找到openyingdi图片")
#按下esc 弹起esc
win32api.keybd_event(27, 0, win32con.KEYEVENTF_EXTENDEDKEY, 0) # 按下ESC
time.sleep(0.1) # 短暂延迟
win32api.keybd_event(27, 0, win32con.KEYEVENTF_EXTENDEDKEY | win32con.KEYEVENTF_KEYUP, 0) # 释放ESC
self.日志输出.info("按下ESC")
time.sleep(0.3) # 等待界面响应
win32api.keybd_event(27, 0, win32con.KEYEVENTF_EXTENDEDKEY, 0) # 再次按下ESC
time.sleep(0.1) # 短暂延迟
return 2
# 点击openyingdi位置
self.日志输出.info("找到openyingdi,正在点击")
self.assist.mouse.click_position(openyingdi_location)
time.sleep(0.5) # 等待界面响应
# 查找chgl图片
chgl_location = self.assist.img_processor.find_image('img/chgl.bmp')
if not chgl_location:
self.日志输出.info("没有打开伺候营地")
return 2
self.日志输出.info("成功打开伺候营地")
return 1
def check_task(self):
"""检查任务状态
返回值:
1 - 在第一个区域找到图片
0 - 在第二个区域找到图片
3 - 两个区域都没找到图片
"""
#检查斥候是否在忙碌
# 第一次查找并点击tansuo图片
tansuo_imgs = {'tansuo': 'img/tansuo.bmp',
'tansuo2': 'img/tansuo2.bmp'
}
print("开始查找tansuo图片")
tansuo_location = self.assist.img_processor.find_images(tansuo_imgs,0.75)
if not tansuo_location:
#关闭 查找关闭
guanbi_location = self.assist.img_processor.find_image('img/guanbi.bmp')
if not guanbi_location:
print("未找到关闭图片")
return False
print("找到关闭,正在点击")
self.assist.mouse.click_position(guanbi_location)
return False
print("开始检查任务状态")
#判断是否有投靠
region2 = (580, 260, 650, 290)
result2 = self.assist.img_processor.find_image('img/tssj.bmp', region=region2)
# if result2:
# print("有投靠任务")
# return 4
# 第一个区域 (655,223) 到 (755,274)
if self.kaitudata['tandong'] != False:
region1 = (720, 260, 820, 300)
result1 = self.assist.img_processor.find_image('img/tssj.bmp', region=region1)
if result1:
print("有山洞任务")
return 1
# 第二个区域 (812,232) 到 (896,289)
region2 = (860, 260, 980, 300)
result2 = self.assist.img_processor.find_image('img/tssj.bmp', region=region2)
if result2:
print("有其他")
return 2
print("无特殊任务")
return 3
"""带重试机制的找图"""
location = self.assist.img_processor.wait_find_images(image_path, threshold=0.85,timeout=3) # 使用更高的阈值
if not location:
print("多次尝试后仍未找到diaocha图片")
return None # 返回None表示未找到图片
def tsshandong(self):
"""处理调查和点击操作"""
#print("开始执行调查和点击操作")
self.日志输出.info("开始执行调查和点击操作")
# 查找是否正在调查
#首先判断如果chc图片存在 则调用 scroll_wheel("down")
diaocha_location = self.assist.img_processor.find_image('img/chc.bmp', threshold=0.75)
if diaocha_location:
self.日志输出.info("找到chc,正在向下滚动")
self.assist.mouse.scroll_wheel("down")
time.sleep(0.5) # 等待界面响应
#然后查找 判断有几个 图片img/diaochazhong.bmp
self.日志输出.info("开始查找调查图片...")
diaocha_location = self.assist.img_processor.find_image_vertically('img/diaochazhong.bmp', threshold=0.6)
#如果没有点击第一个
diancha_cont = len(diaocha_location)
self.日志输出.info(f"diaocha_location: 共计找到了{diancha_cont}")
diaocha_status = 0
self.日志输出.info(f"diaocha_location: {diaocha_location}")
# diaocha_location = self.assist.img_processor.find_image('img/diaochazhong.bmp', threshold=0.6)
if not diaocha_location:
self.日志输出.info("未找到diaochazhong.bmp,尝试查找diaochazhong2.bmp")
diaocha_location2 = self.assist.img_processor.find_image('img/diaochazhong2.bmp', threshold=0.6)
else:
self.日志输出.info("找到diaochazhong.bmp")
diaocha_location2 = None
self.日志输出.info("检测到正在调查中")
diaocha_status = 1
#点击山洞 # 查找shandong图片
if not self.dianjichsd():
return False
#随机延时
time.sleep(random.randint(1, 3) / 10) # 0.1到0.5秒的随机延时
#查找前往的数量 如果数量和 len(diaocha_location) 一样 则返回 直接开图 返回
qianwang_location = self.assist.img_processor.find_image_vertically('img/qw.bmp', threshold=0.6)
if diancha_cont == len(qianwang_location):
self.日志输出.info("数量和 len(diaocha_location) 一样 则返回 直接开图 ")
return False
# 使用智能等待机制等待qw图片出现
qw_locations = []
max_attempts = 3
attempt = 0
# 在指定区域查找qw或qw2
qianwangzb = [
(800, 350, 950, 390),
(800, 430, 950, 470),
(800, 510, 950, 550)
]
qwdata = {
'qw': 'img/qw.bmp',
'qw2': 'img/qw2.bmp',
'qw3': 'img/qw3.bmp',
'qw4': 'img/qw4.bmp',
}
qw_location = self.assist.img_processor.find_images(qwdata,0.7, region=qianwangzb[diancha_cont])
if not qw_location:
self.日志输出.info("未找到qw图片")
return False
#随机延时
time.sleep(random.randint(1, 5) / 10) # 0.1到0.5秒的随机延时
if qw_location:
self.日志输出.info("在指定区域找到qw图片,正在点击")
self.assist.mouse.click_position(qw_location)
time.sleep(random.randint(1, 5) / 10) # 0.1到0.5秒的随机延时
else:
return False
# 使用智能等待机制查找调查图片
max_attempts = 3
attempt = 0
diaocha_location = None
diaochaimgs = {
'diaocha': 'img/diaocha.bmp',
'diaocha2': 'img/diaocha2.bmp',
}
#延时1- 1.5秒
#开启一个计时器开始计时
diaocha_location=self.assist.img_processor.wait_find_images(diaochaimgs,0.7,timeout=5)
for i in range(3):
time.sleep(random.uniform(0.3, 0.5))
print(f"diaocha_location:{diaocha_location}")
if diaocha_location:
#判断是否有探洞tdlvdian 如果有返回
sdzb = (520,270,820,520)
tdlvdian_location = self.assist.img_processor.find_image('img/tdlvdian.bmp',0.85,sdzb)
if tdlvdian_location:
self.日志输出.info("该山洞已经有伺候探寻")
self.assist.gotocs('cs')
#随机延时 0.3 -0.5,秒
self.日志输出.info("该山洞已经有伺候探寻 已回城市 准备点击营地")
time.sleep(1)
self.openyingdi()
self.日志输出.info("该山洞已经有伺候探寻 营地点击成功")
#随机延时
time.sleep(random.uniform(0.5, 0.8))
self.日志输出.info("点击斥候管理的山洞 准备点击")
if not self.dianjichsd():
self.日志输出.info("点击斥候管理的山洞失败")
return False
self.日志输出.info(f"点击斥候管理的山洞成功 ,查找第{i+1}个山洞")
qw_location = self.assist.img_processor.find_images(qwdata,0.7, region=qianwangzb[i])
if not qw_location:
self.日志输出.info("第一次重复后再次探洞")
return False
else:
if qw_location:
self.日志输出.info(f"点击第{i+1}个山洞")
self.assist.mouse.click_position(qw_location)
diaocha_location=self.assist.img_processor.wait_find_images(diaochaimgs,0.7,timeout=5)
else:
self.日志输出.info("该山洞没有被探寻,继续")
break
if not diaocha_location:
self.日志输出.info("多次尝试后仍未找到diaocha图片")
return False
wgxzb = (diaocha_location['x'] -70, diaocha_location['y'], diaocha_location['x'], diaocha_location ['y'] + 70)
wgx_location = self.assist.img_processor.find_image('img/wgx.bmp',0.7,wgxzb)
if wgx_location:
self.日志输出.info("没有勾选驻扎,正在点击")
self.assist.mouse.click_position(wgx_location)
time.sleep(random.randint(1, 3) / 1) # 随机延时0.1-0.3秒
self.日志输出.info("找到diaocha,正在点击")
self.assist.mouse.click_position(diaocha_location)
time.sleep(random.uniform(0.3, 0.5))
# 使用智能等待机制查找派遣图片
#910 75 dao 1080 620查找
region = (1000, 120, 1200, 500)
paiqian_location = self.assist.img_processor.wait_find_images({'paiqian':'img/paiqian.bmp'},0.65, region=region)
if paiqian_location:
#print("找到paiqian,正在点击")
self.日志输出.info("找到派遣")
self.assist.mouse.click_position(paiqian_location)
self.延时.delay()
#随机延时
#随机延时
#再次检测派遣是否还在
paiqian_location = self.assist.img_processor.find_image('img/paiqian.bmp',0.65, region=region)
if not paiqian_location:
self.日志输出.info("已成功派遣")
return True
#定义一个函数 点击斥候管理里面的山洞
def dianjichsd(self):
"""处理点击斥候管理里面的山洞操作"""
shandong_location = self.assist.img_processor.find_image('img/shandong.bmp',0.75)
if not shandong_location:
#print("未找到shandong图片")
self.日志输出.info("未找到山洞")
return False
# 计算随机偏移量
offset_x = random.randint(-20, 50)
offset_y = random.randint(-2, 15)
# 点击shandong位置(带偏移)
#print(f"找到shandong,点击位置偏移: x={offset_x}, y={offset_y}")
self.assist.mouse.click_position(shandong_location, offset_x, offset_y)
#随机延时
#time.sleep(random.uniform(0.3, 0.5))
self.延时.delay()
return True
def tsqita(self):
"""处理其他任务点击操作"""
#print("开始执行其他任务点击操作")
self.日志输出.info("开始执行其他任务点击操作")
# 查找qita图片
qita_location = self.assist.img_processor.find_image('img/qita.bmp')
if not qita_location:
self.日志输出.info("未找到其他任务图片")
return False
# 点击qita位置(带偏移)
#print(f"找到qita,正在点击")
self.assist.mouse.click_position(qita_location)
self.延时.delay()
# 等待界面响应
前往img = {
'前往':'img/qw.bmp',
'前往2':'img/qw2.bmp',
}
# 查找qw图片
qw_location = self.assist.img_processor.find_images(前往img,0.65)
if not qw_location:
self.日志输出.info("未找到前往")
return False
# 点击qw位置
#print("找到qw,正在点击")
self.日志输出.info("点击前往")
self.assist.mouse.click_position(qw_location)
self.延时.delay()
return True
def cunzhuang(self):
"""处理村庄操作"""
#print("开始执行村庄任务")
self.日志输出.info("开始执行村庄任务")
# 查找qita图片
qita_location = self.assist.img_processor.find_image('img/cunzhuang.bmp')
if not qita_location:
self.日志输出.info("未找到村庄图片")
return False
# 点击qita位置(带偏移)
#print(f"找到村庄,正在点击")
self.assist.mouse.click_position(qita_location)
self.延时.delay()
self.日志输出.info("点击村庄")
# 查找qw图片
qw_location = self.assist.img_processor.find_image('img/dahuzi.bmp',0.65)
if not qw_location:
qw_location = self.assist.img_processor.find_image('img/dahuzi2.bmp',0.65)
if not qw_location:
print("未找到大胡子图片")
return False
# 点击大胡子位置
self.assist.mouse.click_position(qw_location)
time.sleep(1) # 等待界面响应
res = self.cunmin()
#如果返回false 则退出 点击完大胡子 没有找到 村民巨鼎 判断需要进入世界 重新来过
if res == False:
if not self.assist.gotocs('sj'):
return False
return False
return True
def cunmin(self):
"""处理村民相关操作"""
print("开始执行村民相关操作")
# 查找村民图片
cunmin_location = self.assist.img_processor.find_image('img/cunmin.bmp',0.85)
if not cunmin_location:
print("未找到村民图片")
return False
else:
print("检测到村民")
#调用村民
print(cunmin_location)
move_x = random.randint(10,10 )
move_y = random.randint(40, 50)
#调鼠标点击
self.assist.mouse.click_position(cunmin_location, 0, 40)
#延时
time.sleep(random.uniform(0.5, 1.0))
self.assist.mouse.click_position(cunmin_location, 0, 40)
#移动到一旁
time.sleep(random.uniform(0.5, 1.0))
move_x = random.randint(30, 80)
move_y = random.randint(-50, 50)
self.assist.mouse.move_to_side(cunmin_location, move_x, move_y)
#延时
time.sleep(random.uniform(0.5, 1.0))
#cunminzi
print("检测到村民子")
# 智能点击和验证
cunminn ={
'cunminzi1': 'img/cunminzi.bmp',
'cunminzi2': 'img/cunminzi2.bmp',
'lingqu': 'img/lingqu.bmp',
'lingqu2': 'img/lingqu2.bmp'
}
cunminzi_location = self.assist.img_processor.find_images(cunminn,0.75)
print(" 查找多图:")
print(cunminzi_location)
if cunminzi_location == None:
print("未找到村民子图片")
return False
elif cunminzi_location['key']== 'lingqu' or cunminzi_location['key']== 'lingqu2' :
print("直接领取")
self.assist.mouse.click_position(cunminzi_location)
time.sleep(1) # 等待界面响应
if not self.assist.gotocs('sj'):
return False
#随机延时
time.sleep(random.uniform(0.5, 1.0))
if not self.assist.gotocs('cs'):
return False
return True
elif cunminzi_location['key']== 'cunminzi1' or cunminzi_location['key']== 'cunminzi2':
print("村民村民 村民")
print("检测到村民子")
# 计算随机偏移量
offset_x = random.randint(0, 5)
offset_y = random.randint(20, 30)
# 点击前等待
time.sleep(random.uniform(0.2, 0.4))
# 点击村民子位置
self.assist.mouse.click_position(cunminzi_location)
time.sleep(0.1) # 短暂延迟
self.assist.mouse.click_position(cunminzi_location, offset_x, offset_y)
# 等待界面响应
time.sleep(random.uniform(0.3, 0.6))
# 如果没有找到领取按钮,再次点击
# 检查当前环境
# 检查领取按钮
#循环3遍
for i in range(3):
print(f"第{i+1}次尝试查找领取按钮")
# 查找领取按钮
lingqu_location = self.assist.img_processor.find_images(cunminn, 0.75)
if lingqu_location:
if lingqu_location['key']== 'lingqu' or lingqu_location['key']== 'lingqu2' :
print("找到领取按钮,直接点击")
self.assist.mouse.click_position(lingqu_location)
time.sleep(1) # 等待界面响应
if not self.assist.gotocs('sj'):
return False
time.sleep(1) # 等待界面响应
if not self.assist.gotocs('cs'):
return False
return True
else:
print("找到村民子,再次点击")
self.assist.mouse.click_position(cunminzi_location)
time.sleep(0.1) # 短暂延迟
self.assist.mouse.click_position(cunminzi_location, offset_x, offset_y)
# 按下ESC
win32api.keybd_event(0x1B, 0, 0, 0) # 按下ESC
time.sleep(0.1)
win32api.keybd_event(0x1B, 0, win32con.KEYEVENTF_KEYUP, 0) # 释放ESC
time.sleep(random.uniform(0.3, 0.6))
return False
else:
print("未找到村民子图片")
return False
def tszc(self):
"""处理探索和派遣操作"""
if self.kaitudata['kaitu'] ==False:
self.日志输出.info("开图功能未开启")
#print("开图功能未开启")
return False
self.日志输出.info("开始执行探索和派遣操作")
#查找 weixuanzc 是否存在 如果存在则点击
#查找cha 如果不存在 则点击
cha_location = self.assist.img_processor.find_image('img/cha.bmp')
if not cha_location:
self.日志输出.info("未找到cha图片,当前不在侦查界面")
weixuanzc_location = self.assist.img_processor.find_image('img/weixuanzc.bmp',0.85)
if weixuanzc_location:
self.日志输出.info("找到weixuanzc,正在点击")
self.assist.mouse.click_position(weixuanzc_location)
time.sleep(0.5)
else:
self.日志输出.info("应该不在侦查界面")
return False
# 第一次查找并点击tansuo图片
tansuo_location = self.assist.img_processor.find_image('img/tansuo.bmp')
if not tansuo_location:
tansuo_location = self.assist.img_processor.find_image('img/tansuo2.bmp', threshold=0.7)
if not tansuo_location:
self.日志输出.info("未找到tansuo图片")
#关闭 查找关闭
guanbi_location = self.assist.img_processor.find_image('img/guanbi.bmp')
if not guanbi_location:
self.日志输出.info("未找到关闭图片")
return False
self.日志输出.info("找到关闭,正在点击")
self.assist.mouse.click_position(guanbi_location)
return False
self.日志输出.info("找到tansuo斥候管理里面的探索,正在点击")
self.assist.mouse.click_position(tansuo_location)
探索图片 = {
'ts1':'img/tansuo.bmp',
'ts2':'img/tansuo2.bmp',
}
self.延时.delay()
self.延时.delay()
# 第二次查找并点击tansuo图片
探索返回 = self.assist.img_processor.wait_find_images(探索图片,threshold=0.75,timeout=5)
if 探索返回:
self.日志输出.info("找到tansuo世界探索任务,正在点击")
self.延时.delay()
#查找图片wgx 如果存在 则点击
#起始点 x1= tansuo_location x1 -70 y1 = tansuo_location y1 x2 = tansuo_location x1 y2 = tansuo_location y1 + 70
wgxzb = (探索返回['x'] -70, 探索返回['y'], 探索返回['x'], 探索返回 ['y'] + 70)
wgx_location = self.assist.img_processor.find_image('img/wgx.bmp',0.85,wgxzb)
if wgx_location:
self.日志输出.info("没有勾选驻扎,正在点击")
self.assist.mouse.click_position(wgx_location)
self.延时.delay()
self.日志输出.info(f"点击探索")
self.assist.mouse.click_position(探索返回)
#self.assist.mouse.click_position(探索返回)
self.延时.delay()
else:
return False
self.延时.delay()
# 使用智能等待机制查找派遣图片
paiqian_location = self.findpaiqian()
if not paiqian_location:
self.日志输出.info("多次尝试后仍未找到paiqian图片,尝试关闭斥候管理")
#关闭 查找关闭
max_attempts = 3
attempt = 0
guanbi_location = None
while attempt < max_attempts:
guanbi_location = self.assist.img_processor.find_image('img/guanbi.bmp')
if guanbi_location:
self.日志输出.info("找到关闭按钮,正在点击")
self.assist.mouse.click_position(guanbi_location)
time.sleep(random.randint(1, 3) / 10) # 随机延时0.1-0.3秒
break
self.日志输出.info(f"第{attempt + 1}次尝试未找到关闭按钮")
attempt += 1
time.sleep(random.randint(1, 3) / 10) # 每次尝试之间随机等待0.1-0.3秒
if not guanbi_location:
self.日志输出.info("多次尝试后仍未找到关闭按钮")
return False
#再次确认派遣是否存在
region = (910, 75, 1080, 620)
paiqian_location = self.assist.img_processor.find_image('img/paiqian.bmp',0.65, region=region)
if not paiqian_location:
self.日志输出.info("多次尝试后仍未找到派遣图片")
paiqian_location = self.findpaiqian()
return False
return True
def findpaiqian(self):
"""查找派遣图片"""
#910 75 dao 1080 620查找
region = (1000, 120, 1200, 500)
paiqian_location = self.assist.img_processor.wait_find_images({'paiqian':'img/paiqian.bmp'},0.65, region=region)
if paiqian_location:
self.日志输出.info("找到paiqian,正在点击")
#随机延时
time.sleep(random.randint(1, 3) / 10) # 随机延时0.1-0.3秒
self.assist.mouse.click_position(paiqian_location)
return True
#随机延时
else:
self.日志输出.info("派遣伺候失败")
return False
def execute(self):
"""执行主逻辑"""
while True:
# 检查停止信号
if hasattr(self, 'should_stop_ref') and callable(self.should_stop_ref) and self.should_stop_ref():
print("[DEBUG] kaitu.execute() 收到停止信号")
self.日志输出.info("📋 开图任务已终止")
return True
if self.assist.gotocs('cs'):
#print("成功回到城市")
#判断返回值
rt = self.openyingdi()
if rt == 1:
self.日志输出.info("成功打开营地")
elif rt == 2:
self.日志输出.info("打开营地失败")
elif rt == 3:
self.日志输出.info("斥候任务中")
else:
self.日志输出.info("回到城市失败")
rt = self.check_task()
if rt == 1:
self.日志输出.info("有山洞")
if self.tsshandong():
self.日志输出.info("山洞任务完成")
else:
self.日志输出.info("山洞任务失败 去开图")
if self.tszc():
self.日志输出.info("开图任务完成")
else:
self.日志输出.info("开图任务失败")
elif rt == 2:
self.日志输出.info("其他")
if self.tsqita():
self.日志输出.info("其他任务完成")
else:
self.日志输出.info("其他任务失败")
elif rt == 3:
#判断开图是否开启
self.日志输出.info("开图")
if self.tszc():
self.日志输出.info("开图任务完成")
else:
self.日志输出.info("开图任务失败")
elif rt == 4:
self.日志输出.info("有村庄投靠")
if self.cunzhuang():
self.日志输出.info("村庄任务完成")
else:
self.日志输出.info("村庄任务失败")
else :
self.日志输出.info("无任务")
return False 加入我的结构
最新发布