#define IMG_UNDEFINED (-1)
#define IMG_EMPTY IMG_EMPTY_SPACE
#define IMG_SP_EMPTY IMG_SP_EMPTY_SPACE
+#define IMG_EXPLOSION IMG_DEFAULT_EXPLODING
#define IMG_CHAR_START IMG_CHAR_SPACE
#define IMG_CUSTOM_START IMG_CUSTOM_1
#define EP_PUSHABLE 24
/* values for special configurable properties (depending on level settings) */
-#define EP_EM_SLIPPERY_WALL 25
+#define EP_EM_SLIPPERY_WALL 32
/* values for special graphics properties (no effect on game engine) */
-#define EP_CAN_BE_CRUMBLED 26
+#define EP_CAN_BE_CRUMBLED 33
/* values for pre-defined properties */
-#define EP_PLAYER 27
-#define EP_CAN_PASS_MAGIC_WALL 28
-#define EP_SWITCHABLE 29
-#define EP_BD_ELEMENT 30
-#define EP_SP_ELEMENT 31
-#define EP_SB_ELEMENT 32
-#define EP_GEM 33
-#define EP_FOOD_DARK_YAMYAM 34
-#define EP_FOOD_PENGUIN 35
-#define EP_FOOD_PIG 36
-#define EP_HISTORIC_WALL 37
-#define EP_HISTORIC_SOLID 38
-#define EP_CLASSIC_ENEMY 39
-#define EP_BELT 40
-#define EP_BELT_ACTIVE 41
-#define EP_BELT_SWITCH 42
-#define EP_TUBE 43
-#define EP_KEYGATE 44
-#define EP_AMOEBOID 45
-#define EP_AMOEBALIVE 46
-#define EP_HAS_CONTENT 47
-#define EP_ACTIVE_BOMB 48
-#define EP_INACTIVE 49
+#define EP_PLAYER 34
+#define EP_CAN_PASS_MAGIC_WALL 35
+#define EP_SWITCHABLE 36
+#define EP_BD_ELEMENT 37
+#define EP_SP_ELEMENT 38
+#define EP_SB_ELEMENT 39
+#define EP_GEM 40
+#define EP_FOOD_DARK_YAMYAM 41
+#define EP_FOOD_PENGUIN 42
+#define EP_FOOD_PIG 43
+#define EP_HISTORIC_WALL 44
+#define EP_HISTORIC_SOLID 45
+#define EP_CLASSIC_ENEMY 46
+#define EP_BELT 47
+#define EP_BELT_ACTIVE 48
+#define EP_BELT_SWITCH 49
+#define EP_TUBE 50
+#define EP_KEYGATE 51
+#define EP_AMOEBOID 52
+#define EP_AMOEBALIVE 53
+#define EP_HAS_CONTENT 54
+#define EP_ACTIVE_BOMB 55
+#define EP_INACTIVE 56
/* values for derived properties (determined from properties above) */
-#define EP_ACCESSIBLE_OVER 50
-#define EP_ACCESSIBLE_INSIDE 51
-#define EP_ACCESSIBLE_UNDER 52
-#define EP_WALKABLE 53
-#define EP_PASSABLE 54
-#define EP_ACCESSIBLE 55
-#define EP_SNAPPABLE 56
-#define EP_WALL 57
-#define EP_SOLID_FOR_PUSHING 58
-#define EP_DRAGONFIRE_PROOF 59
-#define EP_EXPLOSION_PROOF 60
-#define EP_CAN_SMASH 61
-#define EP_CAN_EXPLODE 62
+#define EP_ACCESSIBLE_OVER 57
+#define EP_ACCESSIBLE_INSIDE 58
+#define EP_ACCESSIBLE_UNDER 59
+#define EP_WALKABLE 60
+#define EP_PASSABLE 61
+#define EP_ACCESSIBLE 62
+#define EP_SNAPPABLE 63
+#define EP_WALL 64
+#define EP_SOLID_FOR_PUSHING 65
+#define EP_DRAGONFIRE_PROOF 66
+#define EP_EXPLOSION_PROOF 67
+#define EP_CAN_SMASH 68
+#define EP_CAN_EXPLODE 69
/* values for internal purpose only (level editor) */
-#define EP_EXPLODE_RESULT 63
-#define EP_WALK_TO_OBJECT 64
-#define EP_DEADLY 65
+#define EP_EXPLODE_RESULT 70
+#define EP_WALK_TO_OBJECT 71
+#define EP_DEADLY 72
-#define NUM_ELEMENT_PROPERTIES 66
+#define NUM_ELEMENT_PROPERTIES 73
#define NUM_EP_BITFIELDS ((NUM_ELEMENT_PROPERTIES + 31) / 32)
#define EP_BITFIELD_BASE 0
/* values for change events for custom elements */
#define CE_DELAY 0
-#define CE_PRESSED_BY_PLAYER 1
-#define CE_TOUCHED_BY_PLAYER 2
+#define CE_TOUCHED_BY_PLAYER 1
+#define CE_PRESSED_BY_PLAYER 2
+#define CE_PUSHED_BY_PLAYER 3
+#define CE_COLLISION 4
+#define CE_IMPACT 5
+#define CE_SMASHED 6
+#define CE_OTHER_IS_TOUCHING 7
+#define CE_OTHER_IS_CHANGING 8
+#define CE_OTHER_IS_EXPLODING 9
+#define CE_OTHER_GETS_TOUCHED 10
+#define CE_OTHER_GETS_PRESSED 11
+#define CE_OTHER_GETS_PUSHED 12
+#define CE_OTHER_GETS_COLLECTED 13
/* values for internal purpose only (level editor) */
-#define CE_BY_PLAYER 3
+#define CE_BY_PLAYER 14
+#define CE_BY_COLLISION 15
+#define CE_BY_OTHER 16
-#define NUM_CHANGE_EVENTS 4
+#define NUM_CHANGE_EVENTS 17
#define CE_BITMASK_DEFAULT 0
(CH_EVENT_VAR(e) |= CH_EVENT_BIT(c)) : \
(CH_EVENT_VAR(e) &= ~CH_EVENT_BIT(c))) : 0)
+/* values for change power for custom elements */
+#define CP_NON_DESTRUCTIVE 0
+#define CP_HALF_DESTRUCTIVE 1
+#define CP_FULL_DESTRUCTIVE 2
+
+/* values for special move patterns (bits 0-3: basic move directions) */
+#define MV_BIT_TOWARDS_PLAYER 4
+#define MV_BIT_AWAY_FROM_PLAYER 5
+#define MV_BIT_ALONG_LEFT_SIDE 6
+#define MV_BIT_ALONG_RIGHT_SIDE 7
+#define MV_BIT_TURNING_LEFT 8
+#define MV_BIT_TURNING_RIGHT 9
+
+/* values for special move patterns for custom elements */
+#define MV_HORIZONTAL (MV_LEFT | MV_RIGHT)
+#define MV_VERTICAL (MV_UP | MV_DOWN)
+#define MV_ALL_DIRECTIONS (MV_HORIZONTAL | MV_VERTICAL)
+#define MV_ANY_DIRECTION (MV_ALL_DIRECTIONS)
+#define MV_TOWARDS_PLAYER (1 << MV_BIT_TOWARDS_PLAYER)
+#define MV_AWAY_FROM_PLAYER (1 << MV_BIT_AWAY_FROM_PLAYER)
+#define MV_ALONG_LEFT_SIDE (1 << MV_BIT_ALONG_LEFT_SIDE)
+#define MV_ALONG_RIGHT_SIDE (1 << MV_BIT_ALONG_RIGHT_SIDE)
+#define MV_TURNING_LEFT (1 << MV_BIT_TURNING_LEFT)
+#define MV_TURNING_RIGHT (1 << MV_BIT_TURNING_RIGHT)
+
+/* values for slippery property for custom elements */
+#define SLIPPERY_ANY_RANDOM 0
+#define SLIPPERY_ANY_LEFT_RIGHT 1
+#define SLIPPERY_ANY_RIGHT_LEFT 2
+#define SLIPPERY_ONLY_LEFT 3
+#define SLIPPERY_ONLY_RIGHT 4
/* macros for configurable properties */
#define IS_DIGGABLE(e) HAS_PROPERTY(e, EP_DIGGABLE)
/* boundaries of arrays etc. */
#define MAX_LEVEL_NAME_LEN 32
#define MAX_LEVEL_AUTHOR_LEN 32
+#define MAX_ELEMENT_NAME_LEN 32
#define MAX_TAPELEN (1000 * 50) /* max. time * framerate */
#define MAX_SCORE_ENTRIES 100
#define MAX_NUM_AMOEBA 100
#define EL_BLOCKED (EL_FIRST_RUNTIME_UNREAL + 0)
#define EL_EXPLOSION (EL_FIRST_RUNTIME_UNREAL + 1)
#define EL_NUT_BREAKING (EL_FIRST_RUNTIME_UNREAL + 2)
-#define EL_ACID_SPLASH_LEFT (EL_FIRST_RUNTIME_UNREAL + 3)
-#define EL_ACID_SPLASH_RIGHT (EL_FIRST_RUNTIME_UNREAL + 4)
-#define EL_AMOEBA_GROWING (EL_FIRST_RUNTIME_UNREAL + 5)
-#define EL_AMOEBA_SHRINKING (EL_FIRST_RUNTIME_UNREAL + 6)
-#define EL_EXPANDABLE_WALL_GROWING (EL_FIRST_RUNTIME_UNREAL + 7)
-#define EL_FLAMES (EL_FIRST_RUNTIME_UNREAL + 8)
-#define EL_PLAYER_IS_LEAVING (EL_FIRST_RUNTIME_UNREAL + 9)
-#define EL_QUICKSAND_FILLING (EL_FIRST_RUNTIME_UNREAL + 10)
-#define EL_MAGIC_WALL_FILLING (EL_FIRST_RUNTIME_UNREAL + 11)
-#define EL_BD_MAGIC_WALL_FILLING (EL_FIRST_RUNTIME_UNREAL + 12)
+#define EL_DIAMOND_BREAKING (EL_FIRST_RUNTIME_UNREAL + 3)
+#define EL_ACID_SPLASH_LEFT (EL_FIRST_RUNTIME_UNREAL + 4)
+#define EL_ACID_SPLASH_RIGHT (EL_FIRST_RUNTIME_UNREAL + 5)
+#define EL_AMOEBA_GROWING (EL_FIRST_RUNTIME_UNREAL + 6)
+#define EL_AMOEBA_SHRINKING (EL_FIRST_RUNTIME_UNREAL + 7)
+#define EL_EXPANDABLE_WALL_GROWING (EL_FIRST_RUNTIME_UNREAL + 8)
+#define EL_FLAMES (EL_FIRST_RUNTIME_UNREAL + 9)
+#define EL_PLAYER_IS_LEAVING (EL_FIRST_RUNTIME_UNREAL + 10)
+#define EL_QUICKSAND_FILLING (EL_FIRST_RUNTIME_UNREAL + 11)
+#define EL_MAGIC_WALL_FILLING (EL_FIRST_RUNTIME_UNREAL + 12)
+#define EL_BD_MAGIC_WALL_FILLING (EL_FIRST_RUNTIME_UNREAL + 13)
/* dummy elements (never used as game elements, only used as graphics) */
-#define EL_FIRST_DUMMY (EL_FIRST_RUNTIME_UNREAL + 13)
+#define EL_FIRST_DUMMY (EL_FIRST_RUNTIME_UNREAL + 14)
#define EL_STEELWALL_TOPLEFT (EL_FIRST_DUMMY + 0)
#define EL_STEELWALL_TOPRIGHT (EL_FIRST_DUMMY + 1)
#define EL_DYNABOMB_ACTIVE (EL_FIRST_DUMMY + 13)
#define EL_SHIELD_NORMAL_ACTIVE (EL_FIRST_DUMMY + 14)
#define EL_SHIELD_DEADLY_ACTIVE (EL_FIRST_DUMMY + 15)
+#define EL_DEFAULT (EL_FIRST_DUMMY + 16)
+#define EL_BD_DEFAULT (EL_FIRST_DUMMY + 17)
+#define EL_SP_DEFAULT (EL_FIRST_DUMMY + 18)
+#define EL_SB_DEFAULT (EL_FIRST_DUMMY + 19)
-#define MAX_NUM_ELEMENTS (EL_FIRST_DUMMY + 16)
+#define MAX_NUM_ELEMENTS (EL_FIRST_DUMMY + 20)
/* values for graphics/sounds action types */
#define ACTION_COLLECTING 6
#define ACTION_DROPPING 7
#define ACTION_PUSHING 8
-#define ACTION_PASSING 9
-#define ACTION_IMPACT 10
-#define ACTION_BREAKING 11
-#define ACTION_ACTIVATING 12
-#define ACTION_DEACTIVATING 13
-#define ACTION_OPENING 14
-#define ACTION_CLOSING 15
-#define ACTION_ATTACKING 16
-#define ACTION_GROWING 17
-#define ACTION_SHRINKING 18
-#define ACTION_ACTIVE 19
-#define ACTION_FILLING 20
-#define ACTION_EMPTYING 21
-#define ACTION_CHANGING 22
-#define ACTION_EXPLODING 23
-#define ACTION_DYING 24
-#define ACTION_OTHER 25
-
-#define NUM_ACTIONS 26
+#define ACTION_WALKING 9
+#define ACTION_PASSING 10
+#define ACTION_IMPACT 11
+#define ACTION_BREAKING 12
+#define ACTION_ACTIVATING 13
+#define ACTION_DEACTIVATING 14
+#define ACTION_OPENING 15
+#define ACTION_CLOSING 16
+#define ACTION_ATTACKING 17
+#define ACTION_GROWING 18
+#define ACTION_SHRINKING 19
+#define ACTION_ACTIVE 20
+#define ACTION_FILLING 21
+#define ACTION_EMPTYING 22
+#define ACTION_CHANGING 23
+#define ACTION_EXPLODING 24
+#define ACTION_DYING 25
+#define ACTION_OTHER 26
+
+#define NUM_ACTIONS 27
/* values for special image configuration suffixes (must match game mode) */
#define GFX_SPECIAL_ARG_MAIN 0
boolean gravity;
boolean em_slippery_gems; /* EM style "gems slip from wall" behaviour */
+ short field[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
+
+ boolean use_custom_template; /* use custom properties from template file */
+
boolean no_level_file;
};
int draw_yoffset_default;
int draw_xoffset[NUM_SPECIAL_GFX_ARGS];
int draw_yoffset[NUM_SPECIAL_GFX_ARGS];
+
+ int list_size_default;
+ int list_size[NUM_SPECIAL_GFX_ARGS];
};
struct DoorInfo
{
unsigned long events; /* bitfield for change events */
+ short target_element; /* target element after change */
+
int delay_fixed; /* added frame delay before changed (fixed) */
int delay_random; /* added frame delay before changed (random) */
int delay_frames; /* either 1 (frames) or 50 (seconds; 50 fps) */
- short successor; /* new custom element after change */
+ short trigger_element; /* custom element triggering change */
+
+ int content[3][3]; /* new elements after extended change */
+ boolean use_content; /* use extended change content */
+ boolean only_complete; /* only use complete content */
+ boolean use_random_change; /* use random value for setting content */
+ int random; /* random value for setting content */
+ int power; /* power of extended change */
+
+ boolean explode; /* explode instead of change */
+
+ /* functions that are called before, while and after the change of an
+ element -- currently only used for non-custom elements */
+ void (*pre_change_function)(int x, int y);
+ void (*change_function)(int x, int y);
+ void (*post_change_function)(int x, int y);
};
struct ElementInfo
char *token_name; /* element token used in config files */
char *class_name; /* element class used in config files */
- char *editor_description; /* short description for level editor */
- char *custom_description; /* custom description for level editor */
+ char *editor_description; /* pre-defined description for level editor */
+ char *custom_description; /* alternative description from config file */
+ char description[MAX_ELEMENT_NAME_LEN + 1]; /* for custom elements */
/* ---------- graphic and sound definitions ---------- */
/* ---------- special element property values ---------- */
- boolean use_template; /* use all properties from template file */
-
- boolean use_gfx_element;
+ boolean use_gfx_element; /* use custom graphic element */
short gfx_element; /* optional custom graphic element */
- int score; /* score for collection, smashing, ... */
+ int score; /* score value for collecting */
+ int gem_count; /* gem count value for collecting */
int push_delay_fixed; /* constant frame delay for pushing */
int push_delay_random; /* additional random frame delay for pushing */
int move_direction_initial; /* initial direction element moves to */
int move_stepsize; /* step size element moves with */
+ int slippery_type; /* how/where other elements slip away */
+
int content[3][3]; /* new elements after explosion */
struct ElementChangeInfo change;
+
+ /* ---------- internal values used in level editor ---------- */
+
+ int access_type; /* walkable or passable */
+ int access_layer; /* accessible over/inside/under */
+ int walk_to_action; /* diggable/collectible/pushable */
+ int smash_targets; /* can smash player/enemies/everything */
+ int deadliness; /* deadly when running/colliding/touching */
+ int consistency; /* indestructible/can explode */
+ int change_player_action; /* touched/pressed/pushed by player */
+ int change_collide_action; /* collision/impact/smashed */
+ int change_other_action; /* various change actions */
+
+ boolean can_explode_by_fire; /* element explodes by fire */
+ boolean can_explode_smashed; /* element explodes when smashed */
+ boolean can_explode_impact; /* element explodes on impact */
};
struct FontInfo
extern int redraw_x1, redraw_y1;
extern short Feld[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
-extern short Ur[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
extern short MovPos[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
extern short MovDir[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
extern short MovDelay[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
+extern short ChangeDelay[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
extern short Store[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
extern short Store2[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
extern short StorePlayer[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
extern short Back[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
extern boolean Stop[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
+extern boolean Pushed[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
+extern boolean Changing[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
extern short JustStopped[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
extern short AmoebaNr[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
extern short AmoebaCnt[MAX_NUM_AMOEBA];
extern int graphics_action_mapping[];
-extern struct LevelInfo level;
+extern struct LevelInfo level, level_template;
extern struct PlayerInfo stored_player[], *local_player;
extern struct HiScore highscore[];
extern struct TapeInfo tape;