ClickOnGadget(level_editor_gadget[id], button);
else if (letter == '.')
ClickOnGadget(level_editor_gadget[GADGET_ID_SINGLE_ITEMS], button);
+ else if (key == XK_space || key == XK_Return)
+ ClickOnGadget(level_editor_gadget[GADGET_ID_TEST], button);
else
for (i=0; i<ED_NUM_CTRL_BUTTONS; i++)
if (letter && letter == control_info[i].shortcut)
{
struct GadgetInfo *gi = (struct GadgetInfo *)ptr;
char infotext[MAX_INFOTEXT_LEN + 1];
- char shortcut[20];
+ char shortcut[MAX_INFOTEXT_LEN + 1];
ClearEditorGadgetInfoText();
if (key)
{
- sprintf(shortcut, " ('%s%c')",
- (key >= 'A' && key <= 'Z' ? "Shift-" :
- gi->custom_id == GADGET_ID_SINGLE_ITEMS ? ".' or '" : ""),
- key);
+ if (gi->custom_id == GADGET_ID_SINGLE_ITEMS) /* special case 1 */
+ sprintf(shortcut, " ('.' or '%c')", key);
+ else if (gi->custom_id == GADGET_ID_TEST) /* special case 2 */
+ sprintf(shortcut, " ('Enter' or 'Shift-%c')", key);
+ else /* normal case */
+ sprintf(shortcut, " ('%s%c')",
+ (key >= 'A' && key <= 'Z' ? "Shift-" : ""), key);
if (strlen(infotext) + strlen(shortcut) <= MAX_INFOTEXT_LEN)
strcat(infotext, shortcut);
if (key_status == KEY_RELEASED)
return;
- if (key == XK_Return && game_status == PLAYING && AllPlayersGone)
+ if ((key == XK_Return || key == XK_space) &&
+ game_status == PLAYING && AllPlayersGone)
{
CloseDoor(DOOR_CLOSE_1);
game_status = MAINMENU;
switch(key)
{
case XK_Return:
+ case XK_space:
if (game_status == MAINMENU)
HandleMainMenu(0,0, 0,0, MB_MENU_CHOICE);
else if (game_status == CHOOSELEVEL)
switch(key)
{
case XK_Return:
+ case XK_space:
game_status = MAINMENU;
DrawMainMenu();
BackToFront();
InitJoysticks();
}
+static int getBeltNrFromElement(int element)
+{
+ return (element < EL_BELT2_LEFT ? 0 :
+ element < EL_BELT3_LEFT ? 1 :
+ element < EL_BELT4_LEFT ? 2 : 3);
+}
+
+static int getBeltNrFromSwitchElement(int element)
+{
+ return (element < EL_BELT2_SWITCH_L ? 0 :
+ element < EL_BELT3_SWITCH_L ? 1 :
+ element < EL_BELT4_SWITCH_L ? 2 : 3);
+}
+
+static int getBeltDirNrFromSwitchElement(int element)
+{
+ static int belt_base_element[4] =
+ {
+ EL_BELT1_SWITCH_L,
+ EL_BELT2_SWITCH_L,
+ EL_BELT3_SWITCH_L,
+ EL_BELT4_SWITCH_L
+ };
+
+ int belt_nr = getBeltNrFromSwitchElement(element);
+ int belt_dir_nr = element - belt_base_element[belt_nr];
+
+ return (belt_dir_nr % 3);
+}
+
+static int getBeltDirFromSwitchElement(int element)
+{
+ static int belt_move_dir[3] =
+ {
+ MV_LEFT,
+ MV_NO_MOVING,
+ MV_RIGHT
+ };
+
+ int belt_dir_nr = getBeltDirNrFromSwitchElement(element);
+
+ return belt_move_dir[belt_dir_nr];
+}
+
static void InitField(int x, int y, boolean init_game)
{
switch (Feld[x][y])
Feld[x][y] = EL_EM_KEY_4;
break;
+ case EL_BELT1_SWITCH_L:
+ case EL_BELT1_SWITCH_M:
+ case EL_BELT1_SWITCH_R:
+ case EL_BELT2_SWITCH_L:
+ case EL_BELT2_SWITCH_M:
+ case EL_BELT2_SWITCH_R:
+ case EL_BELT3_SWITCH_L:
+ case EL_BELT3_SWITCH_M:
+ case EL_BELT3_SWITCH_R:
+ case EL_BELT4_SWITCH_L:
+ case EL_BELT4_SWITCH_M:
+ case EL_BELT4_SWITCH_R:
+ if (init_game)
+ {
+ int belt_nr = getBeltNrFromSwitchElement(Feld[x][y]);
+ int belt_dir = getBeltDirFromSwitchElement(Feld[x][y]);
+ int belt_dir_nr = getBeltDirNrFromSwitchElement(Feld[x][y]);
+
+ if (game.belt_dir_nr[belt_nr] == 3) /* initial value */
+ {
+ game.belt_dir[belt_nr] = belt_dir;
+ game.belt_dir_nr[belt_nr] = belt_dir_nr;
+ }
+ else /* more than one switch -- set it like the first switch */
+ {
+ Feld[x][y] = Feld[x][y] - belt_dir_nr + game.belt_dir_nr[belt_nr];
+ }
+ }
default:
break;
}
game.magic_wall_active = FALSE;
game.magic_wall_time_left = 0;
for (i=0; i<4; i++)
+ {
game.belt_dir[i] = MV_NO_MOVING;
+ game.belt_dir_nr[i] = 3; /* no moving, next switch left */
+ }
for (i=0; i<MAX_NUM_AMOEBA; i++)
AmoebaCnt[i] = AmoebaCnt2[i] = 0;
InitMovingField(x, y, left ? MV_LEFT : MV_RIGHT);
}
}
+ else if (IS_BELT(Feld[x][y+1]))
+ {
+ boolean left_is_free = (x>0 && IS_FREE(x-1, y));
+ boolean right_is_free = (x<lev_fieldx-1 && IS_FREE(x+1, y));
+ int belt_nr = getBeltNrFromElement(Feld[x][y+1]);
+ int belt_dir = game.belt_dir[belt_nr];
+
+ if ((belt_dir == MV_LEFT && left_is_free) ||
+ (belt_dir == MV_RIGHT && right_is_free))
+ InitMovingField(x, y, belt_dir);
+ }
}
else if (CAN_MOVE(element))
{
int dy = (direction == MV_UP ? -1 : direction == MV_DOWN ? +1 : 0);
int horiz_move = (dx!=0);
int newx = x + dx, newy = y + dy;
- int step = (horiz_move ? dx : dy) * TILEX/8;
+ int step = (horiz_move ? dx : dy) * TILEX / 8;
if (element == EL_TROPFEN)
- step/=2;
+ step /= 2;
else if (Store[x][y] == EL_MORAST_VOLL || Store[x][y] == EL_MORAST_LEER)
- step/=4;
+ step /= 4;
+ else if (CAN_FALL(element) && horiz_move &&
+ y < lev_fieldy-1 && IS_BELT(Feld[x][y+1]))
+ step /= 2;
+
#if OLD_GAME_BEHAVIOUR
else if (CAN_FALL(element) && horiz_move && !IS_SP_ELEMENT(element))
step*=2;
}
}
+static void DrawBeltAnimation(int x, int y, int element)
+{
+ int belt_nr = getBeltNrFromElement(element);
+ int belt_dir = game.belt_dir[belt_nr];
+
+ if (belt_dir != MV_NO_MOVING)
+ {
+ int delay = 2;
+ int mode = (belt_dir == MV_LEFT ? ANIM_NORMAL : ANIM_REVERSE);
+ int graphic = el2gfx(element) + (belt_dir == MV_LEFT ? 0 : 7);
+
+ DrawGraphicAnimation(x, y, graphic, 8, delay, mode);
+ }
+}
+
static void PlayerActions(struct PlayerInfo *player, byte player_action)
{
static byte stored_player_action[MAX_PLAYERS];
DrawGraphicAnimation(x, y, GFX2_SP_TERMINAL, 7, 12, ANIM_NORMAL);
else if (element == EL_SP_TERMINAL_ACTIVE)
DrawGraphicAnimation(x, y, GFX2_SP_TERMINAL_ACTIVE, 7, 4, ANIM_NORMAL);
+ else if (IS_BELT(element))
+ DrawBeltAnimation(x, y, element);
if (game.magic_wall_active)
{
EL_BELT3_SWITCH_L,
EL_BELT4_SWITCH_L
};
- static int belt_move_dir[3] =
+ static int belt_move_dir[4] =
{
MV_LEFT,
MV_NO_MOVING,
- MV_RIGHT
+ MV_RIGHT,
+ MV_NO_MOVING,
};
- int belt_nr = (element < EL_BELT2_SWITCH_L ? 0 :
- element < EL_BELT3_SWITCH_L ? 1 :
- element < EL_BELT4_SWITCH_L ? 2 : 3);
- int belt_dir_nr = element - belt_base_element[belt_nr];
- int belt_dir_nr_next = (belt_dir_nr + 1) % 3;
- int belt_dir_next = belt_move_dir[belt_dir_nr_next];
+ int belt_nr = getBeltNrFromSwitchElement(element);
+ int belt_dir_nr = (game.belt_dir_nr[belt_nr] + 1) % 4;
+ int belt_dir = belt_move_dir[belt_dir_nr];
int xx, yy;
if (player->Switching)
return MF_ACTION;
- game.belt_dir[belt_nr] = belt_dir_next;
+ game.belt_dir_nr[belt_nr] = belt_dir_nr;
+ game.belt_dir[belt_nr] = belt_dir;
+
+ if (belt_dir_nr == 3)
+ belt_dir_nr = 1;
+
+ player->Switching = TRUE;
for (yy=0; yy<lev_fieldy; yy++)
{
{
if (IS_BELT_SWITCH(Feld[xx][yy]))
{
- int e = Feld[xx][yy];
- int e_belt_nr = (e < EL_BELT2_SWITCH_L ? 0 :
- e < EL_BELT3_SWITCH_L ? 1 :
- e < EL_BELT4_SWITCH_L ? 2 : 3);
+ int e_belt_nr = getBeltNrFromSwitchElement(Feld[xx][yy]);
if (e_belt_nr == belt_nr)
{
- Feld[xx][yy] = belt_base_element[belt_nr] + belt_dir_nr_next;
+ Feld[xx][yy] = belt_base_element[belt_nr] + belt_dir_nr;
DrawLevelField(xx, yy);
}
}
+ else if (belt_dir == MV_NO_MOVING && IS_BELT(Feld[xx][yy]))
+ {
+ int e_belt_nr = getBeltNrFromElement(Feld[xx][yy]);
+
+ if (e_belt_nr == belt_nr)
+ DrawLevelField(xx, yy); /* set belt to parking position */
+ }
}
}
- player->Switching = TRUE;
-
return MF_ACTION;
}
break;
#define MAX_TAPELEN (1000 * 50) /* max. time * framerate */
#define MAX_LEVDIR_ENTRIES 100
#define MAX_SCORE_ENTRIES 100
-#define MAX_ELEMENTS 512
+#define MAX_ELEMENTS 700 /* 500 static + 200 runtime */
#define MAX_NUM_AMOEBA 100
/* values for elements with content */
boolean magic_wall_active;
int magic_wall_time_left;
int belt_dir[4];
+ int belt_dir_nr[4];
};
struct GlobalInfo
#define MICRO_GFX_PER_LINE 128
#define HEROES_PER_LINE 16
+
#define MINI_SP_STARTX 0
#define MINI_SP_STARTY 352
#define MICRO_SP_STARTX 0
#define MINI_DC_STARTX 256
#define MINI_DC_STARTY 0
-#define MICRO_DC_STARTX 0
-#define MICRO_DC_STARTY 0
+#define MICRO_DC_STARTX 256
+#define MICRO_DC_STARTY 384
#define DC_PER_LINE 8
#define MINI_DC_PER_LINE 8
-#define MICRO_DC_PER_LINE 32
+#define MICRO_DC_PER_LINE 8
#define FONT_CHARS_PER_LINE 16
#define FONT_LINES_PER_FONT 4
/* game elements:
-** 0 - 1000: real elements, stored in level file
-** 1000 - 2000: flag elements, only used at runtime
+** 0 - 499: real elements, stored in level file
+** 500 - 699: flag elements, only used at runtime
*/
/* "real" level elements */
#define EL_LEERRAUM 0
#define EL_SAND_INVISIBLE 315
/* "real" (and therefore drawable) runtime elements */
-#define EL_SIEB_LEER 1000
-#define EL_SIEB2_LEER 1001
-#define EL_SIEB_VOLL 1002
-#define EL_SIEB2_VOLL 1003
-#define EL_SIEB_TOT 1004
-#define EL_SIEB2_TOT 1005
-#define EL_AUSGANG_ACT 1006
-#define EL_SP_TERMINAL_ACTIVE 1007
-#define EL_SP_BUG_ACTIVE 1008
-#define EL_EM_KEY_1 1009
-#define EL_EM_KEY_2 1010
-#define EL_EM_KEY_3 1011
-#define EL_EM_KEY_4 1012
-#define EL_DYNABOMB_ACTIVE_1 1013
-#define EL_DYNABOMB_ACTIVE_2 1014
-#define EL_DYNABOMB_ACTIVE_3 1015
-#define EL_DYNABOMB_ACTIVE_4 1016
+#define EL_SIEB_LEER 500
+#define EL_SIEB2_LEER 501
+#define EL_SIEB_VOLL 502
+#define EL_SIEB2_VOLL 503
+#define EL_SIEB_TOT 504
+#define EL_SIEB2_TOT 505
+#define EL_AUSGANG_ACT 506
+#define EL_SP_TERMINAL_ACTIVE 507
+#define EL_SP_BUG_ACTIVE 508
+#define EL_EM_KEY_1 509
+#define EL_EM_KEY_2 510
+#define EL_EM_KEY_3 511
+#define EL_EM_KEY_4 512
+#define EL_DYNABOMB_ACTIVE_1 513
+#define EL_DYNABOMB_ACTIVE_2 514
+#define EL_DYNABOMB_ACTIVE_3 515
+#define EL_DYNABOMB_ACTIVE_4 516
/* "unreal" (and therefore not drawable) runtime elements */
-#define EL_BLOCKED 2000
-#define EL_EXPLODING 2001
-#define EL_CRACKINGNUT 2002
-#define EL_BLURB_LEFT 2003
-#define EL_BLURB_RIGHT 2004
-#define EL_AMOEBING 2005
-#define EL_MAUERND 2006
-#define EL_BURNING 2007
-#define EL_PLAYER_IS_LEAVING 2008
+#define EL_BLOCKED 600
+#define EL_EXPLODING 601
+#define EL_CRACKINGNUT 602
+#define EL_BLURB_LEFT 603
+#define EL_BLURB_RIGHT 604
+#define EL_AMOEBING 605
+#define EL_MAUERND 606
+#define EL_BURNING 607
+#define EL_PLAYER_IS_LEAVING 608
/* game graphics:
** 0 - 255: graphics from "RocksScreen"
else if ((element == EL_FELSBROCKEN || element == EL_SP_ZONK ||
IS_GEM(element)) && !cut_mode)
{
- if (element == EL_FELSBROCKEN || element == EL_SP_ZONK)
+ if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
{
- if (dir == MV_LEFT)
- graphic += (4 - phase4) % 4;
- else if (dir == MV_RIGHT)
- graphic += phase4;
- else
- graphic += phase2 * 2;
+ if (element == EL_FELSBROCKEN || element == EL_SP_ZONK)
+ {
+ if (dir == MV_LEFT)
+ graphic += (4 - phase4) % 4;
+ else if (dir == MV_RIGHT)
+ graphic += phase4;
+ else
+ graphic += phase2 * 2;
+ }
+ else if (element != EL_SP_INFOTRON)
+ graphic += phase2;
}
- else if (element != EL_SP_INFOTRON)
- graphic += phase2;
}
else if (element == EL_SIEB_LEER || element == EL_SIEB2_LEER ||
element == EL_SIEB_VOLL || element == EL_SIEB2_VOLL)
graphic -= GFX_START_ROCKSSP;
graphic -= ((graphic / SP_PER_LINE) * SP_PER_LINE) / 2;
XCopyArea(display, pix[PIX_SP], drawto, gc,
- MICRO_SP_STARTX + (graphic % MICRO_SP_PER_LINE) *MICRO_TILEX,
- MICRO_SP_STARTY + (graphic / MICRO_SP_PER_LINE) *MICRO_TILEY,
+ MICRO_SP_STARTX + (graphic % MICRO_SP_PER_LINE) * MICRO_TILEX,
+ MICRO_SP_STARTY + (graphic / MICRO_SP_PER_LINE) * MICRO_TILEY,
MICRO_TILEX, MICRO_TILEY, xpos, ypos);
}
else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
{
graphic -= GFX_START_ROCKSDC;
- graphic -= ((graphic / DC_PER_LINE) * DC_PER_LINE) / 2;
XCopyArea(display, pix[PIX_DC], drawto, gc,
- MICRO_DC_STARTX + (graphic % MICRO_DC_PER_LINE) *MICRO_TILEX,
- MICRO_DC_STARTY + (graphic / MICRO_DC_PER_LINE) *MICRO_TILEY,
+ MICRO_DC_STARTX + (graphic % MICRO_DC_PER_LINE) * MICRO_TILEX,
+ MICRO_DC_STARTY + (graphic / MICRO_DC_PER_LINE) * MICRO_TILEY,
MICRO_TILEX, MICRO_TILEY, xpos, ypos);
}
else