X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame.c;h=d78023fd15a8472d6f5a04d82b7283d4dfd0c764;hb=95ff39b11bc3c268d8206193bad1433ac9526c94;hp=bbcb6604b16bdccee0f34e8393092cd1bca4a158;hpb=113df1c4ad60b24a31ec6498f8cd3b2d4cd9dbfd;p=rocksndiamonds.git diff --git a/src/game.c b/src/game.c index bbcb6604..d78023fd 100644 --- a/src/game.c +++ b/src/game.c @@ -142,13 +142,15 @@ RND(element_info[e].move_delay_random)) #define GET_MAX_MOVE_DELAY(e) ( (element_info[e].move_delay_fixed) + \ (element_info[e].move_delay_random)) -#define GET_NEW_CUSTOM_VALUE(e) ( (element_info[e].ce_value_fixed_initial) +\ +#define GET_NEW_CE_VALUE(e) ( (element_info[e].ce_value_fixed_initial) +\ RND(element_info[e].ce_value_random_initial)) +#define GET_CE_SCORE(e) ( (element_info[e].collect_score)) #define GET_CHANGE_DELAY(c) ( ((c)->delay_fixed * (c)->delay_frames) + \ RND((c)->delay_random * (c)->delay_frames)) #define GET_CE_DELAY_VALUE(c) ( ((c)->delay_fixed) + \ RND((c)->delay_random)) + #if 1 #define GET_VALID_RUNTIME_ELEMENT(e) \ ((e) >= NUM_RUNTIME_ELEMENTS ? EL_UNKNOWN : (e)) @@ -157,10 +159,13 @@ ((e) >= NUM_FILE_ELEMENTS ? EL_UNKNOWN : (e)) #endif -#define GET_TARGET_ELEMENT(e, ch) \ - ((e) == EL_TRIGGER_PLAYER ? (ch)->actual_trigger_player : \ - (e) == EL_TRIGGER_ELEMENT ? (ch)->actual_trigger_element : \ - (e) == EL_TRIGGER_CE_VALUE ? (ch)->actual_trigger_ce_value : (e)) +#define GET_TARGET_ELEMENT(e, ch, cv, cs) \ + ((e) == EL_TRIGGER_PLAYER ? (ch)->actual_trigger_player : \ + (e) == EL_TRIGGER_ELEMENT ? (ch)->actual_trigger_element : \ + (e) == EL_TRIGGER_CE_VALUE ? (ch)->actual_trigger_ce_value : \ + (e) == EL_TRIGGER_CE_SCORE ? (ch)->actual_trigger_ce_score : \ + (e) == EL_CURRENT_CE_VALUE ? (cv) : \ + (e) == EL_CURRENT_CE_SCORE ? (cs) : (e)) #define CAN_GROW_INTO(e) \ ((e) == EL_SAND || (IS_DIGGABLE(e) && level.grow_into_diggable)) @@ -861,6 +866,32 @@ static int getBeltDirFromBeltSwitchElement(int element) return belt_move_dir[belt_dir_nr]; } +static int get_element_from_group_element(int element) +{ + if (IS_GROUP_ELEMENT(element)) + { + struct ElementGroupInfo *group = element_info[element].group; + int last_anim_random_frame = gfx.anim_random_frame; + int element_pos; + + if (group->choice_mode == ANIM_RANDOM) + gfx.anim_random_frame = RND(group->num_elements_resolved); + + element_pos = getAnimationFrame(group->num_elements_resolved, 1, + group->choice_mode, 0, + group->choice_pos); + + if (group->choice_mode == ANIM_RANDOM) + gfx.anim_random_frame = last_anim_random_frame; + + group->choice_pos++; + + element = group->element_resolved[element_pos]; + } + + return element; +} + static void InitPlayerField(int x, int y, int element, boolean init_game) { if (element == EL_SP_MURPHY) @@ -1114,7 +1145,7 @@ static void InitField(int x, int y, boolean init_game) #if USE_NEW_CUSTOM_VALUE if (!element_info[element].use_last_ce_value || init_game) - CustomValue[x][y] = GET_NEW_CUSTOM_VALUE(Feld[x][y]); + CustomValue[x][y] = GET_NEW_CE_VALUE(Feld[x][y]); #endif } #else @@ -1123,6 +1154,11 @@ static void InitField(int x, int y, boolean init_game) #endif else if (IS_GROUP_ELEMENT(element)) { +#if 1 + Feld[x][y] = get_element_from_group_element(element); + + InitField(x, y, init_game); +#else struct ElementGroupInfo *group = element_info[element].group; int last_anim_random_frame = gfx.anim_random_frame; int element_pos; @@ -1142,6 +1178,7 @@ static void InitField(int x, int y, boolean init_game) Feld[x][y] = group->element_resolved[element_pos]; InitField(x, y, init_game); +#endif } break; } @@ -1156,7 +1193,7 @@ static void InitField(int x, int y, boolean init_game) #if USE_NEW_CUSTOM_VALUE #if 1 - CustomValue[x][y] = GET_NEW_CUSTOM_VALUE(Feld[x][y]); + CustomValue[x][y] = GET_NEW_CE_VALUE(Feld[x][y]); #else CustomValue[x][y] = element_info[Feld[x][y]].custom_value_initial; #endif @@ -1199,12 +1236,16 @@ static inline void InitField_WithBug2(int x, int y, boolean init_game) inline void DrawGameValue_Emeralds(int value) { - DrawText(DX_EMERALDS, DY_EMERALDS, int2str(value, 3), FONT_TEXT_2); + int xpos = (3 * 14 - 3 * getFontWidth(FONT_TEXT_2)) / 2; + + DrawText(DX_EMERALDS + xpos, DY_EMERALDS, int2str(value, 3), FONT_TEXT_2); } inline void DrawGameValue_Dynamite(int value) { - DrawText(DX_DYNAMITE, DY_DYNAMITE, int2str(value, 3), FONT_TEXT_2); + int xpos = (3 * 14 - 3 * getFontWidth(FONT_TEXT_2)) / 2; + + DrawText(DX_DYNAMITE + xpos, DY_DYNAMITE, int2str(value, 3), FONT_TEXT_2); } inline void DrawGameValue_Keys(int key[MAX_NUM_KEYS]) @@ -1230,15 +1271,24 @@ inline void DrawGameValue_Keys(int key[MAX_NUM_KEYS]) inline void DrawGameValue_Score(int value) { - DrawText(DX_SCORE, DY_SCORE, int2str(value, 5), FONT_TEXT_2); + int xpos = (5 * 14 - 5 * getFontWidth(FONT_TEXT_2)) / 2; + + DrawText(DX_SCORE + xpos, DY_SCORE, int2str(value, 5), FONT_TEXT_2); } inline void DrawGameValue_Time(int value) { + int xpos3 = (3 * 14 - 3 * getFontWidth(FONT_TEXT_2)) / 2; + int xpos4 = (4 * 10 - 4 * getFontWidth(FONT_LEVEL_NUMBER)) / 2; + + /* clear background if value just changed its size */ + if (value == 999 || value == 1000) + ClearRectangle(drawto, DX_TIME1, DY_TIME, 14 * 3, 14); + if (value < 1000) - DrawText(DX_TIME1, DY_TIME, int2str(value, 3), FONT_TEXT_2); + DrawText(DX_TIME1 + xpos3, DY_TIME, int2str(value, 3), FONT_TEXT_2); else - DrawText(DX_TIME2, DY_TIME, int2str(value, 4), FONT_LEVEL_NUMBER); + DrawText(DX_TIME2 + xpos4, DY_TIME, int2str(value, 4), FONT_LEVEL_NUMBER); } inline void DrawGameValue_Level(int value) @@ -1646,6 +1696,7 @@ static void InitGameEngine() ei->change_page[j].actual_trigger_player = EL_PLAYER_1; ei->change_page[j].actual_trigger_side = CH_SIDE_NONE; ei->change_page[j].actual_trigger_ce_value = 0; + ei->change_page[j].actual_trigger_ce_score = 0; } } @@ -2031,9 +2082,23 @@ void InitGame() game.envelope_active = FALSE; - game.centered_player_nr = game.centered_player_nr_next = -1; /* focus all */ + /* set focus to local player for network games, else to all players */ + game.centered_player_nr = (network_playing ? local_player->index_nr : -1); + game.centered_player_nr_next = game.centered_player_nr; game.set_centered_player = FALSE; + if (network_playing && tape.recording) + { + /* store client dependent player focus when recording network games */ + tape.centered_player_nr_next = game.centered_player_nr_next; + tape.set_centered_player = TRUE; + } + +#if 0 + printf("::: focus set to player %d [%d]\n", + game.centered_player_nr, local_player->index_nr); +#endif + for (i = 0; i < NUM_BELTS; i++) { game.belt_dir[i] = MV_NONE; @@ -2846,7 +2911,7 @@ int NewHiScore() LoadScore(level_nr); - if (strcmp(setup.player_name, EMPTY_PLAYER_NAME) == 0 || + if (strEqual(setup.player_name, EMPTY_PLAYER_NAME) || local_player->score < highscore[MAX_SCORE_ENTRIES - 1].Score) return -1; @@ -2862,7 +2927,7 @@ int NewHiScore() #ifdef ONE_PER_NAME for (l = k; l < MAX_SCORE_ENTRIES; l++) - if (!strcmp(setup.player_name, highscore[l].Name)) + if (strEqual(setup.player_name, highscore[l].Name)) m = l; if (m == k) /* player's new highscore overwrites his old one */ goto put_into_list; @@ -7830,6 +7895,7 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page) { struct ElementInfo *ei = &element_info[element]; struct ElementChangeInfo *change = &ei->change_page[page]; + int target_element = change->target_element; int action_type = change->action_type; int action_mode = change->action_mode; int action_arg = change->action_arg; @@ -7868,8 +7934,8 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page) action_type == CA_SET_LEVEL_GEMS ? 999 : action_type == CA_SET_LEVEL_TIME ? 9999 : action_type == CA_SET_LEVEL_SCORE ? 99999 : - action_type == CA_SET_CE_SCORE ? 9999 : action_type == CA_SET_CE_VALUE ? 9999 : + action_type == CA_SET_CE_SCORE ? 9999 : CA_ARG_MAX); int action_arg_number_reset = @@ -7877,12 +7943,12 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page) action_type == CA_SET_LEVEL_GEMS ? level.gems_needed : action_type == CA_SET_LEVEL_TIME ? level.time : action_type == CA_SET_LEVEL_SCORE ? 0 : - action_type == CA_SET_CE_SCORE ? 0 : #if 1 - action_type == CA_SET_CE_VALUE ? GET_NEW_CUSTOM_VALUE(element) : + action_type == CA_SET_CE_VALUE ? GET_NEW_CE_VALUE(element) : #else action_type == CA_SET_CE_VALUE ? ei->custom_value_initial : #endif + action_type == CA_SET_CE_SCORE ? 0 : 0); int action_arg_number = @@ -7893,18 +7959,20 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page) action_arg == CA_ARG_NUMBER_MIN ? action_arg_number_min : action_arg == CA_ARG_NUMBER_MAX ? action_arg_number_max : action_arg == CA_ARG_NUMBER_RESET ? action_arg_number_reset : - action_arg == CA_ARG_NUMBER_CE_SCORE ? ei->collect_score : #if USE_NEW_CUSTOM_VALUE action_arg == CA_ARG_NUMBER_CE_VALUE ? CustomValue[x][y] : #else action_arg == CA_ARG_NUMBER_CE_VALUE ? ei->custom_value_initial : #endif + action_arg == CA_ARG_NUMBER_CE_SCORE ? ei->collect_score : action_arg == CA_ARG_NUMBER_CE_DELAY ? GET_CE_DELAY_VALUE(change) : action_arg == CA_ARG_NUMBER_LEVEL_TIME ? level_time_value : action_arg == CA_ARG_NUMBER_LEVEL_GEMS ? local_player->gems_still_needed : action_arg == CA_ARG_NUMBER_LEVEL_SCORE ? local_player->score : - action_arg == CA_ARG_ELEMENT_CV_TARGET ? GET_NEW_CUSTOM_VALUE(change->target_element) : + action_arg == CA_ARG_ELEMENT_CV_TARGET ? GET_NEW_CE_VALUE(target_element): action_arg == CA_ARG_ELEMENT_CV_TRIGGER ? change->actual_trigger_ce_value: + action_arg == CA_ARG_ELEMENT_CS_TARGET ? GET_CE_SCORE(target_element) : + action_arg == CA_ARG_ELEMENT_CS_TRIGGER ? change->actual_trigger_ce_score: action_arg == CA_ARG_ELEMENT_NR_TARGET ? change->target_element : action_arg == CA_ARG_ELEMENT_NR_TRIGGER ? change->actual_trigger_element : -1); @@ -7913,8 +7981,8 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page) (action_type == CA_SET_LEVEL_GEMS ? local_player->gems_still_needed : action_type == CA_SET_LEVEL_TIME ? TimeLeft : action_type == CA_SET_LEVEL_SCORE ? local_player->score : - action_type == CA_SET_CE_SCORE ? ei->collect_score : action_type == CA_SET_CE_VALUE ? CustomValue[x][y] : + action_type == CA_SET_CE_SCORE ? ei->collect_score : 0); int action_arg_number_new = @@ -8175,13 +8243,6 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page) /* ---------- CE actions ---------------------------------------------- */ - case CA_SET_CE_SCORE: - { - ei->collect_score = action_arg_number_new; - - break; - } - case CA_SET_CE_VALUE: { #if USE_NEW_CUSTOM_VALUE @@ -8211,6 +8272,13 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page) break; } + case CA_SET_CE_SCORE: + { + ei->collect_score = action_arg_number_new; + + break; + } + /* ---------- engine actions ------------------------------------------ */ case CA_SET_ENGINE_SCAN_MODE: @@ -8227,22 +8295,26 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page) static void CreateFieldExt(int x, int y, int element, boolean is_change) { + int old_element = Feld[x][y]; + int new_element = get_element_from_group_element(element); int previous_move_direction = MovDir[x][y]; #if USE_NEW_CUSTOM_VALUE int last_ce_value = CustomValue[x][y]; #endif - boolean add_player = (ELEM_IS_PLAYER(element) && - IS_WALKABLE(Feld[x][y])); + boolean add_player = (ELEM_IS_PLAYER(new_element) && + IS_WALKABLE(old_element)); +#if 0 /* check if element under player changes from accessible to unaccessible (needed for special case of dropping element which then changes) */ if (IS_PLAYER(x, y) && !PLAYER_EXPLOSION_PROTECTED(x, y) && - IS_ACCESSIBLE(Feld[x][y]) && !IS_ACCESSIBLE(element)) + IS_ACCESSIBLE(old_element) && !IS_ACCESSIBLE(new_element)) { Bang(x, y); return; } +#endif if (!add_player) { @@ -8251,30 +8323,44 @@ static void CreateFieldExt(int x, int y, int element, boolean is_change) else RemoveField(x, y); - Feld[x][y] = element; + Feld[x][y] = new_element; ResetGfxAnimation(x, y); ResetRandomAnimationValue(x, y); - if (element_info[Feld[x][y]].move_direction_initial == MV_START_PREVIOUS) + if (element_info[new_element].move_direction_initial == MV_START_PREVIOUS) MovDir[x][y] = previous_move_direction; #if USE_NEW_CUSTOM_VALUE - if (element_info[Feld[x][y]].use_last_ce_value) + if (element_info[new_element].use_last_ce_value) CustomValue[x][y] = last_ce_value; #endif InitField_WithBug1(x, y, FALSE); + new_element = Feld[x][y]; /* element may have changed */ + DrawLevelField(x, y); - if (GFX_CRUMBLED(Feld[x][y])) + if (GFX_CRUMBLED(new_element)) DrawLevelFieldCrumbledSandNeighbours(x, y); } +#if 1 + /* check if element under player changes from accessible to unaccessible + (needed for special case of dropping element which then changes) */ + if (IS_PLAYER(x, y) && !PLAYER_EXPLOSION_PROTECTED(x, y) && + IS_ACCESSIBLE(old_element) && !IS_ACCESSIBLE(new_element)) + { + Bang(x, y); + + return; + } +#endif + /* "ChangeCount" not set yet to allow "entered by player" change one time */ - if (ELEM_IS_PLAYER(element)) - RelocatePlayer(x, y, element); + if (ELEM_IS_PLAYER(new_element)) + RelocatePlayer(x, y, new_element); if (is_change) ChangeCount[x][y]++; /* count number of changes in the same frame */ @@ -8311,7 +8397,10 @@ static void CreateElementFromChange(int x, int y, int element) static boolean ChangeElement(int x, int y, int element, int page) { - struct ElementChangeInfo *change = &element_info[element].change_page[page]; + struct ElementInfo *ei = &element_info[element]; + struct ElementChangeInfo *change = &ei->change_page[page]; + int ce_value = CustomValue[x][y]; + int ce_score = ei->collect_score; int target_element; int old_element = Feld[x][y]; @@ -8326,6 +8415,7 @@ static boolean ChangeElement(int x, int y, int element, int page) change->actual_trigger_player = EL_PLAYER_1; change->actual_trigger_side = CH_SIDE_NONE; change->actual_trigger_ce_value = 0; + change->actual_trigger_ce_score = 0; } /* do not change elements more than a specified maximum number of changes */ @@ -8430,7 +8520,8 @@ static boolean ChangeElement(int x, int y, int element, int page) ChangeEvent[ex][ey] = ChangeEvent[x][y]; content_element = change->target_content.e[xx][yy]; - target_element = GET_TARGET_ELEMENT(content_element, change); + target_element = GET_TARGET_ELEMENT(content_element, change, + ce_value, ce_score); CreateElementFromChange(ex, ey, target_element); @@ -8451,7 +8542,8 @@ static boolean ChangeElement(int x, int y, int element, int page) } else { - target_element = GET_TARGET_ELEMENT(change->target_element, change); + target_element = GET_TARGET_ELEMENT(change->target_element, change, + ce_value, ce_score); if (element == EL_DIAGONAL_GROWING || element == EL_DIAGONAL_SHRINKING) @@ -8685,6 +8777,7 @@ static boolean CheckTriggeredElementChangeExt(int trigger_x, int trigger_y, change->actual_trigger_player = EL_PLAYER_1 + log_2(trigger_player); change->actual_trigger_side = trigger_side; change->actual_trigger_ce_value = CustomValue[trigger_x][trigger_y]; + change->actual_trigger_ce_score = GET_CE_SCORE(trigger_element); if ((change->can_change && !change_done) || change->has_action) { @@ -8789,6 +8882,7 @@ static boolean CheckElementChangeExt(int x, int y, change->actual_trigger_player = EL_PLAYER_1 + log_2(trigger_player); change->actual_trigger_side = trigger_side; change->actual_trigger_ce_value = CustomValue[x][y]; + change->actual_trigger_ce_score = GET_CE_SCORE(trigger_element); /* special case: trigger element not at (x,y) position for some events */ if (check_trigger_element) @@ -8811,6 +8905,7 @@ static boolean CheckElementChangeExt(int x, int y, int yy = y + move_xy[MV_DIR_OPPOSITE(trigger_side)].dy; change->actual_trigger_ce_value = CustomValue[xx][yy]; + change->actual_trigger_ce_score = GET_CE_SCORE(trigger_element); } if (change->can_change && !change_done) @@ -12856,7 +12951,10 @@ static void HandleGameButtons(struct GadgetInfo *gi) switch (id) { case GAME_CTRL_ID_STOP: - RequestQuitGame(TRUE); + if (tape.playing) + TapeStop(); + else + RequestQuitGame(TRUE); break; case GAME_CTRL_ID_PAUSE: @@ -12883,7 +12981,7 @@ static void HandleGameButtons(struct GadgetInfo *gi) #endif { tape.pausing = FALSE; - DrawVideoDisplay(VIDEO_STATE_PAUSE_OFF,0); + DrawVideoDisplay(VIDEO_STATE_PAUSE_OFF, 0); } } break;