战舰少女 R,综合脚本
2523
战舰少女 R,综合脚本
CDFLS_mao_zx
·
2021-09-29 20:06:20
·
个人记录
这是一个舰R 的综合脚本,支持自动远征,自动修复舰船,自动战斗(简单战斗),写入了一些常用战斗模式,欢迎大家使用并指出问题。
脚本基于图像处理和键鼠操作,使用电脑运行,并且有合格的键鼠混淆机制,几乎没有封号的风险
脚本使用指令操作,具体指令请结合示例和代码学习或者向作者询问
脚本语言为 \text{python},运行时需要有完整的 \text{python} 开发和调试环境,并安装 \text{pyautogui},\text{keyboard},\text{opencv2}
脚本支持的模拟器为雷电和夜神
脚本运行时可能需要避免广告遮挡内容
如果需求更好的运行稳定性,请自行上线已经完成的错误检查功能
主体代码
from cv2 import calcBackProject, error, pencilSketch, warpPerspective
import pyautogui as pg
import keyboard as kd
import supporter as sp
import sys
import os
import getPath
import work
import time
characterDistance = 63
windowBox = (0,0,0,0)
# 以上是常量
workPagePath = [""]
characterPagePath = [""]
nodePagePath = [""]
operationPagePath = [""]
fightPagePath = [""]
teamPagePath = [""]
repairPagePath = [""]
formationPagePath = [""]
destroyPagePath = [""]
# 以上是图片路径
equipmentType = 1
windowPos = 0
windowDx = [0,813,500]
windowDy = [0,40,40]
statu = 2
workQueue=work.workQueue
commanding = 0
lastFightCount = 0
fullDock = 0
errorExisted = 0
initialDir = ""
# 以上是工作状态
Tod = 0 #3-3 打捞
Tob = 0 #4-3 偷铝
cnt = 0
def command():
global statu,commanding
statu = 1 ; commanding = 1
os.system("cls")
print("请输入指令:")
print("0:退出,继续执行脚本")
print("1:关闭脚本")
print("2:查看工作队列")
print("3:编辑工作队列")
x=input()
if(sp.isIntenger(x)==False):
print("无法识别的参数,请重新输入")
command()
x=int(x)
if(x<0 or x>3):
print("不存在该命令,请重新输入")
if(x == 0):
statu = 2 ; commanding = 0
return
if(x == 1):
statu = 0
return
if(x == 2):
work.printWorkQueue()
if(x == 3):
work.editWorkQueue()
time.sleep(1)
command()
# 相当于是一起执行两个函数,只有暂停后才会停止工作
# def closeNotice():
def pageExistEasy(path, c = 0.9):
return pg.locateOnScreen(path,confidence = c) != None
def getWindowPosition():
global windowPos,windowBox
while(pageExistEasy(workPagePath[equipmentType+3]) == False):
print("未发现工作页面,请确保已开启模拟器,并且只打开了 战舰少女R")
windowPos = pg.locateCenterOnScreen(workPagePath[equipmentType+3],confidence = 0.9)
print("windospos:",windowPos)
windowBox = (windowPos.x-windowDx[equipmentType],windowPos.y-windowDy[equipmentType],1040,620)
def init():
global initialDir
initialDir = os.getcwd()
kd.hook(keyboardCommand)
getPath.init()
global workPagePath,formationPagePath,repairPagePath,teamPagePath
global fightPagePath,characterPagePath,nodePagePath,operationPagePath
global destroyPagePath
workPagePath = getPath.workPagePath
teamPagePath = getPath.teamPagePath
fightPagePath = getPath.fightPagePath
repairPagePath = getPath.repairPagePath
formationPagePath = getPath.formationPagePath
characterPagePath = getPath.characterPagePath
nodePagePath = getPath.nodePagePath
operationPagePath = getPath.operationPagePath
destroyPagePath = getPath.destoryPagePath
getWindowPosition()#1288
def pageExist(path,c = 0.9):
return pg.locateOnScreen(path,region = windowBox ,confidence = c) != None
def clickEasy(path,c = 0.9):
global windowPos
pos = pg.locateCenterOnScreen(path,confidence = c)
pg.click(pos.x,pos.y,duration = 0.25)
def restart():
global errorExisted
errorExisted = 1
if(equipmentType == 1):
os.system("taskkill -f -im dnplayer.exe")
os.chdir(r"E:\LeiDian\LDPlayer4.0")
os.popen(r".\dnplayer.exe")
if(equipmentType == 2):
os.system("taskkill -f -im Nox.exe")
os.chdir(r"D:\Program Files\Nox\bin")
os.popen(r".\Nox.exe")
os.chdir(initialDir)
getWindowPosition()
for i in range(1,100):
time.sleep(1)
if(pageExist(workPagePath[6],0.7)):
time.sleep(1)
clickEasy(workPagePath[6],0.7)
break
for i in range(1,100):
time.sleep(1)
if(pageExist(workPagePath[7])):
time.sleep(1)
clickEasy(workPagePath[7])
break
def click(path,c = 0.9,errorAllowed = 1,maxiumTimeAllowed = 10,dx = 0,dy = 0):
if(errorExisted):
return
global windowPos
cnt = 0
while(pageExist(path,c) == False and cnt <= maxiumTimeAllowed * 2):
cnt += 1
time.sleep(0.5)
print(cnt)
if(cnt > maxiumTimeAllowed * 2):
if(errorAllowed):
print("PNF")
return
else:
print("path:",path,"restart in click")
restart()
return
time.sleep(0.2)
pos = pg.locateCenterOnScreen(path,confidence = c,region = windowBox)
pg.click(pos.x+dx,pos.y+dy,duration = 0.15)
def waitPage(path,c = 0.9,maxiumTimeAllowed = 10, errorAllowed = 1):
if(errorExisted):
return
cnt = 0
while(pageExist(path,c) == False and cnt <= maxiumTimeAllowed * 2):
time.sleep(0.5);cnt+=1
print(cnt)
if(cnt > maxiumTimeAllowed * 2):
if(errorAllowed == 1):
print("PNF")
return False
else:
print("path:",path,"restart in waitPage")
restart()
return False
return True
def clickByposition(pos,dx,dy):
if(errorExisted):
return
if(pos == None):
print("restart in clickByPosition")
restart()
return
time.sleep(0.2)
pg.click(pos.x+dx,pos.y+dy,duration = 0.25)
def closeEveryDayBounds():
click(operationPagePath[14],0.87,1,1.5)
def keyboardCommand(x):
if(x.name == 'c' and x.event_type == 'down'):
print("You pressed C")
if(x.name=='c' and x.event_type=='down' and commanding == 0):
print("entered command page")
command()
def testSpecialMod(chp,nod,mod):
global Tod,Tob
if(chp == 3 and nod == 3 and mod == 1):
if(pageExist(fightPagePath[13],0.97)):
print("In node 3-3 with mod 1,Entered node D")
Tod = 1
if(chp == 4 and nod == 3 and mod == 1):
if(pageExist(fightPagePath[21],0.97)):
print("In node 4-3 with mod 1,Entered node B")
Tob = 1
def clickToContinue():
click(operationPagePath[12],0.8,0)
def getPage():
time.sleep(2)
if(pageExist(workPagePath[1])):
return 1
if(pageExist(workPagePath[2])):
return 2
if(pageExist(workPagePath[3])):
return 3
return 0
def getCharcter():
for i in range (1,9):
if(pageExist(characterPagePath[i])):
return i
restart()
def moveCharacter(target):
characterNow = getCharcter()
if(errorExisted):
return
print("nowcharacter:",characterNow)
pos = pg.locateCenterOnScreen(characterPagePath[characterNow],confidence=0.9)
if(characterNow > target):
for i in range(1,characterNow-target+1):
clickByposition(pos,0,-characterDistance)
time.sleep(2)
else :
for i in range(1,target-characterNow+1):
clickByposition(pos,0,characterDistance)
time.sleep(2)
def getNode():
global nodePagePath
for i in range(1,7):
if(pageExist(nodePagePath[i],0.95)):
return i
restart()
# 检测节点的延时外置
def moveNode(target):
nowNode=getNode()
print("nowNode:",nowNode)
if(errorExisted):
return
pos=pg.locateCenterOnScreen(nodePagePath[nowNode],confidence=0.95)
print(pos)
if(target>nowNode):
for i in range (1,target-nowNode+1):
pg.moveTo(pos.x,pos.y,duration = 1)
pg.dragTo(pos.x-100,pos.y,duration=1)
time.sleep(1)
else:
for i in range (1,nowNode-target+1):
pg.moveTo(pos.x,pos.y,duration = 1)
pg.dragTo(pos.x+100,pos.y,duration = 1)
time.sleep(1)
time.sleep(1)
def moveTeam(team):
print("teamShouldBe:",team)
if(waitPage(teamPagePath[team+4],0.95,2)):
return
else:
click(teamPagePath[team],0.95,0)
def quitToMainPage():
if(errorExisted):
return
global lastFightCount
lastFightCount = 0;cnt = 0
while(pageExist(operationPagePath[2],0.6) == False or pageExist(destroyPagePath[2]) == True):
click(operationPagePath[1],0.9,1,0)
click(repairPagePath[5],0.9,1,0)
cnt += 1
if(cnt > 30):
restart()
print("step 2")
closeEveryDayBounds()
def destroyShip():
quitToMainPage()
click(destroyPagePath[1],0.65,0)# 注意这里白天黑夜的影响
click(destroyPagePath[2],0.9,0)
click(destroyPagePath[3],0.9,0)
click(destroyPagePath[4],0.9,0)
click(destroyPagePath[5],0.9,0)
click(destroyPagePath[6],0.9,0)
pos = pg.locateCenterOnScreen(destroyPagePath[7])
time.sleep(0.5);clickByposition(pos,40,150)
time.sleep(0.5);clickByposition(pos,150,150)
time.sleep(0.5);clickByposition(pos,260,150)
time.sleep(0.5);clickByposition(pos,370,150)
time.sleep(0.5);clickByposition(pos,480,150)
click(destroyPagePath[8],0.9,0)
click(destroyPagePath[9],0.9,0)
time.sleep(1.5)
if(pageExist(destroyPagePath[10])):
click(destroyPagePath[11],0.9,1)
def enterMapPage(): #从非战斗界面进入s
click(operationPagePath[2],0.6,0)
waitPage(workPagePath[2],0.9,10,0)
def enterRepairPage():# 从整备界面进入
click(operationPagePath[4],0.9,0)
def repairShips():# 在修理界面
# enterRepairPage()
time.sleep(2)
while(pageExist(repairPagePath[6]) or pageExist(repairPagePath[7]) or pageExist(repairPagePath[8])):
click(repairPagePath[6],0.9,1,0,20,-100)
time.sleep(2)
click(repairPagePath[7],0.9,1,0,20,-100)
time.sleep(2)
click(repairPagePath[8],0.9,1,0)
time.sleep(2)
def enterPreparePage():#从修理界面进入
click(operationPagePath[5],0.9,0)
def gainBounds():
quitToMainPage()
click(operationPagePath[10],0.8,0)
while(waitPage(operationPagePath[9],0.9,1.5)):
click(operationPagePath[9],0.9,0)
click(operationPagePath[11],0.9,0)
def enterPreparePageFromMapPage():
# 这里需要检查是否进入了远征界面
waitPage(workPagePath[2])
pos = pg.locateCenterOnScreen(workPagePath[2],confidence=0.9)
if(pageExist(operationPagePath[6])):
expedition()
enterMapPage()
enterPreparePageFromMapPage()
else:
clickByposition(pos,0,300)
waitPage(operationPagePath[4])
def expedition():
quitToMainPage()
enterMapPage()
while(waitPage(operationPagePath[6],0.9,2)):
click(operationPagePath[6],0.9,0)
clickToContinue()
click(operationPagePath[13],0.9,0)
quitToMainPage()
def shouldFight(chp,nod,cnt,mod):
# 在阵型界面
# cnt 为当前战数
# 2-1 战利品策略
global Tod,Tob
if(chp == 2 and nod == 1 and mod == 1 and pageExist(fightPagePath[16],0.8)):
return False
# 3-3 赤城打捞策略
if(cnt == 2 and chp == 3 and nod == 3 and mod == 1 and Tod == 0):
return False
# 4-3 偷铝策略
if(chp == 4 and nod == 3 and mod == 1 and (Tob == 0 or cnt == 2 or pageExist(fightPagePath[22]) == False)):
return False
# 5-3 偷钢策略
if(chp == 5 and nod == 3 and mod == 1 and (cnt == 2 or pageExist(fightPagePath[23]) == False)):
return False
# 6-1 炸鱼策略
if(chp == 6 and nod == 1 and mod != 0):
if(mod == 1 and pageExist(fightPagePath[19],0.95) == False):# 6SS
return False
if(mod == 2 and pageExist(fightPagePath[17],0.95) == False):# CLT
return False
if(mod == 3 and pageExist(fightPagePath[18],0.95) == False):# CLV
return False
if(mod == 4 and pageExist(fightPagePath[4],0.95) == False):# 所有
return False
# 8-1 炸鱼
if(chp == 8 and nod == 1 and mod ==1):
if(pageExist(fightPagePath[12]) == False):
return False
return True
def chooseNextOperation(chp,nod,cnt,mod):
# 6-1 炸鱼策略
if(mod>0 and chp == 6 and nod == 1):
return False
# 8-1 炸鱼策略
if(mod>0 and chp == 8 and nod ==1):
return False
# 四战/大破后不继续打
if(cnt>=4 or pageExist(fightPagePath[15],0.8)):
return False
return True
def SSexist():
return (pageExist(fightPagePath[3],0.95) or pageExist(fightPagePath[4],0.95) or pageExist(fightPagePath[11],0.95))
def shouldFightInNight(chp,nod,cnt,mod):
if(cnt == 4) :
return 1
if(chp == 9) :
return 1
# 战役的打法
return 0
def fightInSingleNode(chp,nod,cnt,mod,formation):
# 阵型选择
global errorExisted
if(errorExisted):
return
print("formation:",formation)
val = shouldFightInNight(chp,nod,cnt,mod)
click(formationPagePath[formation],0.9,0)
# 昼战
for i in range(1,100):
time.sleep(0.75)
if(pageExist(operationPagePath[12])):
pos=pg.locateCenterOnScreen(operationPagePath[12],confidence=0.9)
time.sleep(1)
clickToContinue()
time.sleep(0.5);clickByposition(pos,0,0)
time.sleep(0.5);clickByposition(pos,0,0)
return
if(pageExist(fightPagePath[8])):
click(fightPagePath[8-val],0.9,0)
break
# 夜战
for i in range(1,100):
time.sleep(0.75)
if(pageExist(operationPagePath[12])):
pos=pg.locateCenterOnScreen(operationPagePath[12],confidence=0.9)
time.sleep(1)
clickToContinue()
time.sleep(0.5);clickByposition(pos,0,0)
time.sleep(0.5);clickByposition(pos,0,0)
return
print("Fighting has been end unnormal,restarting...")
restart()
def fight(chp,nod,team,mod):
global Tod,Tob,lastFightCount,fullDock
formation = 0
if(lastFightCount == 0):
quitToMainPage()
print("quited")
enterMapPage()
# 是否进入了远征界面
time.sleep(1)
if(pageExist(operationPagePath[6])):
print("Found Expedition Page!!!")
expedition()
enterMapPage()
moveCharacter(chp)
moveNode(nod)
enterPreparePageFromMapPage()
moveTeam(team)
if(pageExist(repairPagePath[7]) or pageExist(repairPagePath[6]) or pageExist(repairPagePath[8])):
enterRepairPage()
repairShips()
enterPreparePage()
if(errorExisted):
return
# 初始化战斗参数
lastFightCount += 1;Tob = Tod = 0;formation = 0
# 调整到战斗界面
if(waitPage(fightPagePath[20],0.95,0)):
formation = 4
click(operationPagePath[3])
cnt = 0
print("fight start")
while(1):#索敌失败会有锅
# 等待进入选择界面
for i in range(1,50):
time.sleep(0.5)
if(cnt == 0 and pageExist(destroyPagePath[12],0.9)):
fullDock = 1
return
testSpecialMod(chp,nod,mod)
if(pageExist(fightPagePath[1]) or pageExist(fightPagePath[5]) or pageExist(formationPagePath[1])):
if(pageExist(fightPagePath[5])):
click(fightPagePath[5],0.9,0)
# 有资源就点击
else :
break
else :
if(cnt == 0 and nod == 1):
if(equipmentType == 1):
clickByposition(windowPos,-313,100)
else:
clickByposition(windowPos,0,100)
cnt += 1;lastFightCount += 1
if(formation != 4):
formation = 2
if(SSexist() and formation != 4):
formation = 5
# 决策阵型
if(waitPage(fightPagePath[1],0.9,2)):
if(shouldFight(chp,nod,cnt,mod)):
click(fightPagePath[1],0.9,0)
else :
click(fightPagePath[2],0.9,0)
break
else:
print("FailToGetEnemy")
restart()
# 索敌失败就直接退出,不做任何决策
fightInSingleNode(chp,nod,cnt,mod,formation)
# 进入单点战斗决策
if(waitPage(fightPagePath[9],0.9,2,1)):
pass
else:
if(waitPage(workPagePath[2],0.9,2.5)):
break
# 该地图是否已经自动结束
if(chooseNextOperation(chp,nod,cnt,mod)):
click(fightPagePath[9],0.9,0)
else:
click(fightPagePath[10],0.9,0)
break
# 进行战斗后的下一步决策,默认四战结束,后期会加入设置战术
# 回退
def repairByBothroom():
if(errorExisted):
return
quitToMainPage()
enterMapPage()
enterPreparePageFromMapPage()
click(repairPagePath[1],0.8,0)
click(repairPagePath[2],0.8,0)
time.sleep(2)
pos = pg.locateCenterOnScreen(repairPagePath[3],confidence=0.9)
clickByposition(pos,0,250)
time.sleep(2)
click(repairPagePath[4],0.9,1,5)
quitToMainPage()
def doWork():
if(len(workQueue) == 0) :
print("工作队列为空")
return
p = workQueue[0].parameterList
if(p[0]==1):
print("节点",p[1],"-",p[2])
print(p[3],"队")
fight(p[1],p[2],p[3],p[4])
p[-1] -= 1
if(p[-1] == 0):
del workQueue[0]
def run():
global fullDock,errorExisted,lastFightCount
printed = 0
for i in range (1,10000):
if(errorExisted):
errorExisted = 0
quitToMainPage()
time.sleep(1)
if(statu == 0):
print("脚本正在关闭")
break
if(statu == 1):
if(printed == 0):
print("脚本已暂停")
quitToMainPage()
printed = 1
continue
if(pageExist(workPagePath[4]) == False and pageExist( workPagePath[5] ) == False ):
print("未发现工作页面,请确保已开启模拟器,并且只打开了 战舰少女R")
continue
if(statu == 2):
printed = 0
print("正在工作")
doWork()
if(lastFightCount >= 30 or i == 5):
print("正在进行远征,任务,舰船修复检查,请勿操作")
gainBounds()
repairByBothroom()
expedition()
print("远征,任务,舰船修复检查已结束")
if(fullDock > 0):
destroyShip()
fullDock = 0
init()
lastFightCount = 0
command()
run()
print("结束运行")
完整的运行包:
请联系作者获取