#include "screens.h"
-/* select level set with EMC X11 graphics before activating EM GFX debugging */
+// select level set with EMC X11 graphics before activating EM GFX debugging
#define DEBUG_EM_GFX FALSE
#define DEBUG_FRAME_TIME FALSE
-/* tool button identifiers */
+// tool button identifiers
#define TOOL_CTRL_ID_YES 0
#define TOOL_CTRL_ID_NO 1
#define TOOL_CTRL_ID_CONFIRM 2
#define NUM_TOOL_BUTTONS 7
-/* constants for number of doors and door parts */
+// constants for number of doors and door parts
#define NUM_DOORS 2
#define NUM_PANELS NUM_DOORS
// #define NUM_PANELS 0
};
-/* forward declaration for internal use */
-static void UnmapToolButtons();
+// forward declaration for internal use
+static void UnmapToolButtons(void);
static void HandleToolButtons(struct GadgetInfo *);
static int el_act_dir2crm(int, int, int);
static int el_act2crm(int, int);
return ly;
}
-static int getFieldbufferOffsetX_RND()
+static int getFieldbufferOffsetX_RND(void)
{
int full_lev_fieldx = lev_fieldx + (BorderElement != EL_EMPTY ? 2 : 0);
int dx = (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
return fx;
}
-static int getFieldbufferOffsetY_RND()
+static int getFieldbufferOffsetY_RND(void)
{
int full_lev_fieldy = lev_fieldy + (BorderElement != EL_EMPTY ? 2 : 0);
int dy = (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
static int getLevelFromScreenX_MM(int sx)
{
-#if 0
int level_xsize = level.native_mm_level->fieldx;
int full_xsize = level_xsize * TILESIZE_VAR;
sx -= (full_xsize < SXSIZE ? (SXSIZE - full_xsize) / 2 : 0);
-#endif
int px = sx - SX;
- int lx = px / TILESIZE_VAR;
+ int lx = (px + TILESIZE_VAR) / TILESIZE_VAR - 1;
return lx;
}
static int getLevelFromScreenY_MM(int sy)
{
-#if 0
int level_ysize = level.native_mm_level->fieldy;
int full_ysize = level_ysize * TILESIZE_VAR;
sy -= (full_ysize < SYSIZE ? (SYSIZE - full_ysize) / 2 : 0);
-#endif
int py = sy - SY;
- int ly = py / TILESIZE_VAR;
+ int ly = (py + TILESIZE_VAR) / TILESIZE_VAR - 1;
return ly;
}
drawto_field = fieldbuffer;
}
- else /* DRAW_TO_BACKBUFFER */
+ else // DRAW_TO_BACKBUFFER
{
FX = SX;
FY = SY;
}
}
-static void RedrawPlayfield_RND()
+static void RedrawPlayfield_RND(void)
{
if (game.envelope_active)
return;
DrawAllPlayers();
}
-void RedrawPlayfield()
+void RedrawPlayfield(void)
{
if (game_status != GAME_MODE_PLAYING)
return;
static void DrawMaskedBorderExt_DOOR_3(int draw_target)
{
- /* currently not available */
+ // currently not available
}
static void DrawMaskedBorderExt_ALL(int draw_target)
static void DrawMaskedBorderExt(int redraw_mask, int draw_target)
{
- /* never draw masked screen borders on borderless screens */
+ // never draw masked screen borders on borderless screens
if (global.border_status == GAME_MODE_LOADING ||
global.border_status == GAME_MODE_TITLE)
return;
}
}
-void DrawMaskedBorder_FIELD()
+void DrawMaskedBorder_FIELD(void)
{
DrawMaskedBorderExt_FIELD(DRAW_TO_BACKBUFFER);
}
}
}
+void DrawTileCursor(int draw_target)
+{
+ Bitmap *fade_bitmap;
+ Bitmap *src_bitmap;
+ int src_x, src_y;
+ int dst_x, dst_y;
+ int graphic = IMG_GLOBAL_TILE_CURSOR;
+ int frame = 0;
+ int tilesize = TILESIZE_VAR;
+ int width = tilesize;
+ int height = tilesize;
+
+ if (game_status != GAME_MODE_PLAYING)
+ return;
+
+ if (!tile_cursor.enabled ||
+ !tile_cursor.active)
+ return;
+
+ if (tile_cursor.moving)
+ {
+ int step = TILESIZE_VAR / 4;
+ int dx = tile_cursor.target_x - tile_cursor.x;
+ int dy = tile_cursor.target_y - tile_cursor.y;
+
+ if (ABS(dx) < step)
+ tile_cursor.x = tile_cursor.target_x;
+ else
+ tile_cursor.x += SIGN(dx) * step;
+
+ if (ABS(dy) < step)
+ tile_cursor.y = tile_cursor.target_y;
+ else
+ tile_cursor.y += SIGN(dy) * step;
+
+ if (tile_cursor.x == tile_cursor.target_x &&
+ tile_cursor.y == tile_cursor.target_y)
+ tile_cursor.moving = FALSE;
+ }
+
+ dst_x = tile_cursor.x;
+ dst_y = tile_cursor.y;
+
+ frame = getGraphicAnimationFrame(graphic, -1);
+
+ getSizedGraphicSource(graphic, frame, tilesize, &src_bitmap, &src_x, &src_y);
+
+ fade_bitmap =
+ (draw_target == DRAW_TO_FADE_SOURCE ? gfx.fade_bitmap_source :
+ draw_target == DRAW_TO_FADE_TARGET ? gfx.fade_bitmap_target : NULL);
+
+ if (draw_target == DRAW_TO_SCREEN)
+ BlitToScreenMasked(src_bitmap, src_x, src_y, width, height, dst_x, dst_y);
+ else
+ BlitBitmapMasked(src_bitmap, fade_bitmap, src_x, src_y, width, height,
+ dst_x, dst_y);
+}
+
void BlitScreenToBitmap_RND(Bitmap *target_bitmap)
{
int fx = getFieldbufferOffsetX_RND();
redraw_mask |= REDRAW_FIELD;
}
-void DrawFramesPerSecond()
+static void DrawFramesPerSecond(void)
{
char text[100];
int font_nr = FONT_TEXT_2;
int draw_deactivation_mask = GetDrawDeactivationMask();
boolean draw_masked = (draw_deactivation_mask == REDRAW_NONE);
- /* draw FPS with leading space (needed if field buffer deactivated) */
+ // draw FPS with leading space (needed if field buffer deactivated)
sprintf(text, " %04.1f fps", global.frames_per_second);
- /* override draw deactivation mask (required for invisible warp mode) */
+ // override draw deactivation mask (required for invisible warp mode)
SetDrawDeactivationMask(REDRAW_NONE);
- /* draw opaque FPS if field buffer deactivated, else draw masked FPS */
+ // draw opaque FPS if field buffer deactivated, else draw masked FPS
DrawTextExt(backbuffer, SX + SXSIZE - font_width * strlen(text), SY, text,
font_nr, (draw_masked ? BLIT_MASKED : BLIT_OPAQUE));
- /* set draw deactivation mask to previous value */
+ // set draw deactivation mask to previous value
SetDrawDeactivationMask(draw_deactivation_mask);
- /* force full-screen redraw in this frame */
+ // force full-screen redraw in this frame
redraw_mask = REDRAW_ALL;
}
#if DEBUG_FRAME_TIME
-static void PrintFrameTimeDebugging()
+static void PrintFrameTimeDebugging(void)
{
static unsigned int last_counter = 0;
unsigned int counter = Counter();
return unifiedRedrawMask(mask_1) == unifiedRedrawMask(mask_2);
}
-void BackToFront()
+void BackToFront(void)
{
static int last_redraw_mask = REDRAW_NONE;
{
if (fade_type_skip != FADE_TYPE_NONE)
{
- /* skip all fade operations until specified fade operation */
+ // skip all fade operations until specified fade operation
if (fade_type & fade_type_skip)
fade_type_skip = FADE_TYPE_NONE;
if (fade_type_skip != FADE_TYPE_NONE)
{
- /* skip all fade operations until specified fade operation */
+ // skip all fade operations until specified fade operation
if (fade_type & fade_type_skip)
fade_type_skip = FADE_TYPE_NONE;
height = FADE_SYSIZE;
if (border.draw_masked_when_fading)
- draw_border_function = DrawMaskedBorder_FIELD; /* update when fading */
+ draw_border_function = DrawMaskedBorder_FIELD; // update when fading
else
- DrawMaskedBorder_FIELD(); /* draw once */
+ DrawMaskedBorder_FIELD(); // draw once
}
- else /* REDRAW_ALL */
+ else // REDRAW_ALL
{
x = 0;
y = 0;
draw_border_function);
redraw_mask &= ~fade_mask;
+
+ ClearAutoRepeatKeyEvents();
}
-static void SetScreenStates_BeforeFadingIn()
+static void SetScreenStates_BeforeFadingIn(void)
{
// temporarily set screen mode for animations to screen after fading in
global.anim_status = global.anim_status_next;
global.anim_status = GAME_MODE_PSEUDO_FADING;
}
-static void SetScreenStates_AfterFadingIn()
+static void SetScreenStates_AfterFadingIn(void)
{
// store new source screen (to use correct masked border for fading)
gfx.fade_border_source_status = global.border_status;
global.anim_status = global.anim_status_next;
}
-static void SetScreenStates_BeforeFadingOut()
+static void SetScreenStates_BeforeFadingOut(void)
{
// store new target screen (to use correct masked border for fading)
gfx.fade_border_target_status = game_status;
PrepareFadeBitmap(DRAW_TO_FADE_SOURCE);
}
-static void SetScreenStates_AfterFadingOut()
+static void SetScreenStates_AfterFadingOut(void)
{
global.border_status = game_status;
}
SetScreenStates_BeforeFadingOut();
+ SetTileCursorActive(FALSE);
SetOverlayActive(FALSE);
#if 0
fading = fading_leave_stored;
}
-void FadeSetEnterMenu()
+void FadeSetEnterMenu(void)
{
fading = menu.enter_menu;
- FadeSetLeaveNext(fading, TRUE); /* (keep same fade mode) */
+ FadeSetLeaveNext(fading, TRUE); // (keep same fade mode)
}
-void FadeSetLeaveMenu()
+void FadeSetLeaveMenu(void)
{
fading = menu.leave_menu;
- FadeSetLeaveNext(fading, TRUE); /* (keep same fade mode) */
+ FadeSetLeaveNext(fading, TRUE); // (keep same fade mode)
}
-void FadeSetEnterScreen()
+void FadeSetEnterScreen(void)
{
fading = menu.enter_screen[game_status];
- FadeSetLeaveNext(menu.leave_screen[game_status], TRUE); /* store */
+ FadeSetLeaveNext(menu.leave_screen[game_status], TRUE); // store
}
-void FadeSetNextScreen()
+void FadeSetNextScreen(void)
{
fading = menu.next_screen[game_status];
// (do not overwrite fade mode set by FadeSetEnterScreen)
- // FadeSetLeaveNext(fading, TRUE); /* (keep same fade mode) */
+ // FadeSetLeaveNext(fading, TRUE); // (keep same fade mode)
}
-void FadeSetLeaveScreen()
+void FadeSetLeaveScreen(void)
{
- FadeSetLeaveNext(menu.leave_screen[game_status], FALSE); /* recall */
+ FadeSetLeaveNext(menu.leave_screen[game_status], FALSE); // recall
}
void FadeSetFromType(int type)
FadeSetLeaveMenu();
}
-void FadeSetDisabled()
+void FadeSetDisabled(void)
{
static struct TitleFadingInfo fading_none = { FADE_MODE_NONE, -1, -1, -1 };
fading = fading_none;
}
-void FadeSkipNextFadeIn()
+void FadeSkipNextFadeIn(void)
{
FadeExt(0, FADE_MODE_SKIP_FADE_IN, FADE_TYPE_SKIP);
}
-void FadeSkipNextFadeOut()
+void FadeSkipNextFadeOut(void)
{
FadeExt(0, FADE_MODE_SKIP_FADE_OUT, FADE_TYPE_SKIP);
}
-Bitmap *getBitmapFromGraphicOrDefault(int graphic, int default_graphic)
+static Bitmap *getBitmapFromGraphicOrDefault(int graphic, int default_graphic)
{
boolean redefined = getImageListEntryFromImageID(graphic)->redefined;
graphic_info[default_graphic].bitmap);
}
-Bitmap *getBackgroundBitmap(int graphic)
+static Bitmap *getBackgroundBitmap(int graphic)
{
return getBitmapFromGraphicOrDefault(graphic, IMG_BACKGROUND);
}
-Bitmap *getGlobalBorderBitmap(int graphic)
+static Bitmap *getGlobalBorderBitmap(int graphic)
{
return getBitmapFromGraphicOrDefault(graphic, IMG_GLOBAL_BORDER);
}
SetDoorBackgroundBitmap(getBackgroundBitmap(graphic));
}
-void SetPanelBackground()
+void SetPanelBackground(void)
{
struct GraphicInfo *gfx = &graphic_info[IMG_BACKGROUND_PANEL];
void DrawBackground(int x, int y, int width, int height)
{
- /* "drawto" might still point to playfield buffer here (hall of fame) */
+ // "drawto" might still point to playfield buffer here (hall of fame)
ClearRectangleOnBackground(backbuffer, x, y, width, height);
if (IN_GFX_FIELD_FULL(x, y))
static int dxsize_last = -1, dysize_last = -1;
static int vx_last = -1, vy_last = -1;
static int vxsize_last = -1, vysize_last = -1;
+static int ex_last = -1, ey_last = -1;
+static int exsize_last = -1, eysize_last = -1;
-boolean CheckIfGlobalBorderHasChanged()
+boolean CheckIfGlobalBorderHasChanged(void)
{
// if game status has not changed, global border has not changed either
if (game_status == game_status_last)
return (global_border_bitmap_last != global_border_bitmap);
}
-boolean CheckIfGlobalBorderRedrawIsNeeded()
+#define ONLY_REDRAW_GLOBAL_BORDER_IF_NEEDED 0
+
+#if ONLY_REDRAW_GLOBAL_BORDER_IF_NEEDED
+static boolean CheckIfGlobalBorderRedrawIsNeeded(void)
{
// if game status has not changed, nothing has to be redrawn
if (game_status == game_status_last)
vxsize_last != VXSIZE || vysize_last != VYSIZE)
return TRUE;
+ // redraw if position or size of editor area has changed
+ if (ex_last != EX || ey_last != EY ||
+ exsize_last != EXSIZE || eysize_last != EYSIZE)
+ return TRUE;
+
return FALSE;
}
+#endif
-void RedrawGlobalBorderFromBitmap(Bitmap *bitmap)
+static void RedrawGlobalBorderFromBitmap(Bitmap *bitmap)
{
if (bitmap)
BlitBitmap(bitmap, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
ClearRectangle(backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE);
}
-void RedrawGlobalBorder()
+void RedrawGlobalBorder(void)
{
Bitmap *bitmap = getGlobalBorderBitmapFromStatus(game_status);
redraw_mask = REDRAW_ALL;
}
-static void RedrawGlobalBorderIfNeeded()
+static void RedrawGlobalBorderIfNeeded(void)
{
+#if ONLY_REDRAW_GLOBAL_BORDER_IF_NEEDED
if (game_status == game_status_last)
return;
+#endif
// copy current draw buffer to later copy back areas that have not changed
if (game_status_last != GAME_MODE_TITLE)
BlitBitmap(backbuffer, bitmap_db_store_1, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
+#if ONLY_REDRAW_GLOBAL_BORDER_IF_NEEDED
if (CheckIfGlobalBorderRedrawIsNeeded())
+#endif
{
// redraw global screen border (or clear, if defined to be empty)
RedrawGlobalBorderFromBitmap(global_border_bitmap);
+ if (game_status == GAME_MODE_EDITOR)
+ DrawSpecialEditorDoor();
+
// copy previous playfield and door areas, if they are defined on both
// previous and current screen and if they still have the same size
BlitBitmap(bitmap_db_store_1, backbuffer,
dx_last, dy_last, DXSIZE, DYSIZE, DX, DY);
- if (vx_last != -1 && vy_last != -1 &&
- VX != -1 && VY != -1 &&
- vxsize_last == VXSIZE && vysize_last == VYSIZE)
- BlitBitmap(bitmap_db_store_1, backbuffer,
- vx_last, vy_last, VXSIZE, VYSIZE, VX, VY);
+ if (game_status != GAME_MODE_EDITOR)
+ {
+ if (vx_last != -1 && vy_last != -1 &&
+ VX != -1 && VY != -1 &&
+ vxsize_last == VXSIZE && vysize_last == VYSIZE)
+ BlitBitmap(bitmap_db_store_1, backbuffer,
+ vx_last, vy_last, VXSIZE, VYSIZE, VX, VY);
+ }
+ else
+ {
+ if (ex_last != -1 && ey_last != -1 &&
+ EX != -1 && EY != -1 &&
+ exsize_last == EXSIZE && eysize_last == EYSIZE)
+ BlitBitmap(bitmap_db_store_1, backbuffer,
+ ex_last, ey_last, EXSIZE, EYSIZE, EX, EY);
+ }
redraw_mask = REDRAW_ALL;
}
vy_last = VY;
vxsize_last = VXSIZE;
vysize_last = VYSIZE;
+ ex_last = EX;
+ ey_last = EY;
+ exsize_last = EXSIZE;
+ eysize_last = EYSIZE;
}
-void ClearField()
+void ClearField(void)
{
RedrawGlobalBorderIfNeeded();
- /* !!! "drawto" might still point to playfield buffer here (see above) !!! */
- /* (when entering hall of fame after playing) */
+ // !!! "drawto" might still point to playfield buffer here (see above) !!!
+ // (when entering hall of fame after playing)
DrawBackground(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
- /* !!! maybe this should be done before clearing the background !!! */
+ // !!! maybe this should be done before clearing the background !!!
if (game_status == GAME_MODE_PLAYING)
{
ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
redraw_mask |= REDRAW_FIELD;
}
-void SetBorderElement()
+void SetBorderElement(void)
{
int x, y;
BorderElement = EL_EMPTY;
- /* the MM game engine does not use a visible border element */
+ // the MM game engine does not use a visible border element
if (level.game_engine_type == GAME_ENGINE_TYPE_MM)
return;
static int check[4][2] = { { -1, 0 }, { 0, -1 }, { 1, 0 }, { 0, 1 } };
static int safety = 0;
- /* check if starting field still has the desired content */
+ // check if starting field still has the desired content
if (field[from_x][from_y] == fill_element)
return;
int getGraphicAnimationFrame(int graphic, int sync_frame)
{
- /* animation synchronized with global frame counter, not move position */
+ // animation synchronized with global frame counter, not move position
if (graphic_info[graphic].anim_global_sync || sync_frame < 0)
sync_frame = FrameCounter;
int src_x = g->src_x + (get_backside ? g->offset2_x : 0);
int src_y = g->src_y + (get_backside ? g->offset2_y : 0);
- if (g->offset_y == 0) /* frames are ordered horizontally */
+ if (g->offset_y == 0) // frames are ordered horizontally
{
int max_width = g->anim_frames_per_line * g->width;
int pos = (src_y / g->height) * max_width + src_x + frame * g->offset_x;
*x = pos % max_width;
*y = src_y % g->height + pos / max_width * g->height;
}
- else if (g->offset_x == 0) /* frames are ordered vertically */
+ else if (g->offset_x == 0) // frames are ordered vertically
{
int max_height = g->anim_frames_per_line * g->height;
int pos = (src_x / g->width) * max_height + src_y + frame * g->offset_y;
*x = src_x % g->width + pos / max_height * g->width;
*y = pos % max_height;
}
- else /* frames are ordered diagonally */
+ else // frames are ordered diagonally
{
*x = src_x + frame * g->offset_x;
*y = src_y + frame * g->offset_y;
{
struct GraphicInfo *g = &graphic_info[graphic];
+ // if no graphics defined at all, use fallback graphics
+ if (g->bitmaps == NULL)
+ *g = graphic_info[IMG_CHAR_EXCLAM];
+
// if no in-game graphics defined, always use standard graphic size
if (g->bitmaps[IMG_BITMAP_GAME] == NULL)
tilesize = TILESIZE;
getSizedGraphicSource(graphic, 0, MINI_TILESIZE, bitmap, x, y);
}
-inline static void getGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
- int *x, int *y, boolean get_backside)
+static void getGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
+ int *x, int *y, boolean get_backside)
{
getSizedGraphicSourceExt(graphic, frame, TILESIZE_VAR, bitmap, x, y,
get_backside);
BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
}
-inline static void DrawGraphicShiftedNormal(int x, int y, int dx, int dy,
- int graphic, int frame,
- int cut_mode, int mask_mode)
+static void DrawGraphicShiftedNormal(int x, int y, int dx, int dy,
+ int graphic, int frame,
+ int cut_mode, int mask_mode)
{
Bitmap *src_bitmap;
int src_x, src_y;
int width = TILEX, height = TILEY;
int cx = 0, cy = 0;
- if (dx || dy) /* shifted graphic */
+ if (dx || dy) // shifted graphic
{
- if (x < BX1) /* object enters playfield from the left */
+ if (x < BX1) // object enters playfield from the left
{
x = BX1;
width = dx;
cx = TILEX - dx;
dx = 0;
}
- else if (x > BX2) /* object enters playfield from the right */
+ else if (x > BX2) // object enters playfield from the right
{
x = BX2;
width = -dx;
dx = TILEX + dx;
}
- else if (x == BX1 && dx < 0) /* object leaves playfield to the left */
+ else if (x == BX1 && dx < 0) // object leaves playfield to the left
{
width += dx;
cx = -dx;
dx = 0;
}
- else if (x == BX2 && dx > 0) /* object leaves playfield to the right */
+ else if (x == BX2 && dx > 0) // object leaves playfield to the right
width -= dx;
- else if (dx) /* general horizontal movement */
+ else if (dx) // general horizontal movement
MarkTileDirty(x + SIGN(dx), y);
- if (y < BY1) /* object enters playfield from the top */
+ if (y < BY1) // object enters playfield from the top
{
- if (cut_mode == CUT_BELOW) /* object completely above top border */
+ if (cut_mode == CUT_BELOW) // object completely above top border
return;
y = BY1;
cy = TILEY - dy;
dy = 0;
}
- else if (y > BY2) /* object enters playfield from the bottom */
+ else if (y > BY2) // object enters playfield from the bottom
{
y = BY2;
height = -dy;
dy = TILEY + dy;
}
- else if (y == BY1 && dy < 0) /* object leaves playfield to the top */
+ else if (y == BY1 && dy < 0) // object leaves playfield to the top
{
height += dy;
cy = -dy;
}
else if (dy > 0 && cut_mode == CUT_ABOVE)
{
- if (y == BY2) /* object completely above bottom border */
+ if (y == BY2) // object completely above bottom border
return;
height = dy;
cy = TILEY - dy;
dy = TILEY;
MarkTileDirty(x, y + 1);
- } /* object leaves playfield to the bottom */
+ } // object leaves playfield to the bottom
else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
height -= dy;
- else if (dy) /* general vertical movement */
+ else if (dy) // general vertical movement
MarkTileDirty(x, y + SIGN(dy));
}
}
}
-inline static void DrawGraphicShiftedDouble(int x, int y, int dx, int dy,
- int graphic, int frame,
- int cut_mode, int mask_mode)
+static void DrawGraphicShiftedDouble(int x, int y, int dx, int dy,
+ int graphic, int frame,
+ int cut_mode, int mask_mode)
{
Bitmap *src_bitmap;
int src_x, src_y;
int x2 = x + SIGN(dx);
int y2 = y + SIGN(dy);
- /* movement with two-tile animations must be sync'ed with movement position,
- not with current GfxFrame (which can be higher when using slow movement) */
+ // movement with two-tile animations must be sync'ed with movement position,
+ // not with current GfxFrame (which can be higher when using slow movement)
int anim_pos = (dx ? ABS(dx) : ABS(dy));
int anim_frames = graphic_info[graphic].anim_frames;
- /* (we also need anim_delay here for movement animations with less frames) */
+ // (we also need anim_delay here for movement animations with less frames)
int anim_delay = graphic_info[graphic].anim_delay;
int sync_frame = anim_pos * anim_frames * anim_delay / TILESIZE;
- boolean draw_start_tile = (cut_mode != CUT_ABOVE); /* only for falling! */
- boolean draw_end_tile = (cut_mode != CUT_BELOW); /* only for falling! */
+ boolean draw_start_tile = (cut_mode != CUT_ABOVE); // only for falling!
+ boolean draw_end_tile = (cut_mode != CUT_BELOW); // only for falling!
- /* re-calculate animation frame for two-tile movement animation */
+ // re-calculate animation frame for two-tile movement animation
frame = getGraphicAnimationFrame(graphic, sync_frame);
- /* check if movement start graphic inside screen area and should be drawn */
+ // check if movement start graphic inside screen area and should be drawn
if (draw_start_tile && IN_SCR_FIELD(x1, y1))
{
getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, TRUE);
MarkTileDirty(x1, y1);
}
- /* check if movement end graphic inside screen area and should be drawn */
+ // check if movement end graphic inside screen area and should be drawn
if (draw_end_tile && IN_SCR_FIELD(x2, y2))
{
getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE);
return;
}
- if (graphic_info[graphic].double_movement) /* EM style movement images */
+ if (graphic_info[graphic].double_movement) // EM style movement images
DrawGraphicShiftedDouble(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
else
DrawGraphicShiftedNormal(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
}
-void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy, int graphic,
- int frame, int cut_mode)
+static void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy,
+ int graphic, int frame, int cut_mode)
{
DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, USE_MASKING);
}
graphic = el_act_dir2img(element, GfxAction[lx][ly], GfxDir[lx][ly]);
frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
- /* do not use double (EM style) movement graphic when not moving */
+ // do not use double (EM style) movement graphic when not moving
if (graphic_info[graphic].double_movement && !dx && !dy)
{
graphic = el_act_dir2img(element, ACTION_DEFAULT, GfxDir[lx][ly]);
frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
}
}
- else /* border element */
+ else // border element
{
graphic = el2img(element);
frame = getGraphicAnimationFrame(graphic, -1);
DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
}
-/* !!! implementation of quicksand is totally broken !!! */
+// !!! implementation of quicksand is totally broken !!!
#define IS_CRUMBLED_TILE(x, y, e) \
(GFX_CRUMBLED(e) && (!IN_LEV_FIELD(x, y) || \
!IS_MOVING(x, y) || \
int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
BorderElement);
- /* check if neighbour field is of same crumble type */
+ // check if neighbour field is of same crumble type
boolean same = (IS_CRUMBLED_TILE(xx, yy, element) &&
graphic_info[graphic].class ==
graphic_info[el_act2crm(element, ACTION_DEFAULT)].class);
- /* return if check prevents inner corner */
+ // return if check prevents inner corner
if (same == (dxx == dx && dyy == dy))
return;
}
- /* if we reach this point, we have an inner corner */
+ // if we reach this point, we have an inner corner
getGraphicSource(graphic, 1, &src_bitmap, &src_x, &src_y);
getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
- /* draw simple, sloppy, non-corner-accurate crumbled border */
+ // draw simple, sloppy, non-corner-accurate crumbled border
width = (dir == 1 || dir == 2 ? crumbled_border_size_var : TILESIZE_VAR);
height = (dir == 0 || dir == 3 ? crumbled_border_size_var : TILESIZE_VAR);
FX + sx * TILEX_VAR + cx,
FY + sy * TILEY_VAR + cy);
- /* (remaining middle border part must be at least as big as corner part) */
+ // (remaining middle border part must be at least as big as corner part)
if (!(graphic_info[graphic].style & STYLE_ACCURATE_BORDERS) ||
crumbled_border_size_var >= TILESIZE_VAR / 3)
return;
- /* correct corners of crumbled border, if needed */
+ // correct corners of crumbled border, if needed
for (i = -1; i <= 1; i += 2)
{
int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
BorderElement);
- /* check if neighbour field is of same crumble type */
+ // check if neighbour field is of same crumble type
if (IS_CRUMBLED_TILE(xx, yy, element) &&
graphic_info[graphic].class ==
graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
{
- /* no crumbled corner, but continued crumbled border */
+ // no crumbled corner, but continued crumbled border
int c1 = (dir == 2 || dir == 3 ? crumbled_border_pos_var : 0);
int c2 = (i == 1 ? crumbled_border_pos_var : 0);
element = TILE_GFX_ELEMENT(x, y);
- if (IS_CRUMBLED_TILE(x, y, element)) /* crumble field itself */
+ if (IS_CRUMBLED_TILE(x, y, element)) // crumble field itself
{
if (!IN_SCR_FIELD(sx, sy))
return;
- /* crumble field borders towards direct neighbour fields */
+ // crumble field borders towards direct neighbour fields
for (i = 0; i < 4; i++)
{
int xx = x + xy[i][0];
element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
BorderElement);
- /* check if neighbour field is of same crumble type */
+ // check if neighbour field is of same crumble type
if (IS_CRUMBLED_TILE(xx, yy, element) &&
graphic_info[graphic].class ==
graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
DrawLevelFieldCrumbledBorders(x, y, graphic, frame, i);
}
- /* crumble inner field corners towards corner neighbour fields */
+ // crumble inner field corners towards corner neighbour fields
if ((graphic_info[graphic].style & STYLE_INNER_CORNERS) &&
graphic_info[graphic].anim_frames == 2)
{
MarkTileDirty(sx, sy);
}
- else /* center field is not crumbled -- crumble neighbour fields */
+ else // center field is not crumbled -- crumble neighbour fields
{
- /* crumble field borders of direct neighbour fields */
+ // crumble field borders of direct neighbour fields
for (i = 0; i < 4; i++)
{
int xx = x + xy[i][0];
MarkTileDirty(sxx, syy);
}
- /* crumble inner field corners of corner neighbour fields */
+ // crumble inner field corners of corner neighbour fields
for (i = 0; i < 4; i++)
{
int dx = (i & 1 ? +1 : -1);
};
int i;
- /* crumble direct neighbour fields (required for field borders) */
+ // crumble direct neighbour fields (required for field borders)
for (i = 0; i < 4; i++)
{
int xx = x + xy[i][0];
DrawLevelField(xx, yy);
}
- /* crumble corner neighbour fields (required for inner field corners) */
+ // crumble corner neighbour fields (required for inner field corners)
for (i = 0; i < 4; i++)
{
int dx = (i & 1 ? +1 : -1);
element, tilesize, el2edimg, masked, element_bits_draw);
}
-void DrawSizedWall_MM(int dst_x, int dst_y, int element, int tilesize,
- int (*el2img_function)(int))
+static void DrawSizedWall_MM(int dst_x, int dst_y, int element, int tilesize,
+ int (*el2img_function)(int))
{
DrawSizedWallExt_MM(dst_x, dst_y, element, tilesize, el2img_function, FALSE,
0x000f);
}
-void DrawSizedElementExt(int x, int y, int element, int tilesize,
- boolean masked)
+static void DrawSizedElementExt(int x, int y, int element, int tilesize,
+ boolean masked)
{
if (IS_MM_WALL(element))
{
DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
}
-void DrawEnvelopeBackgroundTiles(int graphic, int startx, int starty,
- int x, int y, int xsize, int ysize,
- int tile_width, int tile_height)
+static void DrawEnvelopeBackgroundTiles(int graphic, int startx, int starty,
+ int x, int y, int xsize, int ysize,
+ int tile_width, int tile_height)
{
Bitmap *src_bitmap;
int src_x, src_y;
dst_x, dst_y);
}
-void DrawEnvelopeBackground(int graphic, int startx, int starty,
- int x, int y, int xsize, int ysize, int font_nr)
+static void DrawEnvelopeBackground(int graphic, int startx, int starty,
+ int x, int y, int xsize, int ysize,
+ int font_nr)
{
int font_width = getFontWidth(font_nr);
int font_height = getFontHeight(font_nr);
font_width, font_height);
}
-void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
+static void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
{
int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
Bitmap *src_bitmap = graphic_info[graphic].bitmap;
SkipUntilDelayReached(&anim_delay, anim_delay_value, &i, last_frame);
}
+
+ ClearAutoRepeatKeyEvents();
}
void ShowEnvelope(int envelope_nr)
int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
- game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
+ game.envelope_active = TRUE; // needed for RedrawPlayfield() events
PlayMenuSoundStereo(sound_opening, SOUND_MIDDLE);
setRequestPositionExt(x, y, request.width, request.height, add_border_size);
}
-void DrawEnvelopeRequest(char *text)
+static void DrawEnvelopeRequest(char *text)
{
char *text_final = text;
char *text_door_style = NULL;
x, y, x_steps, y_steps,
tile_size, tile_size);
- /* force DOOR font inside door area */
+ // force DOOR font inside door area
SetFontStatus(GAME_MODE_PSEUDO_DOOR);
DrawTextBuffer(sx + sx_offset, sy + sy_offset, text_final, font_nr,
free(text_door_style);
}
-void AnimateEnvelopeRequest(int anim_mode, int action)
+static void AnimateEnvelopeRequest(int anim_mode, int action)
{
int graphic = IMG_BACKGROUND_REQUEST;
boolean draw_masked = graphic_info[graphic].draw_masked;
SkipUntilDelayReached(&anim_delay, anim_delay_value, &i, last_frame);
}
+
+ ClearAutoRepeatKeyEvents();
}
-void ShowEnvelopeRequest(char *text, unsigned int req_state, int action)
+static void ShowEnvelopeRequest(char *text, unsigned int req_state, int action)
{
int graphic = IMG_BACKGROUND_REQUEST;
int sound_opening = SND_REQUEST_OPENING;
int sound_closing = SND_REQUEST_CLOSING;
- int anim_mode_1 = request.anim_mode; /* (higher priority) */
- int anim_mode_2 = graphic_info[graphic].anim_mode; /* (lower priority) */
+ int anim_mode_1 = request.anim_mode; // (higher priority)
+ int anim_mode_2 = graphic_info[graphic].anim_mode; // (lower priority)
int anim_mode = (anim_mode_1 != ANIM_DEFAULT ? anim_mode_1 : anim_mode_2);
int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
DrawEnvelopeRequest(text);
}
- game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
+ game.envelope_active = TRUE; // needed for RedrawPlayfield() events
if (action == ACTION_OPENING)
{
SetDrawtoField(DRAW_TO_FIELDBUFFER);
}
-void DrawPreviewElement(int dst_x, int dst_y, int element, int tilesize)
+static void DrawPreviewElement(int dst_x, int dst_y, int element, int tilesize)
{
if (IS_MM_WALL(element))
{
DrawPreviewLevelInfo(MICROLABEL_LEVEL_NAME);
DrawPreviewLevelInfo(MICROLABEL_LEVEL_AUTHOR);
- /* initialize delay counters */
+ // initialize delay counters
DelayReached(&scroll_delay, 0);
DelayReached(&label_delay, 0);
return;
}
- /* scroll preview level, if needed */
+ // scroll preview level, if needed
if (preview.anim_mode != ANIM_NONE &&
(level_xsize > preview.xsize || level_ysize > preview.ysize) &&
DelayReached(&scroll_delay, scroll_delay_value))
DrawPreviewLevelPlayfield(from_x, from_y);
}
- /* !!! THIS ALL SUCKS -- SHOULD BE CLEANLY REWRITTEN !!! */
- /* redraw micro level label, if needed */
+ // !!! THIS ALL SUCKS -- SHOULD BE CLEANLY REWRITTEN !!!
+ // redraw micro level label, if needed
if (!strEqual(level.name, NAMELESS_LEVEL_NAME) &&
!strEqual(level.author, ANONYMOUS_NAME) &&
!strEqual(level.author, leveldir_current->name) &&
}
}
-void DrawPreviewLevelInitial()
+static void DrawPreviewPlayers(void)
+{
+ if (game_status != GAME_MODE_MAIN)
+ return;
+
+ if (!network.enabled && !setup.team_mode)
+ return;
+
+ boolean player_found[MAX_PLAYERS];
+ int num_players = 0;
+ int i, x, y;
+
+ for (i = 0; i < MAX_PLAYERS; i++)
+ player_found[i] = FALSE;
+
+ // check which players can be found in the level (simple approach)
+ for (x = 0; x < lev_fieldx; x++)
+ {
+ for (y = 0; y < lev_fieldy; y++)
+ {
+ int element = level.field[x][y];
+
+ if (ELEM_IS_PLAYER(element))
+ {
+ int player_nr = GET_PLAYER_NR(element);
+
+ player_nr = MIN(MAX(0, player_nr), MAX_PLAYERS - 1);
+
+ if (!player_found[player_nr])
+ num_players++;
+
+ player_found[player_nr] = TRUE;
+ }
+ }
+ }
+
+ struct TextPosInfo *pos = &menu.main.preview_players;
+ int tile_size = pos->tile_size;
+ int border_size = pos->border_size;
+ int player_xoffset_raw = (pos->vertical ? 0 : tile_size + border_size);
+ int player_yoffset_raw = (pos->vertical ? tile_size + border_size : 0);
+ int player_xoffset = (pos->xoffset != -1 ? pos->xoffset : player_xoffset_raw);
+ int player_yoffset = (pos->yoffset != -1 ? pos->yoffset : player_yoffset_raw);
+ int max_players_width = (MAX_PLAYERS - 1) * player_xoffset + tile_size;
+ int max_players_height = (MAX_PLAYERS - 1) * player_yoffset + tile_size;
+ int all_players_width = (num_players - 1) * player_xoffset + tile_size;
+ int all_players_height = (num_players - 1) * player_yoffset + tile_size;
+ int max_xpos = SX + ALIGNED_XPOS(pos->x, max_players_width, pos->align);
+ int max_ypos = SY + ALIGNED_YPOS(pos->y, max_players_height, pos->valign);
+ int xpos = SX + ALIGNED_XPOS(pos->x, all_players_width, pos->align);
+ int ypos = SY + ALIGNED_YPOS(pos->y, all_players_height, pos->valign);
+
+ // clear area in which the players will be drawn
+ ClearRectangleOnBackground(drawto, max_xpos, max_ypos,
+ max_players_width, max_players_height);
+
+ // only draw players if level is suited for team mode
+ if (num_players < 2)
+ return;
+
+ // draw all players that were found in the level
+ for (i = 0; i < MAX_PLAYERS; i++)
+ {
+ if (player_found[i])
+ {
+ int graphic = el2img(EL_PLAYER_1 + i);
+
+ DrawSizedGraphicThruMaskExt(drawto, xpos, ypos, graphic, 0, tile_size);
+
+ xpos += player_xoffset;
+ ypos += player_yoffset;
+ }
+ }
+}
+
+void DrawPreviewLevelInitial(void)
{
DrawPreviewLevelExt(TRUE);
+ DrawPreviewPlayers();
}
-void DrawPreviewLevelAnimation()
+void DrawPreviewLevelAnimation(void)
{
DrawPreviewLevelExt(FALSE);
}
-inline static void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
- int graphic, int sync_frame,
- int mask_mode)
+static void DrawNetworkPlayer(int x, int y, int player_nr, int tile_size,
+ int border_size, int font_nr)
+{
+ int graphic = el2img(EL_PLAYER_1 + player_nr);
+ int font_height = getFontHeight(font_nr);
+ int player_height = MAX(tile_size, font_height);
+ int xoffset_text = tile_size + border_size;
+ int yoffset_text = (player_height - font_height) / 2;
+ int yoffset_graphic = (player_height - tile_size) / 2;
+ char *player_name = getNetworkPlayerName(player_nr + 1);
+
+ DrawSizedGraphicThruMaskExt(drawto, x, y + yoffset_graphic, graphic, 0,
+ tile_size);
+ DrawText(x + xoffset_text, y + yoffset_text, player_name, font_nr);
+}
+
+static void DrawNetworkPlayersExt(boolean force)
+{
+ if (game_status != GAME_MODE_MAIN)
+ return;
+
+ if (!network.connected && !force)
+ return;
+
+ int num_players = 0;
+ int i;
+
+ for (i = 0; i < MAX_PLAYERS; i++)
+ if (stored_player[i].connected_network)
+ num_players++;
+
+ struct TextPosInfo *pos = &menu.main.network_players;
+ int tile_size = pos->tile_size;
+ int border_size = pos->border_size;
+ int xoffset_text = tile_size + border_size;
+ int font_nr = pos->font;
+ int font_width = getFontWidth(font_nr);
+ int font_height = getFontHeight(font_nr);
+ int player_height = MAX(tile_size, font_height);
+ int player_yoffset = player_height + border_size;
+ int max_players_width = xoffset_text + MAX_PLAYER_NAME_LEN * font_width;
+ int max_players_height = MAX_PLAYERS * player_yoffset - border_size;
+ int all_players_height = num_players * player_yoffset - border_size;
+ int max_xpos = SX + ALIGNED_XPOS(pos->x, max_players_width, pos->align);
+ int max_ypos = SY + ALIGNED_YPOS(pos->y, max_players_height, pos->valign);
+ int ypos = SY + ALIGNED_YPOS(pos->y, all_players_height, pos->valign);
+
+ ClearRectangleOnBackground(drawto, max_xpos, max_ypos,
+ max_players_width, max_players_height);
+
+ // first draw local network player ...
+ for (i = 0; i < MAX_PLAYERS; i++)
+ {
+ if (stored_player[i].connected_network &&
+ stored_player[i].connected_locally)
+ {
+ char *player_name = getNetworkPlayerName(i + 1);
+ int player_width = xoffset_text + getTextWidth(player_name, font_nr);
+ int xpos = SX + ALIGNED_XPOS(pos->x, player_width, pos->align);
+
+ DrawNetworkPlayer(xpos, ypos, i, tile_size, border_size, font_nr);
+
+ ypos += player_yoffset;
+ }
+ }
+
+ // ... then draw all other network players
+ for (i = 0; i < MAX_PLAYERS; i++)
+ {
+ if (stored_player[i].connected_network &&
+ !stored_player[i].connected_locally)
+ {
+ char *player_name = getNetworkPlayerName(i + 1);
+ int player_width = xoffset_text + getTextWidth(player_name, font_nr);
+ int xpos = SX + ALIGNED_XPOS(pos->x, player_width, pos->align);
+
+ DrawNetworkPlayer(xpos, ypos, i, tile_size, border_size, font_nr);
+
+ ypos += player_yoffset;
+ }
+ }
+}
+
+void DrawNetworkPlayers(void)
+{
+ DrawNetworkPlayersExt(FALSE);
+}
+
+void ClearNetworkPlayers(void)
+{
+ DrawNetworkPlayersExt(TRUE);
+}
+
+static void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
+ int graphic, int sync_frame,
+ int mask_mode)
{
int frame = getGraphicAnimationFrame(graphic, sync_frame);
DrawFixedGraphicExt(dst_bitmap, x, y, graphic, frame);
}
-inline static void DrawGraphicAnimation(int x, int y, int graphic)
+static void DrawGraphicAnimation(int x, int y, int graphic)
{
int lx = LEVELX(x), ly = LEVELY(y);
{
if (player->use_murphy)
{
- /* this works only because currently only one player can be "murphy" ... */
+ // this works only because currently only one player can be "murphy" ...
static int last_horizontal_dir = MV_LEFT;
int graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
last_horizontal_dir = move_dir;
- if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
+ if (graphic == IMG_SP_MURPHY) // undefined => use special graphic
{
int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
g1->anim_mode == g2->anim_mode);
}
-void DrawAllPlayers()
+void DrawAllPlayers(void)
{
int i;
int last_player_frame = player->Frame;
int frame = 0;
- /* GfxElement[][] is set to the element the player is digging or collecting;
- remove also for off-screen player if the player is not moving anymore */
+ // GfxElement[][] is set to the element the player is digging or collecting;
+ // remove also for off-screen player if the player is not moving anymore
if (IN_LEV_FIELD(jx, jy) && !player_is_moving)
GfxElement[jx][jy] = EL_UNDEFINED;
InitPlayerGfxAnimation(player, action, move_dir);
- /* ----------------------------------------------------------------------- */
- /* draw things in the field the player is leaving, if needed */
- /* ----------------------------------------------------------------------- */
+ // --------------------------------------------------------------------------
+ // draw things in the field the player is leaving, if needed
+ // --------------------------------------------------------------------------
if (player->is_moving)
{
if (!IN_SCR_FIELD(sx, sy))
return;
- /* ----------------------------------------------------------------------- */
- /* draw things behind the player, if needed */
- /* ----------------------------------------------------------------------- */
+ // --------------------------------------------------------------------------
+ // draw things behind the player, if needed
+ // --------------------------------------------------------------------------
if (Back[jx][jy])
DrawLevelElement(jx, jy, Back[jx][jy]);
{
GfxElement[jx][jy] = EL_UNDEFINED;
- /* make sure that pushed elements are drawn with correct frame rate */
+ // make sure that pushed elements are drawn with correct frame rate
graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
if (player->is_pushing && player->is_moving && !IS_ANIM_MODE_CE(graphic))
}
#if !DRAW_PLAYER_OVER_PUSHED_ELEMENT
- /* ----------------------------------------------------------------------- */
- /* draw player himself */
- /* ----------------------------------------------------------------------- */
+ // -----------------------------------------------------------------------
+ // draw player himself
+ // -----------------------------------------------------------------------
graphic = getPlayerGraphic(player, move_dir);
- /* in the case of changed player action or direction, prevent the current
- animation frame from being restarted for identical animations */
+ // in the case of changed player action or direction, prevent the current
+ // animation frame from being restarted for identical animations
if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
player->Frame = last_player_frame;
}
#endif
- /* ----------------------------------------------------------------------- */
- /* draw things the player is pushing, if needed */
- /* ----------------------------------------------------------------------- */
+ // --------------------------------------------------------------------------
+ // draw things the player is pushing, if needed
+ // --------------------------------------------------------------------------
if (player->is_pushing && player->is_moving)
{
int sync_frame;
int frame;
- if (!IS_MOVING(jx, jy)) /* push movement already finished */
+ if (!IS_MOVING(jx, jy)) // push movement already finished
{
element = Feld[next_jx][next_jy];
gfx_frame = GfxFrame[next_jx][next_jy];
sync_frame = (IS_ANIM_MODE_CE(graphic) ? gfx_frame : player->StepFrame);
frame = getGraphicAnimationFrame(graphic, sync_frame);
- /* draw background element under pushed element (like the Sokoban field) */
+ // draw background element under pushed element (like the Sokoban field)
if (game.use_masked_pushing && IS_MOVING(jx, jy))
{
- /* this allows transparent pushing animation over non-black background */
+ // this allows transparent pushing animation over non-black background
if (Back[jx][jy])
DrawLevelElement(jx, jy, Back[jx][jy]);
DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
#if 1
- /* do not draw (EM style) pushing animation when pushing is finished */
- /* (two-tile animations usually do not contain start and end frame) */
+ // do not draw (EM style) pushing animation when pushing is finished
+ // (two-tile animations usually do not contain start and end frame)
if (graphic_info[graphic].double_movement && !IS_MOVING(jx, jy))
DrawLevelElement(next_jx, next_jy, Feld[next_jx][next_jy]);
else
DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
#else
- /* masked drawing is needed for EMC style (double) movement graphics */
- /* !!! (ONLY WHEN DRAWING PUSHED ELEMENT OVER THE PLAYER) !!! */
+ // masked drawing is needed for EMC style (double) movement graphics
+ // !!! (ONLY WHEN DRAWING PUSHED ELEMENT OVER THE PLAYER) !!!
DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
#endif
}
#if DRAW_PLAYER_OVER_PUSHED_ELEMENT
- /* ----------------------------------------------------------------------- */
- /* draw player himself */
- /* ----------------------------------------------------------------------- */
+ // -----------------------------------------------------------------------
+ // draw player himself
+ // -----------------------------------------------------------------------
graphic = getPlayerGraphic(player, move_dir);
- /* in the case of changed player action or direction, prevent the current
- animation frame from being restarted for identical animations */
+ // in the case of changed player action or direction, prevent the current
+ // animation frame from being restarted for identical animations
if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
player->Frame = last_player_frame;
}
#endif
- /* ----------------------------------------------------------------------- */
- /* draw things in front of player (active dynamite or dynabombs) */
- /* ----------------------------------------------------------------------- */
+ // --------------------------------------------------------------------------
+ // draw things in front of player (active dynamite or dynabombs)
+ // --------------------------------------------------------------------------
if (IS_ACTIVE_BOMB(element))
{
DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
}
- /* ----------------------------------------------------------------------- */
- /* draw elements the player is just walking/passing through/under */
- /* ----------------------------------------------------------------------- */
+ // --------------------------------------------------------------------------
+ // draw elements the player is just walking/passing through/under
+ // --------------------------------------------------------------------------
if (player_is_moving)
{
- /* handle the field the player is leaving ... */
+ // handle the field the player is leaving ...
if (IS_ACCESSIBLE_INSIDE(last_element))
DrawLevelField(last_jx, last_jy);
else if (IS_ACCESSIBLE_UNDER(last_element))
DrawLevelFieldThruMask(last_jx, last_jy);
}
- /* do not redraw accessible elements if the player is just pushing them */
+ // do not redraw accessible elements if the player is just pushing them
if (!player_is_moving || !player->is_pushing)
{
- /* ... and the field the player is entering */
+ // ... and the field the player is entering
if (IS_ACCESSIBLE_INSIDE(element))
DrawLevelField(jx, jy);
else if (IS_ACCESSIBLE_UNDER(element))
MarkTileDirty(sx, sy);
}
-/* ------------------------------------------------------------------------- */
+// ----------------------------------------------------------------------------
-void WaitForEventToContinue()
+void WaitForEventToContinue(void)
{
boolean still_wait = TRUE;
if (program.headless)
return;
- /* simulate releasing mouse button over last gadget, if still pressed */
+ // simulate releasing mouse button over last gadget, if still pressed
if (button_status)
HandleGadgets(-1, -1, 0);
{
switch (event.type)
{
- case EVENT_BUTTONPRESS:
+ case EVENT_BUTTONRELEASE:
case EVENT_KEYPRESS:
#if defined(TARGET_SDL2)
case SDL_CONTROLLERBUTTONDOWN:
static int RequestHandleEvents(unsigned int req_state)
{
- boolean level_solved = (game_status == GAME_MODE_PLAYING &&
- local_player->LevelSolved_GameEnd);
+ boolean game_just_ended = (game_status == GAME_MODE_PLAYING &&
+ checkGameEnded());
int width = request.width;
int height = request.height;
int sx, sy;
int result;
+ // when showing request dialog after game ended, deactivate game panel
+ if (game_just_ended)
+ game.panel.active = FALSE;
+
+ game.request_active = TRUE;
+
setRequestPosition(&sx, &sy, FALSE);
button_status = MB_RELEASED;
while (result < 0)
{
- if (level_solved)
+ if (game_just_ended)
{
- /* the MM game engine does not use a special (scrollable) field buffer */
+ // the MM game engine does not use a special (scrollable) field buffer
if (level.game_engine_type != GAME_ENGINE_TYPE_MM)
SetDrawtoField(DRAW_TO_FIELDBUFFER);
if (global.use_envelope_request)
{
- /* copy current state of request area to middle of playfield area */
+ // copy current state of request area to middle of playfield area
BlitBitmap(bitmap_db_store_2, drawto, sx, sy, width, height, sx, sy);
}
}
button_status = MB_RELEASED;
}
- /* this sets 'request_gadget_id' */
+ // this sets 'request_gadget_id'
HandleGadgets(mx, my, button_status);
switch (request_gadget_id)
break;
case KSYM_Return:
+ case KSYM_y:
#if defined(TARGET_SDL2)
+ case KSYM_Y:
case KSYM_Select:
case KSYM_Menu:
#if defined(KSYM_Rewind)
- case KSYM_Rewind: /* for Amazon Fire TV remote */
+ case KSYM_Rewind: // for Amazon Fire TV remote
#endif
#endif
result = 1;
break;
case KSYM_Escape:
+ case KSYM_n:
#if defined(TARGET_SDL2)
+ case KSYM_N:
case KSYM_Back:
#if defined(KSYM_FastForward)
- case KSYM_FastForward: /* for Amazon Fire TV remote */
+ case KSYM_FastForward: // for Amazon Fire TV remote
#endif
#endif
result = 0;
}
if (req_state & REQ_PLAYER)
- result = 0;
+ {
+ int old_player_nr = setup.network_player_nr;
+
+ if (result != -1)
+ result = old_player_nr + 1;
+
+ switch (key)
+ {
+ case KSYM_space:
+ result = old_player_nr + 1;
+ break;
+
+ case KSYM_Up:
+ case KSYM_1:
+ result = 1;
+ break;
+
+ case KSYM_Right:
+ case KSYM_2:
+ result = 2;
+ break;
+
+ case KSYM_Down:
+ case KSYM_3:
+ result = 3;
+ break;
+
+ case KSYM_Left:
+ case KSYM_4:
+ result = 4;
+ break;
+
+ default:
+ break;
+ }
+ }
break;
}
case SDL_CONTROLLER_BUTTON_A:
case SDL_CONTROLLER_BUTTON_X:
case SDL_CONTROLLER_BUTTON_LEFTSHOULDER:
+ case SDL_CONTROLLER_BUTTON_LEFTSTICK:
result = 1;
break;
case SDL_CONTROLLER_BUTTON_B:
case SDL_CONTROLLER_BUTTON_Y:
case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER:
+ case SDL_CONTROLLER_BUTTON_RIGHTSTICK:
case SDL_CONTROLLER_BUTTON_BACK:
result = 0;
break;
}
if (req_state & REQ_PLAYER)
- result = 0;
+ {
+ int old_player_nr = setup.network_player_nr;
+
+ if (result != -1)
+ result = old_player_nr + 1;
+
+ switch (event.cbutton.button)
+ {
+ case SDL_CONTROLLER_BUTTON_DPAD_UP:
+ case SDL_CONTROLLER_BUTTON_Y:
+ result = 1;
+ break;
+
+ case SDL_CONTROLLER_BUTTON_DPAD_RIGHT:
+ case SDL_CONTROLLER_BUTTON_B:
+ result = 2;
+ break;
+
+ case SDL_CONTROLLER_BUTTON_DPAD_DOWN:
+ case SDL_CONTROLLER_BUTTON_A:
+ result = 3;
+ break;
+
+ case SDL_CONTROLLER_BUTTON_DPAD_LEFT:
+ case SDL_CONTROLLER_BUTTON_X:
+ result = 4;
+ break;
+
+ default:
+ break;
+ }
+ }
break;
else if (joy & JOY_BUTTON_2)
result = 0;
}
+ else if (AnyJoystick())
+ {
+ int joy = AnyJoystick();
- if (level_solved)
+ if (req_state & REQ_PLAYER)
+ {
+ if (joy & JOY_UP)
+ result = 1;
+ else if (joy & JOY_RIGHT)
+ result = 2;
+ else if (joy & JOY_DOWN)
+ result = 3;
+ else if (joy & JOY_LEFT)
+ result = 4;
+ }
+ }
+
+ if (game_just_ended)
{
if (global.use_envelope_request)
{
- /* copy back current state of pressed buttons inside request area */
+ // copy back current state of pressed buttons inside request area
BlitBitmap(drawto, bitmap_db_store_2, sx, sy, width, height, sx, sy);
}
}
BackToFront();
}
+ game.request_active = FALSE;
+
return result;
}
int result;
int ty;
- if (maxWordLengthInString(text) > MAX_REQUEST_LINE_FONT1_LEN)
+ if (maxWordLengthInRequestString(text) > MAX_REQUEST_LINE_FONT1_LEN)
{
max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
font_nr = FONT_TEXT_1;
if (game_status == GAME_MODE_PLAYING)
BlitScreenToBitmap(backbuffer);
- /* disable deactivated drawing when quick-loading level tape recording */
+ // disable deactivated drawing when quick-loading level tape recording
if (tape.playing && tape.deactivate_display)
TapeDeactivateDisplayOff(TRUE);
SetMouseCursor(CURSOR_DEFAULT);
-#if defined(NETWORK_AVALIABLE)
- /* pause network game while waiting for request to answer */
- if (options.network &&
+ // pause network game while waiting for request to answer
+ if (network.enabled &&
game_status == GAME_MODE_PLAYING &&
+ !AllPlayersGone &&
req_state & REQUEST_WAIT_FOR_INPUT)
SendToServer_PausePlaying();
-#endif
old_door_state = GetDoorState();
- /* simulate releasing mouse button over last gadget, if still pressed */
+ // simulate releasing mouse button over last gadget, if still pressed
if (button_status)
HandleGadgets(-1, -1, 0);
UnmapAllGadgets();
- /* draw released gadget before proceeding */
+ // draw released gadget before proceeding
// BackToFront();
if (old_door_state & DOOR_OPEN_1)
{
CloseDoor(DOOR_CLOSE_1);
- /* save old door content */
+ // save old door content
BlitBitmap(bitmap_db_door_1, bitmap_db_door_1,
0 * DXSIZE, 0, DXSIZE, DYSIZE, 1 * DXSIZE, 0);
}
SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
- /* clear door drawing field */
+ // clear door drawing field
DrawBackground(DX, DY, DXSIZE, DYSIZE);
- /* force DOOR font inside door area */
+ // force DOOR font inside door area
SetFontStatus(GAME_MODE_PSEUDO_DOOR);
- /* write text for request */
+ // write text for request
for (text_ptr = text, ty = 0; ty < MAX_REQUEST_LINES; ty++)
{
char text_line[max_request_line_len + 1];
MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
}
- /* copy request gadgets to door backbuffer */
+ // copy request gadgets to door backbuffer
BlitBitmap(drawto, bitmap_db_door_1, DX, DY, DXSIZE, DYSIZE, 0, 0);
OpenDoor(DOOR_OPEN_1);
SetDrawBackgroundMask(REDRAW_FIELD);
}
-#if defined(NETWORK_AVALIABLE)
- /* continue network game after request */
- if (options.network &&
+ // continue network game after request
+ if (network.enabled &&
game_status == GAME_MODE_PLAYING &&
+ !AllPlayersGone &&
req_state & REQUEST_WAIT_FOR_INPUT)
SendToServer_ContinuePlaying();
-#endif
- /* restore deactivated drawing when quick-loading level tape recording */
+ // restore deactivated drawing when quick-loading level tape recording
if (tape.playing && tape.deactivate_display)
TapeDeactivateDisplayOn();
if (game_status == GAME_MODE_PLAYING)
BlitScreenToBitmap(backbuffer);
- /* disable deactivated drawing when quick-loading level tape recording */
+ // disable deactivated drawing when quick-loading level tape recording
if (tape.playing && tape.deactivate_display)
TapeDeactivateDisplayOff(TRUE);
SetMouseCursor(CURSOR_DEFAULT);
-#if defined(NETWORK_AVALIABLE)
- /* pause network game while waiting for request to answer */
- if (options.network &&
+ // pause network game while waiting for request to answer
+ if (network.enabled &&
game_status == GAME_MODE_PLAYING &&
+ !AllPlayersGone &&
req_state & REQUEST_WAIT_FOR_INPUT)
SendToServer_PausePlaying();
-#endif
- /* simulate releasing mouse button over last gadget, if still pressed */
+ // simulate releasing mouse button over last gadget, if still pressed
if (button_status)
HandleGadgets(-1, -1, 0);
// SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
// SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
- /* clear door drawing field */
+ // clear door drawing field
// DrawBackground(DX, DY, DXSIZE, DYSIZE);
ShowEnvelopeRequest(text, req_state, ACTION_OPENING);
SetDrawBackgroundMask(REDRAW_FIELD);
}
-#if defined(NETWORK_AVALIABLE)
- /* continue network game after request */
- if (options.network &&
+ // continue network game after request
+ if (network.enabled &&
game_status == GAME_MODE_PLAYING &&
+ !AllPlayersGone &&
req_state & REQUEST_WAIT_FOR_INPUT)
SendToServer_ContinuePlaying();
-#endif
- /* restore deactivated drawing when quick-loading level tape recording */
+ // restore deactivated drawing when quick-loading level tape recording
if (tape.playing && tape.deactivate_display)
TapeDeactivateDisplayOn();
return compare_result;
}
-void InitGraphicCompatibilityInfo_Doors()
+void InitGraphicCompatibilityInfo_Doors(void)
{
struct
{
struct Rect *door_rect = &door_rect_list[door_index];
boolean door_gfx_redefined = FALSE;
- /* check if any door part graphic definitions have been redefined */
+ // check if any door part graphic definitions have been redefined
for (j = 0; door_part_controls[j].door_token != -1; j++)
{
door_gfx_redefined = TRUE;
}
- /* check for old-style door graphic/animation modifications */
+ // check for old-style door graphic/animation modifications
if (!door_gfx_redefined)
{
struct GraphicInfo *g_part_2 = &graphic_info[part_2];
int num_door_steps, num_panel_steps;
- /* remove door part graphics other than the two default wings */
+ // remove door part graphics other than the two default wings
for (j = 0; door_part_controls[j].door_token != -1; j++)
{
g->bitmap = NULL;
}
- /* set graphics and screen positions of the default wings */
+ // set graphics and screen positions of the default wings
g_part_1->width = door_rect->width;
g_part_1->height = door_rect->height;
door->part_2.y += door_rect->height - door->height;
}
- /* set animation delays for the default wings and panels */
+ // set animation delays for the default wings and panels
door->part_1.step_delay = door->step_delay;
door->part_2.step_delay = door->step_delay;
door->panel.step_delay = door->step_delay;
- /* set animation draw order for the default wings */
+ // set animation draw order for the default wings
- door->part_1.sort_priority = 2; /* draw left wing over ... */
- door->part_2.sort_priority = 1; /* ... right wing */
+ door->part_1.sort_priority = 2; // draw left wing over ...
+ door->part_2.sort_priority = 1; // ... right wing
- /* set animation draw offset for the default wings */
+ // set animation draw offset for the default wings
if (door->anim_mode & ANIM_HORIZONTAL)
{
num_door_steps = g_part_1->height / door->step_offset;
}
- /* set animation draw offset for the default panels */
+ // set animation draw offset for the default panels
if (door->step_offset > 1)
{
}
}
-void InitDoors()
+void InitDoors(void)
{
int i;
struct DoorPartControlInfo *dpc = &door_part_controls[i];
struct DoorPartOrderInfo *dpo = &door_part_order[i];
- /* initialize "start_step_opening" and "start_step_closing", if needed */
+ // initialize "start_step_opening" and "start_step_closing", if needed
if (dpc->pos->start_step_opening == 0 &&
dpc->pos->start_step_closing == 0)
{
dpc->pos->start_step_closing = dpc->pos->start_step;
}
- /* fill structure for door part draw order (sorted below) */
+ // fill structure for door part draw order (sorted below)
dpo->nr = i;
dpo->sort_priority = dpc->pos->sort_priority;
}
- /* sort door part controls according to sort_priority and graphic number */
+ // sort door part controls according to sort_priority and graphic number
qsort(door_part_order, MAX_DOOR_PARTS,
sizeof(struct DoorPartOrderInfo), compareDoorPartOrderInfo);
}
return MoveDoor(door_state);
}
-unsigned int GetDoorState()
+unsigned int GetDoorState(void)
{
return MoveDoor(DOOR_GET_STATE);
}
return MoveDoor(door_state | DOOR_SET_STATE);
}
-int euclid(int a, int b)
+static int euclid(int a, int b)
{
return (b ? euclid(b, a % b) : a);
}
door_state &= ~DOOR_CLOSE_ALL;
}
- if (game_status == GAME_MODE_EDITOR)
+ if (game_status == GAME_MODE_EDITOR && !(door_state & DOOR_FORCE_ANIM))
door_state |= DOOR_NO_DELAY;
if (door_state & DOOR_ACTION)
}
else
{
- /* opening door sound has priority over simultaneously closing door */
+ // opening door sound has priority over simultaneously closing door
if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
{
PlayMenuSoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
current_move_delay += max_step_delay;
- /* prevent OS (Windows) from complaining about program not responding */
+ // prevent OS (Windows) from complaining about program not responding
CheckQuitEvent();
}
if (door_part_done_all)
break;
}
+
+ if (!(door_state & DOOR_NO_DELAY))
+ {
+ // wait for specified door action post delay
+ if (door_state & DOOR_ACTION_1 && door_state & DOOR_ACTION_2)
+ door_delay_value = MAX(door_1.post_delay, door_2.post_delay);
+ else if (door_state & DOOR_ACTION_1)
+ door_delay_value = door_1.post_delay;
+ else if (door_state & DOOR_ACTION_2)
+ door_delay_value = door_2.post_delay;
+
+ while (!DelayReached(&door_delay, door_delay_value))
+ BackToFront();
+ }
}
if (door_state & DOOR_ACTION_1)
DrawMaskedBorder(REDRAW_DOOR_1);
DrawMaskedBorder(REDRAW_DOOR_2);
+ ClearAutoRepeatKeyEvents();
+
return (door1 | door2);
}
-static boolean useSpecialEditorDoor()
+static boolean useSpecialEditorDoor(void)
{
int graphic = IMG_GLOBAL_BORDER_EDITOR;
boolean redefined = getImageListEntryFromImageID(graphic)->redefined;
return TRUE;
}
-void DrawSpecialEditorDoor()
+void DrawSpecialEditorDoor(void)
{
struct GraphicInfo *gfx1 = &graphic_info[IMG_DOOR_2_TOP_BORDER_CORRECTION];
int top_border_width = gfx1->width;
if (!useSpecialEditorDoor())
return;
- /* draw bigger level editor toolbox window */
+ // draw bigger level editor toolbox window
BlitBitmap(gfx1->bitmap, drawto, gfx1->src_x, gfx1->src_y,
top_border_width, top_border_height, ex, ey - top_border_height);
BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto, ex, vy,
redraw_mask |= REDRAW_ALL;
}
-void UndrawSpecialEditorDoor()
+void UndrawSpecialEditorDoor(void)
{
struct GraphicInfo *gfx1 = &graphic_info[IMG_DOOR_2_TOP_BORDER_CORRECTION];
int top_border_width = gfx1->width;
if (!useSpecialEditorDoor())
return;
- /* draw normal tape recorder window */
+ // draw normal tape recorder window
if (graphic_info[IMG_GLOBAL_BORDER].bitmap)
{
BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
}
-/* ---------- new tool button stuff ---------------------------------------- */
+// ---------- new tool button stuff -------------------------------------------
static struct
{
}
};
-void CreateToolButtons()
+void CreateToolButtons(void)
{
int i;
for (i = 0; i < NUM_TOOL_BUTTONS; i++)
{
- struct GraphicInfo *gfx = &graphic_info[toolbutton_info[i].graphic];
+ int graphic = toolbutton_info[i].graphic;
+ struct GraphicInfo *gfx = &graphic_info[graphic];
struct TextPosInfo *pos = toolbutton_info[i].pos;
struct GadgetInfo *gi;
Bitmap *deco_bitmap = None;
int gd_y = gfx->src_y;
int gd_xp = gfx->src_x + gfx->pressed_xoffset;
int gd_yp = gfx->src_y + gfx->pressed_yoffset;
+ int x = pos->x;
+ int y = pos->y;
int id = i;
if (global.use_envelope_request)
+ {
setRequestPosition(&dx, &dy, TRUE);
+ // check if request buttons are outside of envelope and fix, if needed
+ if (x < 0 || x + gfx->width > request.width ||
+ y < 0 || y + gfx->height > request.height)
+ {
+ if (id == TOOL_CTRL_ID_YES)
+ {
+ x = 0;
+ y = request.height - 2 * request.border_size - gfx->height;
+ }
+ else if (id == TOOL_CTRL_ID_NO)
+ {
+ x = request.width - 2 * request.border_size - gfx->width;
+ y = request.height - 2 * request.border_size - gfx->height;
+ }
+ else if (id == TOOL_CTRL_ID_CONFIRM)
+ {
+ x = (request.width - 2 * request.border_size - gfx->width) / 2;
+ y = request.height - 2 * request.border_size - gfx->height;
+ }
+ else if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
+ {
+ int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
+
+ x = (request.width - 2 * request.border_size - gfx->width) / 2;
+ y = request.height - 2 * request.border_size - gfx->height * 2;
+
+ x += (player_nr == 3 ? -1 : player_nr == 1 ? +1 : 0) * gfx->width;
+ y += (player_nr == 0 ? -1 : player_nr == 2 ? +1 : 0) * gfx->height;
+ }
+ }
+ }
+
if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
{
int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
}
gi = CreateGadget(GDI_CUSTOM_ID, id,
+ GDI_IMAGE_ID, graphic,
GDI_INFO_TEXT, toolbutton_info[i].infotext,
- GDI_X, dx + GDI_ACTIVE_POS(pos->x),
- GDI_Y, dy + GDI_ACTIVE_POS(pos->y),
+ GDI_X, dx + x,
+ GDI_Y, dy + y,
GDI_WIDTH, gfx->width,
GDI_HEIGHT, gfx->height,
GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
}
}
-void FreeToolButtons()
+void FreeToolButtons(void)
{
int i;
FreeGadget(tool_gadget[i]);
}
-static void UnmapToolButtons()
+static void UnmapToolButtons(void)
{
int i;
static struct Mapping_EM_to_RND_object
{
int element_em;
- boolean is_rnd_to_em_mapping; /* unique mapping EM <-> RND */
- boolean is_backside; /* backside of moving element */
+ boolean is_rnd_to_em_mapping; // unique mapping EM <-> RND
+ boolean is_backside; // backside of moving element
int element_rnd;
int action;
Xbomb_force_w, FALSE, FALSE,
EL_BOMB, -1, MV_BIT_LEFT
},
-#endif /* EM_ENGINE_BAD_ROLL */
+#endif // EM_ENGINE_BAD_ROLL
{
Xstone, TRUE, FALSE,
{
int i;
- /* return "Xalpha_quest" for all undefined elements in mapping array */
+ // return "Xalpha_quest" for all undefined elements in mapping array
for (i = 0; i < NUM_FILE_ELEMENTS; i++)
mapping_RND_to_EM[i] = Xalpha_quest;
{
int i;
- /* return "EL_UNKNOWN" for all undefined elements in mapping array */
+ // return "EL_UNKNOWN" for all undefined elements in mapping array
for (i = 0; i < TILE_MAX; i++)
mapping_EM_to_RND[i] = EL_UNKNOWN;
int map_element_RND_to_SP(int element_rnd)
{
- int element_sp = 0x20; /* map unknown elements to yellow "hardware" */
+ int element_sp = 0x20; // map unknown elements to yellow "hardware"
if (element_rnd >= EL_SP_START &&
element_rnd <= EL_SP_END)
int map_action_MM_to_RND(int action_mm)
{
- /* all MM actions are defined to exactly match their RND counterparts */
+ // all MM actions are defined to exactly match their RND counterparts
return action_mm;
}
int el_act_dir2img(int element, int action, int direction)
{
element = GFX_ELEMENT(element);
- direction = MV_DIR_TO_BIT(direction); /* default: MV_NONE => MV_DOWN */
+ direction = MV_DIR_TO_BIT(direction); // default: MV_NONE => MV_DOWN
- /* direction_graphic[][] == graphic[] for undefined direction graphics */
+ // direction_graphic[][] == graphic[] for undefined direction graphics
return element_info[element].direction_graphic[action][direction];
}
static int el_act_dir2crm(int element, int action, int direction)
{
element = GFX_ELEMENT(element);
- direction = MV_DIR_TO_BIT(direction); /* default: MV_NONE => MV_DOWN */
+ direction = MV_DIR_TO_BIT(direction); // default: MV_NONE => MV_DOWN
- /* direction_graphic[][] == graphic[] for undefined direction graphics */
+ // direction_graphic[][] == graphic[] for undefined direction graphics
return element_info[element].direction_crumbled[action][direction];
}
return getBeltSwitchElementFromBeltNrAndBeltDirNr(belt_nr, belt_dir_nr);
}
-boolean getTeamMode_EM()
+boolean getTeamMode_EM(void)
{
- return game.team_mode;
+ return game.team_mode || network_playing;
}
int getGameFrameDelay_EM(int native_em_game_frame_delay)
static struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
static struct Mapping_EM_to_RND_player player_mapping[MAX_PLAYERS][SPR_MAX];
-inline static int get_effective_element_EM(int tile, int frame_em)
+static int get_effective_element_EM(int tile, int frame_em)
{
int element = object_mapping[tile].element_rnd;
int action = object_mapping[tile].action;
return element;
}
}
- else /* frame_em == 7 */
+ else // frame_em == 7
{
switch (tile)
{
}
}
-inline static boolean check_linear_animation_EM(int tile)
+static boolean check_linear_animation_EM(int tile)
{
switch (tile)
{
return FALSE;
}
-inline static void set_crumbled_graphics_EM(struct GraphicInfo_EM *g_em,
- boolean has_crumbled_graphics,
- int crumbled, int sync_frame)
+static void set_crumbled_graphics_EM(struct GraphicInfo_EM *g_em,
+ boolean has_crumbled_graphics,
+ int crumbled, int sync_frame)
{
- /* if element can be crumbled, but certain action graphics are just empty
- space (like instantly snapping sand to empty space in 1 frame), do not
- treat these empty space graphics as crumbled graphics in EMC engine */
+ // if element can be crumbled, but certain action graphics are just empty
+ // space (like instantly snapping sand to empty space in 1 frame), do not
+ // treat these empty space graphics as crumbled graphics in EMC engine
if (crumbled == IMG_EMPTY_SPACE)
has_crumbled_graphics = FALSE;
}
}
+#if 0
void ResetGfxAnimation_EM(int x, int y, int tile)
{
GfxFrame[x][y] = 0;
}
+#endif
void SetGfxAnimation_EM(struct GraphicInfo_EM *g_em,
int tile, int frame_em, int x, int y)
action == ACTION_FILLING ||
action == ACTION_EMPTYING);
- /* special case: graphic uses "2nd movement tile" and has defined
- 7 frames for movement animation (or less) => use default graphic
- for last (8th) frame which ends the movement animation */
+ // special case: graphic uses "2nd movement tile" and has defined
+ // 7 frames for movement animation (or less) => use default graphic
+ // for last (8th) frame which ends the movement animation
if (g->double_movement && g->anim_frames < 8 && frame_em == 7)
{
- action = ACTION_DEFAULT; /* (keep action_* unchanged for now) */
+ action = ACTION_DEFAULT; // (keep action_* unchanged for now)
graphic = (direction == MV_NONE ?
el_act2img(effective_element, action) :
el_act_dir2img(effective_element, action, direction));
GfxFrame[x][y]++;
#if 1
- /* !!! TEST !!! NEW !!! DOES NOT WORK RIGHT YET !!! */
+ // !!! TEST !!! NEW !!! DOES NOT WORK RIGHT YET !!!
if (g->double_movement && frame_em == 0)
GfxFrame[x][y] = 0;
#endif
{
GfxFrame[x][y]++;
- /* special case: animation for Xsand_stonesand_quickout_1/2 twice as fast */
+ // special case: animation for Xsand_stonesand_quickout_1/2 twice as fast
if (tile == Xsand_stonesand_quickout_1 ||
tile == Xsand_stonesand_quickout_2)
GfxFrame[x][y]++;
else if (IN_FIELD(x, y, MAX_LEV_FIELDX, MAX_LEV_FIELDY))
sync_frame = GfxFrame[x][y];
else
- sync_frame = 0; /* playfield border (pseudo steel) */
+ sync_frame = 0; // playfield border (pseudo steel)
SetRandomAnimationValue(x, y);
struct GraphicInfo *g = &graphic_info[graphic];
int sync_frame;
- /* special case: graphic uses "2nd movement tile" and has defined
- 7 frames for movement animation (or less) => use default graphic
- for last (8th) frame which ends the movement animation */
+ // special case: graphic uses "2nd movement tile" and has defined
+ // 7 frames for movement animation (or less) => use default graphic
+ // for last (8th) frame which ends the movement animation
if (g->double_movement && g->anim_frames < 8 && frame_em == 7)
{
effective_action = ACTION_DEFAULT;
else if (IN_FIELD(x, y, MAX_LEV_FIELDX, MAX_LEV_FIELDY))
sync_frame = GfxFrame[x][y];
else
- sync_frame = 0; /* playfield border (pseudo steel) */
+ sync_frame = 0; // playfield border (pseudo steel)
SetRandomAnimationValue(x, y);
getGraphicSourceExt(graphic, frame, &g_em->bitmap, &g_em->src_x, &g_em->src_y,
g->double_movement && is_backside);
- /* (updating the "crumbled" graphic definitions is probably not really needed,
- as animations for crumbled graphics can't be longer than one EMC cycle) */
+ // (updating the "crumbled" graphic definitions is probably not really needed,
+ // as animations for crumbled graphics can't be longer than one EMC cycle)
set_crumbled_graphics_EM(g_em, has_crumbled_graphics, crumbled,
sync_frame);
}
if (graphic_info_em_object[0][0].bitmap == NULL)
{
- /* EM graphics not yet initialized in em_open_all() */
+ // EM graphics not yet initialized in em_open_all()
return;
}
printf("::: [4 errors can be ignored (1 x 'bomb', 3 x 'em_dynamite']\n");
#endif
- /* always start with reliable default values */
+ // always start with reliable default values
for (i = 0; i < TILE_MAX; i++)
{
object_mapping[i].element_rnd = EL_UNKNOWN;
object_mapping[i].direction = MV_NONE;
}
- /* always start with reliable default values */
+ // always start with reliable default values
for (p = 0; p < MAX_PLAYERS; p++)
{
for (i = 0; i < SPR_MAX; i++)
struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
Bitmap *src_bitmap;
int src_x, src_y;
- /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
+ // ensure to get symmetric 3-frame, 2-delay animations as used in EM
boolean special_animation = (action != ACTION_DEFAULT &&
g->anim_frames == 3 &&
g->anim_delay == 2 &&
i == Xsand_stoneout_2 ? j + 8 : j) + 1;
int step = (is_backside ? step_frame : num_steps - step_frame);
- if (is_backside) /* tile where movement starts */
+ if (is_backside) // tile where movement starts
{
if (dx < 0 || dy < 0)
{
g_em->dst_offset_y = cy * step;
}
}
- else /* tile where movement ends */
+ else // tile where movement ends
{
if (dx < 0 || dy < 0)
{
g_em->height = TILEY - cy * step;
}
- /* create unique graphic identifier to decide if tile must be redrawn */
+ // create unique graphic identifier to decide if tile must be redrawn
/* bit 31 - 16 (16 bit): EM style graphic
bit 15 - 12 ( 4 bit): EM style frame
bit 11 - 6 ( 6 bit): graphic width
#if DEBUG_EM_GFX
- /* skip check for EMC elements not contained in original EMC artwork */
+ // skip check for EMC elements not contained in original EMC artwork
if (element == EL_EMC_FAKE_ACID)
continue;
direction == MV_RIGHT ? (is_backside? Yspring_eB: Yspring_e) :
Xspring);
- /* no separate animation for "smashed by rock" -- use rock instead */
+ // no separate animation for "smashed by rock" -- use rock instead
struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
struct GraphicInfo_EM *g_xx = &graphic_info_em_object[e][7 - j];
#if DEBUG_EM_GFX
- /* skip check for EMC elements not contained in original EMC artwork */
+ // skip check for EMC elements not contained in original EMC artwork
if (element == EL_PLAYER_3 ||
element == EL_PLAYER_4)
continue;
#endif
}
-void CheckSaveEngineSnapshot_EM(byte action[MAX_PLAYERS], int frame,
- boolean any_player_moving,
- boolean any_player_snapping,
- boolean any_player_dropping)
+static void CheckSaveEngineSnapshot_EM(byte action[MAX_PLAYERS], int frame,
+ boolean any_player_moving,
+ boolean any_player_snapping,
+ boolean any_player_dropping)
{
if (frame == 0 && !any_player_dropping)
{
}
}
-void CheckSaveEngineSnapshot_SP(boolean murphy_is_waiting,
- boolean murphy_is_dropping)
+static void CheckSaveEngineSnapshot_SP(boolean murphy_is_waiting,
+ boolean murphy_is_dropping)
{
if (murphy_is_waiting)
{
}
}
+static void CheckSaveEngineSnapshot_MM(boolean element_clicked,
+ boolean button_released)
+{
+ if (button_released)
+ {
+ if (game.snapshot.mode == SNAPSHOT_MODE_EVERY_MOVE)
+ CheckSaveEngineSnapshotToList();
+ }
+ else if (element_clicked)
+ {
+ if (game.snapshot.mode != SNAPSHOT_MODE_EVERY_MOVE)
+ CheckSaveEngineSnapshotToList();
+
+ game.snapshot.changed_action = TRUE;
+ }
+}
+
void CheckSingleStepMode_EM(byte action[MAX_PLAYERS], int frame,
boolean any_player_moving,
boolean any_player_snapping,
CheckSaveEngineSnapshot_SP(murphy_is_waiting, murphy_is_dropping);
}
+void CheckSingleStepMode_MM(boolean element_clicked,
+ boolean button_released)
+{
+ if (tape.single_step && tape.recording && !tape.pausing)
+ if (button_released)
+ TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
+
+ CheckSaveEngineSnapshot_MM(element_clicked, button_released);
+}
+
void getGraphicSource_SP(struct GraphicInfo_SP *g_sp,
int graphic, int sync_frame, int x, int y)
{
PlaySound(sound);
}
-void PlayMenuSound()
+void PlayMenuSound(void)
{
PlayMenuSoundExt(menu.sound[game_status]);
}
PlaySoundLoop(sound);
}
-void PlayMenuSoundIfLoop()
+void PlayMenuSoundIfLoop(void)
{
PlayMenuSoundIfLoopExt(menu.sound[game_status]);
}
if (!setup.sound_music)
return;
- PlayMusic(music);
+ if (IS_LOOP_MUSIC(music))
+ PlayMusicLoop(music);
+ else
+ PlayMusic(music);
}
-void PlayMenuMusic()
+void PlayMenuMusic(void)
{
char *curr_music = getCurrentlyPlayingMusicFilename();
char *next_music = getMusicInfoEntryFilename(menu.music[game_status]);
PlayMenuMusicExt(menu.music[game_status]);
}
-void PlayMenuSoundsAndMusic()
+void PlayMenuSoundsAndMusic(void)
{
PlayMenuSound();
PlayMenuMusic();
}
-static void FadeMenuSounds()
+static void FadeMenuSounds(void)
{
FadeSounds();
}
-static void FadeMenuMusic()
+static void FadeMenuMusic(void)
{
char *curr_music = getCurrentlyPlayingMusicFilename();
char *next_music = getMusicInfoEntryFilename(menu.music[game_status]);
FadeMusic();
}
-void FadeMenuSoundsAndMusic()
+void FadeMenuSoundsAndMusic(void)
{
FadeMenuSounds();
FadeMenuMusic();
}
-void PlaySoundActivating()
+void PlaySoundActivating(void)
{
#if 0
PlaySound(SND_MENU_ITEM_ACTIVATING);
#endif
}
-void PlaySoundSelecting()
+void PlaySoundSelecting(void)
{
#if 0
PlaySound(SND_MENU_ITEM_SELECTING);
#endif
}
-void ToggleFullscreenOrChangeWindowScalingIfNeeded()
+void ToggleFullscreenOrChangeWindowScalingIfNeeded(void)
{
boolean change_fullscreen = (setup.fullscreen !=
video.fullscreen_enabled);
{
SDLSetWindowFullscreen(setup.fullscreen);
- /* set setup value according to successfully changed fullscreen mode */
+ // set setup value according to successfully changed fullscreen mode
setup.fullscreen = video.fullscreen_enabled;
return;
{
Bitmap *tmp_backbuffer = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
- /* save backbuffer content which gets lost when toggling fullscreen mode */
+ // save backbuffer content which gets lost when toggling fullscreen mode
BlitBitmap(backbuffer, tmp_backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
if (change_window_scaling_percent)
{
- /* keep window mode, but change window scaling */
- video.fullscreen_enabled = TRUE; /* force new window scaling */
+ // keep window mode, but change window scaling
+ video.fullscreen_enabled = TRUE; // force new window scaling
}
- /* toggle fullscreen */
+ // toggle fullscreen
ChangeVideoModeIfNeeded(setup.fullscreen);
- /* set setup value according to successfully changed fullscreen mode */
+ // set setup value according to successfully changed fullscreen mode
setup.fullscreen = video.fullscreen_enabled;
- /* restore backbuffer content from temporary backbuffer backup bitmap */
+ // restore backbuffer content from temporary backbuffer backup bitmap
BlitBitmap(tmp_backbuffer, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
FreeBitmap(tmp_backbuffer);
- /* update visible window/screen */
+ // update visible window/screen
BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
}
}
-void JoinRectangles(int *x, int *y, int *width, int *height,
- int x2, int y2, int width2, int height2)
+static void JoinRectangles(int *x, int *y, int *width, int *height,
+ int x2, int y2, int width2, int height2)
{
// do not join with "off-screen" rectangle
if (x2 == -1 || y2 == -1)
}
}
-void ResetFontStatus()
+void ResetFontStatus(void)
{
SetFontStatus(-1);
}
-void ChangeViewportPropertiesIfNeeded()
+void SetLevelSetInfo(char *identifier, int level_nr)
+{
+ setString(&levelset.identifier, identifier);
+
+ levelset.level_nr = level_nr;
+}
+
+boolean CheckIfPlayfieldViewportHasChanged(void)
+{
+ // if game status has not changed, playfield viewport has not changed either
+ if (game_status == game_status_last)
+ return FALSE;
+
+ // check if playfield viewport has changed with current game status
+ struct RectWithBorder *vp_playfield = &viewport.playfield[game_status];
+ int new_real_sx = vp_playfield->x;
+ int new_real_sy = vp_playfield->y;
+ int new_full_sxsize = vp_playfield->width;
+ int new_full_sysize = vp_playfield->height;
+
+ return (new_real_sx != REAL_SX ||
+ new_real_sy != REAL_SY ||
+ new_full_sxsize != FULL_SXSIZE ||
+ new_full_sysize != FULL_SYSIZE);
+}
+
+boolean CheckIfGlobalBorderOrPlayfieldViewportHasChanged(void)
+{
+ return (CheckIfGlobalBorderHasChanged() ||
+ CheckIfPlayfieldViewportHasChanged());
+}
+
+void ChangeViewportPropertiesIfNeeded(void)
{
boolean use_mini_tilesize = (level.game_engine_type == GAME_ENGINE_TYPE_MM ?
FALSE : setup.small_game_graphics);
if (new_scr_fieldx != SCR_FIELDX ||
new_scr_fieldy != SCR_FIELDY)
{
- /* this always toggles between MAIN and GAME when using small tile size */
+ // this always toggles between MAIN and GAME when using small tile size
SCR_FIELDX = new_scr_fieldx;
SCR_FIELDY = new_scr_fieldy;