mirror of
https://github.com/LmeSzinc/StarRailCopilot.git
synced 2024-11-30 11:19:30 +00:00
131 lines
3.8 KiB
Python
131 lines
3.8 KiB
Python
|
import numpy as np
|
||
|
|
||
|
from module.base.base import ModuleBase
|
||
|
from module.base.button import color_similar
|
||
|
from module.logger import logger
|
||
|
|
||
|
# Location of six HP bar.
|
||
|
LOCATION = [
|
||
|
(36, 195),
|
||
|
(36, 295),
|
||
|
(36, 395),
|
||
|
(36, 497),
|
||
|
(36, 597),
|
||
|
(36, 697)
|
||
|
]
|
||
|
# HP bar size.
|
||
|
SIZE = (67, 4)
|
||
|
# Color that shows on HP bar.
|
||
|
COLOR_HP_GREEN = (156, 235, 57)
|
||
|
COLOR_HP_RED = (99, 44, 24)
|
||
|
# If difference greater than this, change position.
|
||
|
SCOUT_HP_DIFFERENCE_THRESHOLD = 0.2
|
||
|
SCOUT_POSITION = [
|
||
|
(403, 421),
|
||
|
(625, 369),
|
||
|
(821, 326)
|
||
|
]
|
||
|
# Give a normal distribution random offset when swiping to a point.
|
||
|
# (x_min, y_min, x_max, y_max).
|
||
|
POINT_OFFSET = (0, 0, 0, 0)
|
||
|
# Give a normal distribution random offset when moving up and down.
|
||
|
# (x_min, y_min, x_max, y_max).
|
||
|
UP_OFFSET = (0, 10, 0, 10)
|
||
|
DOWN_OFFSET = (0, -10, 0, -10)
|
||
|
|
||
|
|
||
|
class HPBalancer(ModuleBase):
|
||
|
hp = []
|
||
|
_scout_order = (0, 1, 2)
|
||
|
|
||
|
def _calculate_hp(self, location, size):
|
||
|
"""Calculate hp according to color.
|
||
|
|
||
|
Args:
|
||
|
location (tuple): Upper right of HP bar. (x, y)
|
||
|
size (tuple): Size of HP bar. (x, y)
|
||
|
|
||
|
Returns:
|
||
|
float: HP.
|
||
|
"""
|
||
|
area = np.append(np.array(location), np.array(location) + np.array(size))
|
||
|
data = self.image.crop(area).resize((size[0], 1))
|
||
|
data = [
|
||
|
color_similar(pixel, COLOR_HP_GREEN) or color_similar(pixel, COLOR_HP_RED)
|
||
|
for pixel in np.array(data)[0]
|
||
|
]
|
||
|
data = np.sum(data) / size[0]
|
||
|
return data
|
||
|
|
||
|
def get_hp(self):
|
||
|
"""Get current HP from screenshot.
|
||
|
|
||
|
Returns:
|
||
|
list: HP(float) of 6 ship.
|
||
|
"""
|
||
|
self.hp = [self._calculate_hp(loca, SIZE) for loca in LOCATION]
|
||
|
logger.info(
|
||
|
'HP:' + ' '.join([str(int(data*100)).rjust(3)+'%' for data in self.hp])
|
||
|
)
|
||
|
return self.hp
|
||
|
|
||
|
def scout_position_change(self, p1, p2):
|
||
|
"""Exchange KAN-SEN's position.
|
||
|
It need to move up and down a little, even though it moves to the right location.
|
||
|
|
||
|
Args:
|
||
|
p1 (int): Origin position [0, 2].
|
||
|
p2 (int): Target position [0, 2].
|
||
|
"""
|
||
|
logger.info('scout_position_change (%s, %s)' % (p1, p2))
|
||
|
p1 = self.drag_node(SCOUT_POSITION[p1], POINT_OFFSET, 0.25)
|
||
|
p2 = self.drag_node(SCOUT_POSITION[p2], POINT_OFFSET, 0.1)
|
||
|
path = [
|
||
|
p1,
|
||
|
p2,
|
||
|
self.drag_node(p2[:2], UP_OFFSET, 0.1),
|
||
|
self.drag_node(p2[:2], DOWN_OFFSET, 0.1),
|
||
|
p2
|
||
|
]
|
||
|
self.drag(path)
|
||
|
|
||
|
@staticmethod
|
||
|
def _expected_scout_order(hp):
|
||
|
descending = np.sort(hp)[::-1]
|
||
|
sort = np.argsort(hp)[::-1]
|
||
|
|
||
|
if descending[0] - descending[2] > SCOUT_HP_DIFFERENCE_THRESHOLD:
|
||
|
if descending[1] - descending[2] > SCOUT_HP_DIFFERENCE_THRESHOLD:
|
||
|
# 100% 70% 40%
|
||
|
order = [sort[0], sort[2], sort[1]]
|
||
|
else:
|
||
|
# 100% 70% 60%
|
||
|
order = [sort[0], 1, 2]
|
||
|
order[sort[0]] = 0
|
||
|
else:
|
||
|
# 80% 80% 80%
|
||
|
order = [0, 1, 2]
|
||
|
return order
|
||
|
|
||
|
@staticmethod
|
||
|
def _gen_exchange_step(origin, target):
|
||
|
diff = np.array(target) - np.array(origin)
|
||
|
count = np.count_nonzero(diff)
|
||
|
if count == 3:
|
||
|
yield (0, 2)
|
||
|
if np.argsort(target)[0] - np.argsort(origin)[0] == 1:
|
||
|
yield (1, 2)
|
||
|
else:
|
||
|
yield (0, 1)
|
||
|
elif count == 2:
|
||
|
yield tuple(np.nonzero(diff)[0])
|
||
|
elif count == 0:
|
||
|
# Target is the same as origin. Do nothing
|
||
|
pass
|
||
|
|
||
|
def balance_scout_hp(self):
|
||
|
target = self._expected_scout_order(self.hp[3:])
|
||
|
for step in self._gen_exchange_step(self._scout_order, target):
|
||
|
self.scout_position_change(*step)
|
||
|
self.sleep(0.5)
|