+2005-04-24
+ * fixed a delay problem with SDL and too many mouse motion events
+ * added setup option "skip levels" and level skipping functionality
+
2005-03-06
* fixed mapping of obsolete element token names in "editorsetup.conf"
* fixed bug with sound "acid.splashing" treated as a loop sound
-#define COMPILE_DATE_STRING "[2005-04-12 00:03]"
+#define COMPILE_DATE_STRING "[2005-04-23 23:41]"
}
/* skip mouse motion events without pressed button outside level editor */
- if (button_status == MB_RELEASED && game_status != GAME_MODE_EDITOR &&
- game_status != GAME_MODE_PLAYING)
+ if (button_status == MB_RELEASED &&
+ game_status != GAME_MODE_EDITOR && game_status != GAME_MODE_PLAYING)
return 0;
else
return 1;
}
+/* to prevent delay problems, skip mouse motion events if the very next
+ event is also a mouse motion event (and therefore effectively only
+ handling the last of a row of mouse motion events in the event queue) */
+
+boolean SkipPressedMouseMotionEvent(const Event *event)
+{
+ /* nothing to do if the current event is not a mouse motion event */
+ if (event->type != EVENT_MOTIONNOTIFY)
+ return FALSE;
+
+ /* only skip motion events with pressed button outside level editor */
+ if (button_status == MB_RELEASED ||
+ game_status == GAME_MODE_EDITOR || game_status == GAME_MODE_PLAYING)
+ return FALSE;
+
+ if (PendingEvent())
+ {
+ Event next_event;
+
+ PeekEvent(&next_event);
+
+ /* if next event is also a mouse motion event, skip the current one */
+ if (next_event.type == EVENT_MOTIONNOTIFY)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
/* this is only really needed for non-SDL targets to filter unwanted events;
when using SDL with properly installed event filter, this function can be
replaced with a simple "NextEvent()" call, but it doesn't hurt either */
{
while (PendingEvent())
{
+ boolean handle_this_event = FALSE;
+
NextEvent(event);
if (FilterMouseMotionEvents(event))
+ handle_this_event = TRUE;
+
+#if 1
+ if (SkipPressedMouseMotionEvent(event))
+ handle_this_event = FALSE;
+#endif
+
+ if (handle_this_event)
return TRUE;
}
else
button_status = MB_RELEASED;
+#if 0
+ printf("::: button %s\n", event->type == EVENT_BUTTONPRESS ?
+ "pressed" : "released");
+#endif
+
HandleButton(event->x, event->y, button_status);
}
motion_status = TRUE;
+#if 0
+ printf("::: %d, %d\n", event->x, event->y);
+#endif
+
HandleButton(event->x, event->y, button_status);
}
#define SETUP_TOKEN_QUICK_DOORS 10
#define SETUP_TOKEN_TEAM_MODE 11
#define SETUP_TOKEN_HANDICAP 12
-#define SETUP_TOKEN_TIME_LIMIT 13
-#define SETUP_TOKEN_FULLSCREEN 14
-#define SETUP_TOKEN_ASK_ON_ESCAPE 15
-#define SETUP_TOKEN_GRAPHICS_SET 16
-#define SETUP_TOKEN_SOUNDS_SET 17
-#define SETUP_TOKEN_MUSIC_SET 18
-#define SETUP_TOKEN_OVERRIDE_LEVEL_GRAPHICS 19
-#define SETUP_TOKEN_OVERRIDE_LEVEL_SOUNDS 20
-#define SETUP_TOKEN_OVERRIDE_LEVEL_MUSIC 21
-
-#define NUM_GLOBAL_SETUP_TOKENS 22
+#define SETUP_TOKEN_SKIP_LEVELS 13
+#define SETUP_TOKEN_TIME_LIMIT 14
+#define SETUP_TOKEN_FULLSCREEN 15
+#define SETUP_TOKEN_ASK_ON_ESCAPE 16
+#define SETUP_TOKEN_GRAPHICS_SET 17
+#define SETUP_TOKEN_SOUNDS_SET 18
+#define SETUP_TOKEN_MUSIC_SET 19
+#define SETUP_TOKEN_OVERRIDE_LEVEL_GRAPHICS 20
+#define SETUP_TOKEN_OVERRIDE_LEVEL_SOUNDS 21
+#define SETUP_TOKEN_OVERRIDE_LEVEL_MUSIC 22
+
+#define NUM_GLOBAL_SETUP_TOKENS 23
/* editor setup */
#define SETUP_TOKEN_EDITOR_EL_BOULDERDASH 0
{ TYPE_SWITCH, &si.quick_doors, "quick_doors" },
{ TYPE_SWITCH, &si.team_mode, "team_mode" },
{ TYPE_SWITCH, &si.handicap, "handicap" },
+ { TYPE_SWITCH, &si.skip_levels, "skip_levels" },
{ TYPE_SWITCH, &si.time_limit, "time_limit" },
{ TYPE_SWITCH, &si.fullscreen, "fullscreen" },
{ TYPE_SWITCH, &si.ask_on_escape, "ask_on_escape" },
si->quick_doors = FALSE;
si->team_mode = FALSE;
si->handicap = TRUE;
+ si->skip_levels = TRUE;
si->time_limit = TRUE;
si->fullscreen = FALSE;
si->ask_on_escape = TRUE;
{
/* pick sounds to play, if any */
- if (sound_play[SAMPLE_exit] || sound_play[SAMPLE_die])
+ if (sound_play[SAMPLE_exit_open] ||
+ sound_play[SAMPLE_exit_leave] ||
+ sound_play[SAMPLE_die])
sound_play[SAMPLE_boom] = 0; /* no explosions if player goes home */
mix_count = 0;
checked_free(level_dir);
- level_dir = getPath2((node->user_defined ? getUserLevelDir(NULL) :
+ level_dir = getPath2((node->in_user_dir ? getUserLevelDir(NULL) :
options.level_directory), node->fullpath);
return level_dir;
#if 1
printf("subdir == '%s' ['%s', '%s'] [%d])\n",
- node->subdir, node->fullpath, node->basepath, node->user_defined);
+ node->subdir, node->fullpath, node->basepath, node->in_user_dir);
#else
printf("subdir == '%s' (%s) [%s] (%d)\n",
node->subdir, node->name, node->identifier, node->sort_priority);
#define LEVELINFO_TOKEN_FILENAME 15
#define LEVELINFO_TOKEN_FILETYPE 16
#define LEVELINFO_TOKEN_HANDICAP 17
+#define LEVELINFO_TOKEN_SKIP_LEVELS 18
-#define NUM_LEVELINFO_TOKENS 18
+#define NUM_LEVELINFO_TOKENS 19
static LevelDirTree ldi;
{ TYPE_STRING, &ldi.music_set, "music_set" },
{ TYPE_STRING, &ldi.level_filename, "filename" },
{ TYPE_STRING, &ldi.level_filetype, "filetype" },
- { TYPE_BOOLEAN, &ldi.handicap, "handicap" }
+ { TYPE_BOOLEAN, &ldi.handicap, "handicap" },
+ { TYPE_BOOLEAN, &ldi.skip_levels, "skip_levels" }
};
static void setTreeInfoToDefaults(TreeInfo *ldi, int type)
ldi->sort_priority = LEVELCLASS_UNDEFINED; /* default: least priority */
ldi->latest_engine = FALSE; /* default: get from level */
ldi->parent_link = FALSE;
+ ldi->in_user_dir = FALSE;
ldi->user_defined = FALSE;
ldi->color = 0;
ldi->class_desc = NULL;
ldi->handicap_level = 0;
ldi->readonly = TRUE;
ldi->handicap = TRUE;
+ ldi->skip_levels = FALSE;
}
}
ldi->sort_priority = parent->sort_priority;
ldi->latest_engine = parent->latest_engine;
ldi->parent_link = FALSE;
+ ldi->in_user_dir = parent->in_user_dir;
ldi->user_defined = parent->user_defined;
ldi->color = parent->color;
ldi->class_desc = getStringCopy(parent->class_desc);
ldi->handicap_level = 0;
ldi->readonly = TRUE;
ldi->handicap = TRUE;
+ ldi->skip_levels = FALSE;
}
#else
leveldir_new->first_level + leveldir_new->levels - 1;
#if 1
- leveldir_new->user_defined =
+ leveldir_new->in_user_dir =
(strcmp(leveldir_new->basepath, options.level_directory) != 0);
#else
- leveldir_new->user_defined =
+ leveldir_new->in_user_dir =
(leveldir_new->basepath == options.level_directory ? FALSE : TRUE);
#endif
+ leveldir_new->user_defined =
+ (leveldir_new->in_user_dir && IS_LEVELCLASS_PRIVATE(leveldir_new));
+
leveldir_new->color = LEVELCOLOR(leveldir_new);
#if 1
setString(&leveldir_new->class_desc, getLevelClassDescription(leveldir_new));
}
#if 1
- artwork_new->user_defined =
+ artwork_new->in_user_dir =
(strcmp(artwork_new->basepath, OPTIONS_ARTWORK_DIRECTORY(type)) != 0);
#else
- artwork_new->user_defined =
+ artwork_new->in_user_dir =
(artwork_new->basepath == OPTIONS_ARTWORK_DIRECTORY(type) ? FALSE : TRUE);
#endif
/* check for more levels besides the 'levels' field of 'levelinfo.conf' */
- level_directory = getPath2((leveldir_current->user_defined ?
+ level_directory = getPath2((leveldir_current->in_user_dir ?
getUserLevelDir(NULL) :
options.level_directory),
leveldir_current->fullpath);
#endif
}
+inline void PeekEvent(Event *event)
+{
+#if defined(TARGET_SDL)
+ SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_ALLEVENTS);
+#else
+ XPeekEvent(display, event);
+#endif
+}
+
inline Key GetEventKey(KeyEvent *event, boolean with_modifiers)
{
#if defined(TARGET_SDL)
boolean quick_doors;
boolean team_mode;
boolean handicap;
+ boolean skip_levels;
boolean time_limit;
boolean fullscreen;
boolean ask_on_escape;
boolean level_group; /* directory contains more level series directories */
boolean parent_link; /* entry links back to parent directory */
- boolean user_defined; /* user defined levels are stored in home directory */
+ boolean in_user_dir; /* user defined levels are stored in home directory */
+ boolean user_defined; /* levels in user directory and marked as "private" */
boolean readonly; /* readonly levels can not be changed with editor */
boolean handicap; /* level set has no handicap when set to "false" */
+ boolean skip_levels; /* levels can be skipped when set to "true" */
int color; /* color to use on selection screen for this level */
char *class_desc; /* description of level series class */
inline void InitEventFilter(EventFilter);
inline boolean PendingEvent(void);
inline void NextEvent(Event *event);
+inline void PeekEvent(Event *event);
inline Key GetEventKey(KeyEvent *, boolean);
inline KeyMod HandleKeyModState(Key, int);
inline KeyMod GetKeyModState();
if (new_level_nr > leveldir_current->last_level)
new_level_nr = leveldir_current->last_level;
+#if 1
+ if (setup.handicap && new_level_nr > leveldir_current->handicap_level + 1)
+ new_level_nr = leveldir_current->handicap_level;
+
+ if (setup.handicap && new_level_nr > leveldir_current->handicap_level &&
+ leveldir_current->handicap_level < leveldir_current->last_level)
+ {
+ if (setup.skip_levels &&
+ Request("Level still unsolved ! Skip despite handicap ?", REQ_ASK))
+ {
+ leveldir_current->handicap_level++;
+ SaveLevelSetup_SeriesInfo();
+ }
+
+ new_level_nr = leveldir_current->handicap_level;
+ }
+#else
if (setup.handicap && new_level_nr > leveldir_current->handicap_level)
new_level_nr = leveldir_current->handicap_level;
+#endif
if (new_level_nr != old_level_nr &&
DelayReached(&level_delay, GADGET_FRAME_DELAY))
{
{ TYPE_SWITCH, &setup.team_mode, "Team-Mode:" },
{ TYPE_SWITCH, &setup.handicap, "Handicap:" },
+ { TYPE_SWITCH, &setup.skip_levels, "Skip Levels:" },
{ TYPE_SWITCH, &setup.time_limit, "Timelimit:" },
{ TYPE_SWITCH, &setup.autorecord, "Auto-Record:" },
{ TYPE_EMPTY, NULL, "" },