Compare commits
11 Commits
b01d48a88d
...
qhy_dev
| Author | SHA1 | Date | |
|---|---|---|---|
| 2f435f5ca6 | |||
| 45d9e988df | |||
| aa9e2f3ddc | |||
| 971d8be0dc | |||
| 9341ac9a05 | |||
| c77b877b8b | |||
| da741d1e56 | |||
| 647038b27a | |||
| 00729fbe17 | |||
| 2c04796010 | |||
| f3065c5fe7 |
Binary file not shown.
|
After Width: | Height: | Size: 572 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 194 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 722 KiB |
@@ -191,6 +191,16 @@ struct CellFlashEffect
|
|||||||
COLORREF color;
|
COLORREF color;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct GravityFallEffect
|
||||||
|
{
|
||||||
|
int ticks;
|
||||||
|
int totalTicks;
|
||||||
|
int x;
|
||||||
|
int fromY;
|
||||||
|
int toY;
|
||||||
|
int cellValue;
|
||||||
|
};
|
||||||
|
|
||||||
enum ScreenState
|
enum ScreenState
|
||||||
{
|
{
|
||||||
SCREEN_MENU = 0,
|
SCREEN_MENU = 0,
|
||||||
@@ -221,6 +231,7 @@ extern bool suspendFlag;
|
|||||||
extern bool targetFlag;
|
extern bool targetFlag;
|
||||||
extern bool bgmEnabled;
|
extern bool bgmEnabled;
|
||||||
extern bool reviveAvailable;
|
extern bool reviveAvailable;
|
||||||
|
extern bool rogueDemoMode;
|
||||||
extern int workRegion[20][10];
|
extern int workRegion[20][10];
|
||||||
extern Point point;
|
extern Point point;
|
||||||
extern Point target;
|
extern Point target;
|
||||||
@@ -239,6 +250,7 @@ extern ClearEffectState clearEffectState;
|
|||||||
extern FloatingTextEffect floatingTextEffects[8];
|
extern FloatingTextEffect floatingTextEffects[8];
|
||||||
extern ParticleEffect particleEffects[96];
|
extern ParticleEffect particleEffects[96];
|
||||||
extern CellFlashEffect cellFlashEffects[64];
|
extern CellFlashEffect cellFlashEffects[64];
|
||||||
|
extern GravityFallEffect gravityFallEffects[80];
|
||||||
extern int currentScreen;
|
extern int currentScreen;
|
||||||
extern int currentMode;
|
extern int currentMode;
|
||||||
extern int currentFallInterval;
|
extern int currentFallInterval;
|
||||||
@@ -268,8 +280,19 @@ void Restart();
|
|||||||
void StartGameWithMode(int mode);
|
void StartGameWithMode(int mode);
|
||||||
void ReturnToMainMenu();
|
void ReturnToMainMenu();
|
||||||
void ReviveAfterVideo();
|
void ReviveAfterVideo();
|
||||||
|
void StartRogueSkillDemo();
|
||||||
|
void StartRogueSkillDemoAt(int demoIndex);
|
||||||
|
void RestartCurrentRogueSkillDemo();
|
||||||
|
bool IsRogueSkillDemoMode();
|
||||||
|
bool TickRogueSkillDemo();
|
||||||
|
void AdvanceRogueSkillDemo();
|
||||||
|
int GetRogueSkillDemoCount();
|
||||||
|
const TCHAR* GetRogueSkillDemoName(int demoIndex);
|
||||||
|
const TCHAR* GetRogueSkillDemoDetail(int demoIndex);
|
||||||
|
const TCHAR* GetCurrentRogueSkillDemoName();
|
||||||
void SetFeedbackMessage(const TCHAR* title, const TCHAR* detail, int ticks);
|
void SetFeedbackMessage(const TCHAR* title, const TCHAR* detail, int ticks);
|
||||||
void OpenRulesScreen();
|
void OpenRulesScreen();
|
||||||
|
void OpenSkillDemoScreen();
|
||||||
void OpenCreditScreen();
|
void OpenCreditScreen();
|
||||||
void ChangeCreditPage(int direction);
|
void ChangeCreditPage(int direction);
|
||||||
void OpenUpgradeMenu();
|
void OpenUpgradeMenu();
|
||||||
@@ -287,6 +310,7 @@ void TriggerLineClearEffect(const int* rows, int rowCount, int linesCleared);
|
|||||||
void PlayPendingLineClearEffect();
|
void PlayPendingLineClearEffect();
|
||||||
void TriggerCellClearEffect(const Point* cells, int cellCount, bool strongBurst);
|
void TriggerCellClearEffect(const Point* cells, int cellCount, bool strongBurst);
|
||||||
void TriggerColoredCellClearEffect(const Point* cells, int cellCount, COLORREF flashColor, bool strongBurst);
|
void TriggerColoredCellClearEffect(const Point* cells, int cellCount, COLORREF flashColor, bool strongBurst);
|
||||||
|
void TriggerGravityFallEffect(int x, int fromY, int toY, int cellValue);
|
||||||
void AwardRogueSkillClearRewards(int clearedCells, int& scoreGain, int& expGain, bool allowLevelProgress);
|
void AwardRogueSkillClearRewards(int clearedCells, int& scoreGain, int& expGain, bool allowLevelProgress);
|
||||||
void CheckRogueLevelProgress();
|
void CheckRogueLevelProgress();
|
||||||
void ApplyBoardGravity();
|
void ApplyBoardGravity();
|
||||||
|
|||||||
@@ -84,6 +84,11 @@ void RollCurrentPieceSpecialFlags(bool allowRandomSpecials);
|
|||||||
*/
|
*/
|
||||||
void QueueLineClearEffect(const int* rows, int rowCount, int linesCleared);
|
void QueueLineClearEffect(const int* rows, int rowCount, int linesCleared);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 记录固定方块受重力下落的轨迹,用于播放纵向残影特效。
|
||||||
|
*/
|
||||||
|
void TriggerGravityFallEffect(int x, int fromY, int toY, int cellValue);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 尝试把旋转后的方块横向偏移指定格数后放置。
|
* @brief 尝试把旋转后的方块横向偏移指定格数后放置。
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#define IDD_ABOUTBOX 103
|
#define IDD_ABOUTBOX 103
|
||||||
#define IDM_ABOUT 104
|
#define IDM_ABOUT 104
|
||||||
#define IDM_EXIT 105
|
#define IDM_EXIT 105
|
||||||
|
#define IDM_SKILL_DEMO 106
|
||||||
#define IDI_TETRIS 107
|
#define IDI_TETRIS 107
|
||||||
#define IDI_SMALL 108
|
#define IDI_SMALL 108
|
||||||
#define IDC_TETRIS 109
|
#define IDC_TETRIS 109
|
||||||
|
|||||||
Binary file not shown.
+169
-13
@@ -197,6 +197,30 @@ static RECT GetHelpOptionRect(HWND hWnd, int index)
|
|||||||
return rect;
|
return rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static RECT GetHelpSkillDemoItemRect(HWND hWnd, int index)
|
||||||
|
{
|
||||||
|
LayoutMetrics metrics = GetLayoutMetrics(hWnd);
|
||||||
|
RECT rulesCard = GetRulesCardRect(hWnd);
|
||||||
|
RECT contentRect =
|
||||||
|
{
|
||||||
|
rulesCard.left + ScaleValue(metrics, 36),
|
||||||
|
rulesCard.top + ScaleValue(metrics, 126),
|
||||||
|
rulesCard.right - ScaleValue(metrics, 36),
|
||||||
|
rulesCard.bottom - ScaleValue(metrics, 86)
|
||||||
|
};
|
||||||
|
int itemHeight = ScaleValue(metrics, 58);
|
||||||
|
int itemGap = ScaleValue(metrics, 10);
|
||||||
|
int itemTop = contentRect.top + ScaleValue(metrics, 8) - helpScrollOffset;
|
||||||
|
RECT rect =
|
||||||
|
{
|
||||||
|
contentRect.left,
|
||||||
|
itemTop + index * (itemHeight + itemGap),
|
||||||
|
contentRect.right,
|
||||||
|
itemTop + index * (itemHeight + itemGap) + itemHeight
|
||||||
|
};
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
|
||||||
static RECT GetHelpBackHintRect(HWND hWnd)
|
static RECT GetHelpBackHintRect(HWND hWnd)
|
||||||
{
|
{
|
||||||
LayoutMetrics metrics = GetLayoutMetrics(hWnd);
|
LayoutMetrics metrics = GetLayoutMetrics(hWnd);
|
||||||
@@ -744,6 +768,10 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||||||
|
|
||||||
switch (wmId)
|
switch (wmId)
|
||||||
{
|
{
|
||||||
|
case IDM_SKILL_DEMO:
|
||||||
|
OpenSkillDemoScreen();
|
||||||
|
InvalidateRect(hWnd, nullptr, FALSE);
|
||||||
|
break;
|
||||||
case IDM_ABOUT:
|
case IDM_ABOUT:
|
||||||
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
|
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
|
||||||
break;
|
break;
|
||||||
@@ -789,7 +817,15 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||||||
shouldRefresh = true;
|
shouldRefresh = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentMode == MODE_ROGUE && rogueStats.feverTicks > 0)
|
if (IsRogueSkillDemoMode())
|
||||||
|
{
|
||||||
|
if (TickRogueSkillDemo())
|
||||||
|
{
|
||||||
|
shouldRefresh = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentMode == MODE_ROGUE && !IsRogueSkillDemoMode() && rogueStats.feverTicks > 0)
|
||||||
{
|
{
|
||||||
rogueStats.feverTicks--;
|
rogueStats.feverTicks--;
|
||||||
currentFallInterval = GetRogueFallInterval();
|
currentFallInterval = GetRogueFallInterval();
|
||||||
@@ -798,6 +834,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (currentMode == MODE_ROGUE &&
|
if (currentMode == MODE_ROGUE &&
|
||||||
|
!IsRogueSkillDemoMode() &&
|
||||||
rogueStats.timeDilationTicks > 0 &&
|
rogueStats.timeDilationTicks > 0 &&
|
||||||
currentScreen == SCREEN_PLAYING &&
|
currentScreen == SCREEN_PLAYING &&
|
||||||
!suspendFlag &&
|
!suspendFlag &&
|
||||||
@@ -809,7 +846,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||||||
shouldRefresh = true;
|
shouldRefresh = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentMode == MODE_ROGUE && rogueStats.extremeSlowTicks > 0)
|
if (currentMode == MODE_ROGUE && !IsRogueSkillDemoMode() && rogueStats.extremeSlowTicks > 0)
|
||||||
{
|
{
|
||||||
rogueStats.extremeSlowTicks--;
|
rogueStats.extremeSlowTicks--;
|
||||||
currentFallInterval = GetRogueFallInterval();
|
currentFallInterval = GetRogueFallInterval();
|
||||||
@@ -818,6 +855,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (currentMode == MODE_ROGUE &&
|
if (currentMode == MODE_ROGUE &&
|
||||||
|
!IsRogueSkillDemoMode() &&
|
||||||
rogueStats.extremePlayerLevel > 0 &&
|
rogueStats.extremePlayerLevel > 0 &&
|
||||||
currentScreen == SCREEN_PLAYING &&
|
currentScreen == SCREEN_PLAYING &&
|
||||||
!suspendFlag &&
|
!suspendFlag &&
|
||||||
@@ -843,7 +881,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentMode == MODE_ROGUE && rogueStats.holdSlowTicks > 0)
|
if (currentMode == MODE_ROGUE && !IsRogueSkillDemoMode() && rogueStats.holdSlowTicks > 0)
|
||||||
{
|
{
|
||||||
rogueStats.holdSlowTicks--;
|
rogueStats.holdSlowTicks--;
|
||||||
currentFallInterval = GetRogueFallInterval();
|
currentFallInterval = GetRogueFallInterval();
|
||||||
@@ -855,7 +893,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||||||
!suspendFlag &&
|
!suspendFlag &&
|
||||||
!gameOverFlag)
|
!gameOverFlag)
|
||||||
{
|
{
|
||||||
if (currentMode == MODE_ROGUE)
|
if (currentMode == MODE_ROGUE && !IsRogueSkillDemoMode())
|
||||||
{
|
{
|
||||||
int previousFallInterval = currentFallInterval;
|
int previousFallInterval = currentFallInterval;
|
||||||
AdvanceRogueDifficulty(currentFallInterval > 0 ? currentFallInterval : GAME_TIMER_INTERVAL);
|
AdvanceRogueDifficulty(currentFallInterval > 0 ? currentFallInterval : GAME_TIMER_INTERVAL);
|
||||||
@@ -865,7 +903,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentMode == MODE_ROGUE && rogueStats.timeDilationLevel > 0 && rogueStats.timeDilationTicks <= 0)
|
if (currentMode == MODE_ROGUE && !IsRogueSkillDemoMode() && rogueStats.timeDilationLevel > 0 && rogueStats.timeDilationTicks <= 0)
|
||||||
{
|
{
|
||||||
int occupiedHeight = 0;
|
int occupiedHeight = 0;
|
||||||
int playableHeight = GetRoguePlayableHeight();
|
int playableHeight = GetRoguePlayableHeight();
|
||||||
@@ -942,8 +980,21 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (currentScreen != SCREEN_MENU && IsPointInRect(GetBackButtonRect(hWnd), mouseX, mouseY))
|
if (currentScreen != SCREEN_MENU && IsPointInRect(GetBackButtonRect(hWnd), mouseX, mouseY))
|
||||||
|
{
|
||||||
|
if (currentScreen == SCREEN_PLAYING && IsRogueSkillDemoMode())
|
||||||
|
{
|
||||||
|
OpenSkillDemoScreen();
|
||||||
|
}
|
||||||
|
else if (currentScreen == SCREEN_RULES && helpState.currentPage != 0)
|
||||||
|
{
|
||||||
|
helpState.selectedIndex = (helpState.currentPage == 5) ? 3 : helpState.currentPage - 1;
|
||||||
|
helpState.currentPage = 0;
|
||||||
|
helpScrollOffset = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
ReturnToMainMenu();
|
ReturnToMainMenu();
|
||||||
|
}
|
||||||
InvalidateRect(hWnd, nullptr, FALSE);
|
InvalidateRect(hWnd, nullptr, FALSE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -990,8 +1041,17 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||||||
if (IsPointInRect(GetHelpOptionRect(hWnd, i), mouseX, mouseY))
|
if (IsPointInRect(GetHelpOptionRect(hWnd, i), mouseX, mouseY))
|
||||||
{
|
{
|
||||||
helpState.selectedIndex = i;
|
helpState.selectedIndex = i;
|
||||||
|
if (i == 3)
|
||||||
|
{
|
||||||
|
helpState.currentPage = 5;
|
||||||
|
helpState.selectedIndex = 0;
|
||||||
|
helpScrollOffset = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
helpState.currentPage = i + 1;
|
helpState.currentPage = i + 1;
|
||||||
helpScrollOffset = 0;
|
helpScrollOffset = 0;
|
||||||
|
}
|
||||||
InvalidateRect(hWnd, nullptr, FALSE);
|
InvalidateRect(hWnd, nullptr, FALSE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1002,17 +1062,36 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||||||
InvalidateRect(hWnd, nullptr, FALSE);
|
InvalidateRect(hWnd, nullptr, FALSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (IsPointInRect(GetHelpBackHintRect(hWnd), mouseX, mouseY))
|
else if (helpState.currentPage == 5)
|
||||||
{
|
{
|
||||||
if (helpState.currentPage == 4)
|
if (IsPointInRect(GetHelpBackHintRect(hWnd), mouseX, mouseY))
|
||||||
{
|
{
|
||||||
ReturnToMainMenu();
|
helpState.currentPage = 0;
|
||||||
|
helpState.selectedIndex = 3;
|
||||||
|
helpScrollOffset = 0;
|
||||||
|
InvalidateRect(hWnd, nullptr, FALSE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
int demoCount = GetRogueSkillDemoCount();
|
||||||
|
for (int i = 0; i < demoCount; i++)
|
||||||
|
{
|
||||||
|
if (IsPointInRect(GetHelpSkillDemoItemRect(hWnd, i), mouseX, mouseY))
|
||||||
|
{
|
||||||
|
helpState.selectedIndex = i;
|
||||||
|
StartRogueSkillDemoAt(i);
|
||||||
|
ResetGameTimer(hWnd);
|
||||||
|
InvalidateRect(hWnd, nullptr, FALSE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (IsPointInRect(GetHelpBackHintRect(hWnd), mouseX, mouseY))
|
||||||
|
{
|
||||||
|
helpState.selectedIndex = (helpState.currentPage == 5) ? 3 : helpState.currentPage - 1;
|
||||||
helpState.currentPage = 0;
|
helpState.currentPage = 0;
|
||||||
helpScrollOffset = 0;
|
helpScrollOffset = 0;
|
||||||
}
|
|
||||||
InvalidateRect(hWnd, nullptr, FALSE);
|
InvalidateRect(hWnd, nullptr, FALSE);
|
||||||
}
|
}
|
||||||
else if (helpState.currentPage == 4 && IsPointInRect(GetCreditArrowRect(hWnd, -1), mouseX, mouseY))
|
else if (helpState.currentPage == 4 && IsPointInRect(GetCreditArrowRect(hWnd, -1), mouseX, mouseY))
|
||||||
@@ -1235,6 +1314,19 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||||||
ChangeCreditPage(-1);
|
ChangeCreditPage(-1);
|
||||||
InvalidateRect(hWnd, nullptr, FALSE);
|
InvalidateRect(hWnd, nullptr, FALSE);
|
||||||
}
|
}
|
||||||
|
else if (helpState.currentPage == 5)
|
||||||
|
{
|
||||||
|
helpState.selectedIndex--;
|
||||||
|
if (helpState.selectedIndex < 0)
|
||||||
|
{
|
||||||
|
helpState.selectedIndex = GetRogueSkillDemoCount() - 1;
|
||||||
|
}
|
||||||
|
if (helpState.selectedIndex * 68 < helpScrollOffset)
|
||||||
|
{
|
||||||
|
helpScrollOffset = helpState.selectedIndex * 68;
|
||||||
|
}
|
||||||
|
InvalidateRect(hWnd, nullptr, FALSE);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case VK_DOWN:
|
case VK_DOWN:
|
||||||
case VK_RIGHT:
|
case VK_RIGHT:
|
||||||
@@ -1254,13 +1346,42 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||||||
ChangeCreditPage(1);
|
ChangeCreditPage(1);
|
||||||
InvalidateRect(hWnd, nullptr, FALSE);
|
InvalidateRect(hWnd, nullptr, FALSE);
|
||||||
}
|
}
|
||||||
|
else if (helpState.currentPage == 5)
|
||||||
|
{
|
||||||
|
helpState.selectedIndex++;
|
||||||
|
if (helpState.selectedIndex >= GetRogueSkillDemoCount())
|
||||||
|
{
|
||||||
|
helpState.selectedIndex = 0;
|
||||||
|
helpScrollOffset = 0;
|
||||||
|
}
|
||||||
|
else if (helpState.selectedIndex * 68 > helpScrollOffset + 360)
|
||||||
|
{
|
||||||
|
helpScrollOffset = helpState.selectedIndex * 68 - 360;
|
||||||
|
}
|
||||||
|
InvalidateRect(hWnd, nullptr, FALSE);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case VK_RETURN:
|
case VK_RETURN:
|
||||||
case VK_SPACE:
|
case VK_SPACE:
|
||||||
if (helpState.currentPage == 0)
|
if (helpState.currentPage == 0)
|
||||||
|
{
|
||||||
|
if (helpState.selectedIndex == 3)
|
||||||
|
{
|
||||||
|
helpState.currentPage = 5;
|
||||||
|
helpState.selectedIndex = 0;
|
||||||
|
helpScrollOffset = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
helpState.currentPage = helpState.selectedIndex + 1;
|
helpState.currentPage = helpState.selectedIndex + 1;
|
||||||
helpScrollOffset = 0;
|
helpScrollOffset = 0;
|
||||||
|
}
|
||||||
|
InvalidateRect(hWnd, nullptr, FALSE);
|
||||||
|
}
|
||||||
|
else if (helpState.currentPage == 5)
|
||||||
|
{
|
||||||
|
StartRogueSkillDemoAt(helpState.selectedIndex);
|
||||||
|
ResetGameTimer(hWnd);
|
||||||
InvalidateRect(hWnd, nullptr, FALSE);
|
InvalidateRect(hWnd, nullptr, FALSE);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1273,7 +1394,15 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||||||
}
|
}
|
||||||
else if (helpState.currentPage == 4)
|
else if (helpState.currentPage == 4)
|
||||||
{
|
{
|
||||||
ReturnToMainMenu();
|
helpState.currentPage = 0;
|
||||||
|
helpState.selectedIndex = 3;
|
||||||
|
helpScrollOffset = 0;
|
||||||
|
}
|
||||||
|
else if (helpState.currentPage == 5)
|
||||||
|
{
|
||||||
|
helpState.currentPage = 0;
|
||||||
|
helpState.selectedIndex = 3;
|
||||||
|
helpScrollOffset = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1388,20 +1517,47 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||||||
InvalidateRect(hWnd, nullptr, FALSE);
|
InvalidateRect(hWnd, nullptr, FALSE);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'M':
|
||||||
|
ReturnToMainMenu();
|
||||||
|
InvalidateRect(hWnd, nullptr, FALSE);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wParam == 'M')
|
if (IsRogueSkillDemoMode())
|
||||||
|
{
|
||||||
|
if (wParam == 'N')
|
||||||
|
{
|
||||||
|
AdvanceRogueSkillDemo();
|
||||||
|
InvalidateRect(hWnd, nullptr, FALSE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (wParam == 'R')
|
||||||
|
{
|
||||||
|
RestartCurrentRogueSkillDemo();
|
||||||
|
ResetGameTimer(hWnd);
|
||||||
|
InvalidateRect(hWnd, nullptr, FALSE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (wParam == VK_ESCAPE || wParam == VK_BACK || wParam == 'M')
|
||||||
|
{
|
||||||
|
OpenSkillDemoScreen();
|
||||||
|
InvalidateRect(hWnd, nullptr, FALSE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IsRogueSkillDemoMode() && wParam == 'M')
|
||||||
{
|
{
|
||||||
ReturnToMainMenu();
|
ReturnToMainMenu();
|
||||||
InvalidateRect(hWnd, nullptr, FALSE);
|
InvalidateRect(hWnd, nullptr, FALSE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wParam == 'R')
|
if (!IsRogueSkillDemoMode() && wParam == 'R')
|
||||||
{
|
{
|
||||||
StartGameWithMode(currentMode);
|
StartGameWithMode(currentMode);
|
||||||
ResetGameTimer(hWnd);
|
ResetGameTimer(hWnd);
|
||||||
@@ -1409,7 +1565,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wParam == 'P')
|
if (!IsRogueSkillDemoMode() && wParam == 'P')
|
||||||
{
|
{
|
||||||
suspendFlag = !suspendFlag;
|
suspendFlag = !suspendFlag;
|
||||||
InvalidateRect(hWnd, nullptr, FALSE);
|
InvalidateRect(hWnd, nullptr, FALSE);
|
||||||
|
|||||||
@@ -10,11 +10,12 @@ bool gameOverFlag = false;
|
|||||||
bool suspendFlag = false;
|
bool suspendFlag = false;
|
||||||
bool targetFlag = false;
|
bool targetFlag = false;
|
||||||
bool reviveAvailable = false;
|
bool reviveAvailable = false;
|
||||||
|
bool rogueDemoMode = false;
|
||||||
int workRegion[20][10] = { 0 };
|
int workRegion[20][10] = { 0 };
|
||||||
Point point = { 0, 0 };
|
Point point = { 0, 0 };
|
||||||
Point target = { 0, 0 };
|
Point target = { 0, 0 };
|
||||||
MenuState menuState = { 0, 4 };
|
MenuState menuState = { 0, 4 };
|
||||||
HelpState helpState = { 0, 3, 0 };
|
HelpState helpState = { 0, 4, 0 };
|
||||||
int helpScrollOffset = 0;
|
int helpScrollOffset = 0;
|
||||||
int creditPageIndex = 0;
|
int creditPageIndex = 0;
|
||||||
int creditAnimationTicks = 0;
|
int creditAnimationTicks = 0;
|
||||||
@@ -28,6 +29,7 @@ ClearEffectState clearEffectState = { 0, 0, 0, {} };
|
|||||||
FloatingTextEffect floatingTextEffects[8] = {};
|
FloatingTextEffect floatingTextEffects[8] = {};
|
||||||
ParticleEffect particleEffects[96] = {};
|
ParticleEffect particleEffects[96] = {};
|
||||||
CellFlashEffect cellFlashEffects[64] = {};
|
CellFlashEffect cellFlashEffects[64] = {};
|
||||||
|
GravityFallEffect gravityFallEffects[80] = {};
|
||||||
int currentScreen = SCREEN_MENU;
|
int currentScreen = SCREEN_MENU;
|
||||||
int currentMode = MODE_CLASSIC;
|
int currentMode = MODE_CLASSIC;
|
||||||
int currentFallInterval = 500;
|
int currentFallInterval = 500;
|
||||||
@@ -465,7 +467,6 @@ void Fixing()
|
|||||||
voidClearedCount = TriggerMiniBlackHole(5);
|
voidClearedCount = TriggerMiniBlackHole(5);
|
||||||
AwardRogueSkillClearRewards(voidClearedCount, voidScore, voidExp, false);
|
AwardRogueSkillClearRewards(voidClearedCount, voidScore, voidExp, false);
|
||||||
}
|
}
|
||||||
ApplyBoardGravity();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TCHAR rainbowDetail[128];
|
TCHAR rainbowDetail[128];
|
||||||
@@ -544,7 +545,6 @@ void Fixing()
|
|||||||
if (currentMode == MODE_ROGUE && explosiveCellsCleared > 0)
|
if (currentMode == MODE_ROGUE && explosiveCellsCleared > 0)
|
||||||
{
|
{
|
||||||
AwardRogueSkillClearRewards(explosiveCellsCleared, explosiveScoreGain, explosiveExpGain, false);
|
AwardRogueSkillClearRewards(explosiveCellsCleared, explosiveScoreGain, explosiveExpGain, false);
|
||||||
ApplyBoardGravity();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TCHAR explosiveDetail[128];
|
TCHAR explosiveDetail[128];
|
||||||
@@ -590,7 +590,6 @@ void Fixing()
|
|||||||
int laserScore = 0;
|
int laserScore = 0;
|
||||||
int laserExp = 0;
|
int laserExp = 0;
|
||||||
AwardRogueSkillClearRewards(laserCellsCleared, laserScore, laserExp, false);
|
AwardRogueSkillClearRewards(laserCellsCleared, laserScore, laserExp, false);
|
||||||
ApplyBoardGravity();
|
|
||||||
|
|
||||||
TCHAR laserDetail[128];
|
TCHAR laserDetail[128];
|
||||||
_stprintf_s(laserDetail, _T("激光贯穿第 %d 列,清除 %d 格 +%d 分 +%d EXP"), laserColumn + 1, laserCellsCleared, laserScore, laserExp);
|
_stprintf_s(laserDetail, _T("激光贯穿第 %d 列,清除 %d 格 +%d 分 +%d EXP"), laserColumn + 1, laserCellsCleared, laserScore, laserExp);
|
||||||
@@ -644,7 +643,6 @@ void Fixing()
|
|||||||
int crossScore = 0;
|
int crossScore = 0;
|
||||||
int crossExp = 0;
|
int crossExp = 0;
|
||||||
AwardRogueSkillClearRewards(totalCrossCleared, crossScore, crossExp, false);
|
AwardRogueSkillClearRewards(totalCrossCleared, crossScore, crossExp, false);
|
||||||
ApplyBoardGravity();
|
|
||||||
|
|
||||||
TCHAR crossDetail[128];
|
TCHAR crossDetail[128];
|
||||||
_stprintf_s(crossDetail, _T("十字冲击第 %d 行 / 第 %d 列,清除 %d 格 +%d 分 +%d EXP"), crossRow + 1, crossColumn + 1, totalCrossCleared, crossScore, crossExp);
|
_stprintf_s(crossDetail, _T("十字冲击第 %d 行 / 第 %d 列,清除 %d 格 +%d 分 +%d EXP"), crossRow + 1, crossColumn + 1, totalCrossCleared, crossScore, crossExp);
|
||||||
@@ -741,11 +739,6 @@ int DeleteLines()
|
|||||||
}
|
}
|
||||||
|
|
||||||
ApplyLineClearResult(clearedLines);
|
ApplyLineClearResult(clearedLines);
|
||||||
if (currentMode == MODE_CLASSIC && clearedLines > 0)
|
|
||||||
{
|
|
||||||
ApplyBoardGravity();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentScreen == SCREEN_UPGRADE)
|
if (currentScreen == SCREEN_UPGRADE)
|
||||||
{
|
{
|
||||||
QueueLineClearEffect(clearedRows, clearedRowCount, clearedLines);
|
QueueLineClearEffect(clearedRows, clearedRowCount, clearedLines);
|
||||||
@@ -787,7 +780,6 @@ int DeleteLines()
|
|||||||
int followupScore = 0;
|
int followupScore = 0;
|
||||||
int followupExp = 0;
|
int followupExp = 0;
|
||||||
AwardRogueSkillClearRewards(followupCleared, followupScore, followupExp, false);
|
AwardRogueSkillClearRewards(followupCleared, followupScore, followupExp, false);
|
||||||
ApplyBoardGravity();
|
|
||||||
|
|
||||||
TCHAR followupDetail[128];
|
TCHAR followupDetail[128];
|
||||||
_stprintf_s(
|
_stprintf_s(
|
||||||
|
|||||||
@@ -116,6 +116,11 @@ void ResetVisualEffects()
|
|||||||
{
|
{
|
||||||
cellFlashEffects[i].ticks = 0;
|
cellFlashEffects[i].ticks = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 80; i++)
|
||||||
|
{
|
||||||
|
gravityFallEffects[i].ticks = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -158,6 +163,15 @@ bool TickVisualEffects()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 80; i++)
|
||||||
|
{
|
||||||
|
if (gravityFallEffects[i].ticks > 0)
|
||||||
|
{
|
||||||
|
gravityFallEffects[i].ticks--;
|
||||||
|
active = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return active;
|
return active;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -429,6 +443,51 @@ void TriggerColoredCellClearEffect(const Point* cells, int cellCount, COLORREF f
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 为一个受重力下落的固定方块记录纵向残影和落点粒子。
|
||||||
|
*/
|
||||||
|
void TriggerGravityFallEffect(int x, int fromY, int toY, int cellValue)
|
||||||
|
{
|
||||||
|
if (x < 0 || x >= nGameWidth || fromY < 0 || fromY >= nGameHeight ||
|
||||||
|
toY < 0 || toY >= nGameHeight || toY <= fromY || cellValue == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int effectIndex = -1;
|
||||||
|
for (int i = 0; i < 80; i++)
|
||||||
|
{
|
||||||
|
if (gravityFallEffects[i].ticks <= 0)
|
||||||
|
{
|
||||||
|
effectIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (effectIndex < 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int totalTicks = 12 + (toY - fromY) * 2;
|
||||||
|
if (totalTicks > 26)
|
||||||
|
{
|
||||||
|
totalTicks = 26;
|
||||||
|
}
|
||||||
|
|
||||||
|
gravityFallEffects[effectIndex].ticks = totalTicks;
|
||||||
|
gravityFallEffects[effectIndex].totalTicks = totalTicks;
|
||||||
|
gravityFallEffects[effectIndex].x = x;
|
||||||
|
gravityFallEffects[effectIndex].fromY = fromY;
|
||||||
|
gravityFallEffects[effectIndex].toY = toY;
|
||||||
|
gravityFallEffects[effectIndex].cellValue = cellValue;
|
||||||
|
|
||||||
|
COLORREF particleColor = BrickColor[(cellValue - 1) % 7];
|
||||||
|
AddParticle(x * 100 + 50, toY * 100 + 18, -2 - rand() % 5, -12 - rand() % 7, 4, particleColor);
|
||||||
|
AddParticle(x * 100 + 50, toY * 100 + 18, 2 + rand() % 5, -12 - rand() % 7, 4, particleColor);
|
||||||
|
AddCellFlash(x, toY, RGB(210, 245, 255), true);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 判断指定方块、旋转状态和位置是否可以合法放置。
|
* @brief 判断指定方块、旋转状态和位置是否可以合法放置。
|
||||||
*/
|
*/
|
||||||
@@ -518,6 +577,7 @@ void ReviveAfterVideo()
|
|||||||
*/
|
*/
|
||||||
void StartGameWithMode(int mode)
|
void StartGameWithMode(int mode)
|
||||||
{
|
{
|
||||||
|
rogueDemoMode = false;
|
||||||
currentMode = mode;
|
currentMode = mode;
|
||||||
currentScreen = SCREEN_PLAYING;
|
currentScreen = SCREEN_PLAYING;
|
||||||
upgradeListScrollOffset = 0;
|
upgradeListScrollOffset = 0;
|
||||||
@@ -531,6 +591,7 @@ void StartGameWithMode(int mode)
|
|||||||
*/
|
*/
|
||||||
void ReturnToMainMenu()
|
void ReturnToMainMenu()
|
||||||
{
|
{
|
||||||
|
rogueDemoMode = false;
|
||||||
currentScreen = SCREEN_MENU;
|
currentScreen = SCREEN_MENU;
|
||||||
suspendFlag = false;
|
suspendFlag = false;
|
||||||
gameOverFlag = false;
|
gameOverFlag = false;
|
||||||
@@ -558,10 +619,11 @@ void ReturnToMainMenu()
|
|||||||
*/
|
*/
|
||||||
void OpenRulesScreen()
|
void OpenRulesScreen()
|
||||||
{
|
{
|
||||||
|
rogueDemoMode = false;
|
||||||
currentScreen = SCREEN_RULES;
|
currentScreen = SCREEN_RULES;
|
||||||
suspendFlag = false;
|
suspendFlag = false;
|
||||||
helpState.selectedIndex = 0;
|
helpState.selectedIndex = 0;
|
||||||
helpState.optionCount = 3;
|
helpState.optionCount = 4;
|
||||||
helpState.currentPage = 0;
|
helpState.currentPage = 0;
|
||||||
helpScrollOffset = 0;
|
helpScrollOffset = 0;
|
||||||
creditPageIndex = 0;
|
creditPageIndex = 0;
|
||||||
@@ -572,12 +634,27 @@ void OpenRulesScreen()
|
|||||||
/**
|
/**
|
||||||
* @brief 打开致谢界面并重置致谢页切换状态。
|
* @brief 打开致谢界面并重置致谢页切换状态。
|
||||||
*/
|
*/
|
||||||
void OpenCreditScreen()
|
void OpenSkillDemoScreen()
|
||||||
{
|
{
|
||||||
|
rogueDemoMode = false;
|
||||||
currentScreen = SCREEN_RULES;
|
currentScreen = SCREEN_RULES;
|
||||||
suspendFlag = false;
|
suspendFlag = false;
|
||||||
helpState.selectedIndex = 0;
|
helpState.selectedIndex = 0;
|
||||||
helpState.optionCount = 3;
|
helpState.optionCount = 4;
|
||||||
|
helpState.currentPage = 5;
|
||||||
|
helpScrollOffset = 0;
|
||||||
|
creditPageIndex = 0;
|
||||||
|
creditAnimationTicks = 0;
|
||||||
|
creditAnimationDirection = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenCreditScreen()
|
||||||
|
{
|
||||||
|
rogueDemoMode = false;
|
||||||
|
currentScreen = SCREEN_RULES;
|
||||||
|
suspendFlag = false;
|
||||||
|
helpState.selectedIndex = 0;
|
||||||
|
helpState.optionCount = 4;
|
||||||
helpState.currentPage = 4;
|
helpState.currentPage = 4;
|
||||||
helpScrollOffset = 0;
|
helpScrollOffset = 0;
|
||||||
creditPageIndex = 0;
|
creditPageIndex = 0;
|
||||||
@@ -590,6 +667,7 @@ void OpenCreditScreen()
|
|||||||
*/
|
*/
|
||||||
void ChangeCreditPage(int direction)
|
void ChangeCreditPage(int direction)
|
||||||
{
|
{
|
||||||
|
constexpr int creditPageCount = 4;
|
||||||
if (direction == 0)
|
if (direction == 0)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -609,9 +687,9 @@ void ChangeCreditPage(int direction)
|
|||||||
|
|
||||||
if (creditPageIndex < 0)
|
if (creditPageIndex < 0)
|
||||||
{
|
{
|
||||||
creditPageIndex = 1;
|
creditPageIndex = creditPageCount - 1;
|
||||||
}
|
}
|
||||||
if (creditPageIndex > 1)
|
if (creditPageIndex >= creditPageCount)
|
||||||
{
|
{
|
||||||
creditPageIndex = 0;
|
creditPageIndex = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
+267
-32
@@ -131,11 +131,12 @@ static Bitmap* LoadBackgroundImage()
|
|||||||
*/
|
*/
|
||||||
static Bitmap* LoadCreditImage(int index)
|
static Bitmap* LoadCreditImage(int index)
|
||||||
{
|
{
|
||||||
|
constexpr int creditPageCount = 4;
|
||||||
static ULONG_PTR gdiplusToken = 0;
|
static ULONG_PTR gdiplusToken = 0;
|
||||||
static Bitmap* creditImages[2] = {};
|
static Bitmap* creditImages[creditPageCount] = {};
|
||||||
static bool attempted[2] = {};
|
static bool attempted[creditPageCount] = {};
|
||||||
|
|
||||||
if (index < 0 || index >= 2)
|
if (index < 0 || index >= creditPageCount)
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -147,19 +148,29 @@ static Bitmap* LoadCreditImage(int index)
|
|||||||
GdiplusStartupInput startupInput;
|
GdiplusStartupInput startupInput;
|
||||||
if (GdiplusStartup(&gdiplusToken, &startupInput, nullptr) == Ok)
|
if (GdiplusStartup(&gdiplusToken, &startupInput, nullptr) == Ok)
|
||||||
{
|
{
|
||||||
const wchar_t* imageNames[2] =
|
const wchar_t* imageNames[creditPageCount] =
|
||||||
{
|
{
|
||||||
L"assets\\images\\qls.jpg",
|
L"assets\\images\\qls.jpg",
|
||||||
L"assets\\images\\wyk.jpg"
|
L"assets\\images\\wyk.jpg",
|
||||||
|
L"assets\\images\\swj.jpg",
|
||||||
|
L"assets\\images\\qhy.jpg"
|
||||||
};
|
};
|
||||||
const std::wstring candidates[] =
|
const std::wstring creditExtraCandidates[] =
|
||||||
{
|
{
|
||||||
BuildAssetPath(imageNames[index]),
|
BuildAssetPath(imageNames[index]),
|
||||||
BuildWorkingDirAssetPath(imageNames[index])
|
BuildWorkingDirAssetPath(imageNames[index]),
|
||||||
|
BuildAssetPath(L"assets\\images\\qhy.png"),
|
||||||
|
BuildWorkingDirAssetPath(L"assets\\images\\qhy.png"),
|
||||||
|
BuildAssetPath(L"assets\\images\\qhy.jpeg"),
|
||||||
|
BuildWorkingDirAssetPath(L"assets\\images\\qhy.jpeg"),
|
||||||
|
BuildAssetPath(L"assets\\images\\qhy.bmp"),
|
||||||
|
BuildWorkingDirAssetPath(L"assets\\images\\qhy.bmp")
|
||||||
};
|
};
|
||||||
|
int candidateCount = (index == 3) ? 8 : 2;
|
||||||
|
|
||||||
for (const std::wstring& candidate : candidates)
|
for (int i = 0; i < candidateCount; i++)
|
||||||
{
|
{
|
||||||
|
const std::wstring& candidate = creditExtraCandidates[i];
|
||||||
if (candidate.empty())
|
if (candidate.empty())
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
@@ -637,6 +648,10 @@ void TDrawScreen(HDC hdc, HWND hWnd)
|
|||||||
{
|
{
|
||||||
helpTitle = _T("\u81f4\u8c22");
|
helpTitle = _T("\u81f4\u8c22");
|
||||||
}
|
}
|
||||||
|
else if (helpState.currentPage == 5)
|
||||||
|
{
|
||||||
|
helpTitle = _T("\u6280\u80fd\u6f14\u793a");
|
||||||
|
}
|
||||||
DrawText(hdc, helpTitle, -1, &rulesTitleRect, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
|
DrawText(hdc, helpTitle, -1, &rulesTitleRect, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
|
||||||
|
|
||||||
HPEN rulesAccentPen = CreatePen(PS_SOLID, SS(3), accentColor);
|
HPEN rulesAccentPen = CreatePen(PS_SOLID, SS(3), accentColor);
|
||||||
@@ -656,17 +671,19 @@ void TDrawScreen(HDC hdc, HWND hWnd)
|
|||||||
|
|
||||||
if (helpState.currentPage == 0)
|
if (helpState.currentPage == 0)
|
||||||
{
|
{
|
||||||
const TCHAR* optionTitles[3] =
|
const TCHAR* optionTitles[4] =
|
||||||
{
|
{
|
||||||
_T("\u6e38\u620f\u4ecb\u7ecd"),
|
_T("\u6e38\u620f\u4ecb\u7ecd"),
|
||||||
_T("\u64cd\u4f5c\u8bf4\u660e"),
|
_T("\u64cd\u4f5c\u8bf4\u660e"),
|
||||||
_T("\u5f3a\u5316\u56fe\u9274")
|
_T("\u5f3a\u5316\u56fe\u9274"),
|
||||||
|
_T("\u6280\u80fd\u6f14\u793a")
|
||||||
};
|
};
|
||||||
const TCHAR* optionDetails[3] =
|
const TCHAR* optionDetails[4] =
|
||||||
{
|
{
|
||||||
_T("\u7ecf\u5178\u6a21\u5f0f\u3001Rogue \u6a21\u5f0f\u548c\u590d\u6d3b\u89c4\u5219\u6982\u89c8\u3002"),
|
_T("\u7ecf\u5178\u6a21\u5f0f\u3001Rogue \u6a21\u5f0f\u548c\u590d\u6d3b\u89c4\u5219\u6982\u89c8\u3002"),
|
||||||
_T("\u79fb\u52a8\u3001\u65cb\u8f6c\u3001\u786c\u964d\u3001Hold \u4e0e\u6280\u80fd\u5feb\u6377\u952e\u3002"),
|
_T("\u79fb\u52a8\u3001\u65cb\u8f6c\u3001\u786c\u964d\u3001Hold \u4e0e\u6280\u80fd\u5feb\u6377\u952e\u3002"),
|
||||||
_T("\u67e5\u770b Rogue \u6a21\u5f0f\u5168\u90e8\u5f3a\u5316\u7684\u7b80\u8981\u6548\u679c\u3002")
|
_T("\u67e5\u770b Rogue \u6a21\u5f0f\u5168\u90e8\u5f3a\u5316\u7684\u7b80\u8981\u6548\u679c\u3002"),
|
||||||
|
_T("\u9009\u62e9\u4e00\u4e2a\u9884\u8bbe\u573a\u666f\uff0c\u4eb2\u81ea\u64cd\u4f5c\u89e6\u53d1 Rogue \u6280\u80fd\u6548\u679c\u3002")
|
||||||
};
|
};
|
||||||
|
|
||||||
int optionHeight = SS(100);
|
int optionHeight = SS(100);
|
||||||
@@ -765,8 +782,8 @@ void TDrawScreen(HDC hdc, HWND hWnd)
|
|||||||
const TCHAR* categoryTexts[8] =
|
const TCHAR* categoryTexts[8] =
|
||||||
{
|
{
|
||||||
_T("赏金纹章:所有得分收益提高 20%,可重复叠加,是最直接的分数成长。\r\n成长印记:所有 EXP 收益提高 25%,可重复叠加,用来更快进入后续构筑。\r\n缓坠羽翼:降低自然下落速度,最多叠加 4 次。\r\n连击律动:连续消行时追加得分和 EXP,断连后重新累计。\r\n先见之眼:额外显示 1 个后续方块;第三个预览由操控大师解锁。"),
|
_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("最后一搏:首次濒死时自动清理底部 3 行,并保留本局继续机会。\r\n备用仓:解锁 C / Shift,将当前方块放入 Hold 仓或取出备用方块。\r\n完美旋转:旋转被阻挡时尝试左右修正,提高贴墙和缝隙旋转成功率。\r\n时间缓流:堆叠过高时自动减速,给危险局面留出处理时间。\r\n空中换形:可重复补充次数,按 V 将当前下落方块变成 I 块。"),
|
||||||
_T("卸压清场:获得时立刻清除最高的一条占用行,直接降低顶部压力。\r\n底线清道夫:通过消行充能自动清底;每级降低需求,最多 4 级。\r\n清屏炸弹:按 X 主动清理底部 5 行,需要通过消行充能后使用。\r\n黑洞奇点:可重复补充次数,按 Z 吞噬当前场上数量最多的一种颜色方块。"),
|
_T("卸压清场:获得时立刻清除最高的一条占用行,直接降低顶部压力。\r\n底线清道夫:通过消行充能自动清底;每级降低需求,最多 4 级。\r\n清屏炸弹:可重复补充数量,按 X 主动清理底部 5 行,消行也会继续充能。\r\n黑洞奇点:可重复补充次数,按 Z 吞噬当前场上数量最多的一种颜色方块。"),
|
||||||
_T("爆破核心:一次性解锁橙红边框方块,落地后以落点为中心清除 3x3 区域。\r\n棱镜激光:一次性解锁青色边框方块,按落地中心列清除整列固定方块。\r\n十字方块:一次性解锁绿色边框方块,按落地中心同时清除一行一列。\r\n彩虹方块:一次性解锁紫色边框方块,清中心行主色并把覆盖行染成场上主色。\r\n方块改造:提高指定方块出现概率,目前主要强化 I 块生成。"),
|
_T("爆破核心:一次性解锁橙红边框方块,落地后以落点为中心清除 3x3 区域。\r\n棱镜激光:一次性解锁青色边框方块,按落地中心列清除整列固定方块。\r\n十字方块:一次性解锁绿色边框方块,按落地中心同时清除一行一列。\r\n彩虹方块:一次性解锁紫色边框方块,清中心行主色并把覆盖行染成场上主色。\r\n方块改造:提高指定方块出现概率,目前主要强化 I 块生成。"),
|
||||||
_T("连锁火花:完成消行后追加随机破坏,适合配合稳定堆叠扩大收益。\r\n连环炸弹:强化爆破核心,将爆破范围从 3x3 扩大为 5x5。\r\n雷霆四消:三消或四消后追加雷击,额外清除局部方块。\r\n雷霆棱镜:三消或四消后追加激光清列,强化四消后的清场能力。"),
|
_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("狂热节拍:累计清除 12 行进入狂热,狂热期间收益更高。\r\n怒火连段:连击越高倍率越高,适合连续小消和稳定节奏。\r\n无尽狂热:狂热期间继续消行会延长狂热时间。\r\n高压悬赏:游戏速度更快,但高压下收益也更高。\r\n豪赌四消:四消收益更高,但非四消表现更不稳定。\r\n极限玩家:危险高度下获得更高收益,同时承担更高操作压力。\r\n赌徒契约:后续强化有概率翻倍或落空,每级提高概率,最多 4 级。"),
|
||||||
@@ -876,18 +893,108 @@ void TDrawScreen(HDC hdc, HWND hWnd)
|
|||||||
DeleteObject(contentClipRegion);
|
DeleteObject(contentClipRegion);
|
||||||
DeleteObject(oldClipRegion);
|
DeleteObject(oldClipRegion);
|
||||||
}
|
}
|
||||||
|
else if (helpState.currentPage == 5)
|
||||||
|
{
|
||||||
|
int demoCount = GetRogueSkillDemoCount();
|
||||||
|
int itemHeight = SS(58);
|
||||||
|
int itemGap = SS(10);
|
||||||
|
int contentHeight = contentRect.bottom - contentRect.top;
|
||||||
|
int virtualHeight = SS(8) + demoCount * (itemHeight + itemGap);
|
||||||
|
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 itemTop = contentRect.top + SS(8) - helpScrollOffset;
|
||||||
|
for (int i = 0; i < demoCount; i++)
|
||||||
|
{
|
||||||
|
RECT itemRect =
|
||||||
|
{
|
||||||
|
contentRect.left,
|
||||||
|
itemTop + i * (itemHeight + itemGap),
|
||||||
|
contentRect.right,
|
||||||
|
itemTop + i * (itemHeight + itemGap) + itemHeight
|
||||||
|
};
|
||||||
|
|
||||||
|
if (itemRect.bottom < contentRect.top || itemRect.top > contentRect.bottom)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool selected = (i == helpState.selectedIndex);
|
||||||
|
COLORREF itemFill = selected ? RGB(255, 245, 249) : RGB(255, 252, 250);
|
||||||
|
COLORREF itemFrame = selected ? accentColor : frameColor;
|
||||||
|
HPEN itemPen = CreatePen(PS_SOLID, selected ? SS(2) : SS(1), itemFrame);
|
||||||
|
HBRUSH itemBrush = CreateSolidBrush(itemFill);
|
||||||
|
oldPen = (HPEN)SelectObject(hdc, itemPen);
|
||||||
|
oldBrush = (HBRUSH)SelectObject(hdc, itemBrush);
|
||||||
|
RoundRect(hdc, itemRect.left, itemRect.top, itemRect.right, itemRect.bottom, SS(18), SS(18));
|
||||||
|
SelectObject(hdc, oldBrush);
|
||||||
|
SelectObject(hdc, oldPen);
|
||||||
|
DeleteObject(itemBrush);
|
||||||
|
DeleteObject(itemPen);
|
||||||
|
|
||||||
|
SetTextColor(hdc, selected ? titleColor : textColor);
|
||||||
|
SelectObject(hdc, sectionFont);
|
||||||
|
RECT nameRect =
|
||||||
|
{
|
||||||
|
itemRect.left + SS(22),
|
||||||
|
itemRect.top + SS(8),
|
||||||
|
itemRect.left + SS(210),
|
||||||
|
itemRect.bottom - SS(8)
|
||||||
|
};
|
||||||
|
DrawText(hdc, GetRogueSkillDemoName(i), -1, &nameRect, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
|
||||||
|
|
||||||
|
SetTextColor(hdc, RGB(112, 91, 104));
|
||||||
|
SelectObject(hdc, bodyFont);
|
||||||
|
RECT detailRect =
|
||||||
|
{
|
||||||
|
itemRect.left + SS(220),
|
||||||
|
itemRect.top + SS(8),
|
||||||
|
itemRect.right - SS(22),
|
||||||
|
itemRect.bottom - SS(8)
|
||||||
|
};
|
||||||
|
DrawText(hdc, GetRogueSkillDemoDetail(i), -1, &detailRect, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasOldClipRegion == 1)
|
||||||
|
{
|
||||||
|
SelectClipRgn(hdc, oldClipRegion);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SelectClipRgn(hdc, nullptr);
|
||||||
|
}
|
||||||
|
DeleteObject(contentClipRegion);
|
||||||
|
DeleteObject(oldClipRegion);
|
||||||
|
}
|
||||||
else if (helpState.currentPage == 4)
|
else if (helpState.currentPage == 4)
|
||||||
{
|
{
|
||||||
const int creditAnimationTotalTicks = 60;
|
const int creditAnimationTotalTicks = 60;
|
||||||
const TCHAR* creditNames[2] =
|
constexpr int creditPageCount = 4;
|
||||||
|
const TCHAR* creditNames[creditPageCount] =
|
||||||
{
|
{
|
||||||
_T("qls"),
|
_T("qls"),
|
||||||
_T("wyk")
|
_T("wyk"),
|
||||||
|
_T("juju"),
|
||||||
|
_T("qhy")
|
||||||
};
|
};
|
||||||
const TCHAR* creditTexts[2] =
|
const TCHAR* creditTexts[creditPageCount] =
|
||||||
{
|
{
|
||||||
_T("\u611f\u8c22\u6fc0\u60c5\u6295\u8eab\u4e8e\u6d4b\u8bd5\u4e4b\u4e2d\u7684Lisa"),
|
_T("\u611f\u8c22\u6fc0\u60c5\u6295\u8eab\u4e8e\u6d4b\u8bd5\u4e4b\u4e2d\u7684Lisa"),
|
||||||
_T("\u611f\u8c22\u70ed\u5ff1coding\u7684\u5c0f\u86cb\u7cd5")
|
_T("\u611f\u8c22\u70ed\u5ff1coding\u7684\u5c0f\u86cb\u7cd5"),
|
||||||
|
_T("\u611f\u8c22\u8bfe\u524d\u95f2\u91cc\u5077\u5fd9\u7684juju"),
|
||||||
|
_T("\u611f\u8c22qhy\u7684\u5929\u624d\u6784\u60f3")
|
||||||
};
|
};
|
||||||
|
|
||||||
int currentCredit = creditPageIndex;
|
int currentCredit = creditPageIndex;
|
||||||
@@ -895,17 +1002,17 @@ void TDrawScreen(HDC hdc, HWND hWnd)
|
|||||||
{
|
{
|
||||||
currentCredit = 0;
|
currentCredit = 0;
|
||||||
}
|
}
|
||||||
if (currentCredit > 1)
|
if (currentCredit >= creditPageCount)
|
||||||
{
|
{
|
||||||
currentCredit = 1;
|
currentCredit = creditPageCount - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int previousCredit = currentCredit - creditAnimationDirection;
|
int previousCredit = currentCredit - creditAnimationDirection;
|
||||||
if (previousCredit < 0)
|
if (previousCredit < 0)
|
||||||
{
|
{
|
||||||
previousCredit = 1;
|
previousCredit = creditPageCount - 1;
|
||||||
}
|
}
|
||||||
if (previousCredit > 1)
|
if (previousCredit >= creditPageCount)
|
||||||
{
|
{
|
||||||
previousCredit = 0;
|
previousCredit = 0;
|
||||||
}
|
}
|
||||||
@@ -939,8 +1046,11 @@ void TDrawScreen(HDC hdc, HWND hWnd)
|
|||||||
previousOffset = currentOffset - creditAnimationDirection * slideDistance;
|
previousOffset = currentOffset - creditAnimationDirection * slideDistance;
|
||||||
}
|
}
|
||||||
|
|
||||||
Bitmap* preloadedCreditImageA = LoadCreditImage(0);
|
Bitmap* preloadedCreditImages[creditPageCount] = {};
|
||||||
Bitmap* preloadedCreditImageB = LoadCreditImage(1);
|
for (int i = 0; i < creditPageCount; i++)
|
||||||
|
{
|
||||||
|
preloadedCreditImages[i] = LoadCreditImage(i);
|
||||||
|
}
|
||||||
Graphics creditGraphics(hdc);
|
Graphics creditGraphics(hdc);
|
||||||
creditGraphics.SetInterpolationMode(InterpolationModeHighQualityBilinear);
|
creditGraphics.SetInterpolationMode(InterpolationModeHighQualityBilinear);
|
||||||
|
|
||||||
@@ -951,7 +1061,11 @@ void TDrawScreen(HDC hdc, HWND hWnd)
|
|||||||
OffsetRect(&shiftedImageArea, offset, 0);
|
OffsetRect(&shiftedImageArea, offset, 0);
|
||||||
OffsetRect(&shiftedTextArea, offset, 0);
|
OffsetRect(&shiftedTextArea, offset, 0);
|
||||||
|
|
||||||
Bitmap* creditImage = (cardIndex == 0) ? preloadedCreditImageA : preloadedCreditImageB;
|
Bitmap* creditImage = nullptr;
|
||||||
|
if (cardIndex >= 0 && cardIndex < creditPageCount)
|
||||||
|
{
|
||||||
|
creditImage = preloadedCreditImages[cardIndex];
|
||||||
|
}
|
||||||
if (creditImage != nullptr)
|
if (creditImage != nullptr)
|
||||||
{
|
{
|
||||||
int imageWidth = static_cast<int>(creditImage->GetWidth());
|
int imageWidth = static_cast<int>(creditImage->GetWidth());
|
||||||
@@ -1067,7 +1181,7 @@ void TDrawScreen(HDC hdc, HWND hWnd)
|
|||||||
SelectObject(hdc, oldPen);
|
SelectObject(hdc, oldPen);
|
||||||
DeleteObject(chevronPen);
|
DeleteObject(chevronPen);
|
||||||
}
|
}
|
||||||
if (helpState.currentPage != 3 && helpState.currentPage != 4)
|
if (helpState.currentPage != 3 && helpState.currentPage != 4 && helpState.currentPage != 5)
|
||||||
{
|
{
|
||||||
RECT calculateRect = { contentRect.left, contentRect.top, contentRect.right, contentRect.top };
|
RECT calculateRect = { contentRect.left, contentRect.top, contentRect.right, contentRect.top };
|
||||||
DrawText(hdc, pageText, -1, &calculateRect, pageFlags | DT_CALCRECT);
|
DrawText(hdc, pageText, -1, &calculateRect, pageFlags | DT_CALCRECT);
|
||||||
@@ -1117,7 +1231,9 @@ void TDrawScreen(HDC hdc, HWND hWnd)
|
|||||||
? _T("\u65b9\u5411\u952e / WASD \u5207\u6362\uff0cEnter / Space \u786e\u8ba4\uff0cEsc / M \u8fd4\u56de\u4e3b\u83dc\u5355")
|
? _T("\u65b9\u5411\u952e / WASD \u5207\u6362\uff0cEnter / Space \u786e\u8ba4\uff0cEsc / M \u8fd4\u56de\u4e3b\u83dc\u5355")
|
||||||
: (helpState.currentPage == 4
|
: (helpState.currentPage == 4
|
||||||
? _T("\u5de6\u53f3\u65b9\u5411\u952e / A D \u5207\u6362\uff0cEsc / Backspace / M \u8fd4\u56de\u4e3b\u83dc\u5355")
|
? _T("\u5de6\u53f3\u65b9\u5411\u952e / A D \u5207\u6362\uff0cEsc / Backspace / M \u8fd4\u56de\u4e3b\u83dc\u5355")
|
||||||
: _T("\u9f20\u6807\u6eda\u8f6e\u4e0a\u4e0b\u7ffb\u52a8\uff0cEsc / Backspace / M \u8fd4\u56de\u5e2e\u52a9"));
|
: (helpState.currentPage == 5
|
||||||
|
? _T("\u70b9\u51fb\u6280\u80fd\u540d\u79f0\u6216 Enter \u8fdb\u5165\u64cd\u4f5c\u573a\u666f\uff0c\u6eda\u8f6e\u7ffb\u52a8\uff0cEsc / 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);
|
DrawText(hdc, helpHint, -1, &backHintRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
|
||||||
|
|
||||||
SelectClipRgn(hdc, nullptr);
|
SelectClipRgn(hdc, nullptr);
|
||||||
@@ -1357,6 +1473,72 @@ void TDrawScreen(HDC hdc, HWND hWnd)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 80; i++)
|
||||||
|
{
|
||||||
|
if (gravityFallEffects[i].ticks <= 0 || gravityFallEffects[i].totalTicks <= 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gravityFallEffects[i].x < 0 || gravityFallEffects[i].x >= nGameWidth ||
|
||||||
|
gravityFallEffects[i].fromY < 0 || gravityFallEffects[i].fromY >= nGameHeight ||
|
||||||
|
gravityFallEffects[i].toY < 0 || gravityFallEffects[i].toY >= nGameHeight)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int elapsed = gravityFallEffects[i].totalTicks - gravityFallEffects[i].ticks;
|
||||||
|
int travel = gravityFallEffects[i].toY - gravityFallEffects[i].fromY;
|
||||||
|
int offsetY = travel * grid * elapsed / gravityFallEffects[i].totalTicks;
|
||||||
|
int drawX = gameRect.left + gravityFallEffects[i].x * grid;
|
||||||
|
int fromPixelY = gameRect.top + gravityFallEffects[i].fromY * grid;
|
||||||
|
int toPixelY = gameRect.top + gravityFallEffects[i].toY * grid;
|
||||||
|
int currentPixelY = fromPixelY + offsetY;
|
||||||
|
int colorIndex = gravityFallEffects[i].cellValue - 1;
|
||||||
|
if (colorIndex < 0 || colorIndex >= 7)
|
||||||
|
{
|
||||||
|
colorIndex = (gravityFallEffects[i].x + gravityFallEffects[i].toY) % 7;
|
||||||
|
}
|
||||||
|
COLORREF fallColor = BrickColor[colorIndex];
|
||||||
|
|
||||||
|
int alpha = 56 + gravityFallEffects[i].ticks * 150 / gravityFallEffects[i].totalTicks;
|
||||||
|
int trailTop = fromPixelY + grid / 2;
|
||||||
|
int trailBottom = currentPixelY + grid / 2;
|
||||||
|
if (trailBottom < trailTop + SS(8))
|
||||||
|
{
|
||||||
|
trailBottom = trailTop + SS(8);
|
||||||
|
}
|
||||||
|
if (trailBottom > toPixelY + grid / 2)
|
||||||
|
{
|
||||||
|
trailBottom = toPixelY + grid / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
Graphics fallGraphics(hdc);
|
||||||
|
fallGraphics.SetSmoothingMode(SmoothingModeAntiAlias);
|
||||||
|
SolidBrush trailBrush(Color(alpha / 2, GetRValue(fallColor), GetGValue(fallColor), GetBValue(fallColor)));
|
||||||
|
fallGraphics.FillRectangle(
|
||||||
|
&trailBrush,
|
||||||
|
static_cast<INT>(drawX + SS(12)),
|
||||||
|
static_cast<INT>(trailTop),
|
||||||
|
static_cast<INT>(grid - SS(24)),
|
||||||
|
static_cast<INT>(trailBottom - trailTop));
|
||||||
|
|
||||||
|
SolidBrush ghostBrush(Color(alpha, GetRValue(fallColor), GetGValue(fallColor), GetBValue(fallColor)));
|
||||||
|
Pen ghostPen(Color(230, 255, 255, 255), static_cast<REAL>(SS(2)));
|
||||||
|
fallGraphics.FillRectangle(
|
||||||
|
&ghostBrush,
|
||||||
|
static_cast<INT>(drawX + SS(3)),
|
||||||
|
static_cast<INT>(currentPixelY + SS(3)),
|
||||||
|
static_cast<INT>(grid - SS(6)),
|
||||||
|
static_cast<INT>(grid - SS(6)));
|
||||||
|
fallGraphics.DrawRectangle(
|
||||||
|
&ghostPen,
|
||||||
|
static_cast<INT>(drawX + SS(3)),
|
||||||
|
static_cast<INT>(currentPixelY + SS(3)),
|
||||||
|
static_cast<INT>(grid - SS(6)),
|
||||||
|
static_cast<INT>(grid - SS(6)));
|
||||||
|
}
|
||||||
|
|
||||||
if (clearEffectState.ticks > 0 && clearEffectState.totalTicks > 0)
|
if (clearEffectState.ticks > 0 && clearEffectState.totalTicks > 0)
|
||||||
{
|
{
|
||||||
int elapsed = clearEffectState.totalTicks - clearEffectState.ticks;
|
int elapsed = clearEffectState.totalTicks - clearEffectState.ticks;
|
||||||
@@ -1545,12 +1727,50 @@ void TDrawScreen(HDC hdc, HWND hWnd)
|
|||||||
|
|
||||||
if (currentMode == MODE_ROGUE)
|
if (currentMode == MODE_ROGUE)
|
||||||
{
|
{
|
||||||
RECT progressRect =
|
int progressTop = IsRogueSkillDemoMode() ? 350 : 270;
|
||||||
|
int progressBottom = IsRogueSkillDemoMode() ? 568 : 488;
|
||||||
|
int upgradeTop = IsRogueSkillDemoMode() ? 590 : 510;
|
||||||
|
|
||||||
|
if (IsRogueSkillDemoMode())
|
||||||
|
{
|
||||||
|
RECT demoSkillRect =
|
||||||
{
|
{
|
||||||
leftPanelRect.left + SS(20),
|
leftPanelRect.left + SS(20),
|
||||||
leftPanelRect.top + SS(270),
|
leftPanelRect.top + SS(270),
|
||||||
leftPanelRect.right - SS(20),
|
leftPanelRect.right - SS(20),
|
||||||
leftPanelRect.top + SS(488)
|
leftPanelRect.top + SS(332)
|
||||||
|
};
|
||||||
|
DrawPanelCardAlpha(demoSkillRect, RGB(255, 244, 248), RGB(232, 184, 202), 20, panelNestedAlpha);
|
||||||
|
|
||||||
|
SelectObject(hdc, smallFont);
|
||||||
|
SetTextColor(hdc, RGB(132, 102, 118));
|
||||||
|
RECT demoSkillLabelRect =
|
||||||
|
{
|
||||||
|
demoSkillRect.left + SS(18),
|
||||||
|
demoSkillRect.top + SS(8),
|
||||||
|
demoSkillRect.right - SS(18),
|
||||||
|
demoSkillRect.top + SS(26)
|
||||||
|
};
|
||||||
|
DrawText(hdc, _T("\u5f53\u524d\u6280\u80fd"), -1, &demoSkillLabelRect, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
|
||||||
|
|
||||||
|
SelectObject(hdc, sectionFont);
|
||||||
|
SetTextColor(hdc, titleColor);
|
||||||
|
RECT demoSkillNameRect =
|
||||||
|
{
|
||||||
|
demoSkillRect.left + SS(18),
|
||||||
|
demoSkillRect.top + SS(26),
|
||||||
|
demoSkillRect.right - SS(18),
|
||||||
|
demoSkillRect.bottom - SS(8)
|
||||||
|
};
|
||||||
|
DrawText(hdc, GetCurrentRogueSkillDemoName(), -1, &demoSkillNameRect, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
|
||||||
|
}
|
||||||
|
|
||||||
|
RECT progressRect =
|
||||||
|
{
|
||||||
|
leftPanelRect.left + SS(20),
|
||||||
|
leftPanelRect.top + SS(progressTop),
|
||||||
|
leftPanelRect.right - SS(20),
|
||||||
|
leftPanelRect.top + SS(progressBottom)
|
||||||
};
|
};
|
||||||
DrawPanelCardAlpha(progressRect, RGB(255, 248, 251), RGB(233, 191, 208), 24, panelAlpha);
|
DrawPanelCardAlpha(progressRect, RGB(255, 248, 251), RGB(233, 191, 208), 24, panelAlpha);
|
||||||
|
|
||||||
@@ -1654,7 +1874,7 @@ void TDrawScreen(HDC hdc, HWND hWnd)
|
|||||||
RECT upgradeListRect =
|
RECT upgradeListRect =
|
||||||
{
|
{
|
||||||
leftPanelRect.left + SS(20),
|
leftPanelRect.left + SS(20),
|
||||||
leftPanelRect.top + SS(510),
|
leftPanelRect.top + SS(upgradeTop),
|
||||||
leftPanelRect.right - SS(20),
|
leftPanelRect.right - SS(20),
|
||||||
leftPanelRect.bottom - SS(20)
|
leftPanelRect.bottom - SS(20)
|
||||||
};
|
};
|
||||||
@@ -1758,7 +1978,7 @@ void TDrawScreen(HDC hdc, HWND hWnd)
|
|||||||
}
|
}
|
||||||
if (rogueStats.screenBombLevel > 0)
|
if (rogueStats.screenBombLevel > 0)
|
||||||
{
|
{
|
||||||
_stprintf_s(upgradeSummary + lstrlen(upgradeSummary), 512 - lstrlen(upgradeSummary), _T("\u6e05\u5c4f\u70b8\u5f39 Lv.1\r\n"));
|
_stprintf_s(upgradeSummary + lstrlen(upgradeSummary), 512 - lstrlen(upgradeSummary), _T("\u6e05\u5c4f\u70b8\u5f39 Lv.%d \u5269\u4f59 %d \u679a\r\n"), rogueStats.screenBombLevel, rogueStats.screenBombCount);
|
||||||
}
|
}
|
||||||
if (rogueStats.terminalClearLevel > 0)
|
if (rogueStats.terminalClearLevel > 0)
|
||||||
{
|
{
|
||||||
@@ -1810,7 +2030,7 @@ void TDrawScreen(HDC hdc, HWND hWnd)
|
|||||||
}
|
}
|
||||||
if (rogueStats.reshapeLevel > 0)
|
if (rogueStats.reshapeLevel > 0)
|
||||||
{
|
{
|
||||||
_stprintf_s(upgradeSummary + lstrlen(upgradeSummary), 512 - lstrlen(upgradeSummary), _T("\u7a7a\u4e2d\u6362\u5f62 Lv.1\r\n"));
|
_stprintf_s(upgradeSummary + lstrlen(upgradeSummary), 512 - lstrlen(upgradeSummary), _T("\u7a7a\u4e2d\u6362\u5f62 Lv.%d \u5269\u4f59 %d \u6b21\r\n"), rogueStats.reshapeLevel, rogueStats.reshapeCharges);
|
||||||
}
|
}
|
||||||
if (rogueStats.rainbowPieceLevel > 0)
|
if (rogueStats.rainbowPieceLevel > 0)
|
||||||
{
|
{
|
||||||
@@ -2205,6 +2425,20 @@ void TDrawScreen(HDC hdc, HWND hWnd)
|
|||||||
controlRect.bottom - SS(22)
|
controlRect.bottom - SS(22)
|
||||||
};
|
};
|
||||||
if (currentMode == MODE_ROGUE)
|
if (currentMode == MODE_ROGUE)
|
||||||
|
{
|
||||||
|
if (IsRogueSkillDemoMode())
|
||||||
|
{
|
||||||
|
DrawText(
|
||||||
|
hdc,
|
||||||
|
_T("\u79fb\u52a8\uff1a\u2190/\u2192 \u6216 A/D\r\n")
|
||||||
|
_T("\u65cb\u8f6c/\u4e0b\u843d\uff1a\u2191/W\u3001\u2193/S\u3001Space\r\n")
|
||||||
|
_T("演示:R 重置当前 N 下一个 M 菜单\r\n")
|
||||||
|
_T("技能:C 备用仓 Z 黑洞 X 炸弹 V 换形"),
|
||||||
|
-1,
|
||||||
|
&controlBodyRect,
|
||||||
|
DT_LEFT | DT_TOP | DT_WORDBREAK);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
DrawText(
|
DrawText(
|
||||||
hdc,
|
hdc,
|
||||||
@@ -2216,6 +2450,7 @@ void TDrawScreen(HDC hdc, HWND hWnd)
|
|||||||
&controlBodyRect,
|
&controlBodyRect,
|
||||||
DT_LEFT | DT_TOP | DT_WORDBREAK);
|
DT_LEFT | DT_TOP | DT_WORDBREAK);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DrawText(
|
DrawText(
|
||||||
|
|||||||
+822
-12
@@ -73,7 +73,7 @@ static const UpgradeEntry kUpgradePool[] =
|
|||||||
{ UPGRADE_FEVER_MODE, 1, 92, false, _T("狂热节拍"), _T("进阶"), _T("累计消行 12 行后进入 12 秒狂热:得分与 EXP 翻倍。") },
|
{ UPGRADE_FEVER_MODE, 1, 92, false, _T("狂热节拍"), _T("进阶"), _T("累计消行 12 行后进入 12 秒狂热:得分与 EXP 翻倍。") },
|
||||||
{ UPGRADE_RAGE_STACK, 1, 84, false, _T("怒火连段"), _T("进阶"), _T("连续消行越多,得分倍率追加越高。") },
|
{ UPGRADE_RAGE_STACK, 1, 84, false, _T("怒火连段"), _T("进阶"), _T("连续消行越多,得分倍率追加越高。") },
|
||||||
{ UPGRADE_INFINITE_FEVER, 1, 110, false, _T("无尽狂热"), _T("进化"), _T("狂热期间消行可延长狂热时间;连击越高,倍率越凶。") },
|
{ UPGRADE_INFINITE_FEVER, 1, 110, false, _T("无尽狂热"), _T("进化"), _T("狂热期间消行可延长狂热时间;连击越高,倍率越凶。") },
|
||||||
{ UPGRADE_SCREEN_BOMB, 1, 90, false, _T("清屏炸弹"), _T("进阶"), _T("立刻获得 1 枚炸弹;之后累计消行 16 行再获得 1 枚。按 X 清底 5 行。") },
|
{ UPGRADE_SCREEN_BOMB, -1, 90, true, _T("清屏炸弹"), _T("进阶"), _T("立刻获得 1 枚炸弹;可重复选择补充数量,之后累计消行 16 行再获得 1 枚。按 X 清底 5 行。") },
|
||||||
{ UPGRADE_TERMINAL_CLEAR, 1, 108, false, _T("终末清场"), _T("进化"), _T("最后一搏启动时,自动引爆 1 枚清屏炸弹,并进入 10 秒狂热。") },
|
{ UPGRADE_TERMINAL_CLEAR, 1, 108, false, _T("终末清场"), _T("进化"), _T("最后一搏启动时,自动引爆 1 枚清屏炸弹,并进入 10 秒狂热。") },
|
||||||
{ UPGRADE_DUAL_CHOICE, 1, 68, false, _T("双重抉择"), _T("进阶"), _T("每次升级可额外选择 1 个强化,但下一次升级所需 EXP +30%。") },
|
{ UPGRADE_DUAL_CHOICE, 1, 68, false, _T("双重抉择"), _T("进阶"), _T("每次升级可额外选择 1 个强化,但下一次升级所需 EXP +30%。") },
|
||||||
{ UPGRADE_DESTINY_WHEEL, 1, 104, false, _T("命运轮盘"), _T("进化"), _T("升级时出现 6 个选项,可选择 2 个;其中 1 个会携带诅咒。") },
|
{ UPGRADE_DESTINY_WHEEL, 1, 104, false, _T("命运轮盘"), _T("进化"), _T("升级时出现 6 个选项,可选择 2 个;其中 1 个会携带诅咒。") },
|
||||||
@@ -88,7 +88,7 @@ static const UpgradeEntry kUpgradePool[] =
|
|||||||
{ UPGRADE_BLOCK_STORM, 1, 82, false, _T("方块风暴"), _T("爆发"), _T("接下来 5 个方块全部变为 I 块,快速制造四消机会。") },
|
{ UPGRADE_BLOCK_STORM, 1, 82, false, _T("方块风暴"), _T("爆发"), _T("接下来 5 个方块全部变为 I 块,快速制造四消机会。") },
|
||||||
{ UPGRADE_CROSS_PIECE, 1, 84, false, _T("十字方块"), _T("爆发"), _T("解锁十字方块生成。十字方块落地后清除所在行与所在列。") },
|
{ UPGRADE_CROSS_PIECE, 1, 84, false, _T("十字方块"), _T("爆发"), _T("解锁十字方块生成。十字方块落地后清除所在行与所在列。") },
|
||||||
{ UPGRADE_BLACK_HOLE, -1, 88, true, _T("黑洞奇点"), _T("特殊"), _T("获得 2 次黑洞。可重复选择继续补充次数;按 Z 吞噬棋盘上数量最多的一种固定方块。") },
|
{ UPGRADE_BLACK_HOLE, -1, 88, true, _T("黑洞奇点"), _T("特殊"), _T("获得 2 次黑洞。可重复选择继续补充次数;按 Z 吞噬棋盘上数量最多的一种固定方块。") },
|
||||||
{ UPGRADE_AIR_RESHAPE, 1, 82, false, _T("空中换形"), _T("操作"), _T("获得 2 次换形。按 V 将正在下落的方块重塑为 I 块。") },
|
{ UPGRADE_AIR_RESHAPE, -1, 82, true, _T("空中换形"), _T("操作"), _T("获得 2 次换形。可重复选择继续补充次数;按 V 将正在下落的方块重塑为 I 块。") },
|
||||||
{ UPGRADE_RAINBOW_PIECE, 1, 84, false, _T("彩虹方块"), _T("爆发"), _T("解锁彩虹方块生成。落地后清中心行主色,并把覆盖行染成场上主色。") },
|
{ UPGRADE_RAINBOW_PIECE, 1, 84, false, _T("彩虹方块"), _T("爆发"), _T("解锁彩虹方块生成。落地后清中心行主色,并把覆盖行染成场上主色。") },
|
||||||
{ UPGRADE_VOID_CORE, 1, 112, false, _T("虚空核心"), _T("进化"), _T("黑洞后额外生成 1 个彩虹方块;彩虹生效后追加一次小型黑洞。") },
|
{ UPGRADE_VOID_CORE, 1, 112, false, _T("虚空核心"), _T("进化"), _T("黑洞后额外生成 1 个彩虹方块;彩虹生效后追加一次小型黑洞。") },
|
||||||
{ UPGRADE_STABLE_STRUCTURE, -1, 72, true, _T("稳定结构"), _T("特殊"), _T("落地后有小概率填补邻近空洞,让阵型更加稳固。") },
|
{ UPGRADE_STABLE_STRUCTURE, -1, 72, true, _T("稳定结构"), _T("特殊"), _T("落地后有小概率填补邻近空洞,让阵型更加稳固。") },
|
||||||
@@ -109,6 +109,79 @@ static constexpr int kExplosiveBaseInterval = 6;
|
|||||||
static constexpr int kExplosiveMinInterval = 3;
|
static constexpr int kExplosiveMinInterval = 3;
|
||||||
static int pendingUpgradeShockwaveRows = 0;
|
static int pendingUpgradeShockwaveRows = 0;
|
||||||
static bool pendingEvolutionImpactShockwave = false;
|
static bool pendingEvolutionImpactShockwave = false;
|
||||||
|
static int rogueDemoStepIndex = 0;
|
||||||
|
static int rogueDemoTicks = 0;
|
||||||
|
static bool rogueDemoAutoAdvance = true;
|
||||||
|
|
||||||
|
enum RogueDemoKind
|
||||||
|
{
|
||||||
|
DEMO_SCORE_MULTIPLIER = 0,
|
||||||
|
DEMO_EXP_MULTIPLIER,
|
||||||
|
DEMO_SLOW_FALL,
|
||||||
|
DEMO_COMBO_BONUS,
|
||||||
|
DEMO_PREVIEW_PLUS_ONE,
|
||||||
|
DEMO_LAST_CHANCE,
|
||||||
|
DEMO_HOLD,
|
||||||
|
DEMO_PRESSURE_RELIEF,
|
||||||
|
DEMO_SWEEPER,
|
||||||
|
DEMO_EXPLOSIVE,
|
||||||
|
DEMO_STABLE_STRUCTURE,
|
||||||
|
DEMO_DOUBLE_GROWTH,
|
||||||
|
DEMO_PIECE_TUNING,
|
||||||
|
DEMO_GAMBLER,
|
||||||
|
DEMO_CHAIN_BLAST,
|
||||||
|
DEMO_CHAIN_BOMB,
|
||||||
|
DEMO_LASER,
|
||||||
|
DEMO_THUNDER_TETRIS,
|
||||||
|
DEMO_THUNDER_LASER,
|
||||||
|
DEMO_FEVER_MODE,
|
||||||
|
DEMO_RAGE_STACK,
|
||||||
|
DEMO_INFINITE_FEVER,
|
||||||
|
DEMO_SCREEN_BOMB,
|
||||||
|
DEMO_TERMINAL_CLEAR,
|
||||||
|
DEMO_DUAL_CHOICE,
|
||||||
|
DEMO_DESTINY_WHEEL,
|
||||||
|
DEMO_PERFECT_ROTATE,
|
||||||
|
DEMO_TIME_DILATION,
|
||||||
|
DEMO_HIGH_PRESSURE,
|
||||||
|
DEMO_TETRIS_GAMBLE,
|
||||||
|
DEMO_EXTREME_PLAYER,
|
||||||
|
DEMO_UPGRADE_SHOCKWAVE,
|
||||||
|
DEMO_EVOLUTION_IMPACT,
|
||||||
|
DEMO_CONTROL_MASTER,
|
||||||
|
DEMO_BLOCK_STORM,
|
||||||
|
DEMO_CROSS,
|
||||||
|
DEMO_BLACK_HOLE,
|
||||||
|
DEMO_AIR_RESHAPE,
|
||||||
|
DEMO_RAINBOW,
|
||||||
|
DEMO_VOID_CORE
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RogueDemoStep
|
||||||
|
{
|
||||||
|
int kind;
|
||||||
|
const TCHAR* name;
|
||||||
|
const TCHAR* detail;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const RogueDemoStep kRogueDemoSteps[] =
|
||||||
|
{
|
||||||
|
{ DEMO_HOLD, _T("备用仓"), _T("按 C / Shift 换出备用 I 块,再用 Space 填平底行缺口。") },
|
||||||
|
{ DEMO_BLACK_HOLE, _T("黑洞奇点"), _T("按 Z 吞噬场上最多的粉色方块,观察棋盘变化。") },
|
||||||
|
{ DEMO_SCREEN_BOMB, _T("清屏炸弹"), _T("按 X 主动引爆,清理底部 5 行高压区。") },
|
||||||
|
{ DEMO_AIR_RESHAPE, _T("空中换形"), _T("按 V 把当前方块变为 I 块,再用 Space 完成落位。") },
|
||||||
|
{ DEMO_EXPLOSIVE, _T("爆破核心"), _T("用方向键微调红框方块,Space 落地后清除 3x3 区域。") },
|
||||||
|
{ DEMO_CHAIN_BOMB, _T("连环炸弹"), _T("Space 落下红框方块,演示更大的连环爆破范围。") },
|
||||||
|
{ DEMO_LASER, _T("棱镜激光"), _T("把青色边框方块落到中列,落地后贯穿整列。") },
|
||||||
|
{ DEMO_CROSS, _T("十字方块"), _T("把绿色边框方块落到交叉点,清除一行一列。") },
|
||||||
|
{ DEMO_RAINBOW, _T("彩虹方块"), _T("把紫色边框方块落到彩色层,按中心行主色触发清除。") },
|
||||||
|
{ DEMO_VOID_CORE, _T("虚空核心"), _T("按 Z 释放黑洞后,下一枚方块会被召唤成彩虹方块。") },
|
||||||
|
{ DEMO_UPGRADE_SHOCKWAVE, _T("升级冲击波"), _T("Space 消一行立刻升级,不弹强化菜单并清除底部 2 行。") },
|
||||||
|
{ DEMO_STABLE_STRUCTURE, _T("稳定结构"), _T("Space 落地后只触发稳定结构,自动填补局部空洞。") }
|
||||||
|
};
|
||||||
|
|
||||||
|
static constexpr int kRogueDemoStepCount = sizeof(kRogueDemoSteps) / sizeof(kRogueDemoSteps[0]);
|
||||||
|
static constexpr int kRogueDemoStepTicks = 7;
|
||||||
|
|
||||||
static int GetUpgradeCurrentLevel(int upgradeId);
|
static int GetUpgradeCurrentLevel(int upgradeId);
|
||||||
static bool IsUpgradePrerequisiteConsumed(int upgradeId);
|
static bool IsUpgradePrerequisiteConsumed(int upgradeId);
|
||||||
@@ -136,6 +209,14 @@ static void FillUpgradeOptions();
|
|||||||
static void ApplyUpgradeById(int upgradeId, int targetPieceType, int applyCount);
|
static void ApplyUpgradeById(int upgradeId, int targetPieceType, int applyCount);
|
||||||
static void ApplyDestinyCurse();
|
static void ApplyDestinyCurse();
|
||||||
static void ClearLockedRows();
|
static void ClearLockedRows();
|
||||||
|
static void ApplyRogueSkillDemoStep();
|
||||||
|
static void ResetRogueDemoBoard();
|
||||||
|
static void ShowRogueDemoFloatingName(const TCHAR* name);
|
||||||
|
static void FillRogueDemoCell(int y, int x, int value);
|
||||||
|
static void FillRogueDemoRows(int firstRow, int lastRow, int baseValue);
|
||||||
|
static void FillRogueDemoRowExcept(int row, int gapStart, int gapWidth, int baseValue);
|
||||||
|
static void SetRogueDemoCurrentPiece(int pieceType, int pieceState, int x, int y);
|
||||||
|
static void StartRogueSkillDemoInternal(int demoIndex, bool autoAdvance);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 限制 Rogue 模式的下一方块预览数量。
|
* @brief 限制 Rogue 模式的下一方块预览数量。
|
||||||
@@ -211,7 +292,7 @@ static void ClearLockedRows()
|
|||||||
*/
|
*/
|
||||||
void AdvanceRogueDifficulty(int elapsedMs)
|
void AdvanceRogueDifficulty(int elapsedMs)
|
||||||
{
|
{
|
||||||
if (currentMode != MODE_ROGUE || currentScreen != SCREEN_PLAYING || suspendFlag || gameOverFlag || elapsedMs <= 0)
|
if (currentMode != MODE_ROGUE || rogueDemoMode || currentScreen != SCREEN_PLAYING || suspendFlag || gameOverFlag || elapsedMs <= 0)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -891,6 +972,25 @@ void RollCurrentPieceSpecialFlags(bool allowRandomSpecials)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rogueDemoMode)
|
||||||
|
{
|
||||||
|
if (currentMode == MODE_ROGUE && rogueStats.pendingRainbowPieceCount > 0)
|
||||||
|
{
|
||||||
|
rogueStats.pendingRainbowPieceCount--;
|
||||||
|
currentPieceIsExplosive = false;
|
||||||
|
currentPieceIsLaser = false;
|
||||||
|
currentPieceIsCross = false;
|
||||||
|
currentPieceIsRainbow = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentPieceIsExplosive = false;
|
||||||
|
currentPieceIsLaser = false;
|
||||||
|
currentPieceIsCross = false;
|
||||||
|
currentPieceIsRainbow = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (currentMode == MODE_ROGUE && rogueStats.pendingRainbowPieceCount > 0)
|
if (currentMode == MODE_ROGUE && rogueStats.pendingRainbowPieceCount > 0)
|
||||||
{
|
{
|
||||||
rogueStats.pendingRainbowPieceCount--;
|
rogueStats.pendingRainbowPieceCount--;
|
||||||
@@ -1319,6 +1419,10 @@ int TryStabilizeBoard()
|
|||||||
{
|
{
|
||||||
triggerChance = 70;
|
triggerChance = 70;
|
||||||
}
|
}
|
||||||
|
if (rogueDemoMode && kRogueDemoSteps[rogueDemoStepIndex].kind == DEMO_STABLE_STRUCTURE)
|
||||||
|
{
|
||||||
|
triggerChance = 100;
|
||||||
|
}
|
||||||
|
|
||||||
if ((rand() % 100) >= triggerChance)
|
if ((rand() % 100) >= triggerChance)
|
||||||
{
|
{
|
||||||
@@ -1680,7 +1784,7 @@ static void ApplyUpgradeById(int upgradeId, int targetPieceType, int applyCount)
|
|||||||
rogueStats.infiniteFeverLevel = 1;
|
rogueStats.infiniteFeverLevel = 1;
|
||||||
break;
|
break;
|
||||||
case UPGRADE_SCREEN_BOMB:
|
case UPGRADE_SCREEN_BOMB:
|
||||||
rogueStats.screenBombLevel = 1;
|
rogueStats.screenBombLevel += applyCount;
|
||||||
rogueStats.screenBombCount += applyCount;
|
rogueStats.screenBombCount += applyCount;
|
||||||
break;
|
break;
|
||||||
case UPGRADE_TERMINAL_CLEAR:
|
case UPGRADE_TERMINAL_CLEAR:
|
||||||
@@ -1748,7 +1852,7 @@ static void ApplyUpgradeById(int upgradeId, int targetPieceType, int applyCount)
|
|||||||
rogueStats.blackHoleCharges += 2 * applyCount;
|
rogueStats.blackHoleCharges += 2 * applyCount;
|
||||||
break;
|
break;
|
||||||
case UPGRADE_AIR_RESHAPE:
|
case UPGRADE_AIR_RESHAPE:
|
||||||
rogueStats.reshapeLevel = 1;
|
rogueStats.reshapeLevel += applyCount;
|
||||||
rogueStats.reshapeCharges += 2 * applyCount;
|
rogueStats.reshapeCharges += 2 * applyCount;
|
||||||
break;
|
break;
|
||||||
case UPGRADE_RAINBOW_PIECE:
|
case UPGRADE_RAINBOW_PIECE:
|
||||||
@@ -1831,7 +1935,7 @@ void AwardRogueSkillClearRewards(int clearedCells, int& scoreGain, int& expGain,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (allowLevelProgress)
|
if (allowLevelProgress && !rogueDemoMode)
|
||||||
{
|
{
|
||||||
int levelUps = ApplyLevelProgress(rogueStats);
|
int levelUps = ApplyLevelProgress(rogueStats);
|
||||||
if (levelUps > 0)
|
if (levelUps > 0)
|
||||||
@@ -1851,6 +1955,10 @@ void CheckRogueLevelProgress()
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (rogueDemoMode)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int levelUps = ApplyLevelProgress(rogueStats);
|
int levelUps = ApplyLevelProgress(rogueStats);
|
||||||
if (levelUps <= 0)
|
if (levelUps <= 0)
|
||||||
@@ -1908,6 +2016,10 @@ void ApplyBoardGravity()
|
|||||||
int cell = workRegion[y][x];
|
int cell = workRegion[y][x];
|
||||||
workRegion[y][x] = 0;
|
workRegion[y][x] = 0;
|
||||||
workRegion[writeY][x] = cell;
|
workRegion[writeY][x] = cell;
|
||||||
|
if (writeY != y)
|
||||||
|
{
|
||||||
|
TriggerGravityFallEffect(x, y, writeY, cell);
|
||||||
|
}
|
||||||
writeY--;
|
writeY--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2064,7 +2176,6 @@ void ApplyLineClearResult(int linesCleared)
|
|||||||
int chainBlastScore = 0;
|
int chainBlastScore = 0;
|
||||||
int chainBlastExp = 0;
|
int chainBlastExp = 0;
|
||||||
AwardRogueSkillClearRewards(chainBlastCells, chainBlastScore, chainBlastExp, false);
|
AwardRogueSkillClearRewards(chainBlastCells, chainBlastScore, chainBlastExp, false);
|
||||||
ApplyBoardGravity();
|
|
||||||
|
|
||||||
TCHAR blastDetail[128];
|
TCHAR blastDetail[128];
|
||||||
_stprintf_s(
|
_stprintf_s(
|
||||||
@@ -2105,7 +2216,6 @@ void ApplyLineClearResult(int linesCleared)
|
|||||||
int thunderScore = 0;
|
int thunderScore = 0;
|
||||||
int thunderExp = 0;
|
int thunderExp = 0;
|
||||||
AwardRogueSkillClearRewards(thunderRowsCleared, thunderScore, thunderExp, false);
|
AwardRogueSkillClearRewards(thunderRowsCleared, thunderScore, thunderExp, false);
|
||||||
ApplyBoardGravity();
|
|
||||||
SetFeedbackMessage(_T("雷霆四消"), _T("雷击落下,额外清理了 2 行范围内的方块。"), 12);
|
SetFeedbackMessage(_T("雷霆四消"), _T("雷击落下,额外清理了 2 行范围内的方块。"), 12);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2123,7 +2233,6 @@ void ApplyLineClearResult(int linesCleared)
|
|||||||
int laserScore = 0;
|
int laserScore = 0;
|
||||||
int laserExp = 0;
|
int laserExp = 0;
|
||||||
AwardRogueSkillClearRewards(laserCellsCleared, laserScore, laserExp, false);
|
AwardRogueSkillClearRewards(laserCellsCleared, laserScore, laserExp, false);
|
||||||
ApplyBoardGravity();
|
|
||||||
|
|
||||||
TCHAR thunderLaserDetail[128];
|
TCHAR thunderLaserDetail[128];
|
||||||
_stprintf_s(
|
_stprintf_s(
|
||||||
@@ -2163,7 +2272,6 @@ void ApplyLineClearResult(int linesCleared)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int levelUps = ApplyLevelProgress(rogueStats);
|
int levelUps = ApplyLevelProgress(rogueStats);
|
||||||
upgradeUiState.pendingCount += levelUps;
|
|
||||||
tScore = rogueStats.score;
|
tScore = rogueStats.score;
|
||||||
|
|
||||||
if (levelUps > 0)
|
if (levelUps > 0)
|
||||||
@@ -2189,16 +2297,35 @@ void ApplyLineClearResult(int linesCleared)
|
|||||||
TCHAR feedbackTitle[64];
|
TCHAR feedbackTitle[64];
|
||||||
TCHAR feedbackDetail[128];
|
TCHAR feedbackDetail[128];
|
||||||
_stprintf_s(feedbackTitle, _T("灵感涌现 x%d"), levelUps);
|
_stprintf_s(feedbackTitle, _T("灵感涌现 x%d"), levelUps);
|
||||||
|
if (rogueDemoMode)
|
||||||
|
{
|
||||||
|
_stprintf_s(
|
||||||
|
feedbackDetail,
|
||||||
|
_T("演示升级 Lv.%d,普通强化菜单已关闭。"),
|
||||||
|
rogueStats.level);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
_stprintf_s(
|
_stprintf_s(
|
||||||
feedbackDetail,
|
feedbackDetail,
|
||||||
_T("等级 Lv.%d EXP %d/%d 选择新的强化"),
|
_T("等级 Lv.%d EXP %d/%d 选择新的强化"),
|
||||||
rogueStats.level,
|
rogueStats.level,
|
||||||
rogueStats.exp,
|
rogueStats.exp,
|
||||||
rogueStats.requiredExp);
|
rogueStats.requiredExp);
|
||||||
|
}
|
||||||
SetFeedbackMessage(feedbackTitle, feedbackDetail, 10);
|
SetFeedbackMessage(feedbackTitle, feedbackDetail, 10);
|
||||||
|
|
||||||
|
if (rogueDemoMode)
|
||||||
|
{
|
||||||
|
ResolvePendingUpgradeShockwave();
|
||||||
|
PlayPendingLineClearEffect();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
upgradeUiState.pendingCount += levelUps;
|
||||||
OpenUpgradeMenu();
|
OpenUpgradeMenu();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
currentFallInterval = GetRogueFallInterval();
|
currentFallInterval = GetRogueFallInterval();
|
||||||
}
|
}
|
||||||
@@ -2560,7 +2687,6 @@ void UseScreenBomb()
|
|||||||
|
|
||||||
rogueStats.screenBombCount--;
|
rogueStats.screenBombCount--;
|
||||||
int clearedCells = TriggerScreenBomb();
|
int clearedCells = TriggerScreenBomb();
|
||||||
ApplyBoardGravity();
|
|
||||||
int scoreGain = 0;
|
int scoreGain = 0;
|
||||||
int expGain = 0;
|
int expGain = 0;
|
||||||
AwardRogueSkillClearRewards(clearedCells, scoreGain, expGain, true);
|
AwardRogueSkillClearRewards(clearedCells, scoreGain, expGain, true);
|
||||||
@@ -2607,7 +2733,6 @@ void UseBlackHole()
|
|||||||
|
|
||||||
rogueStats.blackHoleCharges--;
|
rogueStats.blackHoleCharges--;
|
||||||
|
|
||||||
ApplyBoardGravity();
|
|
||||||
int scoreGain = 0;
|
int scoreGain = 0;
|
||||||
int expGain = 0;
|
int expGain = 0;
|
||||||
AwardRogueSkillClearRewards(clearedCells, scoreGain, expGain, true);
|
AwardRogueSkillClearRewards(clearedCells, scoreGain, expGain, true);
|
||||||
@@ -2705,3 +2830,688 @@ void UseAirReshape()
|
|||||||
SetFeedbackMessage(_T("空中换形"), detail, 12);
|
SetFeedbackMessage(_T("空中换形"), detail, 12);
|
||||||
ComputeTarget();
|
ComputeTarget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 判断当前是否处于 Rogue 技能自动演示模式。
|
||||||
|
*/
|
||||||
|
bool IsRogueSkillDemoMode()
|
||||||
|
{
|
||||||
|
return rogueDemoMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 返回 Rogue 技能演示条目数量,供帮助页逐行绘制可点击名单。
|
||||||
|
*/
|
||||||
|
int GetRogueSkillDemoCount()
|
||||||
|
{
|
||||||
|
return kRogueDemoStepCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 按序号返回 Rogue 技能演示名称。
|
||||||
|
*/
|
||||||
|
const TCHAR* GetRogueSkillDemoName(int demoIndex)
|
||||||
|
{
|
||||||
|
if (demoIndex < 0 || demoIndex >= kRogueDemoStepCount)
|
||||||
|
{
|
||||||
|
return _T("");
|
||||||
|
}
|
||||||
|
|
||||||
|
return kRogueDemoSteps[demoIndex].name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 按序号返回 Rogue 技能演示说明。
|
||||||
|
*/
|
||||||
|
const TCHAR* GetRogueSkillDemoDetail(int demoIndex)
|
||||||
|
{
|
||||||
|
if (demoIndex < 0 || demoIndex >= kRogueDemoStepCount)
|
||||||
|
{
|
||||||
|
return _T("");
|
||||||
|
}
|
||||||
|
|
||||||
|
return kRogueDemoSteps[demoIndex].detail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 返回当前正在演示的 Rogue 技能名称。
|
||||||
|
*/
|
||||||
|
const TCHAR* GetCurrentRogueSkillDemoName()
|
||||||
|
{
|
||||||
|
if (!rogueDemoMode)
|
||||||
|
{
|
||||||
|
return _T("");
|
||||||
|
}
|
||||||
|
|
||||||
|
return GetRogueSkillDemoName(rogueDemoStepIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 从帮助页进入 Rogue 技能演示,并播放第一段技能展示。
|
||||||
|
*/
|
||||||
|
void StartRogueSkillDemo()
|
||||||
|
{
|
||||||
|
StartRogueSkillDemoInternal(0, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 从帮助页的技能名单进入指定 Rogue 技能演示。
|
||||||
|
*/
|
||||||
|
void StartRogueSkillDemoAt(int demoIndex)
|
||||||
|
{
|
||||||
|
StartRogueSkillDemoInternal(demoIndex, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 重置当前 Rogue 技能演示场景,保留当前选中的技能条目。
|
||||||
|
*/
|
||||||
|
void RestartCurrentRogueSkillDemo()
|
||||||
|
{
|
||||||
|
if (!rogueDemoMode)
|
||||||
|
{
|
||||||
|
StartRogueSkillDemoAt(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
StartRogueSkillDemoInternal(rogueDemoStepIndex, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 进入 Rogue 技能演示并配置起始条目和是否自动轮播。
|
||||||
|
*/
|
||||||
|
static void StartRogueSkillDemoInternal(int demoIndex, bool autoAdvance)
|
||||||
|
{
|
||||||
|
if (demoIndex < 0)
|
||||||
|
{
|
||||||
|
demoIndex = 0;
|
||||||
|
}
|
||||||
|
if (demoIndex >= kRogueDemoStepCount)
|
||||||
|
{
|
||||||
|
demoIndex = kRogueDemoStepCount - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentMode = MODE_ROGUE;
|
||||||
|
currentScreen = SCREEN_PLAYING;
|
||||||
|
rogueDemoMode = true;
|
||||||
|
rogueDemoStepIndex = demoIndex;
|
||||||
|
rogueDemoTicks = 0;
|
||||||
|
rogueDemoAutoAdvance = autoAdvance;
|
||||||
|
|
||||||
|
Restart();
|
||||||
|
rogueDemoMode = true;
|
||||||
|
reviveAvailable = false;
|
||||||
|
suspendFlag = false;
|
||||||
|
gameOverFlag = false;
|
||||||
|
targetFlag = true;
|
||||||
|
upgradeListScrollOffset = 0;
|
||||||
|
currentFallInterval = 500;
|
||||||
|
|
||||||
|
ApplyRogueSkillDemoStep();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 推进 Rogue 技能演示计时,到点后切换到下一项技能。
|
||||||
|
*/
|
||||||
|
bool TickRogueSkillDemo()
|
||||||
|
{
|
||||||
|
if (!rogueDemoMode)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rogueDemoAutoAdvance)
|
||||||
|
{
|
||||||
|
rogueDemoTicks++;
|
||||||
|
if (rogueDemoTicks >= kRogueDemoStepTicks)
|
||||||
|
{
|
||||||
|
AdvanceRogueSkillDemo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 立刻切换到下一项 Rogue 技能演示。
|
||||||
|
*/
|
||||||
|
void AdvanceRogueSkillDemo()
|
||||||
|
{
|
||||||
|
if (!rogueDemoMode)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rogueDemoStepIndex++;
|
||||||
|
if (rogueDemoStepIndex >= kRogueDemoStepCount)
|
||||||
|
{
|
||||||
|
rogueDemoStepIndex = 0;
|
||||||
|
}
|
||||||
|
rogueDemoTicks = 0;
|
||||||
|
ApplyRogueSkillDemoStep();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 清空棋盘和演示状态,为单个技能配置专用局面。
|
||||||
|
*/
|
||||||
|
static void ResetRogueDemoBoard()
|
||||||
|
{
|
||||||
|
for (int y = 0; y < nGameHeight; y++)
|
||||||
|
{
|
||||||
|
for (int x = 0; x < nGameWidth; x++)
|
||||||
|
{
|
||||||
|
workRegion[y][x] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ResetPlayerStats(rogueStats, true);
|
||||||
|
ResetUpgradeUiState();
|
||||||
|
ResetPendingRogueVisualEvents();
|
||||||
|
ResetVisualEffects();
|
||||||
|
pendingLineClearEffectTicks = 0;
|
||||||
|
pendingLineClearEffectRowCount = 0;
|
||||||
|
pendingLineClearEffectLineCount = 0;
|
||||||
|
clearEffectState.ticks = 0;
|
||||||
|
currentPieceIsExplosive = false;
|
||||||
|
currentPieceIsLaser = false;
|
||||||
|
currentPieceIsCross = false;
|
||||||
|
currentPieceIsRainbow = false;
|
||||||
|
holdType = -1;
|
||||||
|
holdUsedThisTurn = false;
|
||||||
|
tScore = 0;
|
||||||
|
currentScreen = SCREEN_PLAYING;
|
||||||
|
currentMode = MODE_ROGUE;
|
||||||
|
gameOverFlag = false;
|
||||||
|
suspendFlag = false;
|
||||||
|
reviveAvailable = false;
|
||||||
|
currentFallInterval = 500;
|
||||||
|
ResetNextQueue();
|
||||||
|
SetRogueDemoCurrentPiece(1, 0, 3, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 在棋盘中央显示当前演示技能名称。
|
||||||
|
*/
|
||||||
|
static void ShowRogueDemoFloatingName(const TCHAR* name)
|
||||||
|
{
|
||||||
|
floatingTextEffects[0].ticks = 70;
|
||||||
|
floatingTextEffects[0].totalTicks = 70;
|
||||||
|
floatingTextEffects[0].boardX = 500;
|
||||||
|
floatingTextEffects[0].boardY = 1000;
|
||||||
|
floatingTextEffects[0].color = RGB(255, 248, 250);
|
||||||
|
lstrcpyn(floatingTextEffects[0].text, name, sizeof(floatingTextEffects[0].text) / sizeof(TCHAR));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 安全写入演示棋盘中的一个固定方块格。
|
||||||
|
*/
|
||||||
|
static void FillRogueDemoCell(int y, int x, int value)
|
||||||
|
{
|
||||||
|
if (y < 0 || y >= nGameHeight || x < 0 || x >= nGameWidth)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
workRegion[y][x] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 按交错颜色填充演示棋盘中的连续压力行,并为每行保留缺口避免开局满行。
|
||||||
|
*/
|
||||||
|
static void FillRogueDemoRows(int firstRow, int lastRow, int baseValue)
|
||||||
|
{
|
||||||
|
if (firstRow < 0)
|
||||||
|
{
|
||||||
|
firstRow = 0;
|
||||||
|
}
|
||||||
|
if (lastRow >= nGameHeight)
|
||||||
|
{
|
||||||
|
lastRow = nGameHeight - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int y = firstRow; y <= lastRow; y++)
|
||||||
|
{
|
||||||
|
int gapX = (baseValue + y) % nGameWidth;
|
||||||
|
for (int x = 0; x < nGameWidth; x++)
|
||||||
|
{
|
||||||
|
if (x == gapX)
|
||||||
|
{
|
||||||
|
workRegion[y][x] = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
workRegion[y][x] = 1 + ((baseValue + y + x) % 7);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 填满演示棋盘中的一行,并在指定范围留下空位。
|
||||||
|
*/
|
||||||
|
static void FillRogueDemoRowExcept(int row, int gapStart, int gapWidth, int baseValue)
|
||||||
|
{
|
||||||
|
if (row < 0 || row >= nGameHeight)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int x = 0; x < nGameWidth; x++)
|
||||||
|
{
|
||||||
|
if (x >= gapStart && x < gapStart + gapWidth)
|
||||||
|
{
|
||||||
|
workRegion[row][x] = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
workRegion[row][x] = 1 + ((baseValue + row + x) % 7);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置演示模式下当前下落方块的类型、旋转和位置。
|
||||||
|
*/
|
||||||
|
static void SetRogueDemoCurrentPiece(int pieceType, int pieceState, int x, int y)
|
||||||
|
{
|
||||||
|
type = pieceType;
|
||||||
|
nType = 0;
|
||||||
|
state = pieceState;
|
||||||
|
point.x = x;
|
||||||
|
point.y = y;
|
||||||
|
target = point;
|
||||||
|
nextTypes[0] = 0;
|
||||||
|
nextTypes[1] = 0;
|
||||||
|
nextTypes[2] = 0;
|
||||||
|
ComputeTarget();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 配置并触发当前 Rogue 技能演示步骤。
|
||||||
|
*/
|
||||||
|
static void ApplyRogueSkillDemoStep()
|
||||||
|
{
|
||||||
|
ResetRogueDemoBoard();
|
||||||
|
|
||||||
|
const RogueDemoStep& demoStep = kRogueDemoSteps[rogueDemoStepIndex];
|
||||||
|
ShowRogueDemoFloatingName(demoStep.name);
|
||||||
|
SetFeedbackMessage(demoStep.name, demoStep.detail, 12);
|
||||||
|
|
||||||
|
switch (demoStep.kind)
|
||||||
|
{
|
||||||
|
case DEMO_SCORE_MULTIPLIER:
|
||||||
|
rogueStats.scoreUpgradeLevel = 2;
|
||||||
|
rogueStats.scoreMultiplierPercent = 160;
|
||||||
|
FillRogueDemoRows(16, 18, 1);
|
||||||
|
FillRogueDemoRowExcept(19, 3, 4, 1);
|
||||||
|
SetRogueDemoCurrentPiece(0, 0, 3, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_EXP_MULTIPLIER:
|
||||||
|
rogueStats.expUpgradeLevel = 2;
|
||||||
|
rogueStats.expMultiplierPercent = 150;
|
||||||
|
FillRogueDemoRows(16, 18, 2);
|
||||||
|
FillRogueDemoRowExcept(19, 3, 4, 2);
|
||||||
|
SetRogueDemoCurrentPiece(0, 0, 3, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_SLOW_FALL:
|
||||||
|
rogueStats.slowFallStacks = 4;
|
||||||
|
currentFallInterval = GetRogueFallInterval();
|
||||||
|
FillRogueDemoRows(16, 19, 3);
|
||||||
|
SetRogueDemoCurrentPiece(1, 0, 3, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_COMBO_BONUS:
|
||||||
|
rogueStats.comboBonusStacks = 2;
|
||||||
|
rogueStats.comboChain = 1;
|
||||||
|
FillRogueDemoRows(16, 18, 4);
|
||||||
|
FillRogueDemoRowExcept(19, 3, 4, 4);
|
||||||
|
SetRogueDemoCurrentPiece(0, 0, 3, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_PREVIEW_PLUS_ONE:
|
||||||
|
rogueStats.previewCount = 2;
|
||||||
|
rogueStats.previewUpgradeLevel = 1;
|
||||||
|
FillRogueDemoRows(16, 19, 5);
|
||||||
|
SetRogueDemoCurrentPiece(4, 0, 4, 0);
|
||||||
|
nextTypes[0] = 0;
|
||||||
|
nextTypes[1] = 1;
|
||||||
|
nextTypes[2] = 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_LAST_CHANCE:
|
||||||
|
rogueStats.lastChanceUpgradeLevel = 1;
|
||||||
|
rogueStats.lastChanceCount = 1;
|
||||||
|
FillRogueDemoRows(0, 5, 5);
|
||||||
|
FillRogueDemoRows(14, 19, 3);
|
||||||
|
SetRogueDemoCurrentPiece(4, 0, 3, -1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_HOLD:
|
||||||
|
rogueStats.holdUnlocked = 1;
|
||||||
|
rogueStats.controlMasterLevel = 1;
|
||||||
|
holdType = 0;
|
||||||
|
FillRogueDemoRows(16, 18, 1);
|
||||||
|
FillRogueDemoRowExcept(19, 3, 4, 1);
|
||||||
|
SetRogueDemoCurrentPiece(2, 0, 3, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_PRESSURE_RELIEF:
|
||||||
|
rogueStats.pressureReliefLevel = 1;
|
||||||
|
FillRogueDemoRows(5, 19, 6);
|
||||||
|
DeleteOneLine(5);
|
||||||
|
SetRogueDemoCurrentPiece(1, 0, 3, 0);
|
||||||
|
SetFeedbackMessage(_T("卸压清场"), _T("最高占用行已被清除,顶部压力立即下降。"), 12);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_SWEEPER:
|
||||||
|
rogueStats.sweeperLevel = 4;
|
||||||
|
FillRogueDemoRows(15, 18, 1);
|
||||||
|
FillRogueDemoRowExcept(19, 3, 4, 3);
|
||||||
|
SetRogueDemoCurrentPiece(0, 0, 3, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_EXPLOSIVE:
|
||||||
|
FillRogueDemoRows(12, 19, 1);
|
||||||
|
FillRogueDemoCell(14, 4, 0);
|
||||||
|
FillRogueDemoCell(15, 5, 0);
|
||||||
|
FillRogueDemoCell(16, 4, 0);
|
||||||
|
currentPieceIsExplosive = true;
|
||||||
|
SetRogueDemoCurrentPiece(1, 0, 3, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_STABLE_STRUCTURE:
|
||||||
|
rogueStats.stableStructureLevel = 4;
|
||||||
|
FillRogueDemoRows(14, 19, 1);
|
||||||
|
workRegion[15][4] = 0;
|
||||||
|
workRegion[16][6] = 0;
|
||||||
|
workRegion[17][5] = 0;
|
||||||
|
SetRogueDemoCurrentPiece(1, 0, 3, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_DOUBLE_GROWTH:
|
||||||
|
rogueStats.doubleGrowthLevel = 1;
|
||||||
|
rogueStats.scoreMultiplierPercent = 115;
|
||||||
|
rogueStats.expMultiplierPercent = 115;
|
||||||
|
FillRogueDemoRows(16, 18, 2);
|
||||||
|
FillRogueDemoRowExcept(19, 3, 4, 2);
|
||||||
|
SetRogueDemoCurrentPiece(0, 0, 3, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_PIECE_TUNING:
|
||||||
|
rogueStats.pieceTuningLevels[0] = 4;
|
||||||
|
FillRogueDemoRows(16, 19, 3);
|
||||||
|
SetRogueDemoCurrentPiece(0, 1, 3, 0);
|
||||||
|
nextTypes[0] = 0;
|
||||||
|
nextTypes[1] = 0;
|
||||||
|
nextTypes[2] = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_GAMBLER:
|
||||||
|
rogueStats.gamblerLevel = 4;
|
||||||
|
FillRogueDemoRows(16, 18, 4);
|
||||||
|
FillRogueDemoRowExcept(19, 3, 4, 4);
|
||||||
|
SetRogueDemoCurrentPiece(0, 0, 3, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_CHAIN_BLAST:
|
||||||
|
rogueStats.chainBlastLevel = 1;
|
||||||
|
FillRogueDemoRows(15, 18, 5);
|
||||||
|
FillRogueDemoRowExcept(19, 3, 4, 5);
|
||||||
|
SetRogueDemoCurrentPiece(0, 0, 3, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_CHAIN_BOMB:
|
||||||
|
rogueStats.chainBombLevel = 1;
|
||||||
|
FillRogueDemoRows(10, 19, 4);
|
||||||
|
for (int y = 13; y <= 17; y++)
|
||||||
|
{
|
||||||
|
FillRogueDemoCell(y, 3, 0);
|
||||||
|
FillRogueDemoCell(y, 6, 0);
|
||||||
|
}
|
||||||
|
currentPieceIsExplosive = true;
|
||||||
|
SetRogueDemoCurrentPiece(1, 0, 3, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_LASER:
|
||||||
|
for (int y = 4; y < nGameHeight; y++)
|
||||||
|
{
|
||||||
|
FillRogueDemoCell(y, 5, 4);
|
||||||
|
if (y >= 12)
|
||||||
|
{
|
||||||
|
FillRogueDemoCell(y, 3, 2);
|
||||||
|
FillRogueDemoCell(y, 7, 6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
currentPieceIsLaser = true;
|
||||||
|
SetRogueDemoCurrentPiece(0, 1, 3, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_THUNDER_TETRIS:
|
||||||
|
rogueStats.thunderTetrisLevel = 1;
|
||||||
|
FillRogueDemoRows(10, 15, 1);
|
||||||
|
FillRogueDemoRows(16, 18, 2);
|
||||||
|
FillRogueDemoRowExcept(19, 3, 4, 2);
|
||||||
|
SetRogueDemoCurrentPiece(0, 0, 3, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_THUNDER_LASER:
|
||||||
|
rogueStats.thunderLaserLevel = 1;
|
||||||
|
FillRogueDemoRows(10, 15, 3);
|
||||||
|
FillRogueDemoRows(16, 18, 4);
|
||||||
|
FillRogueDemoRowExcept(19, 3, 4, 4);
|
||||||
|
SetRogueDemoCurrentPiece(0, 0, 3, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_FEVER_MODE:
|
||||||
|
rogueStats.feverLevel = 1;
|
||||||
|
rogueStats.feverLineCharge = kFeverLineThreshold - 1;
|
||||||
|
FillRogueDemoRows(16, 18, 5);
|
||||||
|
FillRogueDemoRowExcept(19, 3, 4, 5);
|
||||||
|
SetRogueDemoCurrentPiece(0, 0, 3, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_RAGE_STACK:
|
||||||
|
rogueStats.rageStackLevel = 1;
|
||||||
|
rogueStats.comboChain = 3;
|
||||||
|
FillRogueDemoRows(16, 18, 6);
|
||||||
|
FillRogueDemoRowExcept(19, 3, 4, 6);
|
||||||
|
SetRogueDemoCurrentPiece(0, 0, 3, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_INFINITE_FEVER:
|
||||||
|
rogueStats.feverLevel = 1;
|
||||||
|
rogueStats.infiniteFeverLevel = 1;
|
||||||
|
rogueStats.feverTicks = 8;
|
||||||
|
currentFallInterval = GetRogueFallInterval();
|
||||||
|
FillRogueDemoRows(16, 18, 1);
|
||||||
|
FillRogueDemoRowExcept(19, 3, 4, 1);
|
||||||
|
SetRogueDemoCurrentPiece(0, 0, 3, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_SCREEN_BOMB:
|
||||||
|
rogueStats.screenBombLevel = 1;
|
||||||
|
rogueStats.screenBombCount = 1;
|
||||||
|
FillRogueDemoRows(11, 19, 0);
|
||||||
|
SetRogueDemoCurrentPiece(4, 0, 4, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_TERMINAL_CLEAR:
|
||||||
|
rogueStats.lastChanceUpgradeLevel = 1;
|
||||||
|
rogueStats.lastChanceCount = 1;
|
||||||
|
rogueStats.terminalClearLevel = 1;
|
||||||
|
rogueStats.screenBombLevel = 1;
|
||||||
|
rogueStats.screenBombCount = 1;
|
||||||
|
FillRogueDemoRows(0, 5, 2);
|
||||||
|
FillRogueDemoRows(12, 19, 3);
|
||||||
|
SetRogueDemoCurrentPiece(4, 0, 3, -1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_DUAL_CHOICE:
|
||||||
|
rogueStats.dualChoiceLevel = 1;
|
||||||
|
FillRogueDemoRows(16, 18, 4);
|
||||||
|
FillRogueDemoRowExcept(19, 3, 4, 4);
|
||||||
|
SetRogueDemoCurrentPiece(0, 0, 3, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_DESTINY_WHEEL:
|
||||||
|
rogueStats.destinyWheelLevel = 1;
|
||||||
|
FillRogueDemoRows(16, 18, 5);
|
||||||
|
FillRogueDemoRowExcept(19, 3, 4, 5);
|
||||||
|
SetRogueDemoCurrentPiece(0, 0, 3, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_PERFECT_ROTATE:
|
||||||
|
rogueStats.perfectRotateLevel = 1;
|
||||||
|
FillRogueDemoRows(16, 19, 6);
|
||||||
|
for (int y = 10; y < nGameHeight; y++)
|
||||||
|
{
|
||||||
|
FillRogueDemoCell(y, 0, 0);
|
||||||
|
}
|
||||||
|
SetRogueDemoCurrentPiece(2, 1, 0, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_TIME_DILATION:
|
||||||
|
rogueStats.timeDilationLevel = 1;
|
||||||
|
rogueStats.timeDilationTicks = 8;
|
||||||
|
FillRogueDemoRows(3, 19, 4);
|
||||||
|
currentFallInterval = GetRogueFallInterval();
|
||||||
|
SetRogueDemoCurrentPiece(0, 1, 3, 0);
|
||||||
|
SetFeedbackMessage(_T("时间缓流"), _T("堆叠高度危险,短时间内下落速度降低。"), 12);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_HIGH_PRESSURE:
|
||||||
|
rogueStats.highPressureLevel = 1;
|
||||||
|
rogueStats.scoreMultiplierPercent = 150;
|
||||||
|
rogueStats.expMultiplierPercent = 150;
|
||||||
|
currentFallInterval = GetRogueFallInterval();
|
||||||
|
FillRogueDemoRows(16, 18, 1);
|
||||||
|
FillRogueDemoRowExcept(19, 3, 4, 1);
|
||||||
|
SetRogueDemoCurrentPiece(0, 0, 3, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_TETRIS_GAMBLE:
|
||||||
|
rogueStats.tetrisGambleLevel = 1;
|
||||||
|
FillRogueDemoRows(16, 18, 2);
|
||||||
|
FillRogueDemoRowExcept(19, 3, 4, 2);
|
||||||
|
SetRogueDemoCurrentPiece(0, 0, 3, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_EXTREME_PLAYER:
|
||||||
|
rogueStats.extremePlayerLevel = 1;
|
||||||
|
rogueStats.highPressureLevel = 1;
|
||||||
|
rogueStats.tetrisGambleLevel = 1;
|
||||||
|
currentFallInterval = GetRogueFallInterval();
|
||||||
|
FillRogueDemoRows(16, 18, 3);
|
||||||
|
FillRogueDemoRowExcept(19, 3, 4, 3);
|
||||||
|
SetRogueDemoCurrentPiece(0, 0, 3, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_UPGRADE_SHOCKWAVE:
|
||||||
|
rogueStats.upgradeShockwaveLevel = 1;
|
||||||
|
rogueStats.exp = 0;
|
||||||
|
rogueStats.requiredExp = 12;
|
||||||
|
FillRogueDemoRows(12, 18, 2);
|
||||||
|
FillRogueDemoRowExcept(19, 3, 4, 6);
|
||||||
|
SetRogueDemoCurrentPiece(0, 0, 3, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_EVOLUTION_IMPACT:
|
||||||
|
rogueStats.evolutionImpactLevel = 1;
|
||||||
|
rogueStats.exp = 0;
|
||||||
|
rogueStats.requiredExp = 12;
|
||||||
|
FillRogueDemoRows(11, 18, 3);
|
||||||
|
FillRogueDemoRowExcept(19, 3, 4, 3);
|
||||||
|
SetRogueDemoCurrentPiece(0, 0, 3, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_CONTROL_MASTER:
|
||||||
|
rogueStats.holdUnlocked = 1;
|
||||||
|
rogueStats.controlMasterLevel = 1;
|
||||||
|
rogueStats.previewCount = 3;
|
||||||
|
holdType = 0;
|
||||||
|
FillRogueDemoRows(16, 18, 4);
|
||||||
|
FillRogueDemoRowExcept(19, 3, 4, 4);
|
||||||
|
SetRogueDemoCurrentPiece(2, 0, 3, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_BLOCK_STORM:
|
||||||
|
rogueStats.blockStormLevel = 1;
|
||||||
|
rogueStats.blockStormPiecesRemaining = 5;
|
||||||
|
FillRogueDemoRows(15, 19, 0);
|
||||||
|
for (int y = 8; y < nGameHeight; y++)
|
||||||
|
{
|
||||||
|
FillRogueDemoCell(y, 5, 0);
|
||||||
|
}
|
||||||
|
SetRogueDemoCurrentPiece(0, 1, 3, 0);
|
||||||
|
nextTypes[0] = 0;
|
||||||
|
nextTypes[1] = 0;
|
||||||
|
nextTypes[2] = 0;
|
||||||
|
SetFeedbackMessage(_T("方块风暴"), _T("当前和后续预览全部变为 I 块,方便制造四消。"), 12);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_BLACK_HOLE:
|
||||||
|
rogueStats.blackHoleLevel = 1;
|
||||||
|
rogueStats.blackHoleCharges = 1;
|
||||||
|
FillRogueDemoRows(9, 19, 2);
|
||||||
|
for (int y = 8; y < nGameHeight; y++)
|
||||||
|
{
|
||||||
|
for (int x = 1; x < nGameWidth; x += 3)
|
||||||
|
{
|
||||||
|
workRegion[y][x] = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SetRogueDemoCurrentPiece(1, 0, 3, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_AIR_RESHAPE:
|
||||||
|
rogueStats.reshapeLevel = 1;
|
||||||
|
rogueStats.reshapeCharges = 1;
|
||||||
|
FillRogueDemoRows(16, 19, 3);
|
||||||
|
for (int y = 10; y < nGameHeight; y++)
|
||||||
|
{
|
||||||
|
FillRogueDemoCell(y, 9, 0);
|
||||||
|
}
|
||||||
|
SetRogueDemoCurrentPiece(1, 0, 6, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_CROSS:
|
||||||
|
FillRogueDemoRows(13, 17, 5);
|
||||||
|
for (int y = 6; y < nGameHeight; y++)
|
||||||
|
{
|
||||||
|
FillRogueDemoCell(y, 4, 3);
|
||||||
|
}
|
||||||
|
currentPieceIsCross = true;
|
||||||
|
SetRogueDemoCurrentPiece(1, 0, 3, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_RAINBOW:
|
||||||
|
FillRogueDemoRows(10, 16, 2);
|
||||||
|
for (int x = 0; x < nGameWidth; x++)
|
||||||
|
{
|
||||||
|
workRegion[13][x] = (x < 6) ? 3 : 5;
|
||||||
|
}
|
||||||
|
currentPieceIsRainbow = true;
|
||||||
|
SetRogueDemoCurrentPiece(1, 0, 3, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_VOID_CORE:
|
||||||
|
rogueStats.blackHoleLevel = 1;
|
||||||
|
rogueStats.blackHoleCharges = 1;
|
||||||
|
rogueStats.voidCoreLevel = 1;
|
||||||
|
FillRogueDemoRows(8, 19, 6);
|
||||||
|
for (int y = 8; y < nGameHeight; y++)
|
||||||
|
{
|
||||||
|
for (int x = 1; x < nGameWidth; x += 3)
|
||||||
|
{
|
||||||
|
workRegion[y][x] = 6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SetRogueDemoCurrentPiece(1, 0, 3, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ComputeTarget();
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user