Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 59 additions & 17 deletions module/coalition/coalition_scuttle.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,14 @@ class CoalitionScuttleCombat(CoalitionCombat):

def auto_search_combat_execute(self, emotion_reduce=True, fleet_index=1, expected_end=None):
"""
重写自动搜索战斗执行,D评价沉船时不额外扣减10心情
重写自动搜索战斗执行,联盟沉船不额外扣减心情

进入战斗扣减2心情(正常出击代价),D评价不执行 shipwreck=True 的额外扣减。
联盟沉船中一个关卡包含多次战斗(1/2/3/4队),
但游戏只在整个关卡进入时扣1次2点心情,不按内部战斗次数扣减。
D评价也不执行 shipwreck=True 的额外扣减。

Args:
emotion_reduce (bool): 是否扣减心情。
emotion_reduce (bool): 是否扣减心情(仅在第一场战斗时为True)
fleet_index (int): 舰队编号。
expected_end (callable): 自定义结束条件。
"""
Expand All @@ -41,7 +43,8 @@ def auto_search_combat_execute(self, emotion_reduce=True, fleet_index=1, expecte
self.device.stuck_record_clear()
self.device.click_record_clear()

# 进入战斗扣减2心情(正常出击代价)
# 联盟沉船仅在第一场战斗时扣减2心情(关卡进入代价)
# 后续战斗(2/3/4队)不再扣减,与游戏服务端行为一致
if emotion_reduce:
self.emotion.reduce(fleet_index)

Expand Down Expand Up @@ -81,7 +84,7 @@ def auto_search_combat_execute(self, emotion_reduce=True, fleet_index=1, expecte
if self.handle_get_ship():
continue

# D评价沉船:不执行 emotion.reduce(shipwreck=True)
# D评价沉船:不额外扣减心情
if self.appear_then_click(OPTS_INFO_D, offset=(30, 30), interval=2):
self._withdraw = True
self._is_shipwreck = True
Expand All @@ -97,11 +100,10 @@ def auto_search_combat_execute(self, emotion_reduce=True, fleet_index=1, expecte
confirm_timer.reset()
break

# A/B评价正常扣减心情
# A/B/S评价:联盟沉船中不额外扣减心情
# 游戏服务端只在整个关卡进入时扣1次2点,不按战斗结算类型扣减
if self.appear(BATTLE_STATUS_A) or self.appear(BATTLE_STATUS_B) \
or self.appear(EXP_INFO_A) or self.appear(EXP_INFO_B):
if emotion_reduce:
self.emotion.reduce(fleet_index, shipwreck=True)
break

# S评价或自动搜索运行中
Expand All @@ -117,21 +119,23 @@ def auto_search_combat_execute(self, emotion_reduce=True, fleet_index=1, expecte

def coalition_combat(self):
"""
联盟沉船战斗执行,进入战斗扣减2心情,D评价不额外扣减
联盟沉船战斗执行,仅在第一场战斗扣减2心情

原因:沉船任务中舰船被击沉后需要换新船,不应扣减额外心情。
联盟沉船一个关卡包含多次战斗(1/2/3/4队),
但游戏只在整个关卡进入时扣1次2点心情,后续战斗不再扣减。
"""
from module.exception import CampaignEnd

self.battle_count = 0
self.combat_preparation(emotion_reduce=False) # 不在此扣减,由 auto_search_combat_execute 统一扣减
self.combat_preparation(emotion_reduce=False)

try:
while 1:
logger.hr(f'{self.FUNCTION_NAME_BASE}{self.battle_count}', level=2)
self._is_shipwreck = False # 重置沉船标记
self._is_shipwreck = False
# 仅第一场战斗扣减2心情(关卡进入代价),后续战斗不再扣减
self.auto_search_combat_execute(
emotion_reduce=True, # 进入战斗扣减2心情
emotion_reduce=self.battle_count == 0,
fleet_index=1,
expected_end=self.auto_search_combat_end
)
Expand Down Expand Up @@ -247,7 +251,7 @@ def coalition_combat_re_enter(self, skip_first_screenshot=True):


class CoalitionScuttleRun(Coalition, CoalitionScuttleCombat):
"""联盟沉船主循环,沉船任务不扣减心情。"""
"""联盟沉船主循环,沉船任务进入关卡只扣1次2点心情。"""

def handle_combat_low_emotion(self):
"""
Expand All @@ -257,15 +261,53 @@ def handle_combat_low_emotion(self):
"""
return self.handle_popup_confirm('IGNORE_LOW_EMOTION')

def coalition_execute_once(self, event, stage, fleet):
"""执行一次联盟沉船战斗。

覆盖父类方法,将心情预估从多场战斗改为1场(整个关卡只扣1次2点)。
联盟沉船虽然内部有多次战斗(1/2/3/4队),但游戏只在整个关卡进入时扣1次心情。

Args:
event: 活动名称。
stage: 关卡名称。
fleet: 舰队模式。
"""
self.config.override(
Campaign_Name=f'{event}_{stage}',
Campaign_UseAutoSearch=False,
Fleet_FleetOrder='fleet1_all_fleet2_standby',
)
if self.config.Coalition_Fleet == 'single' and self.config.Emotion_Fleet1Control == 'prevent_red_face':
logger.warning('AL does not allow single coalition with emotion < 30, '
'emotion control is forced to prevent_yellow_face')
self.config.override(Emotion_Fleet1Control='prevent_yellow_face')
if stage == 'sp':
self.config.override(Coalition_Fleet='multi')

# 联盟沉船:整个关卡只扣1次2点心情,不按内部战斗次数预估
try:
self.emotion.check_reduce(battle=1)
except ScriptEnd:
self.coalition_map_exit(event)
raise

if self._coalition_has_oil_icon and self.triggered_stop_condition(oil_check=True, coin_check=True):
self.coalition_map_exit(event)
raise ScriptEnd

self.enter_map(event=event, stage=stage, mode=fleet)
self.coalition_combat()

def triggered_stop_condition(self, oil_check=False, pt_check=False, coin_check=False):
"""
检查是否触发了停止条件,在父类基础上增加沉船正常结束检测。
检查是否触发了停止条件。

联盟沉船不因 triggered_normal_end(舰船被击沉)而停止任务,
由 RunCount 控制何时停止。D评价和非D评价都算1次有效战斗。

Returns:
bool: 是否触发了停止条件。
"""
if self.triggered_normal_end:
return True
if super().triggered_stop_condition(oil_check=oil_check, pt_check=pt_check, coin_check=coin_check):
return True

Expand Down
59 changes: 43 additions & 16 deletions module/combat/emotion.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,16 +168,20 @@ def max(self):
def update(self):
"""根据实际经过时间计算情绪恢复。

使用连续时间恢复计算,而非离散6分钟区间。
原方法使用 // 360 计算恢复次数,当 record() 频繁重置时间戳时
(如联盟沉船每2分钟调用一次),恢复永远无法累积。
改为按实际秒数计算恢复量,与游戏服务端行为一致。
"""
time_diff = int(current_time().timestamp()) - int(self.record.timestamp())
使用连续时间恢复计算,保留浮点恢复量以累积分数部分。
游戏服务端按实际经过时间精确计算恢复,每6分钟恢复speed点。
旧方法用 int() 截断恢复量,每次 record() 重置时间戳后,
未满1点的恢复余数被丢弃,长时间运行导致严重低估。
现改为 floor() 取整保留整数部分,同时 record() 仅在整数变化时
重置时间戳并回扣分数秒,确保余数可跨次累积。
"""
time_diff = current_time().timestamp() - self.record.timestamp()
time_diff = max(time_diff, 0)
# speed 为每360秒的恢复量,换算为每秒恢复 speed/360 点
recovery = self.speed * time_diff / 360
self.current = min(max(self.value, 0) + int(recovery), self.max)
# 保留未满1点的恢复余数对应的秒数,用于 record() 回扣
self._fractional_seconds = recovery - int(recovery)

def get_recovered(self, expected_reduce=0):
"""计算情绪恢复到控制阈值的时间。
Expand Down Expand Up @@ -268,25 +272,48 @@ def update(self):
fleet.update()

def record(self):
"""将当前情绪值保存到配置中。"""
"""将当前情绪值保存到配置中。

仅在心情整数值发生变化时更新 Record 时间戳,
并将 Record 回扣 fractional_seconds 对应的等效秒数,
使未满1点的恢复余数可在下次 update() 时继续累积。
"""
if self.using_public:
value = {self.public_fleet.value_name: self.public_fleet.current}
self.config.set_record(**value)
fleet = self.public_fleet
old_value = fleet.value
new_value = fleet.current
# 仅在整数变化时重置时间戳,回扣分数秒
if new_value != old_value:
record_time = current_time().replace(microsecond=0)
fractional = getattr(fleet, '_fractional_seconds', 0)
if fractional > 0:
# 回扣 fractional_seconds 对应的秒数
record_time = record_time - timedelta(seconds=fractional * 360 / fleet.speed)
with self.config.multi_set():
setattr(self.config, fleet.value_name, new_value)
setattr(self.config, fleet.value_name.replace('Value', 'Record'), record_time)
return

value = {}
for fleet in self.fleets:
value[fleet.value_name] = fleet.current

self.config.set_record(**value)
with self.config.multi_set():
for fleet in self.fleets:
old_value = fleet.value
new_value = fleet.current
if new_value != old_value:
record_time = current_time().replace(microsecond=0)
fractional = getattr(fleet, '_fractional_seconds', 0)
if fractional > 0:
record_time = record_time - timedelta(seconds=fractional * 360 / fleet.speed)
setattr(self.config, fleet.value_name, new_value)
setattr(self.config, fleet.value_name.replace('Value', 'Record'), record_time)

def show(self):
"""显示当前计算的心情值(含时间恢复),而非上次保存值。"""
if self.using_public:
logger.attr(f'情绪公海舰队', self.public_fleet.value)
logger.attr(f'情绪公海舰队', self.public_fleet.current)
return

for fleet in self.fleets:
logger.attr(f'情绪舰队_{fleet.fleet}', fleet.value)
logger.attr(f'情绪舰队_{fleet.fleet}', fleet.current)

@property
def reduce_per_battle(self):
Expand Down
Loading