X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Ffiles.c;h=0d4f895c34c050bd381c1df74a63ad641975b1f2;hb=d9b86b7b2ebe0b2be3926656c3bbdcd060ee5811;hp=b11e7a9cfbfb957a8e2989b9cb87aefc4315f6fa;hpb=1e5cae5e3ab889c3bcba80a065c6d7ba1e6d28a2;p=rocksndiamonds.git diff --git a/src/files.c b/src/files.c index b11e7a9c..0d4f895c 100644 --- a/src/files.c +++ b/src/files.c @@ -119,6 +119,10 @@ #define CONF_CONTENTS_ELEMENT(b,c,x,y) ((b[CONF_CONTENT_BYTE_POS(c,x,y)]<< 8)|\ (b[CONF_CONTENT_BYTE_POS(c,x,y) + 1])) +#if 0 +static void LoadLevel_InitPlayfield(struct LevelInfo *, char *); +#endif + static struct LevelInfo li; static struct @@ -286,6 +290,10 @@ static struct EL_PLAYER_4, CONF_VALUE_BOOLEAN_4, &li.use_explosion_element[3], FALSE }, + { + EL_PLAYER_1, CONF_VALUE_INTEGER_1, + &li.initial_player_stepsize, STEPSIZE_NORMAL + }, { EL_EMC_MAGIC_BALL, CONF_VALUE_INTEGER_1, &li.ball_time, 10 @@ -555,7 +563,9 @@ static void setLevelInfoToDefaults(struct LevelInfo *level) level->biomaze[2] = 3; level->biomaze[3] = 3; +#if 0 level->double_speed = FALSE; +#endif level->initial_gravity = FALSE; level->em_slippery_gems = FALSE; level->instant_relocation = FALSE; @@ -712,8 +722,13 @@ static void setLevelInfoToDefaults(struct LevelInfo *level) /* !!! now done in InitElementPropertiesStatic() (see above) !!! */ /* !!! (else properties set there will be overwritten here) !!! */ /* start with no properties at all */ +#if 1 + for (j = 0; j < NUM_EP_BITFIELDS; j++) + ei->properties[j] = EP_BITMASK_DEFAULT; +#else for (j = 0; j < NUM_EP_BITFIELDS; j++) Properties[element][j] = EP_BITMASK_DEFAULT; +#endif #endif /* now set default properties */ @@ -794,9 +809,15 @@ static void setFileInfoToDefaults(struct LevelFileInfo *level_file_info) static void ActivateLevelTemplate() { +#if 1 + /* Currently there is no special action needed to activate the template + data, because 'element_info' property settings overwrite the original + level data, while all other variables do not change. */ +#else /* Currently there is no special action needed to activate the template data, because 'element_info' and 'Properties' overwrite the original level data, while all other variables do not change. */ +#endif } static char *getLevelFilenameFromBasename(char *basename) @@ -1173,7 +1194,10 @@ static int LoadLevel_HEAD(FILE *file, int chunk_size, struct LevelInfo *level) level->time_magic_wall = getFile8Bit(file); level->time_wheel = getFile8Bit(file); level->amoeba_content = getMappedElement(getFile8Bit(file)); - level->double_speed = (getFile8Bit(file) == 1 ? TRUE : FALSE); + + level->initial_player_stepsize = (getFile8Bit(file) == 1 ? STEPSIZE_FAST : + STEPSIZE_NORMAL); + level->initial_gravity = (getFile8Bit(file) == 1 ? TRUE : FALSE); level->encoding_16bit_field = (getFile8Bit(file) == 1 ? TRUE : FALSE); level->em_slippery_gems = (getFile8Bit(file) == 1 ? TRUE : FALSE); @@ -1372,10 +1396,17 @@ static int LoadLevel_CUS1(FILE *file, int chunk_size, struct LevelInfo *level) int element = getFile16BitBE(file); int properties = getFile32BitBE(file); +#if 1 + if (IS_CUSTOM_ELEMENT(element)) + element_info[element].properties[EP_BITFIELD_BASE] = properties; + else + Error(ERR_WARN, "invalid custom element number %d", element); +#else if (IS_CUSTOM_ELEMENT(element)) Properties[element][EP_BITFIELD_BASE] = properties; else Error(ERR_WARN, "invalid custom element number %d", element); +#endif } return chunk_size; @@ -1436,7 +1467,11 @@ static int LoadLevel_CUS3(FILE *file, int chunk_size, struct LevelInfo *level) ei->description[j] = getFile8Bit(file); ei->description[MAX_ELEMENT_NAME_LEN] = 0; +#if 1 + ei->properties[EP_BITFIELD_BASE] = getFile32BitBE(file); +#else Properties[element][EP_BITFIELD_BASE] = getFile32BitBE(file); +#endif /* some free bytes for future properties and padding */ ReadUnusedBytesFromFile(file, 7); @@ -1523,7 +1558,11 @@ static int LoadLevel_CUS4(FILE *file, int chunk_size, struct LevelInfo *level) ei->description[i] = getFile8Bit(file); ei->description[MAX_ELEMENT_NAME_LEN] = 0; +#if 1 + ei->properties[EP_BITFIELD_BASE] = getFile32BitBE(file); +#else Properties[element][EP_BITFIELD_BASE] = getFile32BitBE(file); +#endif ReadUnusedBytesFromFile(file, 4); /* reserved for more base properties */ ei->num_change_pages = getFile8Bit(file); @@ -2380,10 +2419,17 @@ void CopyNativeLevel_RND_to_EM(struct LevelInfo *level) }; struct LevelInfo_EM *level_em = level->native_em_level; struct LEVEL *lev = level_em->lev; - struct PLAYER *ply1 = level_em->ply1; - struct PLAYER *ply2 = level_em->ply2; + struct PLAYER **ply = level_em->ply; int i, j, x, y; +#if 0 + printf("::: A\n"); + for (i = 0; i < MAX_ELEMENT_CONTENTS; i++) + for (j = 0; j < 8; j++) + printf("::: ball %d, %d: %d\n", i, j, + level->ball_content[i].e[ball_xy[j][0]][ball_xy[j][1]]); +#endif + lev->width = MIN(level->fieldx, EM_MAX_CAVE_WIDTH); lev->height = MIN(level->fieldy, EM_MAX_CAVE_HEIGHT); @@ -2436,6 +2482,13 @@ void CopyNativeLevel_RND_to_EM(struct LevelInfo *level) map_element_RND_to_EM(level-> ball_content[i].e[ball_xy[j][0]][ball_xy[j][1]]); +#if 0 + for (i = 0; i < MAX_ELEMENT_CONTENTS; i++) + for (j = 0; j < 8; j++) + printf("::: ball %d, %d: %d\n", i, j, + level->ball_content[i].e[ball_xy[j][0]][ball_xy[j][1]]); +#endif + map_android_clone_elements_RND_to_EM(level); #if 0 @@ -2448,6 +2501,45 @@ void CopyNativeLevel_RND_to_EM(struct LevelInfo *level) for (x = 0; x < EM_MAX_CAVE_WIDTH; x++) level_em->cave[x][y] = ZBORDER; +#if 1 + +#if 0 +#if 1 + LoadLevel_InitPlayfield(); +#else + lev_fieldx = lev->width; /* !!! also in LoadLevel_InitPlayfield() !!! */ + lev_fieldy = lev->height; /* !!! also in LoadLevel_InitPlayfield() !!! */ + SetBorderElement(); /* !!! also in LoadLevel_InitPlayfield() !!! */ +#endif +#endif + +#if 0 + printf("::: BorderElement == %d\n", BorderElement); +#endif + + if (BorderElement == EL_STEELWALL) + { + for (y = 0; y < lev->height + 2; y++) + for (x = 0; x < lev->width + 2; x++) + level_em->cave[x + 1][y + 1] = map_element_RND_to_EM(EL_STEELWALL); + } + + /* then copy the real level contents from level file into the playfield */ + for (y = 0; y < lev->height; y++) for (x = 0; x < lev->width; x++) + { + int new_element = map_element_RND_to_EM(level->field[x][y]); + int offset = (BorderElement == EL_STEELWALL ? 1 : 0); + int xx = x + 1 + offset; + int yy = y + 1 + offset; + + if (level->field[x][y] == EL_AMOEBA_DEAD) + new_element = map_element_RND_to_EM(EL_AMOEBA_WET); + + level_em->cave[xx][yy] = new_element; + } + +#else + /* then copy the real level contents from level file into the playfield */ for (y = 0; y < lev->height; y++) for (x = 0; x < lev->width; x++) { @@ -2459,15 +2551,46 @@ void CopyNativeLevel_RND_to_EM(struct LevelInfo *level) level_em->cave[x + 1][y + 1] = new_element; } +#endif + +#if 1 + + for (i = 0; i < MAX_PLAYERS; i++) + { + ply[i]->x_initial = 0; + ply[i]->y_initial = 0; + } + +#else + ply1->x_initial = 0; ply1->y_initial = 0; ply2->x_initial = 0; ply2->y_initial = 0; +#endif + /* initialize player positions and delete players from the playfield */ for (y = 0; y < lev->height; y++) for (x = 0; x < lev->width; x++) { + +#if 1 + if (ELEM_IS_PLAYER(level->field[x][y])) + { + int player_nr = GET_PLAYER_NR(level->field[x][y]); + int offset = (BorderElement == EL_STEELWALL ? 1 : 0); + int xx = x + 1 + offset; + int yy = y + 1 + offset; + + ply[player_nr]->x_initial = xx; + ply[player_nr]->y_initial = yy; + + level_em->cave[xx][yy] = map_element_RND_to_EM(EL_EMPTY); + } + +#else + #if 1 /* !!! CURRENTLY ONLY SUPPORT FOR ONE PLAYER !!! */ if (ELEM_IS_PLAYER(level->field[x][y])) @@ -2491,6 +2614,17 @@ void CopyNativeLevel_RND_to_EM(struct LevelInfo *level) level_em->cave[x + 1][y + 1] = map_element_RND_to_EM(EL_EMPTY); } #endif + +#endif + + } + + if (BorderElement == EL_STEELWALL) + { +#if 1 + lev->width += 2; + lev->height += 2; +#endif } } @@ -2509,8 +2643,7 @@ void CopyNativeLevel_EM_to_RND(struct LevelInfo *level) }; struct LevelInfo_EM *level_em = level->native_em_level; struct LEVEL *lev = level_em->lev; - struct PLAYER *ply1 = level_em->ply1; - struct PLAYER *ply2 = level_em->ply2; + struct PLAYER **ply = level_em->ply; int i, j, x, y; level->fieldx = MIN(lev->width, MAX_LEV_FIELDX); @@ -2561,11 +2694,27 @@ void CopyNativeLevel_EM_to_RND(struct LevelInfo *level) level->wind_direction_initial = map_direction_EM_to_RND(lev->wind_direction_initial); +#if 0 + printf("::: foo\n"); + for (i = 0; i < MAX_ELEMENT_CONTENTS; i++) + for (j = 0; j < 8; j++) + printf("::: ball %d, %d: %d\n", i, j, + level->ball_content[i].e[ball_xy[j][0]][ball_xy[j][1]]); +#endif + for (i = 0; i < MAX_ELEMENT_CONTENTS; i++) for (j = 0; j < 8; j++) level->ball_content[i].e[ball_xy[j][0]][ball_xy[j][1]] = map_element_EM_to_RND(lev->ball_array[i][j]); +#if 0 + printf("::: bar\n"); + for (i = 0; i < MAX_ELEMENT_CONTENTS; i++) + for (j = 0; j < 8; j++) + printf("::: ball %d, %d: %d\n", i, j, + level->ball_content[i].e[ball_xy[j][0]][ball_xy[j][1]]); +#endif + map_android_clone_elements_EM_to_RND(level); #if 0 @@ -2584,13 +2733,50 @@ void CopyNativeLevel_EM_to_RND(struct LevelInfo *level) level->field[x][y] = new_element; } +#if 0 + printf("::: bar 0\n"); + for (i = 0; i < MAX_ELEMENT_CONTENTS; i++) + for (j = 0; j < 8; j++) + printf("::: ball %d, %d: %d\n", i, j, + level->ball_content[i].e[ball_xy[j][0]][ball_xy[j][1]]); +#endif + +#if 1 + + for (i = 0; i < MAX_PLAYERS; i++) + { + /* in case of all players set to the same field, use the first player */ + int nr = MAX_PLAYERS - i - 1; + int jx = ply[nr]->x_initial - 1; + int jy = ply[nr]->y_initial - 1; + +#if 0 + printf("::: player %d: %d, %d\n", nr, jx, jy); +#endif + + if (jx != -1 && jy != -1) + level->field[jx][jy] = EL_PLAYER_1 + nr; + } + +#else + /* in case of both players set to the same field, use the first player */ level->field[ply2->x_initial - 1][ply2->y_initial - 1] = EL_PLAYER_2; level->field[ply1->x_initial - 1][ply1->y_initial - 1] = EL_PLAYER_1; +#endif + #if 0 printf("::: native Emerald Mine file version: %d\n", level_em->file_version); #endif + +#if 0 + printf("::: bar 2\n"); + for (i = 0; i < MAX_ELEMENT_CONTENTS; i++) + for (j = 0; j < 8; j++) + printf("::: ball %d, %d: %d\n", i, j, + level->ball_content[i].e[ball_xy[j][0]][ball_xy[j][1]]); +#endif } static void LoadLevelFromFileInfo_EM(struct LevelInfo *level, @@ -2608,6 +2794,30 @@ void CopyNativeLevel_RND_to_Native(struct LevelInfo *level) void CopyNativeLevel_Native_to_RND(struct LevelInfo *level) { + +#if 0 + { + static int ball_xy[8][2] = + { + { 0, 0 }, + { 1, 0 }, + { 2, 0 }, + { 0, 1 }, + { 2, 1 }, + { 0, 2 }, + { 1, 2 }, + { 2, 2 }, + }; + int i, j; + + printf("::: A6\n"); + for (i = 0; i < MAX_ELEMENT_CONTENTS; i++) + for (j = 0; j < 8; j++) + printf("::: ball %d, %d: %d\n", i, j, + level->ball_content[i].e[ball_xy[j][0]][ball_xy[j][1]]); + } +#endif + if (level->game_engine_type == GAME_ENGINE_TYPE_EM) CopyNativeLevel_EM_to_RND(level); } @@ -2990,10 +3200,15 @@ void LoadLevelFromFileInfo(struct LevelInfo *level, if (level->game_engine_type == GAME_ENGINE_TYPE_UNKNOWN) level->game_engine_type = GAME_ENGINE_TYPE_RND; +#if 1 + if (level_file_info->type != LEVEL_FILE_TYPE_RND) + CopyNativeLevel_Native_to_RND(level); +#else if (level_file_info->type == LEVEL_FILE_TYPE_RND) CopyNativeLevel_RND_to_Native(level); else CopyNativeLevel_Native_to_RND(level); +#endif } void LoadLevelFromFilename(struct LevelInfo *level, char *filename) @@ -3015,6 +3230,15 @@ static void LoadLevel_InitVersion(struct LevelInfo *level, char *filename) if (leveldir_current == NULL) /* only when dumping level */ return; + /* all engine modifications also valid for levels which use latest engine */ +#if 1 + if (level->game_version < VERSION_IDENT(3,2,0,5)) + { + /* time bonus score was given for 10 s instead of 1 s before 3.2.0-5 */ + level->score[SC_TIME_BONUS] /= 10; + } +#endif + if (leveldir_current->latest_engine) { /* ---------- use latest game engine ----------------------------------- */ @@ -3056,7 +3280,7 @@ static void LoadLevel_InitVersion(struct LevelInfo *level, char *filename) /* player was faster than enemies in 1.0.0 and before */ if (level->file_version == FILE_VERSION_1_0) - level->double_speed = TRUE; + level->initial_player_stepsize = STEPSIZE_FAST; /* default behaviour for EM style gems was "slippery" only in 2.0.1 */ if (level->game_version == VERSION_IDENT(2,0,1,0)) @@ -3077,8 +3301,10 @@ static void LoadLevel_InitVersion(struct LevelInfo *level, char *filename) /* extra time score was same value as time left score before 3.2.0-5 */ level->extra_time_score = level->score[SC_TIME_BONUS]; +#if 0 /* time bonus score was given for 10 s instead of 1 s before 3.2.0-5 */ level->score[SC_TIME_BONUS] /= 10; +#endif } /* only few elements were able to actively move into acid before 3.1.0 */ @@ -3281,6 +3507,21 @@ static void LoadLevel_InitPlayfield(struct LevelInfo *level, char *filename) SetBorderElement(); } +static void LoadLevel_InitNativeEngines(struct LevelInfo *level,char *filename) +{ + struct LevelFileInfo *level_file_info = &level->file_info; + +#if 1 + if (level_file_info->type == LEVEL_FILE_TYPE_RND) + CopyNativeLevel_RND_to_Native(level); +#else + if (level_file_info->type == LEVEL_FILE_TYPE_RND) + CopyNativeLevel_RND_to_Native(level); + else + CopyNativeLevel_Native_to_RND(level); +#endif +} + void LoadLevelTemplate(int nr) { char *filename; @@ -3311,6 +3552,8 @@ void LoadLevel(int nr) LoadLevel_InitVersion(&level, filename); LoadLevel_InitElements(&level, filename); LoadLevel_InitPlayfield(&level, filename); + + LoadLevel_InitNativeEngines(&level, filename); } static void SaveLevel_VERS(FILE *file, struct LevelInfo *level) @@ -3345,7 +3588,7 @@ static void SaveLevel_HEAD(FILE *file, struct LevelInfo *level) putFile8Bit(file, level->time_wheel); putFile8Bit(file, (level->encoding_16bit_amoeba ? EL_EMPTY : level->amoeba_content)); - putFile8Bit(file, (level->double_speed ? 1 : 0)); + putFile8Bit(file, (level->initial_player_stepsize == STEPSIZE_FAST ? 1 : 0)); putFile8Bit(file, (level->initial_gravity ? 1 : 0)); putFile8Bit(file, (level->encoding_16bit_field ? 1 : 0)); putFile8Bit(file, (level->em_slippery_gems ? 1 : 0)); @@ -3489,6 +3732,20 @@ static void SaveLevel_CUS1(FILE *file, struct LevelInfo *level, { int element = EL_CUSTOM_START + i; +#if 1 + struct ElementInfo *ei = &element_info[element]; + + if (ei->properties[EP_BITFIELD_BASE] != EP_BITMASK_DEFAULT) + { + if (check < num_changed_custom_elements) + { + putFile16BitBE(file, element); + putFile32BitBE(file, ei->properties[EP_BITFIELD_BASE]); + } + + check++; + } +#else if (Properties[element][EP_BITFIELD_BASE] != EP_BITMASK_DEFAULT) { if (check < num_changed_custom_elements) @@ -3499,6 +3756,7 @@ static void SaveLevel_CUS1(FILE *file, struct LevelInfo *level, check++; } +#endif } if (check != num_changed_custom_elements) /* should not happen */ @@ -3557,7 +3815,11 @@ static void SaveLevel_CUS3(FILE *file, struct LevelInfo *level, for (j = 0; j < MAX_ELEMENT_NAME_LEN; j++) putFile8Bit(file, ei->description[j]); +#if 1 + putFile32BitBE(file, ei->properties[EP_BITFIELD_BASE]); +#else putFile32BitBE(file, Properties[element][EP_BITFIELD_BASE]); +#endif /* some free bytes for future properties and padding */ WriteUnusedBytesToFile(file, 7); @@ -3630,7 +3892,11 @@ static void SaveLevel_CUS4(FILE *file, struct LevelInfo *level, int element) for (i = 0; i < MAX_ELEMENT_NAME_LEN; i++) putFile8Bit(file, ei->description[i]); +#if 1 + putFile32BitBE(file, ei->properties[EP_BITFIELD_BASE]); +#else putFile32BitBE(file, Properties[element][EP_BITFIELD_BASE]); +#endif WriteUnusedBytesToFile(file, 4); /* reserved for more base properties */ putFile8Bit(file, ei->num_change_pages); @@ -4045,7 +4311,7 @@ void DumpLevel(struct LevelInfo *level) printf("Amoeba speed: %d\n", level->amoeba_speed); printf("\n"); printf("Initial gravity: %s\n", (level->initial_gravity ? "yes" : "no")); - printf("Double speed movement: %s\n", (level->double_speed ? "yes" : "no")); + printf("Initial player stepsize: %d\n", level->initial_player_stepsize); printf("EM style slippery gems: %s\n", (level->em_slippery_gems ? "yes" : "no")); printf("Player blocks last field: %s\n", (level->block_last_field ? "yes" : "no")); printf("SP player blocks last field: %s\n", (level->sp_block_last_field ? "yes" : "no")); @@ -4503,6 +4769,7 @@ void SaveTape(int nr) void DumpTape(struct TapeInfo *tape) { + int tape_frame_counter; int i, j; if (tape->no_valid_file) @@ -4520,12 +4787,14 @@ void DumpTape(struct TapeInfo *tape) printf("Level series identifier: '%s'\n", tape->level_identifier); printf_line("-", 79); + tape_frame_counter = 0; + for (i = 0; i < tape->length; i++) { if (i >= MAX_TAPE_LEN) break; - printf("%03d: ", i); + printf("%04d: ", i); for (j = 0; j < MAX_PLAYERS; j++) { @@ -4544,7 +4813,10 @@ void DumpTape(struct TapeInfo *tape) } } - printf("(%03d)\n", tape->pos[i].delay); + printf("(%03d) ", tape->pos[i].delay); + printf("[%05d]\n", tape_frame_counter); + + tape_frame_counter += tape->pos[i].delay; } printf_line("-", 79); @@ -4657,14 +4929,15 @@ void SaveScore(int nr) #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 SETUP_TOKEN_QUICK_SWITCH 17 +#define SETUP_TOKEN_GRAPHICS_SET 18 +#define SETUP_TOKEN_SOUNDS_SET 19 +#define SETUP_TOKEN_MUSIC_SET 20 +#define SETUP_TOKEN_OVERRIDE_LEVEL_GRAPHICS 21 +#define SETUP_TOKEN_OVERRIDE_LEVEL_SOUNDS 22 +#define SETUP_TOKEN_OVERRIDE_LEVEL_MUSIC 23 -#define NUM_GLOBAL_SETUP_TOKENS 23 +#define NUM_GLOBAL_SETUP_TOKENS 24 /* editor setup */ #define SETUP_TOKEN_EDITOR_EL_BOULDERDASH 0 @@ -4767,6 +5040,7 @@ static struct TokenInfo global_setup_tokens[] = { TYPE_SWITCH, &si.time_limit, "time_limit" }, { TYPE_SWITCH, &si.fullscreen, "fullscreen" }, { TYPE_SWITCH, &si.ask_on_escape, "ask_on_escape" }, + { TYPE_SWITCH, &si.quick_switch, "quick_player_switch" }, { TYPE_STRING, &si.graphics_set, "graphics_set" }, { TYPE_STRING, &si.sounds_set, "sounds_set" }, { TYPE_STRING, &si.music_set, "music_set" }, @@ -4887,6 +5161,7 @@ static void setSetupInfoToDefaults(struct SetupInfo *si) si->time_limit = TRUE; si->fullscreen = FALSE; si->ask_on_escape = TRUE; + si->quick_switch = FALSE; si->graphics_set = getStringCopy(GFX_CLASSIC_SUBDIR); si->sounds_set = getStringCopy(SND_CLASSIC_SUBDIR); @@ -5689,7 +5964,7 @@ void LoadHelpAnimInfo() i_to_a(element_action_info[i].value)); /* do not store direction index (bit) here, but direction value! */ - for (i = 0; i < NUM_DIRECTIONS; i++) + for (i = 0; i < NUM_DIRECTIONS_FULL; i++) setHashEntry(direction_hash, element_direction_info[i].suffix, i_to_a(1 << element_direction_info[i].value)); @@ -5851,7 +6126,8 @@ void LoadHelpAnimInfo() #if 0 for (i = 0; i < num_list_entries; i++) - printf("::: %d, %d, %d => %d\n", + printf("::: '%s': %d, %d, %d => %d\n", + EL_NAME(helpanim_info[i].element), helpanim_info[i].element, helpanim_info[i].action, helpanim_info[i].direction,