Beispiel #1
0
/*++
 Generate the battle scene into the scene buffer.
 --*/
VOID PAL_BattleMakeScene(void)
{
    int          i;
    PAL_POS      pos;
    LPBYTE       pSrc, pDst;
    BYTE         b;
    
    //
    // Draw the background
    //
    pSrc = g_Battle.lpBackground->pixels;
    pDst = g_Battle.lpSceneBuf->pixels;
    
    for (i = 0; i < g_Battle.lpSceneBuf->pitch * g_Battle.lpSceneBuf->h; i++)
    {
        b = (*pSrc & 0x0F);
        b += g_Battle.sBackgroundColorShift;
        
        if (b & 0x80)
        {
            b = 0;
        }
        else if (b & 0x70)
        {
            b = 0x0F;
        }
        
        *pDst = (b | (*pSrc & 0xF0));
        
        ++pSrc;
        ++pDst;
    }
    
    PAL_ApplyWave(g_Battle.lpSceneBuf);
    
    //
    // Draw the enemies
    //
    for (i = g_Battle.wMaxEnemyIndex; i >= 0; i--)
    {
        pos = g_Battle.rgEnemy[i].pos;
        
        if (g_Battle.rgEnemy[i].rgwStatus[kStatusConfused] > 0 &&
            g_Battle.rgEnemy[i].rgwStatus[kStatusSleep] == 0 &&
            g_Battle.rgEnemy[i].rgwStatus[kStatusParalyzed] == 0)
        {
            //
            // Enemy is confused
            //
            pos = PAL_XY(PAL_X(pos) + RandomLong(-1, 1), PAL_Y(pos));
        }
        
        pos = PAL_XY(PAL_X(pos) - PAL_RLEGetWidth(PAL_SpriteGetFrame(g_Battle.rgEnemy[i].lpSprite, g_Battle.rgEnemy[i].wCurrentFrame)) / 2,
                     PAL_Y(pos) - PAL_RLEGetHeight(PAL_SpriteGetFrame(g_Battle.rgEnemy[i].lpSprite, g_Battle.rgEnemy[i].wCurrentFrame)));
        
        if (g_Battle.rgEnemy[i].wObjectID != 0)
        {
            if (g_Battle.rgEnemy[i].iColorShift)
            {
                PAL_RLEBlitWithColorShift(PAL_SpriteGetFrame(g_Battle.rgEnemy[i].lpSprite, g_Battle.rgEnemy[i].wCurrentFrame),
                                          g_Battle.lpSceneBuf, pos, g_Battle.rgEnemy[i].iColorShift);
            }
            else
            {
                PAL_RLEBlitToSurface(PAL_SpriteGetFrame(g_Battle.rgEnemy[i].lpSprite, g_Battle.rgEnemy[i].wCurrentFrame),
                                     g_Battle.lpSceneBuf, pos);
            }
        }
    }
    
    if (g_Battle.lpSummonSprite != NULL)
    {
        //
        // Draw the summoned god
        //
        pos = PAL_XY(PAL_X(g_Battle.posSummon) - PAL_RLEGetWidth(PAL_SpriteGetFrame(g_Battle.lpSummonSprite, g_Battle.iSummonFrame)) / 2,
                     PAL_Y(g_Battle.posSummon) - PAL_RLEGetHeight(PAL_SpriteGetFrame(g_Battle.lpSummonSprite, g_Battle.iSummonFrame)));
        
        PAL_RLEBlitToSurface(PAL_SpriteGetFrame(g_Battle.lpSummonSprite, g_Battle.iSummonFrame),
                             g_Battle.lpSceneBuf, pos);
    }
    else
    {
        //
        // Draw the players
        //
        for (i = gpGlobals->wMaxPartyMemberIndex; i >= 0; i--)
        {
            pos = g_Battle.rgPlayer[i].pos;
            
            if (gpGlobals->rgPlayerStatus[gpGlobals->rgParty[i].wPlayerRole][kStatusConfused] != 0 &&
                gpGlobals->rgPlayerStatus[gpGlobals->rgParty[i].wPlayerRole][kStatusSleep] == 0 &&
                gpGlobals->rgPlayerStatus[gpGlobals->rgParty[i].wPlayerRole][kStatusParalyzed] == 0 &&
                gpGlobals->g.PlayerRoles.rgwHP[gpGlobals->rgParty[i].wPlayerRole] > 0)
            {
                //
                // Player is confused
                //
                continue;
            }
            
            pos = PAL_XY(PAL_X(pos) - PAL_RLEGetWidth(PAL_SpriteGetFrame(g_Battle.rgPlayer[i].lpSprite, g_Battle.rgPlayer[i].wCurrentFrame)) / 2,
                         PAL_Y(pos) - PAL_RLEGetHeight(PAL_SpriteGetFrame(g_Battle.rgPlayer[i].lpSprite, g_Battle.rgPlayer[i].wCurrentFrame)));
            
            if (g_Battle.rgPlayer[i].iColorShift != 0)
            {
                PAL_RLEBlitWithColorShift(PAL_SpriteGetFrame(g_Battle.rgPlayer[i].lpSprite, g_Battle.rgPlayer[i].wCurrentFrame),
                                          g_Battle.lpSceneBuf, pos, g_Battle.rgPlayer[i].iColorShift);
            }
            else if (g_Battle.iHidingTime == 0)
            {
                PAL_RLEBlitToSurface(PAL_SpriteGetFrame(g_Battle.rgPlayer[i].lpSprite, g_Battle.rgPlayer[i].wCurrentFrame),
                                     g_Battle.lpSceneBuf, pos);
            }
        }
        
        //
        // Confused players should be drawn on top of normal players
        //
        for (i = gpGlobals->wMaxPartyMemberIndex; i >= 0; i--)
        {
            if (gpGlobals->rgPlayerStatus[gpGlobals->rgParty[i].wPlayerRole][kStatusConfused] != 0 &&
                gpGlobals->rgPlayerStatus[gpGlobals->rgParty[i].wPlayerRole][kStatusSleep] == 0 &&
                gpGlobals->rgPlayerStatus[gpGlobals->rgParty[i].wPlayerRole][kStatusParalyzed] == 0 &&
                gpGlobals->g.PlayerRoles.rgwHP[gpGlobals->rgParty[i].wPlayerRole] > 0)
            {
                //
                // Player is confused
                //
                pos = PAL_XY(PAL_X(g_Battle.rgPlayer[i].pos), PAL_Y(g_Battle.rgPlayer[i].pos) + RandomLong(-1, 1));
                pos = PAL_XY(PAL_X(pos) - PAL_RLEGetWidth(PAL_SpriteGetFrame(g_Battle.rgPlayer[i].lpSprite, g_Battle.rgPlayer[i].wCurrentFrame)) / 2,
                             PAL_Y(pos) - PAL_RLEGetHeight(PAL_SpriteGetFrame(g_Battle.rgPlayer[i].lpSprite, g_Battle.rgPlayer[i].wCurrentFrame)));
                
                if (g_Battle.rgPlayer[i].iColorShift != 0)
                {
                    PAL_RLEBlitWithColorShift(PAL_SpriteGetFrame(g_Battle.rgPlayer[i].lpSprite, g_Battle.rgPlayer[i].wCurrentFrame),
                                              g_Battle.lpSceneBuf, pos, g_Battle.rgPlayer[i].iColorShift);
                }
                else if (g_Battle.iHidingTime == 0)
                {
                    PAL_RLEBlitToSurface(PAL_SpriteGetFrame(g_Battle.rgPlayer[i].lpSprite, g_Battle.rgPlayer[i].wCurrentFrame),
                                         g_Battle.lpSceneBuf, pos);
                }
            }
        }
    }
}
Beispiel #2
0
VOID
PAL_StartDialog(
   BYTE         bDialogLocation,
   BYTE         bFontColor,
   INT          iNumCharFace,
   BOOL         fPlayingRNG
)
/*++
  Purpose:

    Start a new dialog.

  Parameters:

    [IN]  bDialogLocation - the location of the text on the screen.

    [IN]  bFontColor - the font color of the text.

    [IN]  iNumCharFace - number of the character face in RGM.MKF.

    [IN]  fPlayingRNG - whether we are playing a RNG video or not.

  Return value:

    None.

--*/
{
   PAL_LARGE BYTE buf[16384];
   SDL_Rect       rect;

   if (gpGlobals->fInBattle && !g_fUpdatedInBattle)
   {
      //
      // Update the screen in battle, or the graphics may seem messed up
      //
      VIDEO_UpdateScreen(NULL);
      g_fUpdatedInBattle = TRUE;
   }

   g_TextLib.bIcon = 0;
   g_TextLib.posIcon = 0;
   g_TextLib.nCurrentDialogLine = 0;
   g_TextLib.posDialogTitle = PAL_XY(12, 8);
   g_TextLib.fUserSkip = FALSE;

   if (bFontColor != 0)
   {
      g_TextLib.bCurrentFontColor = bFontColor;
   }

   if (fPlayingRNG && iNumCharFace)
   {
      VIDEO_BackupScreen();
      g_TextLib.fPlayingRNG = TRUE;
   }

   switch (bDialogLocation)
   {
   case kDialogUpper:
      if (iNumCharFace > 0)
      {
         //
         // Display the character face at the upper part of the screen
         //
         if (PAL_MKFReadChunk(buf, 16384, iNumCharFace, gpGlobals->f.fpRGM) > 0)
         {
            rect.w = PAL_RLEGetWidth((LPCBITMAPRLE)buf);
            rect.h = PAL_RLEGetHeight((LPCBITMAPRLE)buf);
            rect.x = 48 - rect.w / 2;
            rect.y = 55 - rect.h / 2;

            if (rect.x < 0)
            {
               rect.x = 0;
            }

            if (rect.y < 0)
            {
               rect.y = 0;
            }

            PAL_RLEBlitToSurface((LPCBITMAPRLE)buf, gpScreen, PAL_XY(rect.x, rect.y));

            if (rect.x < 0)
            {
               rect.x = 0;
            }
            if (rect.y < 0)
            {
               rect.y = 0;
            }

            VIDEO_UpdateScreen(&rect);
         }
      }
      g_TextLib.posDialogTitle = PAL_XY(iNumCharFace > 0 ? 80 : 12, 8);
      g_TextLib.posDialogText = PAL_XY(iNumCharFace > 0 ? 96 : 44, 26);
      break;

   case kDialogCenter:
      g_TextLib.posDialogText = PAL_XY(80, 40);
      break;

   case kDialogLower:
      if (iNumCharFace > 0)
      {
         //
         // Display the character face at the lower part of the screen
         //
         if (PAL_MKFReadChunk(buf, 16384, iNumCharFace, gpGlobals->f.fpRGM) > 0)
         {
            rect.x = 270 - PAL_RLEGetWidth((LPCBITMAPRLE)buf) / 2;
            rect.y = 144 - PAL_RLEGetHeight((LPCBITMAPRLE)buf) / 2;

            PAL_RLEBlitToSurface((LPCBITMAPRLE)buf, gpScreen, PAL_XY(rect.x, rect.y));

            VIDEO_UpdateScreen(NULL);
         }
      }
      g_TextLib.posDialogTitle = PAL_XY(iNumCharFace > 0 ? 4 : 12, 108);
      g_TextLib.posDialogText = PAL_XY(iNumCharFace > 0 ? 20 : 44, 126);
      break;

   case kDialogCenterWindow:
      g_TextLib.posDialogText = PAL_XY(160, 40);
      break;
   }

   g_TextLib.bDialogPosition = bDialogLocation;
}
Beispiel #3
0
static VOID
PAL_SceneDrawSprites(
   VOID
)
/*++
   Purpose:

     Draw all the sprites to scene.

   Parameters:

     None.

   Return value:

     None.

--*/
{
   int i, x, y, vy;

   g_nSpriteToDraw = 0;

   //
   // Put all the sprites to be drawn into our array.
   //

   //
   // Players
   //
   for (i = 0; i <= (short)gpGlobals->wMaxPartyMemberIndex + gpGlobals->nFollower; i++)
   {
      LPCBITMAPRLE lpBitmap =
         PAL_SpriteGetFrame(PAL_GetPlayerSprite((BYTE)i), gpGlobals->rgParty[i].wFrame);

      if (lpBitmap == NULL)
      {
         continue;
      }

      //
      // Add it to our array
      //
      PAL_AddSpriteToDraw(lpBitmap,
         gpGlobals->rgParty[i].x - PAL_RLEGetWidth(lpBitmap) / 2,
         gpGlobals->rgParty[i].y + gpGlobals->wLayer + 10,
         gpGlobals->wLayer + 6);

      //
      // Calculate covering tiles on the map
      //
      PAL_CalcCoverTiles(&g_rgSpriteToDraw[g_nSpriteToDraw - 1]);
   }

   //
   // Event Objects (Monsters/NPCs/others)
   //
   for (i = gpGlobals->g.rgScene[gpGlobals->wNumScene - 1].wEventObjectIndex;
      i < gpGlobals->g.rgScene[gpGlobals->wNumScene].wEventObjectIndex; i++)
   {
      LPCBITMAPRLE     lpFrame;
      LPCSPRITE        lpSprite;

      LPEVENTOBJECT    lpEvtObj = &(gpGlobals->g.lprgEventObject[i]);

      int              iFrame;

      if (lpEvtObj->sState == kObjStateHidden || lpEvtObj->sVanishTime > 0 ||
         lpEvtObj->sState < 0)
      {
         continue;
      }

      //
      // Get the sprite
      //
      lpSprite = PAL_GetEventObjectSprite((WORD)i + 1);
      if (lpSprite == NULL)
      {
         continue;
      }

      iFrame = lpEvtObj->wCurrentFrameNum;
      if (lpEvtObj->nSpriteFrames == 3)
      {
         //
         // walking character
         //
         if (iFrame == 2)
         {
            iFrame = 0;
         }

         if (iFrame == 3)
         {
            iFrame = 2;
         }
      }

      lpFrame = PAL_SpriteGetFrame(lpSprite,
         lpEvtObj->wDirection * lpEvtObj->nSpriteFrames + iFrame);

      if (lpFrame == NULL)
      {
         continue;
      }

      //
      // Calculate the coordinate and check if outside the screen
      //
      x = (SHORT)lpEvtObj->x - PAL_X(gpGlobals->viewport);
      x -= PAL_RLEGetWidth(lpFrame) / 2;

      if (x >= 320 || x < -(int)PAL_RLEGetWidth(lpFrame))
      {
         //
         // outside the screen; skip it
         //
         continue;
      }

      y = (SHORT)lpEvtObj->y - PAL_Y(gpGlobals->viewport);
      y += lpEvtObj->sLayer * 8 + 9;

      vy = y - PAL_RLEGetHeight(lpFrame) - lpEvtObj->sLayer * 8 + 2;
      if (vy >= 200 || vy < -(int)PAL_RLEGetHeight(lpFrame))
      {
         //
         // outside the screen; skip it
         //
         continue;
      }

      //
      // Add it into the array
      //
      PAL_AddSpriteToDraw(lpFrame, x, y, lpEvtObj->sLayer * 8 + 2);

      //
      // Calculate covering map tiles
      //
      PAL_CalcCoverTiles(&g_rgSpriteToDraw[g_nSpriteToDraw - 1]);
   }

   //
   // All sprites are now in our array; sort them by their vertical positions.
   //
   for (x = 0; x < g_nSpriteToDraw - 1; x++)
   {
      SPRITE_TO_DRAW           tmp;
      BOOL                     fSwap = FALSE;

      for (y = 0; y < g_nSpriteToDraw - 1 - x; y++)
      {
         if (PAL_Y(g_rgSpriteToDraw[y].pos) > PAL_Y(g_rgSpriteToDraw[y + 1].pos))
         {
            fSwap = TRUE;

            tmp = g_rgSpriteToDraw[y];
            g_rgSpriteToDraw[y] = g_rgSpriteToDraw[y + 1];
            g_rgSpriteToDraw[y + 1] = tmp;
         }
      }

      if (!fSwap)
      {
         break;
      }
   }

   //
   // Draw all the sprites to the screen.
   //
   for (i = 0; i < g_nSpriteToDraw; i++)
   {
      SPRITE_TO_DRAW *p = &g_rgSpriteToDraw[i];

      x = PAL_X(p->pos);
      y = PAL_Y(p->pos) - PAL_RLEGetHeight(p->lpSpriteFrame) - p->iLayer;

      PAL_RLEBlitToSurface(p->lpSpriteFrame, gpScreen, PAL_XY(x, y));
   }
}
Beispiel #4
0
static VOID
PAL_CalcCoverTiles(
   SPRITE_TO_DRAW         *lpSpriteToDraw
)
/*++
   Purpose:

     Calculate all the tiles which may cover the specified sprite. Add the tiles
     into our list as well.

   Parameters:

     [IN]  lpSpriteToDraw - pointer to SPRITE_TO_DRAW struct.

   Return value:

     None.

--*/
{
   int             x, y, i, l, iTileHeight;
   LPCBITMAPRLE    lpTile;

   const int       sx = PAL_X(gpGlobals->viewport) + PAL_X(lpSpriteToDraw->pos);
   const int       sy = PAL_Y(gpGlobals->viewport) + PAL_Y(lpSpriteToDraw->pos);
   const int       sh = ((sx % 32) ? 1 : 0);

   const int       width = PAL_RLEGetWidth(lpSpriteToDraw->lpSpriteFrame);
   const int       height = PAL_RLEGetHeight(lpSpriteToDraw->lpSpriteFrame);

   int             dx = 0;
   int             dy = 0;
   int             dh = 0;

   //
   // Loop through all the tiles in the area of the sprite.
   //
   for (y = (sy - height - 15) / 16; y <= sy / 16; y++)
   {
      for (x = (sx - width / 2) / 32; x <= (sx + width / 2) / 32; x++)
      {
         for (i = ((x == (sx - width / 2) / 32) ? 0 : 3); i < 5; i++)
         {
            //
            // Scan tiles in the following form (* = to scan):
            //
            // . . . * * * . . .
            //  . . . * * . . . .
            //
            switch (i)
            {
               case 0:
                  dx = x;
                  dy = y;
                  dh = sh;
                  break;

               case 1:
                  dx = x - 1;
                  break;

               case 2:
                  dx = (sh ? x : (x - 1));
                  dy = (sh ? (y + 1) : y);
                  dh = 1 - sh;
                  break;

               case 3:
                  dx = x + 1;
                  dy = y;
                  dh = sh;
                  break;

               case 4:
                  dx = (sh ? (x + 1) : x);
                  dy = (sh ? (y + 1) : y);
                  dh = 1 - sh;
                  break;
            }

            for (l = 0; l < 2; l++)
            {
               lpTile = PAL_MapGetTileBitmap(dx, dy, dh, l, PAL_GetCurrentMap());
               iTileHeight = (signed char)PAL_MapGetTileHeight(dx, dy, dh, l, PAL_GetCurrentMap());

               //
               // Check if this tile may cover the sprites
               //
               if (lpTile != NULL && iTileHeight > 0 && (dy + iTileHeight) * 16 + dh * 8 >= sy)
               {
                  //
                  // This tile may cover the sprite
                  //
                  PAL_AddSpriteToDraw(lpTile,
                     dx * 32 + dh * 16 - 16 - PAL_X(gpGlobals->viewport),
                     dy * 16 + dh * 8 + 7 + l + iTileHeight * 8 - PAL_Y(gpGlobals->viewport),
                     iTileHeight * 8 + l);
               }
            }
         }
      }
   }
}
Beispiel #5
0
LPBOX
PAL_CreateSingleLineBox(
   PAL_POS        pos,
   INT            nLen,
   BOOL           fSaveScreen
)
/*++
  Purpose:

    Create a single-line box on the screen.

  Parameters:

    [IN]  pos - position of the box.

    [IN]  nLen - length of the box.

    [IN]  fSaveScreen - whether save the used screen area or not.

  Return value:

    Pointer to a BOX structure. NULL if failed.
    If fSaveScreen is false, then always returns NULL.

--*/
{
   static const int      iNumLeftSprite   = 44;
   static const int      iNumMidSprite    = 45;
   static const int      iNumRightSprite  = 46;

   LPCBITMAPRLE          lpBitmapLeft;
   LPCBITMAPRLE          lpBitmapMid;
   LPCBITMAPRLE          lpBitmapRight;
   SDL_Surface          *save;
   SDL_Rect              rect;
   LPBOX                 lpBox = NULL;
   int                   i;

   //
   // Get the bitmaps
   //
   lpBitmapLeft = PAL_SpriteGetFrame(gpSpriteUI, iNumLeftSprite);
   lpBitmapMid = PAL_SpriteGetFrame(gpSpriteUI, iNumMidSprite);
   lpBitmapRight = PAL_SpriteGetFrame(gpSpriteUI, iNumRightSprite);

   rect.x = PAL_X(pos);
   rect.y = PAL_Y(pos);

   //
   // Get the total width and total height of the box
   //
   rect.w = PAL_RLEGetWidth(lpBitmapLeft) + PAL_RLEGetWidth(lpBitmapRight);
   rect.w += PAL_RLEGetWidth(lpBitmapMid) * nLen;
   rect.h = PAL_RLEGetHeight(lpBitmapLeft);

   if (fSaveScreen)
   {
      //
      // Save the used part of the screen
      //
      save = SDL_CreateRGBSurface(gpScreen->flags, rect.w, rect.h, 8,
         gpScreen->format->Rmask, gpScreen->format->Gmask,
         gpScreen->format->Bmask, gpScreen->format->Amask);

      if (save == NULL)
      {
         return NULL;
      }

      lpBox = (LPBOX)calloc(1, sizeof(BOX));
      if (lpBox == NULL)
      {
         SDL_FreeSurface(gpScreen);
         return NULL;
      }

      SDL_BlitSurface(gpScreen, &rect, save, NULL);

      lpBox->pos = pos;
      lpBox->lpSavedArea = save;
      lpBox->wHeight = (WORD)rect.w;
      lpBox->wWidth = (WORD)rect.h;
   }

   //
   // Draw the box
   //
   PAL_RLEBlitToSurface(lpBitmapLeft, gpScreen, pos);

   rect.x += PAL_RLEGetWidth(lpBitmapLeft);

   for (i = 0; i < nLen; i++)
   {
      PAL_RLEBlitToSurface(lpBitmapMid, gpScreen, PAL_XY(rect.x, rect.y));
      rect.x += PAL_RLEGetWidth(lpBitmapMid);
   }

   PAL_RLEBlitToSurface(lpBitmapRight, gpScreen, PAL_XY(rect.x, rect.y));

   return lpBox;
}
Beispiel #6
0
LPBOX
PAL_CreateBox(
   PAL_POS        pos,
   INT            nRows,
   INT            nColumns,
   INT            iStyle,
   BOOL           fSaveScreen
)
/*++
  Purpose:

    Create a box on the screen.

  Parameters:

    [IN]  pos - position of the box.

    [IN]  nRows - number of rows of the box.

    [IN]  nColumns - number of columns of the box.

    [IN]  iStyle - style of the box (0 or 1).

    [IN]  fSaveScreen - whether save the used screen area or not.

  Return value:

    Pointer to a BOX structure. NULL if failed.
    If fSaveScreen is false, then always returns NULL.

--*/
{
   int              i, j, x, m, n;
   LPCBITMAPRLE     rglpBorderBitmap[3][3];
   LPBOX            lpBox = NULL;
   SDL_Surface     *save;
   SDL_Rect         rect;

   //
   // Get the bitmaps
   //
   for (i = 0; i < 3; i++)
   {
      for (j = 0; j < 3; j++)
      {
         rglpBorderBitmap[i][j] = PAL_SpriteGetFrame(gpSpriteUI, i * 3 + j + iStyle * 9);
      }
   }

   rect.x = PAL_X(pos);
   rect.y = PAL_Y(pos);
   rect.w = 0;
   rect.h = 0;

   //
   // Get the total width and total height of the box
   //
   for (i = 0; i < 3; i++)
   {
      if (i == 1)
      {
         rect.w += PAL_RLEGetWidth(rglpBorderBitmap[0][i]) * nColumns;
         rect.h += PAL_RLEGetHeight(rglpBorderBitmap[i][0]) * nRows;
      }
      else
      {
         rect.w += PAL_RLEGetWidth(rglpBorderBitmap[0][i]);
         rect.h += PAL_RLEGetHeight(rglpBorderBitmap[i][0]);
      }
   }

   if (fSaveScreen)
   {
      //
      // Save the used part of the screen
      //
      save = SDL_CreateRGBSurface(gpScreen->flags, rect.w, rect.h, 8,
         gpScreen->format->Rmask, gpScreen->format->Gmask,
         gpScreen->format->Bmask, gpScreen->format->Amask);

      if (save == NULL)
      {
         return NULL;
      }

      lpBox = (LPBOX)calloc(1, sizeof(BOX));
      if (lpBox == NULL)
      {
         SDL_FreeSurface(save);
         return NULL;
      }

      SDL_BlitSurface(gpScreen, &rect, save, NULL);

      lpBox->lpSavedArea = save;
      lpBox->pos = pos;
      lpBox->wWidth = rect.w;
      lpBox->wHeight = rect.h;
   }

   //
   // Border takes 2 additional rows and columns...
   //
   nRows += 2;
   nColumns += 2;

   //
   // Draw the box
   //
   for (i = 0; i < nRows; i++)
   {
      x = rect.x;
      m = (i == 0) ? 0 : ((i == nRows - 1) ? 2 : 1);

      for (j = 0; j < nColumns; j++)
      {
         n = (j == 0) ? 0 : ((j == nColumns - 1) ? 2 : 1);
         PAL_RLEBlitToSurface(rglpBorderBitmap[m][n], gpScreen, PAL_XY(x, rect.y));
         x += PAL_RLEGetWidth(rglpBorderBitmap[m][n]);
      }

      rect.y += PAL_RLEGetHeight(rglpBorderBitmap[m][0]);
   }

   return lpBox;
}
Beispiel #7
0
static BOOL
PAL_BattleDisplayStatChange(
   VOID
)
/*++
  Purpose:

    Display the HP and MP changes of all players and enemies.

  Parameters:

    None.

  Return value:

    TRUE if there are any number displayed, FALSE if not.

--*/
{
   int i, x, y;
   SHORT sDamage;
   WORD wPlayerRole;
   BOOL f = FALSE;

   for (i = 0; i <= g_Battle.wMaxEnemyIndex; i++)
   {
      if (g_Battle.rgEnemy[i].wObjectID == 0)
      {
         continue;
      }

      if (g_Battle.rgEnemy[i].wPrevHP != g_Battle.rgEnemy[i].e.wHealth)
      {
         //
         // Show the number of damage
         //
         sDamage = g_Battle.rgEnemy[i].e.wHealth - g_Battle.rgEnemy[i].wPrevHP;
 
         x = PAL_X(g_Battle.rgEnemy[i].pos);
         y = PAL_Y(g_Battle.rgEnemy[i].pos) - 70;

         x += PAL_RLEGetWidth(PAL_SpriteGetFrame(g_Battle.rgEnemy[i].lpSprite, g_Battle.rgEnemy[i].wCurrentFrame)) / 2;
         y += PAL_RLEGetHeight(PAL_SpriteGetFrame(g_Battle.rgEnemy[i].lpSprite, g_Battle.rgEnemy[i].wCurrentFrame)) / 2;

         if (y < 10)
         {
            y = 10;
         }

         if (sDamage < 0)
         {
            PAL_BattleUIShowNum((WORD)(-sDamage), PAL_XY(x, y), kNumColorBlue);
         }
         else
         {
            PAL_BattleUIShowNum((WORD)(sDamage), PAL_XY(x, y), kNumColorYellow);
         }

         f = TRUE;
      }
   }

   for (i = 0; i <= gpGlobals->wMaxPartyMemberIndex; i++)
   {
      wPlayerRole = gpGlobals->rgParty[i].wPlayerRole;

      if (g_Battle.rgPlayer[i].wPrevHP != gpGlobals->g.PlayerRoles.rgwHP[wPlayerRole])
      {
         sDamage =
            gpGlobals->g.PlayerRoles.rgwHP[wPlayerRole] - g_Battle.rgPlayer[i].wPrevHP;

         x = PAL_X(g_Battle.rgPlayer[i].pos);
         y = PAL_Y(g_Battle.rgPlayer[i].pos) - 70;

         x += PAL_RLEGetWidth(PAL_SpriteGetFrame(g_Battle.rgPlayer[i].lpSprite, g_Battle.rgPlayer[i].wCurrentFrame)) / 2;
         y += PAL_RLEGetHeight(PAL_SpriteGetFrame(g_Battle.rgPlayer[i].lpSprite, g_Battle.rgPlayer[i].wCurrentFrame));

         if (y < 10)
         {
            y = 10;
         }

         if (sDamage < 0)
         {
            PAL_BattleUIShowNum((WORD)(-sDamage), PAL_XY(x, y), kNumColorBlue);
         }
         else
         {
            PAL_BattleUIShowNum((WORD)(sDamage), PAL_XY(x, y), kNumColorYellow);
         }

         f = TRUE;
      }

      if (g_Battle.rgPlayer[i].wPrevMP != gpGlobals->g.PlayerRoles.rgwMP[wPlayerRole])
      {
         sDamage =
            gpGlobals->g.PlayerRoles.rgwMP[wPlayerRole] - g_Battle.rgPlayer[i].wPrevMP;

         x = PAL_X(g_Battle.rgPlayer[i].pos);
         y = PAL_Y(g_Battle.rgPlayer[i].pos) - 62;

         x += PAL_RLEGetWidth(PAL_SpriteGetFrame(g_Battle.rgPlayer[i].lpSprite, g_Battle.rgPlayer[i].wCurrentFrame)) / 2;
         y += PAL_RLEGetHeight(PAL_SpriteGetFrame(g_Battle.rgPlayer[i].lpSprite, g_Battle.rgPlayer[i].wCurrentFrame));

         if (y < 10)
         {
            y = 10;
         }

         if (sDamage < 0)
         {
            PAL_BattleUIShowNum((WORD)(-sDamage), PAL_XY(x, y), kNumColorBlue);
         }
         else
         {
            PAL_BattleUIShowNum((WORD)(sDamage), PAL_XY(x, y), kNumColorCyan);
         }

         f = TRUE;
      }
   }

   return f;
}
Beispiel #8
0
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]--;
      }
   }
}
Beispiel #9
0
static VOID
PAL_BattleShowPlayerAttackAnim(
   WORD        wPlayerIndex,
   BOOL        fCritical
)
/*++
  Purpose:

    Show the physical attack effect for player.

  Parameters:

    [IN]  wPlayerIndex - the index of the player.

    [IN]  fCritical - TRUE if this is a critical hit.

  Return value:

    None.

--*/
{
   WORD wPlayerRole = gpGlobals->rgParty[wPlayerIndex].wPlayerRole;
   SHORT sTarget = g_Battle.rgPlayer[wPlayerIndex].action.sTarget;

   int index, i, j;
   int enemy_x = 0, enemy_y = 0, enemy_h = 0, x, y, dist = 0;
   int w, h;

   DWORD dwTime;

   if (sTarget != -1)
   {
      enemy_x = PAL_X(g_Battle.rgEnemy[sTarget].pos);
      enemy_y = PAL_Y(g_Battle.rgEnemy[sTarget].pos);

      enemy_x += PAL_RLEGetWidth(PAL_SpriteGetFrame(g_Battle.rgEnemy[sTarget].lpSprite, g_Battle.rgEnemy[sTarget].wCurrentFrame)) / 2;
      enemy_h = PAL_RLEGetHeight(PAL_SpriteGetFrame(g_Battle.rgEnemy[sTarget].lpSprite, g_Battle.rgEnemy[sTarget].wCurrentFrame));
      enemy_y += enemy_h;

      if (sTarget >= 3)
      {
         dist = (sTarget - wPlayerIndex) * 8;
      }
   }
   else
   {
      enemy_x = 150;
      enemy_y = 100;
   }

   index = gpGlobals->g.rgwBattleEffectIndex[gpGlobals->g.PlayerRoles.rgwSpriteNumInBattle[wPlayerRole]][1];
   index *= 3;

   //
   // Play the attack voice
   //
   if (gpGlobals->g.PlayerRoles.rgwHP[wPlayerRole] > 0)
   {
      if (!fCritical)
      {
         SOUND_Play(gpGlobals->g.PlayerRoles.rgwAttackSound[wPlayerRole]);
      }
      else
      {
         SOUND_Play(gpGlobals->g.PlayerRoles.rgwCriticalSound[wPlayerRole]);
      }
   }

   //
   // Show the animation
   //
   x = enemy_x - dist + 64;
   y = enemy_y + dist + 20;

   g_Battle.rgPlayer[wPlayerIndex].wCurrentFrame = 8;
   w = PAL_RLEGetWidth(PAL_SpriteGetFrame(g_Battle.rgPlayer[wPlayerIndex].lpSprite, 8));
   h = PAL_RLEGetHeight(PAL_SpriteGetFrame(g_Battle.rgPlayer[wPlayerIndex].lpSprite, 8));
   g_Battle.rgPlayer[wPlayerIndex].pos = PAL_XY(x - w / 2, y - h);

   PAL_BattleDelay(2, 0);

   x -= 10;
   y -= 2;
   g_Battle.rgPlayer[wPlayerIndex].pos = PAL_XY(x - w / 2, y - h);

   PAL_BattleDelay(1, 0);

   g_Battle.rgPlayer[wPlayerIndex].wCurrentFrame = 9;
   x -= 16;
   y -= 4;

   SOUND_Play(gpGlobals->g.PlayerRoles.rgwWeaponSound[wPlayerRole]);

   x = enemy_x;
   y = enemy_y - enemy_h / 3 + 10;

   dwTime = SDL_GetTicks() + BATTLE_FRAME_TIME;

   for (i = 0; i < 3; i++)
   {
      LPCBITMAPRLE b = PAL_SpriteGetFrame(g_Battle.lpEffectSprite, index++);

      //
      // Clear the input state of previous frame.
      //
      PAL_ClearKeyState();

      //
      // 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;

      //
      // Update the gesture of enemies.
      //
      for (j = 0; j <= g_Battle.wMaxEnemyIndex; j++)
      {
         if (g_Battle.rgEnemy[j].wObjectID == 0)
         {
            continue;
         }

         if (--g_Battle.rgEnemy[j].e.wIdleAnimSpeed == 0)
         {
            g_Battle.rgEnemy[j].wCurrentFrame++;
            g_Battle.rgEnemy[j].e.wIdleAnimSpeed =
               gpGlobals->g.lprgEnemy[gpGlobals->g.rgObject[g_Battle.rgEnemy[j].wObjectID].enemy.wEnemyID].wIdleAnimSpeed;
         }

         if (g_Battle.rgEnemy[j].wCurrentFrame >= g_Battle.rgEnemy[j].e.wIdleFrames)
         {
            g_Battle.rgEnemy[j].wCurrentFrame = 0;
         }
      }

      PAL_BattleMakeScene();
      SDL_BlitSurface(g_Battle.lpSceneBuf, NULL, gpScreen, NULL);

      PAL_RLEBlitToSurface(b, gpScreen, PAL_XY(x - PAL_RLEGetWidth(b) / 2, y - PAL_RLEGetHeight(b)));
      x -= 16;
      y += 16;

      PAL_BattleUIUpdate();

      if (i == 0)
      {
         if (sTarget == -1)
         {
            for (j = 0; j <= g_Battle.wMaxEnemyIndex; j++)
            {
               g_Battle.rgEnemy[j].iColorShift = 6;
            }
         }
         else
         {
            g_Battle.rgEnemy[sTarget].iColorShift = 6;
         }

         //
         // Flash the screen if it's a critical hit
         //
         if (fCritical)
         {
            SDL_FillRect(gpScreen, NULL, 15);
         }
      }

      VIDEO_UpdateScreen(NULL);

      if (i == 1)
      {
         g_Battle.rgPlayer[wPlayerIndex].pos =
            PAL_XY(PAL_X(g_Battle.rgPlayer[wPlayerIndex].pos) + 2,
                   PAL_Y(g_Battle.rgPlayer[wPlayerIndex].pos) + 1);
      }
   }

   dist = 8;

   for (i = 0; i <= g_Battle.wMaxEnemyIndex; i++)
   {
      g_Battle.rgEnemy[i].iColorShift = 0;
   }

   if (sTarget == -1)
   {
      for (i = 0; i < 3; i++)
      {
         for (j = 0; j <= g_Battle.wMaxEnemyIndex; j++)
         {
            x = PAL_X(g_Battle.rgEnemy[j].pos);
            y = PAL_Y(g_Battle.rgEnemy[j].pos);

            x -= dist;
            y -= dist / 2;
            g_Battle.rgEnemy[j].pos = PAL_XY(x, y);
         }

         PAL_BattleDelay(1, 0);
         dist /= -2;
      }
   }
   else
   {
      x = PAL_X(g_Battle.rgEnemy[sTarget].pos);
      y = PAL_Y(g_Battle.rgEnemy[sTarget].pos);

      for (i = 0; i < 3; i++)
      {
         x -= dist;
         dist /= -2;
         y += dist;
         g_Battle.rgEnemy[sTarget].pos = PAL_XY(x, y);

         PAL_BattleDelay(1, 0);
      }
   }
}
Beispiel #10
0
VOID
PAL_BattleUIUpdate(
   VOID
)
/*++
  Purpose:

    Update the status of battle UI.

  Parameters:

    None.

  Return value:

    None.

--*/
{
   int              i, j, x, y;
   WORD             wPlayerRole, w;
   static int       s_iFrame = 0;

   s_iFrame++;

   if (g_Battle.UI.fAutoAttack && !gpGlobals->fAutoBattle)
   {
      //
      // Draw the "auto attack" message if in the autoattack mode.
      //
      if (g_InputState.dwKeyPress & kKeyMenu)
      {
         g_Battle.UI.fAutoAttack = FALSE;
      }
      else
      {
         PAL_DrawText(PAL_GetWord(BATTLEUI_LABEL_AUTO), PAL_XY(280, 10),
            MENUITEM_COLOR_CONFIRMED, TRUE, FALSE);
      }
   }

   if (gpGlobals->fAutoBattle)
   {
      PAL_BattlePlayerCheckReady();

      for (i = 0; i <= gpGlobals->wMaxPartyMemberIndex; i++)
      {
         if (g_Battle.rgPlayer[i].state == kFighterCom)
         {
            PAL_BattleUIPlayerReady(i);
            break;
         }
      }

      if (g_Battle.UI.state != kBattleUIWait)
      {
         w = PAL_BattleUIPickAutoMagic(gpGlobals->rgParty[g_Battle.UI.wCurPlayerIndex].wPlayerRole, 9999);

         if (w == 0)
         {
            g_Battle.UI.wActionType = kBattleActionAttack;
            g_Battle.UI.wSelectedIndex = PAL_BattleSelectAutoTarget();
         }
         else
         {
            g_Battle.UI.wActionType = kBattleActionMagic;
            g_Battle.UI.wObjectID = w;

            if (gpGlobals->g.rgObject[w].magic.wFlags & kMagicFlagApplyToAll)
            {
               g_Battle.UI.wSelectedIndex = -1;
            }
            else
            {
               g_Battle.UI.wSelectedIndex = PAL_BattleSelectAutoTarget();
            }
         }

         PAL_BattleCommitAction(FALSE);
      }

      goto end;
   }

   if (g_InputState.dwKeyPress & kKeyAuto)
   {
      g_Battle.UI.fAutoAttack = !g_Battle.UI.fAutoAttack;
      g_Battle.UI.MenuState = kBattleMenuMain;
   }

#ifdef PAL_CLASSIC
   if (g_Battle.Phase == kBattlePhasePerformAction)
   {
      goto end;
   }

   if (!g_Battle.UI.fAutoAttack)
#endif
   {
      //
      // Draw the player info boxes.
      //
      for (i = 0; i <= gpGlobals->wMaxPartyMemberIndex; i++)
      {
         wPlayerRole = gpGlobals->rgParty[i].wPlayerRole;
         w = F2int(g_Battle.rgPlayer[i].flTimeMeter);

         j = TIMEMETER_COLOR_DEFAULT;

#ifndef PAL_CLASSIC
         if (gpGlobals->rgPlayerStatus[wPlayerRole][kStatusHaste] > 0)
         {
            j = TIMEMETER_COLOR_HASTE;
         }
         else if (gpGlobals->rgPlayerStatus[wPlayerRole][kStatusSlow] > 0)
         {
            j = TIMEMETER_COLOR_SLOW;
         }
#endif

         if (gpGlobals->rgPlayerStatus[wPlayerRole][kStatusSleep] != 0 ||
            gpGlobals->rgPlayerStatus[wPlayerRole][kStatusConfused] != 0 ||
            gpGlobals->rgPlayerStatus[wPlayerRole][kStatusPuppet] != 0)
         {
            w = 0;
         }

         PAL_PlayerInfoBox(PAL_XY(91 + 77 * i, 165), wPlayerRole,
            w, j, FALSE);
      }
   }

   if (g_InputState.dwKeyPress & kKeyStatus)
   {
      PAL_PlayerStatus();
      goto end;
   }

   if (g_Battle.UI.state != kBattleUIWait)
   {
      wPlayerRole = gpGlobals->rgParty[g_Battle.UI.wCurPlayerIndex].wPlayerRole;

      if (gpGlobals->g.PlayerRoles.rgwHP[wPlayerRole] == 0 &&
         gpGlobals->rgPlayerStatus[wPlayerRole][kStatusPuppet])
      {
         g_Battle.UI.wActionType = kBattleActionAttack;

         if (PAL_PlayerCanAttackAll(gpGlobals->rgParty[g_Battle.UI.wCurPlayerIndex].wPlayerRole))
         {
            g_Battle.UI.wSelectedIndex = -1;
         }
         else
         {
            g_Battle.UI.wSelectedIndex = PAL_BattleSelectAutoTarget();
         }

         PAL_BattleCommitAction(FALSE);
         goto end; // don't go further
      }

      //
      // Cancel any actions if player is dead or sleeping.
      //
      if (gpGlobals->g.PlayerRoles.rgwHP[wPlayerRole] == 0 ||
         gpGlobals->rgPlayerStatus[wPlayerRole][kStatusSleep] != 0 ||
         gpGlobals->rgPlayerStatus[wPlayerRole][kStatusParalyzed] != 0)
      {
         g_Battle.UI.wActionType = kBattleActionPass;
         PAL_BattleCommitAction(FALSE);
         goto end; // don't go further
      }

      if (gpGlobals->rgPlayerStatus[wPlayerRole][kStatusConfused] != 0)
      {
         g_Battle.UI.wActionType = kBattleActionAttackMate;
         PAL_BattleCommitAction(FALSE);
         goto end; // don't go further
      }

      if (g_Battle.UI.fAutoAttack)
      {
         g_Battle.UI.wActionType = kBattleActionAttack;

         if (PAL_PlayerCanAttackAll(gpGlobals->rgParty[g_Battle.UI.wCurPlayerIndex].wPlayerRole))
         {
            g_Battle.UI.wSelectedIndex = -1;
         }
         else
         {
            g_Battle.UI.wSelectedIndex = PAL_BattleSelectAutoTarget();
         }

         PAL_BattleCommitAction(FALSE);
         goto end; // don't go further
      }

      //
      // Draw the arrow on the player's head.
      //
      i = SPRITENUM_BATTLE_ARROW_CURRENTPLAYER_RED;
      if (s_iFrame & 1)
      {
         i = SPRITENUM_BATTLE_ARROW_CURRENTPLAYER;
      }

      x = g_rgPlayerPos[gpGlobals->wMaxPartyMemberIndex][g_Battle.UI.wCurPlayerIndex][0] - 8;
      y = g_rgPlayerPos[gpGlobals->wMaxPartyMemberIndex][g_Battle.UI.wCurPlayerIndex][1] - 74;

      PAL_RLEBlitToSurface(PAL_SpriteGetFrame(gpSpriteUI, i), gpScreen, PAL_XY(x, y));
   }

   switch (g_Battle.UI.state)
   {
   case kBattleUIWait:
      if (!g_Battle.fEnemyCleared)
      {
         PAL_BattlePlayerCheckReady();

         for (i = 0; i <= gpGlobals->wMaxPartyMemberIndex; i++)
         {
            if (g_Battle.rgPlayer[i].state == kFighterCom)
            {
               PAL_BattleUIPlayerReady(i);
               break;
            }
         }
      }
      break;

   case kBattleUISelectMove:
      //
      // Draw the icons
      //
      {
         struct {
            int               iSpriteNum;
            PAL_POS           pos;
            BATTLEUIACTION    action;
         } rgItems[] =
         {
            {SPRITENUM_BATTLEICON_ATTACK,    PAL_XY(27, 140), kBattleUIActionAttack},
            {SPRITENUM_BATTLEICON_MAGIC,     PAL_XY(0, 155),  kBattleUIActionMagic},
            {SPRITENUM_BATTLEICON_COOPMAGIC, PAL_XY(54, 155), kBattleUIActionCoopMagic},
            {SPRITENUM_BATTLEICON_MISCMENU,  PAL_XY(27, 170), kBattleUIActionMisc}
         };

         if (g_Battle.UI.MenuState == kBattleMenuMain)
         {
            if (g_InputState.dir == kDirNorth)
            {
               g_Battle.UI.wSelectedAction = 0;
            }
            else if (g_InputState.dir == kDirSouth)
            {
               g_Battle.UI.wSelectedAction = 3;
            }
            else if (g_InputState.dir == kDirWest)
            {
               if (PAL_BattleUIIsActionValid(kBattleUIActionMagic))
               {
                  g_Battle.UI.wSelectedAction = 1;
               }
            }
            else if (g_InputState.dir == kDirEast)
            {
               if (PAL_BattleUIIsActionValid(kBattleUIActionCoopMagic))
               {
                  g_Battle.UI.wSelectedAction = 2;
               }
            }
         }

         if (!PAL_BattleUIIsActionValid(rgItems[g_Battle.UI.wSelectedAction].action))
         {
            g_Battle.UI.wSelectedAction = 0;
         }

         for (i = 0; i < 4; i++)
         {
            if (g_Battle.UI.wSelectedAction == i)
            {
               PAL_RLEBlitToSurface(PAL_SpriteGetFrame(gpSpriteUI, rgItems[i].iSpriteNum),
                  gpScreen, rgItems[i].pos);
            }
            else if (PAL_BattleUIIsActionValid(rgItems[i].action))
            {
               PAL_RLEBlitMonoColor(PAL_SpriteGetFrame(gpSpriteUI, rgItems[i].iSpriteNum),
                  gpScreen, rgItems[i].pos, 0, -4);
            }
            else
            {
               PAL_RLEBlitMonoColor(PAL_SpriteGetFrame(gpSpriteUI, rgItems[i].iSpriteNum),
                  gpScreen, rgItems[i].pos, 0x10, -4);
            }
         }

         switch (g_Battle.UI.MenuState)
         {
         case kBattleMenuMain:
            if (g_InputState.dwKeyPress & kKeySearch)
            {
               switch (g_Battle.UI.wSelectedAction)
               {
               case 0:
                  //
                  // Attack
                  //
                  g_Battle.UI.wActionType = kBattleActionAttack;
                  if (PAL_PlayerCanAttackAll(gpGlobals->rgParty[g_Battle.UI.wCurPlayerIndex].wPlayerRole))
                  {
                     g_Battle.UI.state = kBattleUISelectTargetEnemyAll;
                  }
                  else
                  {
                     g_Battle.UI.wSelectedIndex = g_Battle.UI.wPrevEnemyTarget;
                     g_Battle.UI.state = kBattleUISelectTargetEnemy;
                  }
                  break;

               case 1:
                  //
                  // Magic
                  //
                  g_Battle.UI.MenuState = kBattleMenuMagicSelect;
                  PAL_MagicSelectionMenuInit(wPlayerRole, TRUE, 0);
                  break;

               case 2:
                  //
                  // Cooperative magic
                  //
                  w = gpGlobals->rgParty[g_Battle.UI.wCurPlayerIndex].wPlayerRole;
                  w = PAL_GetPlayerCooperativeMagic(w);

                  g_Battle.UI.wActionType = kBattleActionCoopMagic;
                  g_Battle.UI.wObjectID = w;

                  if (gpGlobals->g.rgObject[w].magic.wFlags & kMagicFlagUsableToEnemy)
                  {
                     if (gpGlobals->g.rgObject[w].magic.wFlags & kMagicFlagApplyToAll)
                     {
                        g_Battle.UI.state = kBattleUISelectTargetEnemyAll;
                     }
                     else
                     {
                        g_Battle.UI.wSelectedIndex = g_Battle.UI.wPrevEnemyTarget;
                        g_Battle.UI.state = kBattleUISelectTargetEnemy;
                     }
                  }
                  else
                  {
                     if (gpGlobals->g.rgObject[w].magic.wFlags & kMagicFlagApplyToAll)
                     {
                        g_Battle.UI.state = kBattleUISelectTargetPlayerAll;
                     }
                     else
                     {
#ifdef PAL_CLASSIC
                        g_Battle.UI.wSelectedIndex = 0;
#else
                        g_Battle.UI.wSelectedIndex = g_Battle.UI.wCurPlayerIndex;
#endif
                        g_Battle.UI.state = kBattleUISelectTargetPlayer;
                     }
                  }
                  break;

               case 3:
                  //
                  // Misc menu
                  //
                  g_Battle.UI.MenuState = kBattleMenuMisc;
                  g_iCurMiscMenuItem = 0;
                  break;
               }
            }
            else if (g_InputState.dwKeyPress & kKeyDefend)
            {
               g_Battle.UI.wActionType = kBattleActionDefend;
               PAL_BattleCommitAction(FALSE);
            }
            else if (g_InputState.dwKeyPress & kKeyForce)
            {
               w = PAL_BattleUIPickAutoMagic(gpGlobals->rgParty[g_Battle.UI.wCurPlayerIndex].wPlayerRole, 60);

               if (w == 0)
               {
                  g_Battle.UI.wActionType = kBattleActionAttack;

                  if (PAL_PlayerCanAttackAll(gpGlobals->rgParty[g_Battle.UI.wCurPlayerIndex].wPlayerRole))
                  {
                     g_Battle.UI.wSelectedIndex = -1;
                  }
                  else
                  {
                     g_Battle.UI.wSelectedIndex = PAL_BattleSelectAutoTarget();
                  }
               }
               else
               {
                  g_Battle.UI.wActionType = kBattleActionMagic;
                  g_Battle.UI.wObjectID = w;

                  if (gpGlobals->g.rgObject[w].magic.wFlags & kMagicFlagApplyToAll)
                  {
                     g_Battle.UI.wSelectedIndex = -1;
                  }
                  else
                  {
                     g_Battle.UI.wSelectedIndex = PAL_BattleSelectAutoTarget();
                  }
               }

               PAL_BattleCommitAction(FALSE);
            }
            else if (g_InputState.dwKeyPress & kKeyFlee)
            {
               g_Battle.UI.wActionType = kBattleActionFlee;
               PAL_BattleCommitAction(FALSE);
            }
            else if (g_InputState.dwKeyPress & kKeyUseItem)
            {
               g_Battle.UI.MenuState = kBattleMenuUseItemSelect;
               PAL_ItemSelectMenuInit(kItemFlagUsable);
            }
            else if (g_InputState.dwKeyPress & kKeyThrowItem)
            {
               g_Battle.UI.MenuState = kBattleMenuThrowItemSelect;
               PAL_ItemSelectMenuInit(kItemFlagThrowable);
            }
            else if (g_InputState.dwKeyPress & kKeyRepeat)
            {
               PAL_BattleCommitAction(TRUE);
            }
#ifdef PAL_CLASSIC
            else if (g_InputState.dwKeyPress & kKeyMenu)
            {
               g_Battle.rgPlayer[g_Battle.UI.wCurPlayerIndex].state = kFighterWait;
               g_Battle.UI.state = kBattleUIWait;

               if (g_Battle.UI.wCurPlayerIndex > 0)
               {
                  //
                  // Revert to the previous player
                  //
                  do
                  {
                     g_Battle.rgPlayer[--g_Battle.UI.wCurPlayerIndex].state = kFighterWait;

                     if (g_Battle.rgPlayer[g_Battle.UI.wCurPlayerIndex].action.ActionType == kBattleActionThrowItem)
                     {
                        for (i = 0; i < MAX_INVENTORY; i++)
                        {
                           if (gpGlobals->rgInventory[i].wItem ==
                              g_Battle.rgPlayer[g_Battle.UI.wCurPlayerIndex].action.wActionID)
                           {
                              gpGlobals->rgInventory[i].nAmountInUse--;
                              break;
                           }
                        }
                     }
                     else if (g_Battle.rgPlayer[g_Battle.UI.wCurPlayerIndex].action.ActionType == kBattleActionUseItem)
                     {
                        if (gpGlobals->g.rgObject[g_Battle.rgPlayer[g_Battle.UI.wCurPlayerIndex].action.wActionID].item.wFlags & kItemFlagConsuming)
                        {
                           for (i = 0; i < MAX_INVENTORY; i++)
                           {
                              if (gpGlobals->rgInventory[i].wItem ==
                                 g_Battle.rgPlayer[g_Battle.UI.wCurPlayerIndex].action.wActionID)
                              {
                                 gpGlobals->rgInventory[i].nAmountInUse--;
                                 break;
                              }
                           }
                        }
                     }
                  } while (g_Battle.UI.wCurPlayerIndex > 0 &&
                     (gpGlobals->g.PlayerRoles.rgwHP[gpGlobals->rgParty[g_Battle.UI.wCurPlayerIndex].wPlayerRole] == 0 ||
                      gpGlobals->rgPlayerStatus[gpGlobals->rgParty[g_Battle.UI.wCurPlayerIndex].wPlayerRole][kStatusConfused] > 0 ||
                      gpGlobals->rgPlayerStatus[gpGlobals->rgParty[g_Battle.UI.wCurPlayerIndex].wPlayerRole][kStatusSleep] > 0 ||
                      gpGlobals->rgPlayerStatus[gpGlobals->rgParty[g_Battle.UI.wCurPlayerIndex].wPlayerRole][kStatusParalyzed] > 0));
               }
            }
#else
            else if (g_InputState.dwKeyPress & kKeyMenu)
            {
               FLOAT flMin = int2F(-1);
               j = -1;

               for (i = 0; i <= gpGlobals->wMaxPartyMemberIndex; i++)
               {
                  if (g_Battle.rgPlayer[i].flTimeMeter >= 100)
                  {
                     g_Battle.rgPlayer[i].flTimeMeter += 100; // HACKHACK: Prevent the time meter from going below 100

                     if ((g_Battle.rgPlayer[i].flTimeMeter < flMin || flMin < 0) &&
                        i != (int)g_Battle.UI.wCurPlayerIndex &&
                        g_Battle.rgPlayer[i].state == kFighterWait)
                     {
                        flMin = g_Battle.rgPlayer[i].flTimeMeter;
                        j = i;
                     }
                  }
               }

               if (j != -1)
               {
                  g_Battle.rgPlayer[g_Battle.UI.wCurPlayerIndex].flTimeMeter = flMin - int2F(99);
                  g_Battle.rgPlayer[g_Battle.UI.wCurPlayerIndex].state = kFighterWait;
                  g_Battle.UI.state = kBattleUIWait;
               }
            }
#endif
            break;

         case kBattleMenuMagicSelect:
            w = PAL_MagicSelectionMenuUpdate();

            if (w != 0xFFFF)
            {
               g_Battle.UI.MenuState = kBattleMenuMain;

               if (w != 0)
               {
                  g_Battle.UI.wActionType = kBattleActionMagic;
                  g_Battle.UI.wObjectID = w;

                  if (gpGlobals->g.rgObject[w].magic.wFlags & kMagicFlagUsableToEnemy)
                  {
                     if (gpGlobals->g.rgObject[w].magic.wFlags & kMagicFlagApplyToAll)
                     {
                        g_Battle.UI.state = kBattleUISelectTargetEnemyAll;
                     }
                     else
                     {
                        g_Battle.UI.wSelectedIndex = g_Battle.UI.wPrevEnemyTarget;
                        g_Battle.UI.state = kBattleUISelectTargetEnemy;
                     }
                  }
                  else
                  {
                     if (gpGlobals->g.rgObject[w].magic.wFlags & kMagicFlagApplyToAll)
                     {
                        g_Battle.UI.state = kBattleUISelectTargetPlayerAll;
                     }
                     else
                     {
#ifdef PAL_CLASSIC
                        g_Battle.UI.wSelectedIndex = 0;
#else
                        g_Battle.UI.wSelectedIndex = g_Battle.UI.wCurPlayerIndex;
#endif
                        g_Battle.UI.state = kBattleUISelectTargetPlayer;
                     }
                  }
               }
            }
            break;

         case kBattleMenuUseItemSelect:
            PAL_BattleUIUseItem();
            break;

         case kBattleMenuThrowItemSelect:
            PAL_BattleUIThrowItem();
            break;

         case kBattleMenuMisc:
            w = PAL_BattleUIMiscMenuUpdate();

            if (w != 0xFFFF)
            {
               g_Battle.UI.MenuState = kBattleMenuMain;

               switch (w)
               {
#ifdef PAL_CLASSIC
               case 2: // item
#else
               case 1: // item
#endif
                  g_Battle.UI.MenuState = kBattleMenuMiscItemSubMenu;
                  g_iCurSubMenuItem = 0;
                  break;

#ifdef PAL_CLASSIC
               case 3: // defend
#else
               case 2: // defend
#endif
                  g_Battle.UI.wActionType = kBattleActionDefend;
                  PAL_BattleCommitAction(FALSE);
                  break;

#ifdef PAL_CLASSIC
               case 1: // auto
#else
               case 3: // auto
#endif
                  g_Battle.UI.fAutoAttack = TRUE;
                  break;

               case 4: // flee
                  g_Battle.UI.wActionType = kBattleActionFlee;
                  PAL_BattleCommitAction(FALSE);
                  break;

               case 5: // status
                  PAL_PlayerStatus();
                  break;
               }
            }
            break;

         case kBattleMenuMiscItemSubMenu:
            w = PAL_BattleUIMiscItemSubMenuUpdate();

            if (w != 0xFFFF)
            {
               g_Battle.UI.MenuState = kBattleMenuMain;

               switch (w)
               {
               case 1: // use
                  g_Battle.UI.MenuState = kBattleMenuUseItemSelect;
                  PAL_ItemSelectMenuInit(kItemFlagUsable);
                  break;

               case 2: // throw
                  g_Battle.UI.MenuState = kBattleMenuThrowItemSelect;
                  PAL_ItemSelectMenuInit(kItemFlagThrowable);
                  break;
               }
            }
            break;
         }
      }
      break;

   case kBattleUISelectTargetEnemy:
      x = -1;
      y = 0;

      for (i = 0; i <= g_Battle.wMaxEnemyIndex; i++)
      {
         if (g_Battle.rgEnemy[i].wObjectID != 0)
         {
            x = i;
            y++;
         }
      }

      if (x == -1)
      {
         g_Battle.UI.state = kBattleUISelectMove;
         break;
      }

      if (g_Battle.UI.wActionType == kBattleActionCoopMagic)
      {
         if (!PAL_BattleUIIsActionValid(kBattleActionCoopMagic))
         {
            g_Battle.UI.state = kBattleUISelectMove;
            break;
         }
      }

#ifdef PAL_CLASSIC
      //
      // Don't bother selecting when only 1 enemy left
      //
      if (y == 1)
      {
         g_Battle.UI.wPrevEnemyTarget = (WORD)x;
         PAL_BattleCommitAction(FALSE);
         break;
      }
#endif
      if (g_Battle.UI.wSelectedIndex > x)
      {
         g_Battle.UI.wSelectedIndex = x;
      }

      for (i = 0; i <= x; i++)
      {
         if (g_Battle.rgEnemy[g_Battle.UI.wSelectedIndex].wObjectID != 0)
         {
            break;
         }
         g_Battle.UI.wSelectedIndex++;
         g_Battle.UI.wSelectedIndex %= x + 1;
      }

      //
      // Highlight the selected enemy
      //
      if (s_iFrame & 1)
      {
         i = g_Battle.UI.wSelectedIndex;

         x = PAL_X(g_Battle.rgEnemy[i].pos);
         y = PAL_Y(g_Battle.rgEnemy[i].pos);

         x -= PAL_RLEGetWidth(PAL_SpriteGetFrame(g_Battle.rgEnemy[i].lpSprite, g_Battle.rgEnemy[i].wCurrentFrame)) / 2;
         y -= PAL_RLEGetHeight(PAL_SpriteGetFrame(g_Battle.rgEnemy[i].lpSprite, g_Battle.rgEnemy[i].wCurrentFrame));

         PAL_RLEBlitWithColorShift(PAL_SpriteGetFrame(g_Battle.rgEnemy[i].lpSprite, g_Battle.rgEnemy[i].wCurrentFrame),
            gpScreen, PAL_XY(x, y), 7);
      }

      if (g_InputState.dwKeyPress & kKeyMenu)
      {
         g_Battle.UI.state = kBattleUISelectMove;
      }
      else if (g_InputState.dwKeyPress & kKeySearch)
      {
         g_Battle.UI.wPrevEnemyTarget = g_Battle.UI.wSelectedIndex;
         PAL_BattleCommitAction(FALSE);
      }
      else if (g_InputState.dwKeyPress & (kKeyLeft | kKeyDown))
      {
         if (g_Battle.UI.wSelectedIndex != 0)
         {
            g_Battle.UI.wSelectedIndex--;
            while (g_Battle.UI.wSelectedIndex != 0 &&
               g_Battle.rgEnemy[g_Battle.UI.wSelectedIndex].wObjectID == 0)
            {
               g_Battle.UI.wSelectedIndex--;
            }
         }
      }
      else if (g_InputState.dwKeyPress & (kKeyRight | kKeyUp))
      {
         if (g_Battle.UI.wSelectedIndex < x)
         {
            g_Battle.UI.wSelectedIndex++;
            while (g_Battle.UI.wSelectedIndex < x &&
               g_Battle.rgEnemy[g_Battle.UI.wSelectedIndex].wObjectID == 0)
            {
               g_Battle.UI.wSelectedIndex++;
            }
         }
      }
      break;

   case kBattleUISelectTargetPlayer:
#ifdef PAL_CLASSIC
      //
      // Don't bother selecting when only 1 player is in the party
      //
      if (gpGlobals->wMaxPartyMemberIndex == 0)
      {
         g_Battle.UI.wSelectedIndex = 0;
         PAL_BattleCommitAction(FALSE);
      }
#endif

      j = SPRITENUM_BATTLE_ARROW_SELECTEDPLAYER;
      if (s_iFrame & 1)
      {
         j = SPRITENUM_BATTLE_ARROW_SELECTEDPLAYER_RED;
      }

      //
      // Draw arrows on the selected player
      //
      x = g_rgPlayerPos[gpGlobals->wMaxPartyMemberIndex][g_Battle.UI.wSelectedIndex][0] - 8;
      y = g_rgPlayerPos[gpGlobals->wMaxPartyMemberIndex][g_Battle.UI.wSelectedIndex][1] - 67;

      PAL_RLEBlitToSurface(PAL_SpriteGetFrame(gpSpriteUI, j), gpScreen, PAL_XY(x, y));

      if (g_InputState.dwKeyPress & kKeyMenu)
      {
         g_Battle.UI.state = kBattleUISelectMove;
      }
      else if (g_InputState.dwKeyPress & kKeySearch)
      {
         PAL_BattleCommitAction(FALSE);
      }
      else if (g_InputState.dwKeyPress & (kKeyLeft | kKeyDown))
      {
         if (g_Battle.UI.wSelectedIndex != 0)
         {
            g_Battle.UI.wSelectedIndex--;
         }
         else
         {
            g_Battle.UI.wSelectedIndex = gpGlobals->wMaxPartyMemberIndex;
         }
      }
      else if (g_InputState.dwKeyPress & (kKeyRight | kKeyUp))
      {
         if (g_Battle.UI.wSelectedIndex < gpGlobals->wMaxPartyMemberIndex)
         {
            g_Battle.UI.wSelectedIndex++;
         }
         else
         {
            g_Battle.UI.wSelectedIndex = 0;
         }
      }

      break;

   case kBattleUISelectTargetEnemyAll:
#ifdef PAL_CLASSIC
      //
      // Don't bother selecting
      //
      g_Battle.UI.wSelectedIndex = (WORD)-1;
      PAL_BattleCommitAction(FALSE);
#else
      if (g_Battle.UI.wActionType == kBattleActionCoopMagic)
      {
         if (!PAL_BattleUIIsActionValid(kBattleActionCoopMagic))
         {
            g_Battle.UI.state = kBattleUISelectMove;
            break;
         }
      }

      if (s_iFrame & 1)
      {
         //
         // Highlight all enemies
         //
         for (i = g_Battle.wMaxEnemyIndex; i >= 0; i--)
         {
            if (g_Battle.rgEnemy[i].wObjectID == 0)
            {
               continue;
            }

            x = PAL_X(g_Battle.rgEnemy[i].pos);
            y = PAL_Y(g_Battle.rgEnemy[i].pos);

            x -= PAL_RLEGetWidth(PAL_SpriteGetFrame(g_Battle.rgEnemy[i].lpSprite, g_Battle.rgEnemy[i].wCurrentFrame)) / 2;
            y -= PAL_RLEGetHeight(PAL_SpriteGetFrame(g_Battle.rgEnemy[i].lpSprite, g_Battle.rgEnemy[i].wCurrentFrame));

            PAL_RLEBlitWithColorShift(PAL_SpriteGetFrame(g_Battle.rgEnemy[i].lpSprite, g_Battle.rgEnemy[i].wCurrentFrame),
               gpScreen, PAL_XY(x, y), 7);
         }
      }
      if (g_InputState.dwKeyPress & kKeyMenu)
      {
         g_Battle.UI.state = kBattleUISelectMove;
      }
      else if (g_InputState.dwKeyPress & kKeySearch)
      {
         g_Battle.UI.wSelectedIndex = (WORD)-1;
         PAL_BattleCommitAction(FALSE);
      }
#endif
      break;

   case kBattleUISelectTargetPlayerAll:
#ifdef PAL_CLASSIC
      //
      // Don't bother selecting
      //
      g_Battle.UI.wSelectedIndex = (WORD)-1;
      PAL_BattleCommitAction(FALSE);
#else
      j = SPRITENUM_BATTLE_ARROW_SELECTEDPLAYER;
      if (s_iFrame & 1)
      {
         j = SPRITENUM_BATTLE_ARROW_SELECTEDPLAYER_RED;
      }
      for (i = 0; i <= gpGlobals->wMaxPartyMemberIndex; i++)
      {
         if (g_Battle.UI.wActionType == kBattleActionMagic)
         {
            w = gpGlobals->g.rgObject[g_Battle.UI.wObjectID].magic.wMagicNumber;

            if (gpGlobals->g.lprgMagic[w].wType == kMagicTypeTrance)
            {
               if (i != g_Battle.UI.wCurPlayerIndex)
                  continue;
            }
         }

         //
         // Draw arrows on all players, despite of dead or not
         //
         x = g_rgPlayerPos[gpGlobals->wMaxPartyMemberIndex][i][0] - 8;
         y = g_rgPlayerPos[gpGlobals->wMaxPartyMemberIndex][i][1] - 67;

         PAL_RLEBlitToSurface(PAL_SpriteGetFrame(gpSpriteUI, j), gpScreen, PAL_XY(x, y));
      }

      if (g_InputState.dwKeyPress & kKeyMenu)
      {
         g_Battle.UI.state = kBattleUISelectMove;
      }
      else if (g_InputState.dwKeyPress & kKeySearch)
      {
         g_Battle.UI.wSelectedIndex = (WORD)-1;
         PAL_BattleCommitAction(FALSE);
      }
#endif
      break;
   }

end:
   //
   // Show the text message if there is one.
   //
#ifndef PAL_CLASSIC
   if (SDL_GetTicks() < g_Battle.UI.dwMsgShowTime)
   {
      //
      // The text should be shown in a small window at the center of the screen
      //
      PAL_POS    pos;
      int        len = strlen(g_Battle.UI.szMsg);

      //
      // Create the window box
      //
      pos = PAL_XY(160 - len * 4, 40);
      PAL_CreateSingleLineBox(pos, (len + 1) / 2, FALSE);

      //
      // Show the text on the screen
      //
      pos = PAL_XY(PAL_X(pos) + 8 + ((len & 1) << 2), PAL_Y(pos) + 10);
      PAL_DrawText(g_Battle.UI.szMsg, pos, 0, FALSE, FALSE);
   }
   else if (g_Battle.UI.szNextMsg[0] != '\0')
   {
      strcpy(g_Battle.UI.szMsg, g_Battle.UI.szNextMsg);
      g_Battle.UI.dwMsgShowTime = SDL_GetTicks() + g_Battle.UI.wNextMsgDuration;
      g_Battle.UI.szNextMsg[0] = '\0';
   }
#endif

   //
   // Draw the numbers
   //
   for (i = 0; i < BATTLEUI_MAX_SHOWNUM; i++)
   {
      if (g_Battle.UI.rgShowNum[i].wNum > 0)
      {
         if ((SDL_GetTicks() - g_Battle.UI.rgShowNum[i].dwTime) / BATTLE_FRAME_TIME > 10)
         {
            g_Battle.UI.rgShowNum[i].wNum = 0;
         }
         else
         {
            PAL_DrawNumber(g_Battle.UI.rgShowNum[i].wNum, 5,
               PAL_XY(PAL_X(g_Battle.UI.rgShowNum[i].pos), PAL_Y(g_Battle.UI.rgShowNum[i].pos) - (SDL_GetTicks() - g_Battle.UI.rgShowNum[i].dwTime) / BATTLE_FRAME_TIME),
               g_Battle.UI.rgShowNum[i].color, kNumAlignRight);
         }
      }
   }

   PAL_ClearKeyState();
}
Beispiel #11
0
VOID
PAL_BattleMakeScene(
   VOID
)
/*++
  Purpose:

    Generate the battle scene into the scene buffer.

  Parameters:

    None.

  Return value:

    None.

--*/
{
   int          i;
   PAL_POS      pos;
   LPBYTE       pSrc, pDst;
   //BYTE         b;

   //
   // Draw the background
   //
   pSrc = g_Battle.lpBackground->pixels;
   pDst = g_Battle.lpSceneBuf->pixels;

   // optimized by ZBY
   ZBY_TIMING_BEGIN(2);
   make_colorshift_table(g_Battle.sBackgroundColorShift);
   if (0) { //if (g_Battle.sBackgroundColorShift == 0) {
       memcpy(pDst, pSrc, g_Battle.lpSceneBuf->pitch * g_Battle.lpSceneBuf->h);
   } else {
       i = g_Battle.lpSceneBuf->pitch * g_Battle.lpSceneBuf->h;
       while (i--)
       {
          /*b = (*pSrc & 0x0F);
          
          b += g_Battle.sBackgroundColorShift;

          if (b & 0x80)
          {
             b = 0;
          }
          else if (b & 0x70)
          {
             b = 0x0F;
          }

          *pDst = (b | (*pSrc & 0xF0));
          assert(*pDst == cs_table[*pSrc]);
          */
          *pDst = cs_table[*pSrc];

          ++pSrc;
          ++pDst;
       }
   }
   ZBY_TIMING_END(2, "PAL_BattleMakeScene");

   PAL_ApplyWave(g_Battle.lpSceneBuf);

   //
   // Draw the enemies
   //
   for (i = g_Battle.wMaxEnemyIndex; i >= 0; i--)
   {
      pos = g_Battle.rgEnemy[i].pos;

      if (g_Battle.rgEnemy[i].rgwStatus[kStatusConfused] > 0 &&
         g_Battle.rgEnemy[i].rgwStatus[kStatusSleep] == 0 &&
         g_Battle.rgEnemy[i].rgwStatus[kStatusParalyzed] == 0)
      {
         //
         // Enemy is confused
         //
         pos = PAL_XY(PAL_X(pos) + RandomLong(-1, 1), PAL_Y(pos));
      }

      pos = PAL_XY(PAL_X(pos) - PAL_RLEGetWidth(PAL_SpriteGetFrame(g_Battle.rgEnemy[i].lpSprite, g_Battle.rgEnemy[i].wCurrentFrame)) / 2,
         PAL_Y(pos) - PAL_RLEGetHeight(PAL_SpriteGetFrame(g_Battle.rgEnemy[i].lpSprite, g_Battle.rgEnemy[i].wCurrentFrame)));

      if (g_Battle.rgEnemy[i].wObjectID != 0)
      {
         if (g_Battle.rgEnemy[i].iColorShift)
         {
            PAL_RLEBlitWithColorShift(PAL_SpriteGetFrame(g_Battle.rgEnemy[i].lpSprite, g_Battle.rgEnemy[i].wCurrentFrame),
               g_Battle.lpSceneBuf, pos, g_Battle.rgEnemy[i].iColorShift);
         }
         else
         {
            PAL_RLEBlitToSurface(PAL_SpriteGetFrame(g_Battle.rgEnemy[i].lpSprite, g_Battle.rgEnemy[i].wCurrentFrame),
               g_Battle.lpSceneBuf, pos);
         }
      }
   }

   if (g_Battle.lpSummonSprite != NULL)
   {
      //
      // Draw the summoned god
      //
      pos = PAL_XY(PAL_X(g_Battle.posSummon) - PAL_RLEGetWidth(PAL_SpriteGetFrame(g_Battle.lpSummonSprite, g_Battle.iSummonFrame)) / 2,
         PAL_Y(g_Battle.posSummon) - PAL_RLEGetHeight(PAL_SpriteGetFrame(g_Battle.lpSummonSprite, g_Battle.iSummonFrame)));

      PAL_RLEBlitToSurface(PAL_SpriteGetFrame(g_Battle.lpSummonSprite, g_Battle.iSummonFrame),
         g_Battle.lpSceneBuf, pos);
   }
   else
   {
      //
      // Draw the players
      //
      for (i = gpGlobals->wMaxPartyMemberIndex; i >= 0; i--)
      {
         pos = g_Battle.rgPlayer[i].pos;

         if (gpGlobals->rgPlayerStatus[gpGlobals->rgParty[i].wPlayerRole][kStatusConfused] != 0 &&
            gpGlobals->rgPlayerStatus[gpGlobals->rgParty[i].wPlayerRole][kStatusSleep] == 0 &&
            gpGlobals->rgPlayerStatus[gpGlobals->rgParty[i].wPlayerRole][kStatusParalyzed] == 0 &&
            gpGlobals->g.PlayerRoles.rgwHP[gpGlobals->rgParty[i].wPlayerRole] > 0)
         {
            //
            // Player is confused
            //
            continue;
         }

         pos = PAL_XY(PAL_X(pos) - PAL_RLEGetWidth(PAL_SpriteGetFrame(g_Battle.rgPlayer[i].lpSprite, g_Battle.rgPlayer[i].wCurrentFrame)) / 2,
            PAL_Y(pos) - PAL_RLEGetHeight(PAL_SpriteGetFrame(g_Battle.rgPlayer[i].lpSprite, g_Battle.rgPlayer[i].wCurrentFrame)));

         if (g_Battle.rgPlayer[i].iColorShift != 0)
         {
            PAL_RLEBlitWithColorShift(PAL_SpriteGetFrame(g_Battle.rgPlayer[i].lpSprite, g_Battle.rgPlayer[i].wCurrentFrame),
               g_Battle.lpSceneBuf, pos, g_Battle.rgPlayer[i].iColorShift);
         }
         else if (g_Battle.iHidingTime == 0)
         {
            PAL_RLEBlitToSurface(PAL_SpriteGetFrame(g_Battle.rgPlayer[i].lpSprite, g_Battle.rgPlayer[i].wCurrentFrame),
               g_Battle.lpSceneBuf, pos);
         }
      }

      //
      // Confused players should be drawn on top of normal players
      //
      for (i = gpGlobals->wMaxPartyMemberIndex; i >= 0; i--)
      {
         if (gpGlobals->rgPlayerStatus[gpGlobals->rgParty[i].wPlayerRole][kStatusConfused] != 0 &&
            gpGlobals->rgPlayerStatus[gpGlobals->rgParty[i].wPlayerRole][kStatusSleep] == 0 &&
            gpGlobals->rgPlayerStatus[gpGlobals->rgParty[i].wPlayerRole][kStatusParalyzed] == 0 &&
            gpGlobals->g.PlayerRoles.rgwHP[gpGlobals->rgParty[i].wPlayerRole] > 0)
         {
            //
            // Player is confused
            //
            pos = PAL_XY(PAL_X(g_Battle.rgPlayer[i].pos), PAL_Y(g_Battle.rgPlayer[i].pos) + RandomLong(-1, 1));
            pos = PAL_XY(PAL_X(pos) - PAL_RLEGetWidth(PAL_SpriteGetFrame(g_Battle.rgPlayer[i].lpSprite, g_Battle.rgPlayer[i].wCurrentFrame)) / 2,
               PAL_Y(pos) - PAL_RLEGetHeight(PAL_SpriteGetFrame(g_Battle.rgPlayer[i].lpSprite, g_Battle.rgPlayer[i].wCurrentFrame)));

            if (g_Battle.rgPlayer[i].iColorShift != 0)
            {
               PAL_RLEBlitWithColorShift(PAL_SpriteGetFrame(g_Battle.rgPlayer[i].lpSprite, g_Battle.rgPlayer[i].wCurrentFrame),
                  g_Battle.lpSceneBuf, pos, g_Battle.rgPlayer[i].iColorShift);
            }
            else if (g_Battle.iHidingTime == 0)
            {
               PAL_RLEBlitToSurface(PAL_SpriteGetFrame(g_Battle.rgPlayer[i].lpSprite, g_Battle.rgPlayer[i].wCurrentFrame),
                  g_Battle.lpSceneBuf, pos);
            }
         }
      }
   }
}