/*++ Update the effects of all equipped items for all players. --*/ VOID PAL_UpdateEquipments(void) { int i, j; WORD w; memset(&(gpGlobals->rgEquipmentEffect), 0, sizeof(gpGlobals->rgEquipmentEffect)); for (i = 0; i < MAX_PLAYER_ROLES; i++) { for (j = 0; j < MAX_PLAYER_EQUIPMENTS; j++) { w = gpGlobals->g.PlayerRoles.rgwEquipment[j][i]; if (w != 0) { gpGlobals->g.rgObject[w].item.wScriptOnEquip = PAL_RunTriggerScript(gpGlobals->g.rgObject[w].item.wScriptOnEquip, (WORD)i); } } } }
VOID PAL_UpdateEquipments( VOID ) /*++ Purpose: Update the effects of all equipped items for all players. Parameters: None. Return value: None. --*/ { int i, j; WORD w; memset(&(gpGlobals->rgEquipmentEffect), 0, sizeof(gpGlobals->rgEquipmentEffect)); for (i = 0; i < MAX_PLAYER_ROLES; i++) { for (j = 0; j < MAX_PLAYER_EQUIPMENTS; j++) { w = gpGlobals->g.PlayerRoles.rgwEquipment[j][i]; if (w != 0) { gpGlobals->g.rgObject[w].item.wScriptOnEquip = PAL_RunTriggerScript(gpGlobals->g.rgObject[w].item.wScriptOnEquip, (WORD)i); } } } }
/*++ Show the "you win" message and add the experience points for players. --*/ static VOID PAL_BattleWon(void) { const SDL_Rect rect = {65, 60, 200, 100}; const SDL_Rect rect1 = {80, 0, 180, 200}; int i, j, iTotalCount; DWORD dwExp; WORD w; BOOL fLevelUp; PLAYERROLES OrigPlayerRoles; // // Backup the initial player stats // OrigPlayerRoles = gpGlobals->g.PlayerRoles; if (g_Battle.iExpGained > 0) { // // Play the "battle win" music // PAL_PlayMUS(g_Battle.fIsBoss ? 2 : 3, FALSE, 0); // // Show the message about the total number of exp. and cash gained // PAL_CreateSingleLineBox(PAL_XY(83, 60), 8, FALSE); PAL_CreateSingleLineBox(PAL_XY(65, 105), 10, FALSE); PAL_DrawText(PAL_GetWord(BATTLEWIN_GETEXP_LABEL), PAL_XY(95, 70), 0, FALSE, FALSE); PAL_DrawText(PAL_GetWord(BATTLEWIN_BEATENEMY_LABEL), PAL_XY(77, 115), 0, FALSE, FALSE); PAL_DrawText(PAL_GetWord(BATTLEWIN_DOLLAR_LABEL), PAL_XY(197, 115), 0, FALSE, FALSE); PAL_DrawNumber(g_Battle.iExpGained, 5, PAL_XY(182, 74), kNumColorYellow, kNumAlignRight); PAL_DrawNumber(g_Battle.iCashGained, 5, PAL_XY(162, 119), kNumColorYellow, kNumAlignMid); VIDEO_UpdateScreen(&rect); PAL_WaitForKey(g_Battle.fIsBoss ? 5500 : 3000); } // // Add the cash value // gpGlobals->dwCash += g_Battle.iCashGained; // // Add the experience points for each players // for (i = 0; i <= gpGlobals->wMaxPartyMemberIndex; i++) { fLevelUp = FALSE; w = gpGlobals->rgParty[i].wPlayerRole; if (gpGlobals->g.PlayerRoles.rgwHP[w] == 0) { continue; // don't care about dead players } dwExp = gpGlobals->Exp.rgPrimaryExp[w].wExp; dwExp += g_Battle.iExpGained; if (gpGlobals->g.PlayerRoles.rgwLevel[w] > MAX_LEVELS) { gpGlobals->g.PlayerRoles.rgwLevel[w] = MAX_LEVELS; } while (dwExp >= gpGlobals->g.rgLevelUpExp[gpGlobals->g.PlayerRoles.rgwLevel[w]]) { dwExp -= gpGlobals->g.rgLevelUpExp[gpGlobals->g.PlayerRoles.rgwLevel[w]]; if (gpGlobals->g.PlayerRoles.rgwLevel[w] < MAX_LEVELS) { fLevelUp = TRUE; PAL_PlayerLevelUp(w, 1); gpGlobals->g.PlayerRoles.rgwHP[w] = gpGlobals->g.PlayerRoles.rgwMaxHP[w]; gpGlobals->g.PlayerRoles.rgwMP[w] = gpGlobals->g.PlayerRoles.rgwMaxMP[w]; } } gpGlobals->Exp.rgPrimaryExp[w].wExp = (WORD)dwExp; if (fLevelUp) { // // Player has gained a level. Show the message // PAL_CreateSingleLineBox(PAL_XY(80, 0), 10, FALSE); PAL_CreateBox(PAL_XY(82, 32), 7, 8, 1, FALSE); PAL_DrawText(PAL_GetWord(gpGlobals->g.PlayerRoles.rgwName[w]), PAL_XY(110, 10), 0, FALSE, FALSE); PAL_DrawText(PAL_GetWord(STATUS_LABEL_LEVEL), PAL_XY(110 + 16 * 3, 10), 0, FALSE, FALSE); PAL_DrawText(PAL_GetWord(BATTLEWIN_LEVELUP_LABEL), PAL_XY(110 + 16 * 5, 10), 0, FALSE, FALSE); for (j = 0; j < 8; j++) { PAL_RLEBlitToSurface(PAL_SpriteGetFrame(gpSpriteUI, SPRITENUM_ARROW), gpScreen, PAL_XY(183, 48 + 18 * j)); } PAL_DrawText(PAL_GetWord(STATUS_LABEL_LEVEL), PAL_XY(100, 44), BATTLEWIN_LEVELUP_LABEL_COLOR, TRUE, FALSE); PAL_DrawText(PAL_GetWord(STATUS_LABEL_HP), PAL_XY(100, 62), BATTLEWIN_LEVELUP_LABEL_COLOR, TRUE, FALSE); PAL_DrawText(PAL_GetWord(STATUS_LABEL_MP), PAL_XY(100, 80), BATTLEWIN_LEVELUP_LABEL_COLOR, TRUE, FALSE); PAL_DrawText(PAL_GetWord(STATUS_LABEL_ATTACKPOWER), PAL_XY(100, 98), BATTLEWIN_LEVELUP_LABEL_COLOR, TRUE, FALSE); PAL_DrawText(PAL_GetWord(STATUS_LABEL_MAGICPOWER), PAL_XY(100, 116), BATTLEWIN_LEVELUP_LABEL_COLOR, TRUE, FALSE); PAL_DrawText(PAL_GetWord(STATUS_LABEL_RESISTANCE), PAL_XY(100, 134), BATTLEWIN_LEVELUP_LABEL_COLOR, TRUE, FALSE); PAL_DrawText(PAL_GetWord(STATUS_LABEL_DEXTERITY), PAL_XY(100, 152), BATTLEWIN_LEVELUP_LABEL_COLOR, TRUE, FALSE); PAL_DrawText(PAL_GetWord(STATUS_LABEL_FLEERATE), PAL_XY(100, 170), BATTLEWIN_LEVELUP_LABEL_COLOR, TRUE, FALSE); // // Draw the original stats and stats after level up // PAL_DrawNumber(OrigPlayerRoles.rgwLevel[w], 4, PAL_XY(133, 47), kNumColorYellow, kNumAlignRight); PAL_DrawNumber(gpGlobals->g.PlayerRoles.rgwLevel[w], 4, PAL_XY(195, 47), kNumColorYellow, kNumAlignRight); PAL_DrawNumber(OrigPlayerRoles.rgwHP[w], 4, PAL_XY(133, 64), kNumColorYellow, kNumAlignRight); PAL_DrawNumber(OrigPlayerRoles.rgwMaxHP[w], 4, PAL_XY(154, 68), kNumColorBlue, kNumAlignRight); PAL_RLEBlitToSurface(PAL_SpriteGetFrame(gpSpriteUI, SPRITENUM_SLASH), gpScreen, PAL_XY(156, 66)); PAL_DrawNumber(gpGlobals->g.PlayerRoles.rgwHP[w], 4, PAL_XY(195, 64), kNumColorYellow, kNumAlignRight); PAL_DrawNumber(gpGlobals->g.PlayerRoles.rgwMaxHP[w], 4, PAL_XY(216, 68), kNumColorBlue, kNumAlignRight); PAL_RLEBlitToSurface(PAL_SpriteGetFrame(gpSpriteUI, SPRITENUM_SLASH), gpScreen, PAL_XY(218, 66)); PAL_DrawNumber(OrigPlayerRoles.rgwMP[w], 4, PAL_XY(133, 82), kNumColorYellow, kNumAlignRight); PAL_DrawNumber(OrigPlayerRoles.rgwMaxMP[w], 4, PAL_XY(154, 86), kNumColorBlue, kNumAlignRight); PAL_RLEBlitToSurface(PAL_SpriteGetFrame(gpSpriteUI, SPRITENUM_SLASH), gpScreen, PAL_XY(156, 84)); PAL_DrawNumber(gpGlobals->g.PlayerRoles.rgwMP[w], 4, PAL_XY(195, 82), kNumColorYellow, kNumAlignRight); PAL_DrawNumber(gpGlobals->g.PlayerRoles.rgwMaxMP[w], 4, PAL_XY(216, 86), kNumColorBlue, kNumAlignRight); PAL_RLEBlitToSurface(PAL_SpriteGetFrame(gpSpriteUI, SPRITENUM_SLASH), gpScreen, PAL_XY(218, 84)); PAL_DrawNumber(OrigPlayerRoles.rgwAttackStrength[w] + PAL_GetPlayerAttackStrength(w) - gpGlobals->g.PlayerRoles.rgwAttackStrength[w], 4, PAL_XY(133, 101), kNumColorYellow, kNumAlignRight); PAL_DrawNumber(PAL_GetPlayerAttackStrength(w), 4, PAL_XY(195, 101), kNumColorYellow, kNumAlignRight); PAL_DrawNumber(OrigPlayerRoles.rgwMagicStrength[w] + PAL_GetPlayerMagicStrength(w) - gpGlobals->g.PlayerRoles.rgwMagicStrength[w], 4, PAL_XY(133, 119), kNumColorYellow, kNumAlignRight); PAL_DrawNumber(PAL_GetPlayerMagicStrength(w), 4, PAL_XY(195, 119), kNumColorYellow, kNumAlignRight); PAL_DrawNumber(OrigPlayerRoles.rgwDefense[w] + PAL_GetPlayerDefense(w) - gpGlobals->g.PlayerRoles.rgwDefense[w], 4, PAL_XY(133, 137), kNumColorYellow, kNumAlignRight); PAL_DrawNumber(PAL_GetPlayerDefense(w), 4, PAL_XY(195, 137), kNumColorYellow, kNumAlignRight); PAL_DrawNumber(OrigPlayerRoles.rgwDexterity[w] + PAL_GetPlayerDexterity(w) - gpGlobals->g.PlayerRoles.rgwDexterity[w], 4, PAL_XY(133, 155), kNumColorYellow, kNumAlignRight); PAL_DrawNumber(PAL_GetPlayerDexterity(w), 4, PAL_XY(195, 155), kNumColorYellow, kNumAlignRight); PAL_DrawNumber(OrigPlayerRoles.rgwFleeRate[w] + PAL_GetPlayerFleeRate(w) - gpGlobals->g.PlayerRoles.rgwFleeRate[w], 4, PAL_XY(133, 173), kNumColorYellow, kNumAlignRight); PAL_DrawNumber(PAL_GetPlayerFleeRate(w), 4, PAL_XY(195, 173), kNumColorYellow, kNumAlignRight); // // Update the screen and wait for key // VIDEO_UpdateScreen(&rect1); PAL_WaitForKey(3000); OrigPlayerRoles = gpGlobals->g.PlayerRoles; } // // Increasing of other hidden levels // iTotalCount = 0; iTotalCount += gpGlobals->Exp.rgAttackExp[w].wCount; iTotalCount += gpGlobals->Exp.rgDefenseExp[w].wCount; iTotalCount += gpGlobals->Exp.rgDexterityExp[w].wCount; iTotalCount += gpGlobals->Exp.rgFleeExp[w].wCount; iTotalCount += gpGlobals->Exp.rgHealthExp[w].wCount; iTotalCount += gpGlobals->Exp.rgMagicExp[w].wCount; iTotalCount += gpGlobals->Exp.rgMagicPowerExp[w].wCount; if (iTotalCount > 0) { #define CHECK_HIDDEN_EXP(expname, statname, label) \ { \ dwExp = g_Battle.iExpGained; \ dwExp *= gpGlobals->Exp.expname[w].wCount; \ dwExp /= iTotalCount; \ dwExp *= 2; \ \ dwExp += gpGlobals->Exp.expname[w].wExp; \ \ if (gpGlobals->Exp.expname[w].wLevel > MAX_LEVELS) \ { \ gpGlobals->Exp.expname[w].wLevel = MAX_LEVELS; \ } \ \ while (dwExp >= gpGlobals->g.rgLevelUpExp[gpGlobals->Exp.expname[w].wLevel]) \ { \ dwExp -= gpGlobals->g.rgLevelUpExp[gpGlobals->Exp.expname[w].wLevel]; \ gpGlobals->g.PlayerRoles.statname[w] += RandomLong(1, 2); \ if (gpGlobals->Exp.expname[w].wLevel < MAX_LEVELS) \ { \ gpGlobals->Exp.expname[w].wLevel++; \ } \ } \ \ gpGlobals->Exp.expname[w].wExp = (WORD)dwExp; \ \ if (gpGlobals->g.PlayerRoles.statname[w] != \ OrigPlayerRoles.statname[w]) \ { \ PAL_CreateSingleLineBox(PAL_XY(83, 60), 8, FALSE); \ PAL_DrawText(PAL_GetWord(gpGlobals->g.PlayerRoles.rgwName[w]), PAL_XY(95, 70), \ 0, FALSE, FALSE); \ PAL_DrawText(PAL_GetWord(label), PAL_XY(143, 70), \ 0, FALSE, FALSE); \ PAL_DrawText(PAL_GetWord(BATTLEWIN_LEVELUP_LABEL), PAL_XY(175, 70), \ 0, FALSE, FALSE); \ PAL_DrawNumber(gpGlobals->g.PlayerRoles.statname[w] - \ OrigPlayerRoles.statname[w], \ 5, PAL_XY(188, 74), kNumColorYellow, kNumAlignRight); \ VIDEO_UpdateScreen(&rect); \ PAL_WaitForKey(3000); \ } \ } CHECK_HIDDEN_EXP(rgHealthExp, rgwMaxHP, STATUS_LABEL_HP); CHECK_HIDDEN_EXP(rgMagicExp, rgwMaxMP, STATUS_LABEL_MP); CHECK_HIDDEN_EXP(rgAttackExp, rgwAttackStrength, STATUS_LABEL_ATTACKPOWER); CHECK_HIDDEN_EXP(rgMagicPowerExp, rgwMagicStrength, STATUS_LABEL_MAGICPOWER); CHECK_HIDDEN_EXP(rgDefenseExp, rgwDefense, STATUS_LABEL_RESISTANCE); CHECK_HIDDEN_EXP(rgDexterityExp, rgwDexterity, STATUS_LABEL_DEXTERITY); CHECK_HIDDEN_EXP(rgFleeExp, rgwFleeRate, STATUS_LABEL_FLEERATE); #undef CHECK_HIDDEN_EXP } // // Learn all magics at the current level // j = 0; while (j < gpGlobals->g.nLevelUpMagic) { if (gpGlobals->g.lprgLevelUpMagic[j].m[w].wMagic == 0 || gpGlobals->g.lprgLevelUpMagic[j].m[w].wLevel > gpGlobals->g.PlayerRoles.rgwLevel[w]) { j++; continue; } if (PAL_AddMagic(w, gpGlobals->g.lprgLevelUpMagic[j].m[w].wMagic)) { PAL_CreateSingleLineBox(PAL_XY(65, 105), 10, FALSE); PAL_DrawText(PAL_GetWord(gpGlobals->g.PlayerRoles.rgwName[w]), PAL_XY(75, 115), 0, FALSE, FALSE); PAL_DrawText(PAL_GetWord(BATTLEWIN_ADDMAGIC_LABEL), PAL_XY(75 + 16 * 3, 115), 0, FALSE, FALSE); PAL_DrawText(PAL_GetWord(gpGlobals->g.lprgLevelUpMagic[j].m[w].wMagic), PAL_XY(75 + 16 * 5, 115), 0x1B, FALSE, FALSE); VIDEO_UpdateScreen(&rect); PAL_WaitForKey(3000); } j++; } } // // Run the post-battle scripts // for (i = 0; i <= g_Battle.wMaxEnemyIndex; i++) { PAL_RunTriggerScript(g_Battle.rgEnemy[i].wScriptOnBattleEnd, i); } // // Recover automatically after each battle // for (i = 0; i <= gpGlobals->wMaxPartyMemberIndex; i++) { w = gpGlobals->rgParty[i].wPlayerRole; #if 1//def PAL_CLASSIC gpGlobals->g.PlayerRoles.rgwHP[w] += (gpGlobals->g.PlayerRoles.rgwMaxHP[w] - gpGlobals->g.PlayerRoles.rgwHP[w]) / 2; gpGlobals->g.PlayerRoles.rgwMP[w] += (gpGlobals->g.PlayerRoles.rgwMaxMP[w] - gpGlobals->g.PlayerRoles.rgwMP[w]) / 2; #else if (gpGlobals->g.PlayerRoles.rgwHP[w] == 0) { gpGlobals->g.PlayerRoles.rgwHP[w] = 1; } else if (g_Battle.iExpGained > 0) { FLOAT f = (gpGlobals->g.rgLevelUpExp[gpGlobals->g.PlayerRoles.rgwLevel[w]] / 5.0f) / g_Battle.iExpGained; if (f < 2) { f = 2; } gpGlobals->g.PlayerRoles.rgwHP[w] += (gpGlobals->g.PlayerRoles.rgwMaxHP[w] - gpGlobals->g.PlayerRoles.rgwHP[w]) / f; gpGlobals->g.PlayerRoles.rgwMP[w] += (gpGlobals->g.PlayerRoles.rgwMaxMP[w] - gpGlobals->g.PlayerRoles.rgwMP[w]) / f / 1.2; } #endif } }
/*++ The main battle routine. Return value: The result of the battle. --*/ static BATTLERESULT PAL_BattleMain(void) { int i; DWORD dwTime; VIDEO_BackupScreen(); // // Generate the scene and draw the scene to the screen buffer // PAL_BattleMakeScene(); SDL_BlitSurface(g_Battle.lpSceneBuf, NULL, gpScreen, NULL); // // Fade out the music and delay for a while // PAL_PlayMUS(0, FALSE, 1); UTIL_Delay(200); // // Switch the screen // VIDEO_SwitchScreen(5); // // Play the battle music // PAL_PlayMUS(gpGlobals->wNumBattleMusic, TRUE, 0); // // Fade in the screen when needed // if (gpGlobals->fNeedToFadeIn) { PAL_FadeIn(gpGlobals->wNumPalette, gpGlobals->fNightPalette, 1); gpGlobals->fNeedToFadeIn = FALSE; } // // Run the pre-battle scripts for each enemies // for (i = 0; i <= g_Battle.wMaxEnemyIndex; i++) { g_Battle.rgEnemy[i].wScriptOnTurnStart = PAL_RunTriggerScript(g_Battle.rgEnemy[i].wScriptOnTurnStart, i); if (g_Battle.BattleResult != kBattleResultPreBattle) { break; } } if (g_Battle.BattleResult == kBattleResultPreBattle) { g_Battle.BattleResult = kBattleResultOnGoing; } #ifndef PAL_CLASSIC PAL_UpdateTimeChargingUnit(); #endif dwTime = SDL_GetTicks(); PAL_ClearKeyState(); // // Run the main battle loop. // while (TRUE) { // // Break out if the battle ended. // if (g_Battle.BattleResult != kBattleResultOnGoing) { break; } // // Wait for the time of one frame. Accept input here. // PAL_ProcessEvent(); while (SDL_GetTicks() <= dwTime) { PAL_ProcessEvent(); SDL_Delay(1); } // // Set the time of the next frame. // dwTime = SDL_GetTicks() + BATTLE_FRAME_TIME; // // Run the main frame routine. // PAL_BattleStartFrame(); // // Update the screen. // VIDEO_UpdateScreen(NULL); } // // Return the battle result // return g_Battle.BattleResult; }
VOID PAL_InGameMagicMenu( VOID ) /*++ Purpose: Show the magic menu. Parameters: None. Return value: None. --*/ { MENUITEM rgMenuItem[MAX_PLAYERS_IN_PARTY]; int i, y; static WORD w; WORD wMagic; const SDL_Rect rect = {35, 62, 95, 90}; // // Draw the player info boxes // y = 45; for (i = 0; i <= gpGlobals->wMaxPartyMemberIndex; i++) { PAL_PlayerInfoBox(PAL_XY(y, 165), gpGlobals->rgParty[i].wPlayerRole, 100, TIMEMETER_COLOR_DEFAULT, TRUE); y += 78; } y = 75; // // Generate one menu items for each player in the party // for (i = 0; i <= gpGlobals->wMaxPartyMemberIndex; i++) { assert(i <= MAX_PLAYERS_IN_PARTY); rgMenuItem[i].wValue = i; rgMenuItem[i].wNumWord = gpGlobals->g.PlayerRoles.rgwName[gpGlobals->rgParty[i].wPlayerRole]; rgMenuItem[i].fEnabled = (gpGlobals->g.PlayerRoles.rgwHP[gpGlobals->rgParty[i].wPlayerRole] > 0); rgMenuItem[i].pos = PAL_XY(48, y); y += 18; } // // Draw the box // PAL_CreateBox(PAL_XY(35, 62), gpGlobals->wMaxPartyMemberIndex, 2, 0, FALSE); VIDEO_UpdateScreen(&rect); w = PAL_ReadMenu(NULL, rgMenuItem, gpGlobals->wMaxPartyMemberIndex + 1, w, MENUITEM_COLOR); if (w == MENUITEM_VALUE_CANCELLED) { return; } wMagic = 0; while (TRUE) { wMagic = PAL_MagicSelectionMenu(gpGlobals->rgParty[w].wPlayerRole, FALSE, wMagic); if (wMagic == 0) { break; } if (gpGlobals->g.rgObject[wMagic].magic.wFlags & kMagicFlagApplyToAll) { gpGlobals->g.rgObject[wMagic].magic.wScriptOnUse = PAL_RunTriggerScript(gpGlobals->g.rgObject[wMagic].magic.wScriptOnUse, 0); if (g_fScriptSuccess) { gpGlobals->g.rgObject[wMagic].magic.wScriptOnSuccess = PAL_RunTriggerScript(gpGlobals->g.rgObject[wMagic].magic.wScriptOnSuccess, 0); gpGlobals->g.PlayerRoles.rgwMP[gpGlobals->rgParty[w].wPlayerRole] -= gpGlobals->g.lprgMagic[gpGlobals->g.rgObject[wMagic].magic.wMagicNumber].wCostMP; } if (gpGlobals->fNeedToFadeIn) { PAL_FadeIn(gpGlobals->wNumPalette, gpGlobals->fNightPalette, 1); gpGlobals->fNeedToFadeIn = FALSE; } } else { // // Need to select which player to use the magic on. // WORD wPlayer = 0; SDL_Rect rect; while (wPlayer != MENUITEM_VALUE_CANCELLED) { // // Redraw the player info boxes first // y = 45; for (i = 0; i <= gpGlobals->wMaxPartyMemberIndex; i++) { PAL_PlayerInfoBox(PAL_XY(y, 165), gpGlobals->rgParty[i].wPlayerRole, 100, TIMEMETER_COLOR_DEFAULT, TRUE); y += 78; } // // Draw the cursor on the selected item // rect.x = 70 + 78 * wPlayer; rect.y = 193; rect.w = 9; rect.h = 6; PAL_RLEBlitToSurface(PAL_SpriteGetFrame(gpSpriteUI, SPRITENUM_CURSOR), gpScreen, PAL_XY(rect.x, rect.y)); VIDEO_UpdateScreen(&rect); while (TRUE) { PAL_ClearKeyState(); PAL_ProcessEvent(); if (g_InputState.dwKeyPress & kKeyMenu) { wPlayer = MENUITEM_VALUE_CANCELLED; break; } else if (g_InputState.dwKeyPress & kKeySearch) { gpGlobals->g.rgObject[wMagic].magic.wScriptOnUse = PAL_RunTriggerScript(gpGlobals->g.rgObject[wMagic].magic.wScriptOnUse, gpGlobals->rgParty[wPlayer].wPlayerRole); if (g_fScriptSuccess) { gpGlobals->g.rgObject[wMagic].magic.wScriptOnSuccess = PAL_RunTriggerScript(gpGlobals->g.rgObject[wMagic].magic.wScriptOnSuccess, gpGlobals->rgParty[wPlayer].wPlayerRole); if (g_fScriptSuccess) { gpGlobals->g.PlayerRoles.rgwMP[gpGlobals->rgParty[w].wPlayerRole] -= gpGlobals->g.lprgMagic[gpGlobals->g.rgObject[wMagic].magic.wMagicNumber].wCostMP; // // Check if we have run out of MP // if (gpGlobals->g.PlayerRoles.rgwMP[gpGlobals->rgParty[w].wPlayerRole] < gpGlobals->g.lprgMagic[gpGlobals->g.rgObject[wMagic].magic.wMagicNumber].wCostMP) { // // Don't go further if run out of MP // wPlayer = MENUITEM_VALUE_CANCELLED; } } } break; } else if (g_InputState.dwKeyPress & (kKeyLeft | kKeyUp)) { if (wPlayer > 0) { wPlayer--; break; } } else if (g_InputState.dwKeyPress & (kKeyRight | kKeyDown)) { if (wPlayer < gpGlobals->wMaxPartyMemberIndex) { wPlayer++; break; } } SDL_Delay(1); } } } // // Redraw the player info boxes // y = 45; for (i = 0; i <= gpGlobals->wMaxPartyMemberIndex; i++) { PAL_PlayerInfoBox(PAL_XY(y, 165), gpGlobals->rgParty[i].wPlayerRole, 100, TIMEMETER_COLOR_DEFAULT, TRUE); y += 78; } } }
VOID PAL_EquipItemMenu( WORD wItem ) /*++ Purpose: Show the menu which allow players to equip the specified item. Parameters: [IN] wItem - the object ID of the item. Return value: None. --*/ { PAL_LARGE BYTE bufBackground[320 * 200]; PAL_LARGE BYTE bufImage[2048]; WORD w; int iCurrentPlayer, i; BYTE bColor, bSelectedColor; DWORD dwColorChangeTime; gpGlobals->wLastUnequippedItem = wItem; PAL_MKFDecompressChunk(bufBackground, 320 * 200, EQUIPMENU_BACKGROUND_FBPNUM, gpGlobals->f.fpFBP); iCurrentPlayer = 0; bSelectedColor = MENUITEM_COLOR_SELECTED_FIRST; dwColorChangeTime = SDL_GetTicks() + (600 / MENUITEM_COLOR_SELECTED_TOTALNUM); while (TRUE) { wItem = gpGlobals->wLastUnequippedItem; // // Draw the background // PAL_FBPBlitToSurface(bufBackground, gpScreen); // // Draw the item picture // if (PAL_MKFReadChunk(bufImage, 2048, gpGlobals->g.rgObject[wItem].item.wBitmap, gpGlobals->f.fpBALL) > 0) { PAL_RLEBlitToSurface(bufImage, gpScreen, PAL_XY(16, 16)); } // // Draw the current equipment of the selected player // w = gpGlobals->rgParty[iCurrentPlayer].wPlayerRole; for (i = 0; i < MAX_PLAYER_EQUIPMENTS; i++) { if (gpGlobals->g.PlayerRoles.rgwEquipment[i][w] != 0) { PAL_DrawText(PAL_GetWord(gpGlobals->g.PlayerRoles.rgwEquipment[i][w]), PAL_XY(130, 11 + i * 22), MENUITEM_COLOR, TRUE, FALSE); } } // // Draw the stats of the currently selected player // PAL_DrawNumber(PAL_GetPlayerAttackStrength(w), 4, PAL_XY(260, 14), kNumColorCyan, kNumAlignRight); PAL_DrawNumber(PAL_GetPlayerMagicStrength(w), 4, PAL_XY(260, 36), kNumColorCyan, kNumAlignRight); PAL_DrawNumber(PAL_GetPlayerDefense(w), 4, PAL_XY(260, 58), kNumColorCyan, kNumAlignRight); PAL_DrawNumber(PAL_GetPlayerDexterity(w), 4, PAL_XY(260, 80), kNumColorCyan, kNumAlignRight); PAL_DrawNumber(PAL_GetPlayerFleeRate(w), 4, PAL_XY(260, 102), kNumColorCyan, kNumAlignRight); // // Draw a box for player selection // PAL_CreateBox(PAL_XY(2, 95), gpGlobals->wMaxPartyMemberIndex, 2, 0, FALSE); // // Draw the label of players // for (i = 0; i <= gpGlobals->wMaxPartyMemberIndex; i++) { w = gpGlobals->rgParty[i].wPlayerRole; if (iCurrentPlayer == i) { if (gpGlobals->g.rgObject[wItem].item.wFlags & (kItemFlagEquipableByPlayerRole_First << w)) { bColor = bSelectedColor; } else { bColor = MENUITEM_COLOR_SELECTED_INACTIVE; } } else { if (gpGlobals->g.rgObject[wItem].item.wFlags & (kItemFlagEquipableByPlayerRole_First << w)) { bColor = MENUITEM_COLOR; } else { bColor = MENUITEM_COLOR_INACTIVE; } } PAL_DrawText(PAL_GetWord(gpGlobals->g.PlayerRoles.rgwName[w]), PAL_XY(15, 108 + 18 * i), bColor, TRUE, FALSE); } // // Draw the text label and amount of the item // if (wItem != 0) { PAL_DrawText(PAL_GetWord(wItem), PAL_XY(5, 70), MENUITEM_COLOR_CONFIRMED, TRUE, FALSE); PAL_DrawNumber(PAL_GetItemAmount(wItem), 2, PAL_XY(65, 73), kNumColorCyan, kNumAlignRight); } // // Update the screen // VIDEO_UpdateScreen(NULL); // // Accept input // PAL_ClearKeyState(); while (TRUE) { PAL_ProcessEvent(); // // See if we should change the highlight color // if (SDL_GetTicks() > dwColorChangeTime) { if ((WORD)bSelectedColor + 1 >= (WORD)MENUITEM_COLOR_SELECTED_FIRST + MENUITEM_COLOR_SELECTED_TOTALNUM) { bSelectedColor = MENUITEM_COLOR_SELECTED_FIRST; } else { bSelectedColor++; } dwColorChangeTime = SDL_GetTicks() + (600 / MENUITEM_COLOR_SELECTED_TOTALNUM); // // Redraw the selected item if needed. // w = gpGlobals->rgParty[iCurrentPlayer].wPlayerRole; if (gpGlobals->g.rgObject[wItem].item.wFlags & (kItemFlagEquipableByPlayerRole_First << w)) { PAL_DrawText(PAL_GetWord(gpGlobals->g.PlayerRoles.rgwName[w]), PAL_XY(15, 108 + 18 * iCurrentPlayer), bSelectedColor, TRUE, TRUE); } } if (g_InputState.dwKeyPress != 0) { break; } SDL_Delay(1); } if (wItem == 0) { return; } if (g_InputState.dwKeyPress & (kKeyUp | kKeyLeft)) { iCurrentPlayer--; if (iCurrentPlayer < 0) { iCurrentPlayer = 0; } } else if (g_InputState.dwKeyPress & (kKeyDown | kKeyRight)) { iCurrentPlayer++; if (iCurrentPlayer > gpGlobals->wMaxPartyMemberIndex) { iCurrentPlayer = gpGlobals->wMaxPartyMemberIndex; } } else if (g_InputState.dwKeyPress & kKeyMenu) { return; } else if (g_InputState.dwKeyPress & kKeySearch) { w = gpGlobals->rgParty[iCurrentPlayer].wPlayerRole; if (gpGlobals->g.rgObject[wItem].item.wFlags & (kItemFlagEquipableByPlayerRole_First << w)) { // // Run the equip script // gpGlobals->g.rgObject[wItem].item.wScriptOnEquip = PAL_RunTriggerScript(gpGlobals->g.rgObject[wItem].item.wScriptOnEquip, gpGlobals->rgParty[iCurrentPlayer].wPlayerRole); } } } }
VOID PAL_BattleStartFrame( VOID ) /*++ Purpose: Called once per video frame in battle. Parameters: None. Return value: None. --*/ { int i; int iMax; BOOL fEnded; WORD wPlayerRole; WORD wDexterity; FLOAT flMax; PAL_BattleUpdateFighters(); // // Update the scene // PAL_BattleMakeScene(); SDL_BlitSurface(g_Battle.lpSceneBuf, NULL, gpScreen, NULL); // // Check if the battle is over // fEnded = TRUE; for (i = 0; i <= g_Battle.wMaxEnemyIndex; i++) { if (g_Battle.rgEnemy[i].wObjectID != 0) { fEnded = FALSE; break; } } if (fEnded) { // // All enemies are cleared. Won the battle. // g_Battle.BattleResult = kBattleResultWon; SOUND_Play(-1); return; } else { fEnded = TRUE; for (i = 0; i <= gpGlobals->wMaxPartyMemberIndex; i++) { wPlayerRole = gpGlobals->rgParty[i].wPlayerRole; if (gpGlobals->g.PlayerRoles.rgwHP[wPlayerRole] != 0 || gpGlobals->rgPlayerStatus[wPlayerRole][kStatusPuppet] != 0) { fEnded = FALSE; break; } } if (fEnded) { // // All players are dead. Lost the battle. // g_Battle.BattleResult = kBattleResultLost; return; } } // // Run the logic for all enemies // for (i = 0; i <= g_Battle.wMaxEnemyIndex; i++) { if (g_Battle.rgEnemy[i].wObjectID == 0) { continue; } if (g_Battle.rgEnemy[i].fTurnStart) { g_Battle.rgEnemy[i].wScriptOnTurnStart = PAL_RunTriggerScript(g_Battle.rgEnemy[i].wScriptOnTurnStart, i); g_Battle.rgEnemy[i].fTurnStart = FALSE; } } for (i = 0; i <= g_Battle.wMaxEnemyIndex; i++) { if (g_Battle.rgEnemy[i].wObjectID == 0) { continue; } switch (g_Battle.rgEnemy[i].state) { case kFighterWait: flMax = PAL_GetTimeChargingSpeed(PAL_GetEnemyDexterity(i)); if (flMax != 0) { g_Battle.rgEnemy[i].flTimeMeter += flMax; if (g_Battle.rgEnemy[i].flTimeMeter > 100 && flMax > 0) { g_Battle.rgEnemy[i].state = kFighterCom; } } break; case kFighterCom: g_Battle.rgEnemy[i].wScriptOnReady = PAL_RunTriggerScript(g_Battle.rgEnemy[i].wScriptOnReady, i); g_Battle.rgEnemy[i].state = kFighterAct; break; case kFighterAct: ////TEST/////////////////////////////////////////////////////////// SOUND_Play(g_Battle.rgEnemy[i].e.wAttackSound); if (g_Battle.rgEnemy[i].fFirstMoveDone) PAL_BattleUIShowText(va("enemy %d attack (2nd)",i), 500); else PAL_BattleUIShowText(va("enemy %d attack",i), 500); g_Battle.rgEnemy[i].flTimeMeter =0; g_Battle.rgEnemy[i].state = kFighterWait; //////////////////////////////////////////////////////////////////// if (!g_Battle.rgEnemy[i].fFirstMoveDone) { if (g_Battle.rgEnemy[i].e.wDualMove >= 2 || (g_Battle.rgEnemy[i].e.wDualMove != 0 && RandomLong(0, 1))) { g_Battle.rgEnemy[i].flTimeMeter = 100; g_Battle.rgEnemy[i].state = kFighterWait; g_Battle.rgEnemy[i].fFirstMoveDone = TRUE; break; } } g_Battle.rgEnemy[i].fFirstMoveDone = FALSE; g_Battle.rgEnemy[i].fTurnStart = TRUE; break; } } // // Update the battle UI // PAL_BattleUIUpdate(); // // Run the logic for all players // for (i = 0; i <= gpGlobals->wMaxPartyMemberIndex; i++) { wPlayerRole = gpGlobals->rgParty[i].wPlayerRole; // // Skip dead players // if (gpGlobals->g.PlayerRoles.rgwHP[wPlayerRole] == 0 && gpGlobals->rgPlayerStatus[wPlayerRole][kStatusPuppet] == 0) { g_Battle.rgPlayer[i].state = kFighterWait; g_Battle.rgPlayer[i].flTimeMeter = 0; continue; } switch (g_Battle.rgPlayer[i].state) { case kFighterWait: wDexterity = PAL_GetPlayerActualDexterity(wPlayerRole); g_Battle.rgPlayer[i].flTimeMeter += PAL_GetTimeChargingSpeed(wDexterity) * g_Battle.rgPlayer[i].flTimeSpeedModifier; break; case kFighterCom: if (g_Battle.UI.state == kBattleUIWait) { PAL_BattleUIPlayerReady(i); } break; case kFighterAct: wDexterity = PAL_GetPlayerActualDexterity(wPlayerRole); g_Battle.rgPlayer[i].action.flRemainingTime -= PAL_GetTimeChargingSpeed(wDexterity); if (g_Battle.rgPlayer[i].action.flRemainingTime < 0) { // // Perform the action for this player. // PAL_BattlePlayerPerformAction(i); // // Reduce the time for other players when uses coopmagic // if (g_Battle.rgPlayer[i].action.ActionType == kBattleActionCoopMagic) { for (iMax = 0; iMax <= gpGlobals->wMaxPartyMemberIndex; iMax++) { g_Battle.rgPlayer[iMax].flTimeMeter = 0; g_Battle.rgPlayer[iMax].flTimeSpeedModifier = 2.0f; } } else { g_Battle.rgPlayer[i].flTimeMeter = 0; } // // Revert this player back to waiting state. // g_Battle.rgPlayer[i].state = kFighterWait; g_Battle.rgPlayer[i].flTimeSpeedModifier = 1.0f; } break; } } // // Start the UI for the fastest and ready player // flMax = 0; iMax = 0; for (i = 0; i <= gpGlobals->wMaxPartyMemberIndex; i++) { if (g_Battle.rgPlayer[i].state == kFighterCom || (g_Battle.rgPlayer[i].state == kFighterAct && g_Battle.rgPlayer[i].action.ActionType == kBattleActionCoopMagic)) { flMax = 0; break; } else if (g_Battle.rgPlayer[i].state == kFighterWait) { if (g_Battle.rgPlayer[i].flTimeMeter > flMax) { iMax = i; flMax = g_Battle.rgPlayer[i].flTimeMeter; } } } if (flMax > 100.0f) { g_Battle.rgPlayer[iMax].state = kFighterCom; g_Battle.rgPlayer[iMax].fDefending = FALSE; } ////TEST/////////////////////////////////////////////////////////-START if (g_InputState.dwKeyPress & kKeyFlee){ for (i = 0; i < 5; i++){ gpGlobals->g.PlayerRoles.rgwHP[i] = 0; } return; } ////TEST/////////////////////////////////////////////////////////-END }
VOID PAL_BattlePlayerPerformAction( WORD wPlayerIndex ) /*++ Purpose: Perform the selected action for a player. Parameters: [IN] wPlayerIndex - the index of the player. Return value: None. --*/ { // TODO SHORT sDamage; WORD wPlayerRole = gpGlobals->rgParty[wPlayerIndex].wPlayerRole; SHORT sTarget = g_Battle.rgPlayer[wPlayerIndex].action.sTarget; int x, y; int i, t; WORD str, def, res, wObject; BOOL fCritical, fPoisoned; PAL_BattlePlayerValidateAction(wPlayerIndex); PAL_BattleBackupStat(); switch (g_Battle.rgPlayer[wPlayerIndex].action.ActionType) { case kBattleActionAttack: if (sTarget != -1) { // // Attack one enemy // if (g_Battle.rgEnemy[sTarget].wObjectID == 0) { sTarget = PAL_BattleSelectAutoTarget(); g_Battle.rgPlayer[wPlayerIndex].action.sTarget = sTarget; } for (t = 0; t < (gpGlobals->rgPlayerStatus[wPlayerRole][kStatusDualAttack] ? 2 : 1); t++) { str = PAL_GetPlayerAttackStrength(wPlayerRole); def = g_Battle.rgEnemy[sTarget].e.wDefense; def += (g_Battle.rgEnemy[sTarget].e.wLevel + 6) * 4; res = g_Battle.rgEnemy[sTarget].e.wAttackResistance; fCritical = FALSE; sDamage = PAL_CalcPhysicalAttackDamage(str, def, res); if (RandomLong(0, 5) == 0) { // // Critical Hit // sDamage *= 3; fCritical = TRUE; } if (wPlayerRole == 0 && RandomLong(0, 11) == 0) { // // Bonus hit for Li Xiaoyao // sDamage *= 2; fCritical = TRUE; } if (sDamage <= 0) { sDamage = 1; } if (g_Battle.rgEnemy[sTarget].e.wHealth > (WORD)sDamage) { g_Battle.rgEnemy[sTarget].e.wHealth -= sDamage; } else { g_Battle.rgEnemy[sTarget].e.wHealth = 0; } if (t == 0) { g_Battle.rgPlayer[wPlayerIndex].wCurrentFrame = 7; PAL_BattleDelay(4, 0); } PAL_BattleShowPlayerAttackAnim(wPlayerIndex, fCritical); // // Show the number of damage // x = PAL_X(g_Battle.rgEnemy[sTarget].pos); y = PAL_Y(g_Battle.rgEnemy[sTarget].pos) - 70; x += PAL_RLEGetWidth(PAL_SpriteGetFrame(g_Battle.rgEnemy[sTarget].lpSprite, g_Battle.rgEnemy[sTarget].wCurrentFrame)) / 2; y += PAL_RLEGetHeight(PAL_SpriteGetFrame(g_Battle.rgEnemy[sTarget].lpSprite, g_Battle.rgEnemy[sTarget].wCurrentFrame)) / 2; if (y < 10) { y = 10; } PAL_BattleUIShowNum((WORD)sDamage, PAL_XY(x, y), kNumColorBlue); } } else { // // Attack all enemies // for (t = 0; t < (gpGlobals->rgPlayerStatus[wPlayerRole][kStatusDualAttack] ? 2 : 1); t++) { int division = 1; const int index[MAX_ENEMIES_IN_TEAM] = {2, 1, 0, 4, 3}; fCritical = (RandomLong(0, 5) == 0); if (t == 0) { g_Battle.rgPlayer[wPlayerIndex].wCurrentFrame = 7; PAL_BattleDelay(4, 0); } PAL_BattleShowPlayerAttackAnim(wPlayerIndex, fCritical); for (i = 0; i < MAX_ENEMIES_IN_TEAM; i++) { if (g_Battle.rgEnemy[index[i]].wObjectID == 0 || index[i] > g_Battle.wMaxEnemyIndex) { continue; } str = PAL_GetPlayerAttackStrength(wPlayerRole); def = g_Battle.rgEnemy[index[i]].e.wDefense; def += (g_Battle.rgEnemy[index[i]].e.wLevel + 6) * 4; res = g_Battle.rgEnemy[index[i]].e.wAttackResistance; sDamage = PAL_CalcPhysicalAttackDamage(str, def, res); if (fCritical) { // // Critical Hit // sDamage *= 3; } sDamage /= division; if (sDamage <= 0) { sDamage = 1; } if (g_Battle.rgEnemy[index[i]].e.wHealth > (WORD)sDamage) { g_Battle.rgEnemy[index[i]].e.wHealth -= sDamage; } else { g_Battle.rgEnemy[index[i]].e.wHealth = 0; } // // Show the number of damage // x = PAL_X(g_Battle.rgEnemy[index[i]].pos); y = PAL_Y(g_Battle.rgEnemy[index[i]].pos) - 70; x += PAL_RLEGetWidth(PAL_SpriteGetFrame(g_Battle.rgEnemy[index[i]].lpSprite, g_Battle.rgEnemy[index[i]].wCurrentFrame)) / 2; y += PAL_RLEGetHeight(PAL_SpriteGetFrame(g_Battle.rgEnemy[index[i]].lpSprite, g_Battle.rgEnemy[index[i]].wCurrentFrame)) / 2; if (y < 10) { y = 10; } PAL_BattleUIShowNum((WORD)sDamage, PAL_XY(x, y), kNumColorBlue); division++; if (division > 3) { division = 3; } } } } PAL_BattleUpdateFighters(); PAL_BattleMakeScene(); PAL_BattleDelay(5, 0); break; case kBattleActionAttackMate: break; case kBattleActionCoopMagic: break; case kBattleActionDefend: g_Battle.rgPlayer[wPlayerIndex].fDefending = TRUE; break; case kBattleActionFlee: break; case kBattleActionMagic: break; case kBattleActionThrowItem: break; case kBattleActionUseItem: wObject = g_Battle.rgPlayer[wPlayerIndex].action.wActionID; PAL_BattleShowPlayerUseItemAnim(wPlayerIndex, wObject, sTarget); // // Run the script // gpGlobals->g.rgObject[wObject].item.wScriptOnUse = PAL_RunTriggerScript(gpGlobals->g.rgObject[wObject].item.wScriptOnUse, (sTarget == -1) ? 0xFFFF : gpGlobals->rgParty[sTarget].wPlayerRole); // // Remove the item if the item is consuming and the script succeeded // if ((gpGlobals->g.rgObject[wObject].item.wFlags & kItemFlagConsuming) && g_fScriptSuccess) { PAL_AddItemToInventory(wObject, -1); } PAL_BattleUpdateFighters(); PAL_BattleDisplayStatChange(); PAL_BattleDelay(8, 0); break; case kBattleActionPass: break; } PAL_BattlePostActionCheck(FALSE); // // Check for poisons // fPoisoned = FALSE; PAL_BattleBackupStat(); for (i = 0; i < MAX_POISONS; i++) { wObject = gpGlobals->rgPoisonStatus[i][wPlayerIndex].wPoisonID; if (wObject != 0) { fPoisoned = TRUE; gpGlobals->rgPoisonStatus[i][wPlayerIndex].wPoisonScript = PAL_RunTriggerScript(gpGlobals->rgPoisonStatus[i][wPlayerIndex].wPoisonScript, wPlayerRole); } } if (fPoisoned) { PAL_BattleDelay(3, 0); PAL_BattleUpdateFighters(); if (PAL_BattleDisplayStatChange()) { PAL_BattleDelay(12, 0); } } // // Update statuses // for (i = 0; i < kStatusAll; i++) { if (gpGlobals->rgPlayerStatus[wPlayerRole][i] > 0) { gpGlobals->rgPlayerStatus[wPlayerRole][i]--; } } }
VOID PAL_Search( VOID ) /*++ Purpose: Process searching trigger events. Parameters: None. Return value: None. --*/ { int x, y, xOffset, yOffset, dx, dy, dh, ex, ey, eh, i, k, l; LPEVENTOBJECT p; PAL_POS rgPos[13]; // // Get the party location // x = PAL_X(gpGlobals->viewport) + PAL_X(gpGlobals->partyoffset); y = PAL_Y(gpGlobals->viewport) + PAL_Y(gpGlobals->partyoffset); if (gpGlobals->wPartyDirection == kDirNorth || gpGlobals->wPartyDirection == kDirEast) { xOffset = 16; } else { xOffset = -16; } if (gpGlobals->wPartyDirection == kDirEast || gpGlobals->wPartyDirection == kDirSouth) { yOffset = 8; } else { yOffset = -8; } rgPos[0] = PAL_XY(x, y); for (i = 0; i < 4; i++) { rgPos[i * 3 + 1] = PAL_XY(x + xOffset, y + yOffset); rgPos[i * 3 + 2] = PAL_XY(x, y + yOffset * 2); rgPos[i * 3 + 3] = PAL_XY(x + xOffset, y); x += xOffset; y += yOffset; } for (i = 0; i < 13; i++) { // // Convert to map location // dh = ((PAL_X(rgPos[i]) % 32) ? 1 : 0); dx = PAL_X(rgPos[i]) / 32; dy = PAL_Y(rgPos[i]) / 16; // // Loop through all event objects // for (k = gpGlobals->g.rgScene[gpGlobals->wNumScene - 1].wEventObjectIndex; k < gpGlobals->g.rgScene[gpGlobals->wNumScene].wEventObjectIndex; k++) { p = &(gpGlobals->g.lprgEventObject[k]); ex = p->x / 32; ey = p->y / 16; eh = ((p->x % 32) ? 1 : 0); if (p->sState <= 0 || p->wTriggerMode >= kTriggerTouchNear || p->wTriggerMode * 6 - 4 < i || dx != ex || dy != ey || dh != eh) { continue; } // // Adjust direction/gesture for party members and the event object // if (p->nSpriteFrames * 4 > p->wCurrentFrameNum) { p->wCurrentFrameNum = 0; // use standing gesture p->wDirection = (gpGlobals->wPartyDirection + 2) % 4; // face the party for (l = 0; l <= gpGlobals->wMaxPartyMemberIndex; l++) { // // All party members should face the event object // gpGlobals->rgParty[l].wFrame = gpGlobals->wPartyDirection * 3; } // // Redraw everything // PAL_MakeScene(); VIDEO_UpdateScreen(NULL); } // // Execute the script // p->wTriggerScript = PAL_RunTriggerScript(p->wTriggerScript, k + 1); // // Clear inputs and delay for a short time // UTIL_Delay(50); PAL_ClearKeyState(); return; // don't go further } } }
VOID PAL_GameUpdate( BOOL fTrigger ) /*++ Purpose: The main game logic routine. Update the status of everything. Parameters: [IN] fTrigger - whether to process trigger events or not. Return value: None. --*/ { WORD wEventObjectID, wDir; int i; LPEVENTOBJECT p; // // Check for trigger events // if (fTrigger) { // // Check if we are entering a new scene // if (gpGlobals->fEnteringScene) { // // Run the script for entering the scene // gpGlobals->fEnteringScene = FALSE; i = gpGlobals->wNumScene - 1; gpGlobals->g.rgScene[i].wScriptOnEnter = PAL_RunTriggerScript(gpGlobals->g.rgScene[i].wScriptOnEnter, 0xFFFF); if (gpGlobals->fEnteringScene || gpGlobals->fGameStart) { // // Don't go further as we're switching to another scene // return; } PAL_ClearKeyState(); PAL_MakeScene(); } // // Update the vanish time for all event objects // for (wEventObjectID = 0; wEventObjectID < gpGlobals->g.nEventObject; wEventObjectID++) { p = &gpGlobals->g.lprgEventObject[wEventObjectID]; if (p->sVanishTime != 0) { p->sVanishTime += ((p->sVanishTime < 0) ? 1 : -1); } } // // Loop through all event objects in the current scene // for (wEventObjectID = gpGlobals->g.rgScene[gpGlobals->wNumScene - 1].wEventObjectIndex + 1; wEventObjectID <= gpGlobals->g.rgScene[gpGlobals->wNumScene].wEventObjectIndex; wEventObjectID++) { p = &gpGlobals->g.lprgEventObject[wEventObjectID - 1]; if (p->sVanishTime != 0) { continue; } if (p->sState < 0) { if (p->x < PAL_X(gpGlobals->viewport) || p->x > PAL_X(gpGlobals->viewport) + 320 || p->y < PAL_Y(gpGlobals->viewport) || p->y > PAL_Y(gpGlobals->viewport) + 320) { p->sState = abs(p->sState); p->wCurrentFrameNum = 0; } } else if (p->sState > 0 && p->wTriggerMode >= kTriggerTouchNear) { // // This event object can be triggered without manually exploring // if (abs(PAL_X(gpGlobals->viewport) + PAL_X(gpGlobals->partyoffset) - p->x) + abs(PAL_Y(gpGlobals->viewport) + PAL_Y(gpGlobals->partyoffset) - p->y) * 2 < (p->wTriggerMode - kTriggerTouchNear) * 32 + 16) { // // Player is in the trigger zone. // if (p->nSpriteFrames) { // // The sprite has multiple frames. Try to adjust the direction. // int xOffset, yOffset; p->wCurrentFrameNum = 0; xOffset = PAL_X(gpGlobals->viewport) + PAL_X(gpGlobals->partyoffset) - p->x; yOffset = PAL_Y(gpGlobals->viewport) + PAL_Y(gpGlobals->partyoffset) - p->y; if (xOffset > 0) { p->wDirection = ((yOffset > 0) ? kDirEast : kDirNorth); } else { p->wDirection = ((yOffset > 0) ? kDirSouth : kDirWest); } // // Redraw the scene // PAL_UpdatePartyGestures(FALSE); PAL_MakeScene(); VIDEO_UpdateScreen(NULL); } // // Execute the script. // p->wTriggerScript = PAL_RunTriggerScript(p->wTriggerScript, wEventObjectID); PAL_ClearKeyState(); if (gpGlobals->fEnteringScene || gpGlobals->fGameStart) { // // Don't go further on scene switching // return; } } } } } // // Run autoscript for each event objects // for (wEventObjectID = gpGlobals->g.rgScene[gpGlobals->wNumScene - 1].wEventObjectIndex + 1; wEventObjectID <= gpGlobals->g.rgScene[gpGlobals->wNumScene].wEventObjectIndex; wEventObjectID++) { p = &gpGlobals->g.lprgEventObject[wEventObjectID - 1]; if (p->sState > 0 && p->sVanishTime == 0) { WORD wScriptEntry = p->wAutoScript; if (wScriptEntry != 0) { p->wAutoScript = PAL_RunAutoScript(wScriptEntry, wEventObjectID); if (gpGlobals->fEnteringScene || gpGlobals->fGameStart) { // // Don't go further on scene switching // return; } } } // // Check if the player is in the way // if (fTrigger && p->sState >= kObjStateBlocker && p->wSpriteNum != 0 && abs(p->x - PAL_X(gpGlobals->viewport) - PAL_X(gpGlobals->partyoffset)) + abs(p->y - PAL_Y(gpGlobals->viewport) - PAL_Y(gpGlobals->partyoffset)) * 2 <= 12) { // // Player is in the way, try to move a step // wDir = (p->wDirection + 1) % 4; for (i = 0; i < 4; i++) { int x, y; PAL_POS pos; x = PAL_X(gpGlobals->viewport) + PAL_X(gpGlobals->partyoffset); y = PAL_Y(gpGlobals->viewport) + PAL_Y(gpGlobals->partyoffset); x += ((wDir == kDirWest || wDir == kDirSouth) ? -16 : 16); y += ((wDir == kDirWest || wDir == kDirNorth) ? -8 : 8); pos = PAL_XY(x, y); if (!PAL_CheckObstacle(pos, TRUE, 0)) { // // move here // gpGlobals->viewport = PAL_XY( PAL_X(pos) - PAL_X(gpGlobals->partyoffset), PAL_Y(pos) - PAL_Y(gpGlobals->partyoffset)); break; } wDir = (wDir + 1) % 4; } } } gpGlobals->dwFrameNum++; }
VOID PAL_GameUseItem( VOID ) /*++ Purpose: Allow player use an item in the game. Parameters: None. Return value: None. --*/ { WORD wObject; while (TRUE) { wObject = PAL_ItemSelectMenu(NULL, kItemFlagUsable); if (wObject == 0) { return; } if (!(gpGlobals->g.rgObject[wObject].item.wFlags & kItemFlagApplyToAll)) { // // Select the player to use the item on // WORD wPlayer = 0; while (TRUE) { wPlayer = PAL_ItemUseMenu(wObject); if (wPlayer == MENUITEM_VALUE_CANCELLED) { break; } // // Run the script // gpGlobals->g.rgObject[wObject].item.wScriptOnUse = PAL_RunTriggerScript(gpGlobals->g.rgObject[wObject].item.wScriptOnUse, wPlayer); // // Remove the item if the item is consuming and the script succeeded // if ((gpGlobals->g.rgObject[wObject].item.wFlags & kItemFlagConsuming) && g_fScriptSuccess) { PAL_AddItemToInventory(wObject, -1); } } } else { // // Run the script // gpGlobals->g.rgObject[wObject].item.wScriptOnUse = PAL_RunTriggerScript(gpGlobals->g.rgObject[wObject].item.wScriptOnUse, 0xFFFF); // // Remove the item if the item is consuming and the script succeeded // if ((gpGlobals->g.rgObject[wObject].item.wFlags & kItemFlagConsuming) && g_fScriptSuccess) { PAL_AddItemToInventory(wObject, -1); } return; } } }