升级改为四选一并重做赌徒与方块改造机制

This commit is contained in:
2026-04-25 12:19:37 +08:00
parent 4bcc62f01a
commit 332573a28c
6 changed files with 1349 additions and 102 deletions
+9 -9
View File
@@ -7,7 +7,7 @@
- [x] 保留当前原版俄罗斯方块玩法,作为“经典模式”
- [x] 新增开始菜单,进入游戏前先选择模式
- [x] 模式至少包含:`经典模式``Rogue 模式`
- [x] 强化选择界面固定为“选一”个选项框,视觉参考《吸血鬼幸存者》
- [x] 强化选择界面固定为“选一”个选项框,视觉参考《吸血鬼幸存者》
- [ ] 美术、图标、特效、音频先全部使用占位符资源
## 阶段 0:重构准备与技术基线
@@ -100,7 +100,7 @@
- [x] 消行后可以稳定增加分数和经验
- [x] 达到阈值后必定进入升级选择状态
## 阶段 5:强化池与选一系统
## 阶段 5:强化池与选一系统
目标:先完成最关键的 Rogue 核心体验。
@@ -112,33 +112,33 @@
- [x] `preview_plus_one`
- [x] `exp_multiplier`
- [x] `last_chance`
- [x] 随机抽取 3 个不重复选项,避免当前局内明显无效选项
- [x] 随机抽取 4 个不重复选项,避免当前局内明显无效选项
- [x] 支持重复强化的层数叠加
- [x] 选中后立即应用效果并返回游戏
- [x] 为后续强化扩展预留 `applyUpgradeById()` 分发函数
完成标准:
- [x] 每次升级都稳定弹出个选项框
- [x] 每次升级都稳定弹出个选项框
- [x] 选择任一选项后效果立即生效
## 阶段 6:升级界面 UI
目标:实现参考《吸血鬼幸存者》的选一视觉结构,先用占位表现。
目标:实现参考《吸血鬼幸存者》的选一视觉结构,先用占位表现。
- [x] 增加全屏或半透明遮罩,压暗游戏场景
- [x] 中央显示个横向或纵向排列的选项框
- [x] 中央显示个横向或纵向排列的选项框
- [x] 每个选项框至少包含:占位图标、强化名、强化说明、强化分类、当前层数
- [x] 支持键盘选择:`A/D` 或方向键切换,`Enter/Space` 确认
- [ ] 高亮态、选中态、禁用态视觉区分明确
- [x] 保证个框尺寸一致、布局稳定,不因文本长度错位
- [x] 保证个框尺寸一致、布局稳定,不因文本长度错位
- [x] 右侧现有信息面板在升级状态下保留或弱化显示,但不能抢焦点
- [ ] 占位资源统一放入 `assets`,命名先按 `placeholder_*`
完成标准:
- [x] 升级界面可以独立显示
- [x] 个选项框可操作、可确认、可关闭
- [x] 个选项框可操作、可确认、可关闭
- [x] 视觉结构已经接近目标形式,后续只需替换资源
## 阶段 7:玩法强化第一轮
@@ -204,7 +204,7 @@
- [ ] 开局正常生成方块
- [ ] 消行得分与经验正确
- [x] 升级必出 3 个选项框
- [x] 升级必出 4 个选项框
- [x] 选择后恢复游戏且不丢状态
- [ ] 复活、暂停、失败、重开互不冲突
+3 -2
View File
@@ -56,14 +56,15 @@ struct PlayerStats
int explosiveLevel;
int stableStructureLevel;
int doubleGrowthLevel;
int luckyRollLevel;
int gamblerLevel;
int pieceTuningLevels[7];
};
struct UpgradeOption
{
int id;
int currentLevel;
int targetPieceType;
const TCHAR* name;
const TCHAR* category;
const TCHAR* description;
@@ -85,7 +86,7 @@ struct UpgradeUiState
int optionCount;
int pendingCount;
int totalChosenCount;
UpgradeOption options[3];
UpgradeOption options[4];
};
struct FeedbackState
+38 -4
View File
@@ -264,20 +264,54 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
case VK_LEFT:
case 'A':
upgradeUiState.selectedIndex--;
if (upgradeUiState.selectedIndex < 0)
if (upgradeUiState.optionCount > 1)
{
upgradeUiState.selectedIndex = upgradeUiState.optionCount - 1;
if ((upgradeUiState.selectedIndex % 2) == 1)
{
upgradeUiState.selectedIndex--;
}
else
{
upgradeUiState.selectedIndex = (upgradeUiState.selectedIndex + 1 < upgradeUiState.optionCount)
? upgradeUiState.selectedIndex + 1
: upgradeUiState.selectedIndex;
}
}
InvalidateRect(hWnd, nullptr, FALSE);
break;
case VK_RIGHT:
case 'D':
if (upgradeUiState.optionCount > 1)
{
if ((upgradeUiState.selectedIndex % 2) == 0 && upgradeUiState.selectedIndex + 1 < upgradeUiState.optionCount)
{
upgradeUiState.selectedIndex++;
if (upgradeUiState.selectedIndex >= upgradeUiState.optionCount)
}
else
{
upgradeUiState.selectedIndex--;
if (upgradeUiState.selectedIndex < 0)
{
upgradeUiState.selectedIndex = 0;
}
}
}
InvalidateRect(hWnd, nullptr, FALSE);
break;
case VK_UP:
case 'W':
if (upgradeUiState.optionCount > 2 && upgradeUiState.selectedIndex >= 2)
{
upgradeUiState.selectedIndex -= 2;
}
InvalidateRect(hWnd, nullptr, FALSE);
break;
case VK_DOWN:
case 'S':
if (upgradeUiState.optionCount > 2 && upgradeUiState.selectedIndex + 2 < upgradeUiState.optionCount)
{
upgradeUiState.selectedIndex += 2;
}
InvalidateRect(hWnd, nullptr, FALSE);
break;
case VK_RETURN:
+151 -61
View File
@@ -38,7 +38,7 @@ enum UpgradeId
UPGRADE_EXPLOSIVE_PIECE = 9,
UPGRADE_STABLE_STRUCTURE = 10,
UPGRADE_DOUBLE_GROWTH = 11,
UPGRADE_LUCKY_ROLL = 12,
UPGRADE_PIECE_TUNING = 12,
UPGRADE_GAMBLER = 13
};
@@ -56,8 +56,8 @@ static const UpgradeEntry kUpgradePool[] =
{ UPGRADE_EXPLOSIVE_PIECE, -1, true, _T("\u7206\u7834\u65b9\u5757"), _T("\u7279\u6b8a"), _T("\u63d0\u9ad8\u7206\u7834\u65b9\u5757\u51fa\u73b0\u6982\u7387\uff0c\u843d\u5730\u65f6\u89e6\u53d1 3x3 \u6e05\u9664\u3002") },
{ UPGRADE_STABLE_STRUCTURE, -1, true, _T("\u7a33\u5b9a\u7ed3\u6784"), _T("\u7279\u6b8a"), _T("\u843d\u5730\u540e\u5c0f\u6982\u7387\u81ea\u52a8\u586b\u8865\u90bb\u8fd1\u7a7a\u6d1e\uff0c\u63d0\u9ad8\u76d8\u9762\u7ed3\u6784\u7a33\u5b9a\u6027\u3002") },
{ UPGRADE_DOUBLE_GROWTH, -1, true, _T("\u53cc\u500d\u6210\u957f"), _T("\u7279\u6b8a"), _T("\u989d\u5916\u63d0\u9ad8\u6d88\u884c\u5f97\u5206\u4e0e EXP \u6536\u76ca\uff0c\u6bcf\u5c42\u518d\u8ffd\u52a0 15%\u3002") },
{ UPGRADE_LUCKY_ROLL, -1, true, _T("\u65b9\u5757\u6539\u8fd0"), _T("\u7279\u6b8a"), _T("\u4f18\u5316 Next \u961f\u5217\uff0c\u964d\u4f4e\u8fde\u7eed\u91cd\u590d\u65b9\u5757\u51fa\u73b0\u7684\u6982\u7387\u3002") },
{ UPGRADE_GAMBLER, -1, true, _T("\u8d4c\u5f92"), _T("\u7279\u6b8a"), _T("\u6d88\u884c\u6536\u76ca\u4f1a\u989d\u5916\u968f\u673a\u6ce2\u52a8\uff0c\u5c42\u6570\u8d8a\u9ad8\u6ce2\u52a8\u8d8a\u5927\u3002") }
{ UPGRADE_PIECE_TUNING, -1, true, _T("\u65b9\u5757\u6539\u9020"), _T("\u7279\u6b8a"), _T("\u9009\u62e9\u4e00\u79cd\u65b9\u5757\uff0c\u964d\u4f4e\u5176\u540e\u7eed\u51fa\u73b0\u6982\u7387\u3002") },
{ UPGRADE_GAMBLER, -1, true, _T("\u8d4c\u5f92"), _T("\u7279\u6b8a"), _T("\u9009\u62e9\u5f3a\u5316\u65f6\uff0c\u6709\u6982\u7387\u53cc\u500d\u751f\u6548\uff0c\u4e5f\u6709\u6982\u7387\u5b8c\u5168\u843d\u7a7a\u3002") }
};
static constexpr int kUpgradePoolSize = sizeof(kUpgradePool) / sizeof(kUpgradePool[0]);
@@ -215,8 +215,11 @@ static void ResetPlayerStats(PlayerStats& stats, bool useRogueRules)
stats.explosiveLevel = 0;
stats.stableStructureLevel = 0;
stats.doubleGrowthLevel = 0;
stats.luckyRollLevel = 0;
stats.gamblerLevel = 0;
for (int i = 0; i < 7; i++)
{
stats.pieceTuningLevels[i] = 0;
}
}
static int GetNextPreviewLimit()
@@ -267,8 +270,6 @@ static int GetUpgradeCurrentLevel(int upgradeId)
return rogueStats.stableStructureLevel;
case UPGRADE_DOUBLE_GROWTH:
return rogueStats.doubleGrowthLevel;
case UPGRADE_LUCKY_ROLL:
return rogueStats.luckyRollLevel;
case UPGRADE_GAMBLER:
return rogueStats.gamblerLevel;
default:
@@ -276,6 +277,27 @@ static int GetUpgradeCurrentLevel(int upgradeId)
}
}
static const TCHAR* GetPieceShortName(int pieceType)
{
static const TCHAR* kPieceNames[7] =
{
_T("I"),
_T("T"),
_T("L"),
_T("J"),
_T("O"),
_T("S"),
_T("Z")
};
if (pieceType < 0 || pieceType >= 7)
{
return _T("?");
}
return kPieceNames[pieceType];
}
static bool IsUpgradeSelectable(const UpgradeEntry& entry)
{
if (entry.repeatable)
@@ -390,42 +412,37 @@ static int ClearExplosiveAreaAt(int centerY, int centerX)
static int RollNextPieceType()
{
int candidate = rand() % 7;
int weights[7] = { 100, 100, 100, 100, 100, 100, 100 };
if (currentMode != MODE_ROGUE || rogueStats.luckyRollLevel <= 0)
if (currentMode == MODE_ROGUE)
{
return candidate;
for (int i = 0; i < 7; i++)
{
weights[i] -= rogueStats.pieceTuningLevels[i] * 20;
if (weights[i] < 20)
{
weights[i] = 20;
}
int rerollCount = rogueStats.luckyRollLevel;
if (rerollCount > 3)
{
rerollCount = 3;
}
for (int attempt = 0; attempt < rerollCount; attempt++)
{
bool matchesCurrent = (candidate == type);
bool matchesQueue = false;
for (int i = 0; i < 3; i++)
{
if (nextTypes[i] == candidate)
{
matchesQueue = true;
break;
}
}
if (!matchesCurrent && !matchesQueue)
int totalWeight = 0;
for (int i = 0; i < 7; i++)
{
break;
totalWeight += weights[i];
}
candidate = rand() % 7;
int roll = rand() % totalWeight;
for (int i = 0; i < 7; i++)
{
if (roll < weights[i])
{
return i;
}
roll -= weights[i];
}
return candidate;
return rand() % 7;
}
static int TryStabilizeBoard()
@@ -544,7 +561,7 @@ static void FillUpgradeOptions()
}
}
int optionCount = selectableCount < 3 ? selectableCount : 3;
int optionCount = selectableCount < 4 ? selectableCount : 4;
upgradeUiState.optionCount = optionCount;
upgradeUiState.selectedIndex = 0;
@@ -556,10 +573,45 @@ static void FillUpgradeOptions()
upgradeUiState.options[i].id = pickedEntry.id;
upgradeUiState.options[i].currentLevel = GetUpgradeCurrentLevel(pickedEntry.id);
upgradeUiState.options[i].targetPieceType = -1;
upgradeUiState.options[i].name = pickedEntry.name;
upgradeUiState.options[i].category = pickedEntry.category;
upgradeUiState.options[i].description = pickedEntry.description;
if (pickedEntry.id == UPGRADE_PIECE_TUNING)
{
int targetPieceType = rand() % 7;
bool duplicatedPiece = true;
int guard = 0;
while (duplicatedPiece && guard < 16)
{
duplicatedPiece = false;
for (int optionIndex = 0; optionIndex < i; optionIndex++)
{
if (upgradeUiState.options[optionIndex].id == UPGRADE_PIECE_TUNING &&
upgradeUiState.options[optionIndex].targetPieceType == targetPieceType)
{
duplicatedPiece = true;
targetPieceType = (targetPieceType + 1) % 7;
break;
}
}
guard++;
}
upgradeUiState.options[i].targetPieceType = targetPieceType;
upgradeUiState.options[i].currentLevel = rogueStats.pieceTuningLevels[targetPieceType];
upgradeUiState.options[i].name = _T("\u65b9\u5757\u6539\u9020");
static TCHAR tuningDescriptions[4][64];
_stprintf_s(
tuningDescriptions[i],
_T("\u964d\u4f4e %s \u65b9\u5757\u7684\u51fa\u73b0\u6982\u7387\u3002"),
GetPieceShortName(targetPieceType));
upgradeUiState.options[i].description = tuningDescriptions[i];
}
selectableIndexes[pickSlot] = selectableIndexes[selectableCount - 1];
selectableCount--;
}
@@ -570,77 +622,80 @@ static int GetRogueFallInterval()
return 500 + rogueStats.slowFallStacks * 80;
}
static void ApplyUpgradeById(int upgradeId)
static void ApplyUpgradeById(int upgradeId, int targetPieceType, int applyCount)
{
if (applyCount <= 0)
{
return;
}
switch (upgradeId)
{
case UPGRADE_SCORE_MULTIPLIER:
rogueStats.scoreMultiplierPercent += 20;
rogueStats.scoreUpgradeLevel++;
rogueStats.scoreMultiplierPercent += 20 * applyCount;
rogueStats.scoreUpgradeLevel += applyCount;
break;
case UPGRADE_COMBO_BONUS:
rogueStats.comboBonusStacks++;
rogueStats.comboBonusStacks += applyCount;
break;
case UPGRADE_EXP_MULTIPLIER:
rogueStats.expMultiplierPercent += 25;
rogueStats.expUpgradeLevel++;
rogueStats.expMultiplierPercent += 25 * applyCount;
rogueStats.expUpgradeLevel += applyCount;
break;
case UPGRADE_SLOW_FALL:
rogueStats.slowFallStacks++;
rogueStats.slowFallStacks += applyCount;
currentFallInterval = GetRogueFallInterval();
break;
case UPGRADE_PREVIEW_PLUS_ONE:
for (int i = 0; i < applyCount; i++)
{
if (rogueStats.previewCount < 3)
{
rogueStats.previewCount++;
}
}
rogueStats.previewUpgradeLevel = rogueStats.previewCount - 1;
break;
case UPGRADE_LAST_CHANCE:
rogueStats.lastChanceCount = 1;
rogueStats.lastChanceUpgradeLevel = 1;
rogueStats.lastChanceCount += applyCount;
rogueStats.lastChanceUpgradeLevel += applyCount;
break;
case UPGRADE_HOLD_UNLOCK:
rogueStats.holdUnlocked = 1;
break;
case UPGRADE_PRESSURE_RELIEF:
{
rogueStats.pressureReliefLevel++;
rogueStats.pressureReliefLevel += applyCount;
for (int i = 0; i < applyCount; i++)
{
int topOccupiedRow = GetTopOccupiedRow();
if (topOccupiedRow >= 0)
{
DeleteOneLine(topOccupiedRow);
SetFeedbackMessage(_T("\u51cf\u538b\u751f\u6548"), _T("\u5df2\u7acb\u5373\u6e05\u9664\u5f53\u524d\u6700\u9ad8\u5360\u7528\u884c\u3002"), 12);
}
else
{
SetFeedbackMessage(_T("\u51cf\u538b\u751f\u6548"), _T("\u5f53\u524d\u76d8\u9762\u8fd8\u5f88\u7a7a\uff0c\u672c\u6b21\u6ca1\u6709\u989d\u5916\u6e05\u9664\u884c\u3002"), 12);
}
break;
}
case UPGRADE_SWEEPER:
rogueStats.sweeperLevel++;
SetFeedbackMessage(_T("\u6e05\u626b\u8005\u5df2\u52a0\u5165"), _T("\u7d2f\u8ba1\u6d88\u884c\u540e\u5c06\u81ea\u52a8\u6e05\u7406\u5e95\u90e8\u79ef\u538b\u3002"), 12);
rogueStats.sweeperLevel += applyCount;
break;
case UPGRADE_EXPLOSIVE_PIECE:
rogueStats.explosiveLevel++;
SetFeedbackMessage(_T("\u7206\u7834\u65b9\u5757\u5df2\u5f3a\u5316"), _T("\u540e\u7eed\u5c06\u6709\u66f4\u9ad8\u6982\u7387\u51fa\u73b0\u7206\u7834\u65b9\u5757\u3002"), 12);
rogueStats.explosiveLevel += applyCount;
break;
case UPGRADE_STABLE_STRUCTURE:
rogueStats.stableStructureLevel++;
SetFeedbackMessage(_T("\u7a33\u5b9a\u7ed3\u6784\u5df2\u5f3a\u5316"), _T("\u540e\u7eed\u843d\u5730\u7ed3\u7b97\u65f6\u5c06\u6709\u6982\u7387\u81ea\u52a8\u8865\u6d1e\u3002"), 12);
rogueStats.stableStructureLevel += applyCount;
break;
case UPGRADE_DOUBLE_GROWTH:
rogueStats.doubleGrowthLevel++;
SetFeedbackMessage(_T("\u53cc\u500d\u6210\u957f\u5df2\u53e0\u52a0"), _T("\u540e\u7eed\u6d88\u884c\u7684\u5f97\u5206\u548c EXP \u6536\u76ca\u4f1a\u66f4\u9ad8\u3002"), 12);
rogueStats.doubleGrowthLevel += applyCount;
break;
case UPGRADE_LUCKY_ROLL:
rogueStats.luckyRollLevel++;
SetFeedbackMessage(_T("\u65b9\u5757\u6539\u8fd0\u5df2\u5f3a\u5316"), _T("Next \u961f\u5217\u4f1a\u66f4\u5c11\u51fa\u73b0\u8fde\u7eed\u91cd\u590d\u5757\u578b\u3002"), 12);
case UPGRADE_PIECE_TUNING:
if (targetPieceType >= 0 && targetPieceType < 7)
{
rogueStats.pieceTuningLevels[targetPieceType] += applyCount;
}
break;
case UPGRADE_GAMBLER:
rogueStats.gamblerLevel++;
SetFeedbackMessage(_T("\u8d4c\u5f92\u5df2\u53e0\u52a0"), _T("\u540e\u7eed\u6d88\u884c\u7684\u5206\u6570\u548c EXP \u4f1a\u989d\u5916\u968f\u673a\u6ce2\u52a8\u3002"), 12);
rogueStats.gamblerLevel += applyCount;
break;
default:
break;
@@ -1272,12 +1327,47 @@ void ConfirmUpgradeSelection()
}
UpgradeOption selectedOption = upgradeUiState.options[upgradeUiState.selectedIndex];
ApplyUpgradeById(selectedOption.id);
int applyCount = 1;
TCHAR gamblerSuffix[64] = _T("");
if (currentMode == MODE_ROGUE && rogueStats.gamblerLevel > 0)
{
int gamblerChance = 20 + (rogueStats.gamblerLevel - 1) * 5;
if (gamblerChance > 40)
{
gamblerChance = 40;
}
int roll = rand() % 100;
if (roll < gamblerChance)
{
applyCount = 2;
_stprintf_s(gamblerSuffix, _T(" \u8d4c\u5f92\uff1a\u53cc\u500d"));
}
else if (roll >= 100 - gamblerChance)
{
applyCount = 0;
_stprintf_s(gamblerSuffix, _T(" \u8d4c\u5f92\uff1a\u843d\u7a7a"));
}
}
ApplyUpgradeById(selectedOption.id, selectedOption.targetPieceType, applyCount);
upgradeUiState.totalChosenCount++;
TCHAR feedbackTitle[64];
TCHAR feedbackDetail[128];
_stprintf_s(feedbackTitle, _T("\u5df2\u83b7\u5f97\uff1a%s"), selectedOption.name);
_stprintf_s(feedbackDetail, _T("%s"), selectedOption.description);
if (selectedOption.id == UPGRADE_PIECE_TUNING && selectedOption.targetPieceType >= 0)
{
_stprintf_s(
feedbackDetail,
_T("\u964d\u4f4e %s \u65b9\u5757\u51fa\u73b0\u6982\u7387%s"),
GetPieceShortName(selectedOption.targetPieceType),
gamblerSuffix);
}
else
{
_stprintf_s(feedbackDetail, _T("%s%s"), selectedOption.description, gamblerSuffix);
}
SetFeedbackMessage(feedbackTitle, feedbackDetail, 12);
if (upgradeUiState.pendingCount > 0)
+42 -15
View File
@@ -362,7 +362,7 @@ void TDrawScreen(HDC hdc, HWND hWnd)
hdc,
_T("\u7ecf\u5178\u6a21\u5f0f\uff1a\u4fdd\u6301\u539f\u7248\u4fc4\u7f57\u65af\u65b9\u5757\u73a9\u6cd5\uff0c\u4ee5\u6d88\u884c\u548c\u751f\u5b58\u4e3a\u4e3b\u3002\r\n\r\n")
_T("Rogue \u6a21\u5f0f\uff1a\u6d88\u884c\u540e\u9664\u4e86\u83b7\u5f97\u5206\u6570\uff0c\u8fd8\u4f1a\u83b7\u5f97 EXP\u3002EXP \u8fbe\u5230\u9608\u503c\u540e\u89e6\u53d1\u5347\u7ea7\uff0c\u4ece\u4e09\u4e2a\u5f3a\u5316\u4e2d\u9009\u4e00\u4e2a\u3002\r\n\r\n")
_T("\u5f53\u524d\u5df2\u63a5\u5165\uff1a\u5206\u6570\u500d\u7387\u3001EXP \u500d\u7387\u3001\u6162\u901f\u4e0b\u843d\u3001Hold \u89e3\u9501\u3001\u51cf\u538b\u3001\u6e05\u626b\u8005\u3001\u7206\u7834\u65b9\u5757\u3001\u7a33\u5b9a\u7ed3\u6784\u3001\u53cc\u500d\u6210\u957f\u3001\u65b9\u5757\u6539\u8fd0\u3001\u8d4c\u5f92\u3002\r\n\r\n")
_T("\u5f53\u524d\u5df2\u63a5\u5165\uff1a\u5206\u6570\u500d\u7387\u3001EXP \u500d\u7387\u3001\u6162\u901f\u4e0b\u843d\u3001Hold \u89e3\u9501\u3001\u51cf\u538b\u3001\u6e05\u626b\u8005\u3001\u7206\u7834\u65b9\u5757\u3001\u7a33\u5b9a\u7ed3\u6784\u3001\u53cc\u500d\u6210\u957f\u3001\u65b9\u5757\u6539\u9020\u3001\u8d4c\u5f92\u3002\r\n\r\n")
_T("\u63d0\u793a\uff1a\u6682\u505c\u3001\u5931\u8d25\u548c\u5347\u7ea7\u4f1a\u8fdb\u5165\u4e0d\u540c\u754c\u9762\uff0c\u8bf7\u6839\u636e\u5c4f\u5e55\u63d0\u793a\u64cd\u4f5c\u3002"),
-1,
&rulesBody,
@@ -699,10 +699,18 @@ void TDrawScreen(HDC hdc, HWND hWnd)
TextOut(hdc, combatRect.left + SS(18), combatRect.top + SS(178), growthText, lstrlen(growthText));
}
if (rogueStats.luckyRollLevel > 0)
int tunedPieces = 0;
for (int pieceType = 0; pieceType < 7; pieceType++)
{
if (rogueStats.pieceTuningLevels[pieceType] > 0)
{
tunedPieces++;
}
}
if (tunedPieces > 0)
{
TCHAR luckyText[96];
_stprintf_s(luckyText, _T("\u6539\u8fd0\u91cd\u63b7 %d \u6b21"), rogueStats.luckyRollLevel > 3 ? 3 : rogueStats.luckyRollLevel);
_stprintf_s(luckyText, _T("\u65b9\u5757\u6539\u9020 %d \u79cd\u5df2\u8c03\u6574"), tunedPieces);
TextOut(hdc, combatRect.left + SS(18), combatRect.top + SS(210), luckyText, lstrlen(luckyText));
}
@@ -710,11 +718,11 @@ void TDrawScreen(HDC hdc, HWND hWnd)
{
TCHAR gamblerText[96];
int variance = 20 + (rogueStats.gamblerLevel - 1) * 10;
if (variance > 50)
if (variance > 40)
{
variance = 50;
variance = 40;
}
_stprintf_s(gamblerText, _T("\u8d4c\u5f92\u6ce2\u52a8 \u00b1%d%%"), variance);
_stprintf_s(gamblerText, _T("\u8d4c\u5f92\u6982\u7387 \u53cc\u500d/%u\u6548 %d%%"), variance, variance);
TextOut(hdc, combatRect.left + SS(18), combatRect.top + SS(242), gamblerText, lstrlen(gamblerText));
}
@@ -788,9 +796,24 @@ void TDrawScreen(HDC hdc, HWND hWnd)
{
_stprintf_s(upgradeSummary + lstrlen(upgradeSummary), 512 - lstrlen(upgradeSummary), _T("\u53cc\u500d\u6210\u957f Lv.%d\r\n"), rogueStats.doubleGrowthLevel);
}
if (rogueStats.luckyRollLevel > 0)
int tunedPieceCount = 0;
for (int pieceType = 0; pieceType < 7; pieceType++)
{
_stprintf_s(upgradeSummary + lstrlen(upgradeSummary), 512 - lstrlen(upgradeSummary), _T("\u65b9\u5757\u6539\u8fd0 Lv.%d\r\n"), rogueStats.luckyRollLevel);
if (rogueStats.pieceTuningLevels[pieceType] > 0)
{
tunedPieceCount++;
_stprintf_s(
upgradeSummary + lstrlen(upgradeSummary),
512 - lstrlen(upgradeSummary),
_T("%s \u65b9\u5757\u6539\u9020 Lv.%d\r\n"),
(pieceType == 0 ? _T("I") :
pieceType == 1 ? _T("T") :
pieceType == 2 ? _T("L") :
pieceType == 3 ? _T("J") :
pieceType == 4 ? _T("O") :
pieceType == 5 ? _T("S") : _T("Z")),
rogueStats.pieceTuningLevels[pieceType]);
}
}
if (rogueStats.gamblerLevel > 0)
{
@@ -1108,22 +1131,26 @@ void TDrawScreen(HDC hdc, HWND hWnd)
DrawText(hdc, _T("\u8bf7\u4ece\u4e09\u4e2a\u9009\u9879\u4e2d\u9009\u62e9\u4e00\u4e2a\u5f3a\u5316"), -1, &overlaySubtitleRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
int gap = SS(18);
int cardWidth = (overlayRect.right - overlayRect.left - SS(72) - gap * 2) / 3;
int cardTop = overlayRect.top + SS(138);
int cardBottom = overlayRect.bottom - SS(72);
int horizontalPadding = SS(36);
int verticalTop = overlayRect.top + SS(138);
int cardWidth = (overlayRect.right - overlayRect.left - horizontalPadding * 2 - gap) / 2;
int cardHeight = (overlayRect.bottom - verticalTop - SS(72) - gap) / 2;
for (int i = 0; i < upgradeUiState.optionCount; i++)
{
bool isSelected = (i == upgradeUiState.selectedIndex);
int left = overlayRect.left + SS(36) + i * (cardWidth + gap);
int column = i % 2;
int row = i / 2;
int left = overlayRect.left + horizontalPadding + column * (cardWidth + gap);
int top = verticalTop + row * (cardHeight + gap);
int right = left + cardWidth;
RECT cardRect =
{
left,
cardTop,
top,
right,
cardBottom
top + cardHeight
};
HBRUSH cardBrush = CreateSolidBrush(isSelected ? RGB(255, 235, 242) : RGB(255, 247, 250));
@@ -1219,7 +1246,7 @@ void TDrawScreen(HDC hdc, HWND hWnd)
overlayRect.right - SS(30),
overlayRect.bottom - SS(18)
};
DrawText(hdc, _T("A / D \u6216\u65b9\u5411\u952e\u5207\u6362\uff0cEnter \u6216 Space \u786e\u8ba4"), -1, &hintRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
DrawText(hdc, _T("W/A/S/D \u6216\u65b9\u5411\u952e\u5207\u6362\uff0cEnter \u6216 Space \u786e\u8ba4"), -1, &hintRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
SelectObject(hdc, oldFont);
+1095
View File
File diff suppressed because it is too large Load Diff