优化选择强化逻辑

This commit is contained in:
2026-04-26 19:30:32 +08:00
parent 34c36306fe
commit a5747ff55c
6 changed files with 280 additions and 72 deletions
+183 -51
View File
@@ -695,68 +695,152 @@ void TDrawScreen(HDC hdc, HWND hWnd)
};
const TCHAR* categoryTexts[8] =
{
_T("赏金纹章:得分+20%,可叠加\r\n成长印记:EXP+25%,可叠加\r\n缓坠羽翼:自然下落变慢\r\n连击律动:连续消行追加奖励\r\n先见之眼:下一方块预览+1"),
_T("最后一搏:首次濒死清底3行\r\n备用仓:C / Shift 暂存方块\r\n完美旋转:旋转受阻时左右修正\r\n时间缓流:堆叠自动减速\r\n空中换形:V 将当前方块变 I"),
_T("卸压清场:立刻清最高占用行\r\n底线清道夫:消行充能后清底\r\n清屏炸弹:X 清底5行,消行充能\r\n黑洞奇点:Z 吞噬数量最多的方块"),
_T("爆破核心:橙红边框,落地清 3x3\r\n棱镜激光:青色边框,按落地中心清整\r\n十字方块:绿色边框,按落地中心清行列\r\n彩虹方块:清中心行主色覆盖行染场上主色\r\n方块改造:提高 I 块生成概率"),
_T("连锁火花:消行后追加随机破坏\r\n连环炸弹:爆破扩大为 5x5\r\n雷霆四消:三消/四消额外轰击\r\n雷霆棱镜:三消/四消追加激光"),
_T("狂热节拍:累计12行进入狂热\r\n怒火连段:连击越高倍率越高\r\n无尽狂热:狂热中消行延时\r\n高压悬赏:更快但收益更高\r\n豪赌四消 / 极限玩家:偏向四消爆发"),
_T("双重抉择:升级可多选1个\r\n命运轮盘:6选2但含诅咒\r\n升级冲击波:升级后清底2行\r\n进化冲击:升级后清底3行\r\n成长核心:永久得分/EXP +15%"),
_T("操控大师:Hold 后减速并预览+1\r\n方块风暴:接下来5个全 I 块\r\n稳定结构:概率填局部小洞\r\n虚空核心:黑洞生成彩虹,彩虹生效追加小黑洞\r\n赌徒契约:强化20%翻倍/20%落空,收益波动")
_T("赏金纹章:所有得分收益提高 20%,可重复叠加,是最直接的分数成长。\r\n成长印记:所有 EXP 收益提高 25%,可重复叠加,用来更快进入后续构筑。\r\n缓坠羽翼:降低自然下落速度,最多叠加 4 次。\r\n连击律动:连续消行追加得分和 EXP,断连后重新累计。\r\n先见之眼:额外显示 1 个后续方块;第三个预览由操控大师解锁。"),
_T("最后一搏:首次濒死时自动清理底部 3 行,并保留本局继续机会。\r\n备用仓:解锁 C / Shift,将当前方块放入 Hold 仓或取出备用方块\r\n完美旋转:旋转被阻挡时尝试左右修正,提高贴墙和缝隙旋转成功率。\r\n时间缓流:堆叠过高时自动减速,给危险局面留出处理时间。\r\n空中换形:V 将当前下落方块变 I 块,次数有限。"),
_T("卸压清场:获得时立刻清最高的一条占用行,直接降低顶部压力。\r\n底线清道夫:通过消行充能,充满后自动清理底部行。\r\n清屏炸弹:按 X 主动清理底部 5 行,需要通过消行充能后使用。\r\n黑洞奇点:Z 吞噬当前场上数量最多的一种颜色方块"),
_T("爆破核心:一次性解锁橙红边框方块,落地后以落点为中心清除 3x3 区域。\r\n棱镜激光:一次性解锁青色边框方块,按落地中心列清除整列固定方块。\r\n十字方块:一次性解锁绿色边框方块,按落地中心同时清除一行一列。\r\n彩虹方块:一次性解锁紫色边框方块,清中心行主色并把覆盖行染场上主色\r\n方块改造:提高指定方块出现概率,目前主要强化 I 块生成"),
_T("连锁火花:完成消行后追加随机破坏,适合配合稳定堆叠扩大收益。\r\n连环炸弹:强化爆破核心,将爆破范围从 3x3 扩大为 5x5\r\n雷霆四消:三消四消后追加雷击,额外清除局部方块。\r\n雷霆棱镜:三消四消追加激光清列,强化四消后的清场能力。"),
_T("狂热节拍:累计清除 12 行进入狂热,狂热期间收益更高。\r\n怒火连段:连击越高倍率越高,适合连续小消和稳定节奏。\r\n无尽狂热:狂热期间继续消行会延长狂热时间。\r\n高压悬赏:游戏速度更快,但高压下收益更高\r\n豪赌四消:四消收益更高,但非四消表现更不稳定。\r\n极限玩家:危险高度下获得更高收益,同时承担更高操作压力。\r\n赌徒契约:后续强化有概率翻倍或落空,每级提高概率,最多 4 级。"),
_T("双重抉择:升级时可额外选择 1 个强化,加快构筑成型。\r\n命运轮盘:升级变为 6 选 2,但选项中可能混入诅咒\r\n升级冲击波:每次升级后清理底部 2 行。\r\n进化冲击:升级后清理底部 3 行,是升级冲击波的进阶路线。\r\n成长核心:永久提高得分和 EXP 收益 15%"),
_T("操控大师:使用 Hold 后短暂减速,并额外增加预览能力。\r\n方块风暴:接下来 5 个方块都变为 I 块,适合冲四消或紧急清场。\r\n稳定结构:落地后概率填局部小洞,让场地更平整。\r\n虚空核心:黑洞生效后生成彩虹方块,彩虹生效时会追加小黑洞")
};
int columnGap = SS(18);
int rowGap = SS(14);
int columnWidth = (contentRect.right - contentRect.left - columnGap) / 2;
int rowHeight = (contentRect.bottom - contentRect.top - rowGap * 3) / 4;
int sectionGap = SS(18);
int titleHeight = SS(34);
int bodyPadding = SS(16);
int contentHeight = contentRect.bottom - contentRect.top;
int virtualHeight = 0;
SelectObject(hdc, bodyFont);
for (int i = 0; i < 8; ++i)
{
int column = i % 2;
int row = i / 2;
RECT calculateBodyRect =
{
contentRect.left + bodyPadding,
0,
contentRect.right - bodyPadding,
0
};
DrawText(hdc, categoryTexts[i], -1, &calculateBodyRect, DT_LEFT | DT_TOP | DT_WORDBREAK | DT_CALCRECT);
virtualHeight += titleHeight + (calculateBodyRect.bottom - calculateBodyRect.top) + sectionGap;
}
int maxHelpScroll = virtualHeight - contentHeight;
if (maxHelpScroll < 0)
{
maxHelpScroll = 0;
}
if (helpScrollOffset > maxHelpScroll)
{
helpScrollOffset = maxHelpScroll;
}
HRGN oldClipRegion = CreateRectRgn(0, 0, 0, 0);
int hasOldClipRegion = GetClipRgn(hdc, oldClipRegion);
HRGN contentClipRegion = CreateRectRgn(contentRect.left, contentRect.top, contentRect.right, contentRect.bottom);
SelectClipRgn(hdc, contentClipRegion);
int sectionTop = contentRect.top - helpScrollOffset;
for (int i = 0; i < 8; ++i)
{
RECT bodyCalculateRect =
{
contentRect.left + bodyPadding,
0,
contentRect.right - bodyPadding,
0
};
SelectObject(hdc, bodyFont);
DrawText(hdc, categoryTexts[i], -1, &bodyCalculateRect, DT_LEFT | DT_TOP | DT_WORDBREAK | DT_CALCRECT);
int bodyHeight = bodyCalculateRect.bottom - bodyCalculateRect.top;
RECT categoryRect =
{
contentRect.left + column * (columnWidth + columnGap),
contentRect.top + row * (rowHeight + rowGap),
contentRect.left + column * (columnWidth + columnGap) + columnWidth,
contentRect.top + row * (rowHeight + rowGap) + rowHeight
contentRect.left,
sectionTop,
contentRect.right,
sectionTop + titleHeight + bodyHeight + SS(12)
};
HPEN categoryPen = CreatePen(PS_SOLID, 1, RGB(232, 202, 215));
HBRUSH categoryBrush = CreateSolidBrush(RGB(255, 252, 250));
oldPen = (HPEN)SelectObject(hdc, categoryPen);
oldBrush = (HBRUSH)SelectObject(hdc, categoryBrush);
RoundRect(hdc, categoryRect.left, categoryRect.top, categoryRect.right, categoryRect.bottom, SS(16), SS(16));
SelectObject(hdc, oldBrush);
SelectObject(hdc, oldPen);
DeleteObject(categoryBrush);
DeleteObject(categoryPen);
if (categoryRect.bottom < contentRect.top || categoryRect.top > contentRect.bottom)
{
sectionTop += titleHeight + bodyHeight + sectionGap;
continue;
}
SetTextColor(hdc, titleColor);
SelectObject(hdc, bodyFont);
SelectObject(hdc, sectionFont);
RECT categoryTitleRect =
{
categoryRect.left + SS(16),
categoryRect.top + SS(10),
categoryRect.right - SS(16),
categoryRect.top + SS(34)
categoryRect.left,
categoryRect.top,
categoryRect.right,
categoryRect.top + titleHeight
};
DrawText(hdc, categoryNames[i], -1, &categoryTitleRect, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
HPEN categoryLinePen = CreatePen(PS_SOLID, 1, RGB(232, 202, 215));
oldPen = (HPEN)SelectObject(hdc, categoryLinePen);
MoveToEx(hdc, categoryRect.left, categoryTitleRect.bottom, nullptr);
LineTo(hdc, categoryRect.right, categoryTitleRect.bottom);
SelectObject(hdc, oldPen);
DeleteObject(categoryLinePen);
SetTextColor(hdc, RGB(86, 66, 80));
SelectObject(hdc, smallFont);
SelectObject(hdc, bodyFont);
RECT categoryBodyRect =
{
categoryRect.left + SS(16),
categoryRect.top + SS(40),
categoryRect.right - SS(16),
categoryRect.bottom - SS(10)
categoryRect.left + bodyPadding,
categoryTitleRect.bottom + SS(10),
categoryRect.right - bodyPadding,
categoryTitleRect.bottom + SS(10) + bodyHeight
};
DrawText(hdc, categoryTexts[i], -1, &categoryBodyRect, DT_LEFT | DT_TOP | DT_WORDBREAK);
sectionTop += titleHeight + bodyHeight + sectionGap;
}
if (hasOldClipRegion == 1)
{
SelectClipRgn(hdc, oldClipRegion);
}
else
{
SelectClipRgn(hdc, nullptr);
}
DeleteObject(contentClipRegion);
DeleteObject(oldClipRegion);
}
if (helpState.currentPage != 3)
{
DrawText(hdc, pageText, -1, &contentRect, pageFlags);
RECT calculateRect = { contentRect.left, contentRect.top, contentRect.right, contentRect.top };
DrawText(hdc, pageText, -1, &calculateRect, pageFlags | DT_CALCRECT);
int maxHelpScroll = (calculateRect.bottom - calculateRect.top) - (contentRect.bottom - contentRect.top);
if (maxHelpScroll < 0)
{
maxHelpScroll = 0;
}
if (helpScrollOffset > maxHelpScroll)
{
helpScrollOffset = maxHelpScroll;
}
HRGN oldClipRegion = CreateRectRgn(0, 0, 0, 0);
int hasOldClipRegion = GetClipRgn(hdc, oldClipRegion);
HRGN contentClipRegion = CreateRectRgn(contentRect.left, contentRect.top, contentRect.right, contentRect.bottom);
SelectClipRgn(hdc, contentClipRegion);
RECT scrolledContentRect = contentRect;
scrolledContentRect.top -= helpScrollOffset;
scrolledContentRect.bottom += maxHelpScroll;
DrawText(hdc, pageText, -1, &scrolledContentRect, pageFlags);
if (hasOldClipRegion == 1)
{
SelectClipRgn(hdc, oldClipRegion);
}
else
{
SelectClipRgn(hdc, nullptr);
}
DeleteObject(contentClipRegion);
DeleteObject(oldClipRegion);
}
}
@@ -771,7 +855,7 @@ void TDrawScreen(HDC hdc, HWND hWnd)
};
const TCHAR* helpHint = helpState.currentPage == 0
? _T("\u65b9\u5411\u952e / WASD \u5207\u6362\uff0cEnter / Space \u786e\u8ba4\uff0cEsc / M \u8fd4\u56de\u4e3b\u83dc\u5355")
: _T("Esc / Backspace / M \u8fd4\u56de\u5e2e\u52a9");
: _T("\u9f20\u6807\u6eda\u8f6e\u4e0a\u4e0b\u7ffb\u52a8\uff0cEsc / Backspace / M \u8fd4\u56de\u5e2e\u52a9");
DrawText(hdc, helpHint, -1, &backHintRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
DrawBackButton();
@@ -1317,6 +1401,17 @@ void TDrawScreen(HDC hdc, HWND hWnd)
SetTextColor(hdc, textColor);
TextOut(hdc, upgradeListRect.left + SS(18), upgradeListRect.top + SS(16), _T("已掌握强化"), lstrlen(_T("已掌握强化")));
SelectObject(hdc, smallFont);
SetTextColor(hdc, RGB(148, 118, 132));
RECT upgradeScrollHintRect =
{
upgradeListRect.left + SS(116),
upgradeListRect.top + SS(17),
upgradeListRect.right - SS(18),
upgradeListRect.top + SS(42)
};
DrawText(hdc, _T("J/K / 滚轮"), -1, &upgradeScrollHintRect, DT_RIGHT | DT_VCENTER | DT_SINGLELINE);
SelectObject(hdc, smallFont);
SetTextColor(hdc, RGB(128, 104, 118));
RECT upgradeBodyRect =
@@ -1495,7 +1590,44 @@ void TDrawScreen(HDC hdc, HWND hWnd)
_stprintf_s(upgradeSummary, _T("尚未掌握强化。\r\n下一次升级将开启构筑。"));
}
DrawText(hdc, upgradeSummary, -1, &upgradeBodyRect, DT_LEFT | DT_TOP | DT_WORDBREAK);
RECT upgradeCalculateRect =
{
upgradeBodyRect.left,
upgradeBodyRect.top,
upgradeBodyRect.right,
upgradeBodyRect.top
};
DrawText(hdc, upgradeSummary, -1, &upgradeCalculateRect, DT_LEFT | DT_TOP | DT_WORDBREAK | DT_CALCRECT);
int maxUpgradeScroll = (upgradeCalculateRect.bottom - upgradeCalculateRect.top) - (upgradeBodyRect.bottom - upgradeBodyRect.top);
if (maxUpgradeScroll < 0)
{
maxUpgradeScroll = 0;
}
if (upgradeListScrollOffset > maxUpgradeScroll)
{
upgradeListScrollOffset = maxUpgradeScroll;
}
HRGN oldUpgradeClipRegion = CreateRectRgn(0, 0, 0, 0);
int hasOldUpgradeClipRegion = GetClipRgn(hdc, oldUpgradeClipRegion);
HRGN upgradeClipRegion = CreateRectRgn(upgradeBodyRect.left, upgradeBodyRect.top, upgradeBodyRect.right, upgradeBodyRect.bottom);
SelectClipRgn(hdc, upgradeClipRegion);
RECT scrolledUpgradeBodyRect = upgradeBodyRect;
scrolledUpgradeBodyRect.top -= upgradeListScrollOffset;
scrolledUpgradeBodyRect.bottom += maxUpgradeScroll;
DrawText(hdc, upgradeSummary, -1, &scrolledUpgradeBodyRect, DT_LEFT | DT_TOP | DT_WORDBREAK);
if (hasOldUpgradeClipRegion == 1)
{
SelectClipRgn(hdc, oldUpgradeClipRegion);
}
else
{
SelectClipRgn(hdc, nullptr);
}
DeleteObject(upgradeClipRegion);
DeleteObject(oldUpgradeClipRegion);
SelectObject(hdc, sectionFont);
SetTextColor(hdc, textColor);
}
@@ -2150,7 +2282,7 @@ void TDrawScreen(HDC hdc, HWND hWnd)
cardRect.left + SS(20),
cardRect.top + SS(18),
cardRect.right - SS(116),
cardRect.top + SS(44)
cardRect.top + SS(40)
};
DrawText(hdc, synthesisPath, -1, &synthesisRect, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
}
@@ -2160,30 +2292,30 @@ void TDrawScreen(HDC hdc, HWND hWnd)
RECT nameRect =
{
cardRect.left + SS(20),
cardRect.top + (hasSynthesisPath ? SS(54) : SS(44)),
cardRect.right - SS(96),
cardRect.top + (hasSynthesisPath ? SS(106) : SS(98))
cardRect.top + (hasSynthesisPath ? SS(44) : SS(38)),
cardRect.right - SS(20),
cardRect.top + (hasSynthesisPath ? SS(76) : SS(70))
};
DrawText(hdc, upgradeUiState.options[i].name, -1, &nameRect, DT_LEFT | DT_TOP | DT_WORDBREAK);
DrawText(hdc, upgradeUiState.options[i].name, -1, &nameRect, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
SelectObject(hdc, bodyFont);
SelectObject(hdc, smallFont);
SetTextColor(hdc, descColor);
RECT descRect =
{
cardRect.left + SS(20),
cardRect.top + (hasSynthesisPath ? SS(124) : SS(116)),
cardRect.top + (hasSynthesisPath ? SS(84) : SS(78)),
cardRect.right - SS(20),
cardRect.bottom - SS(64)
cardRect.bottom - SS(48)
};
DrawText(hdc, upgradeUiState.options[i].description, -1, &descRect, DT_LEFT | DT_WORDBREAK);
DrawText(hdc, upgradeUiState.options[i].description, -1, &descRect, DT_LEFT | DT_TOP | DT_WORDBREAK | DT_END_ELLIPSIS);
SelectObject(hdc, smallFont);
RECT footerRect =
{
cardRect.left + SS(20),
cardRect.bottom - SS(42),
cardRect.bottom - SS(34),
cardRect.right - SS(20),
cardRect.bottom - SS(14)
cardRect.bottom - SS(10)
};
SetTextColor(hdc, footerColor);
DrawText(