X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fgame_bd%2Fbd_caveengine.c;h=aba15aff9688eb46cc7ac4fe7aa83ff899ce4e37;hb=1f0d80712e543e4d664ffe9a1f672db34207e7b9;hp=b3723b9b5b12852e867ec59257ce201421c64f13;hpb=25eedddf7e2f4d0802a31ffbc43f42a48f0e8b3b;p=rocksndiamonds.git diff --git a/src/game_bd/bd_caveengine.c b/src/game_bd/bd_caveengine.c index b3723b9b..aba15aff 100644 --- a/src/game_bd/bd_caveengine.c +++ b/src/game_bd/bd_caveengine.c @@ -135,29 +135,51 @@ static void play_sound_of_element(GdCave *cave, GdElement element, int x, int y) switch (element) { case O_NUT: + gd_sound_play(cave, GD_S_NUT_FALLING, element, x, y); + break; + case O_NUT_F: - gd_sound_play(cave, GD_S_NUT, element, x, y); + gd_sound_play(cave, GD_S_NUT_IMPACT, element, x, y); break; case O_STONE: + gd_sound_play(cave, GD_S_STONE_FALLING, element, x, y); + break; + case O_STONE_F: + gd_sound_play(cave, GD_S_STONE_IMPACT, element, x, y); + break; + case O_FLYING_STONE: + gd_sound_play(cave, GD_S_FLYING_STONE_FALLING, element, x, y); + break; + case O_FLYING_STONE_F: + gd_sound_play(cave, GD_S_FLYING_STONE_IMPACT, element, x, y); + break; + case O_MEGA_STONE: + gd_sound_play(cave, GD_S_MEGA_STONE_FALLING, element, x, y); + break; + case O_MEGA_STONE_F: - case O_WAITING_STONE: - case O_CHASING_STONE: - gd_sound_play(cave, GD_S_STONE, element, x, y); + gd_sound_play(cave, GD_S_MEGA_STONE_IMPACT, element, x, y); break; case O_NITRO_PACK: + gd_sound_play(cave, GD_S_NITRO_PACK_FALLING, element, x, y); + break; + case O_NITRO_PACK_F: - gd_sound_play(cave, GD_S_NITRO_PACK, element, x, y); + gd_sound_play(cave, GD_S_NITRO_PACK_IMPACT, element, x, y); break; case O_FALLING_WALL: + gd_sound_play(cave, GD_S_FALLING_WALL_FALLING, element, x, y); + break; + case O_FALLING_WALL_F: - gd_sound_play(cave, GD_S_FALLING_WALL, element, x, y); + gd_sound_play(cave, GD_S_FALLING_WALL_IMPACT, element, x, y); break; case O_H_EXPANDING_WALL: @@ -170,10 +192,19 @@ static void play_sound_of_element(GdCave *cave, GdElement element, int x, int y) break; case O_DIAMOND: + gd_sound_play(cave, GD_S_DIAMOND_FALLING_RANDOM, element, x, y); + break; + case O_DIAMOND_F: + gd_sound_play(cave, GD_S_DIAMOND_IMPACT_RANDOM, element, x, y); + break; + case O_FLYING_DIAMOND: + gd_sound_play(cave, GD_S_FLYING_DIAMOND_FALLING_RANDOM, element, x, y); + break; + case O_FLYING_DIAMOND_F: - gd_sound_play(cave, GD_S_DIAMOND_RANDOM, element, x, y); + gd_sound_play(cave, GD_S_FLYING_DIAMOND_IMPACT_RANDOM, element, x, y); break; case O_BLADDER_SPENDER: @@ -208,10 +239,19 @@ static void play_sound_of_element(GdCave *cave, GdElement element, int x, int y) break; case O_DIRT_BALL: + gd_sound_play(cave, GD_S_DIRT_BALL_FALLING, element, x, y); + break; + case O_DIRT_BALL_F: + gd_sound_play(cave, GD_S_DIRT_BALL_IMPACT, element, x, y); + break; + case O_DIRT_LOOSE: + gd_sound_play(cave, GD_S_DIRT_LOOSE_FALLING, element, x, y); + break; + case O_DIRT_LOOSE_F: - gd_sound_play(cave, GD_S_DIRT_BALL, element, x, y); + gd_sound_play(cave, GD_S_DIRT_LOOSE_IMPACT, element, x, y); break; default: @@ -220,6 +260,81 @@ static void play_sound_of_element(GdCave *cave, GdElement element, int x, int y) } } +/* play sound of given element being pushed. */ +static void play_sound_of_element_pushing(GdCave *cave, GdElement element, int x, int y) +{ + switch (element) + { + case O_NUT: + gd_sound_play(cave, GD_S_NUT_PUSHING, element, x, y); + break; + + case O_STONE: + gd_sound_play(cave, GD_S_STONE_PUSHING, element, x, y); + break; + + case O_FLYING_STONE: + gd_sound_play(cave, GD_S_FLYING_STONE_PUSHING, element, x, y); + break; + + case O_MEGA_STONE: + gd_sound_play(cave, GD_S_MEGA_STONE_PUSHING, element, x, y); + break; + + case O_WAITING_STONE: + gd_sound_play(cave, GD_S_WAITING_STONE_PUSHING, element, x, y); + break; + + case O_CHASING_STONE: + gd_sound_play(cave, GD_S_CHASING_STONE_PUSHING, element, x, y); + break; + + case O_NITRO_PACK: + gd_sound_play(cave, GD_S_NITRO_PACK_PUSHING, element, x, y); + break; + + case O_BLADDER: + gd_sound_play(cave, GD_S_BLADDER_PUSHING, element, x, y); + break; + + default: + /* do nothing. */ + break; + } +} + +static inline int getx(const GdCave *cave, const int x, const int y) +{ + return cave->getx(cave, x, y); +} + +static inline int gety(const GdCave *cave, const int x, const int y) +{ + return cave->gety(cave, x, y); +} + +/* perfect (non-lineshifting) GET x/y functions; returns range corrected x/y position */ +static inline int getx_perfect(const GdCave *cave, const int x, const int y) +{ + return (x + cave->w) % cave->w; +} + +static inline int gety_perfect(const GdCave *cave, const int x, const int y) +{ + return (y + cave->h) % cave->h; +} + +/* line shifting GET x/y function; returns range corrected x/y position */ +static inline int getx_shift(const GdCave *cave, int x, int y) +{ + return (x + cave->w) % cave->w; +} + +static inline int gety_shift(const GdCave *cave, int x, int y) +{ + return ((x < 0 ? y - 1 : x >= cave->w ? y + 1 : y) + cave->h) % cave->h; +} + static inline GdElement *getp(const GdCave *cave, const int x, const int y) { return cave->getp(cave, x, y); @@ -406,11 +521,24 @@ static inline boolean is_element_dir(const GdCave *cave, const int x, const int static inline boolean is_space_dir(const GdCave *cave, const int x, const int y, const GdDirection dir) { - GdElement e = get_dir(cave, x, y, dir)&O_MASK; + GdElement e = get_dir(cave, x, y, dir) & O_MASK; return (e == O_SPACE || e == O_LAVA); } +static inline void store_dir_buffer(GdCave *cave, const int x, const int y, const GdDirection dir) +{ + /* raw values without range correction */ + int raw_x = x + gd_dx[dir]; + int raw_y = y + gd_dy[dir]; + /* final values with range correction */ + int new_x = getx(cave, raw_x, raw_y); + int new_y = gety(cave, raw_x, raw_y); + int new_dir = (dir > GD_MV_TWICE ? dir - GD_MV_TWICE : dir); + + game_bd.game->dir_buffer[new_y][new_x] = new_dir; +} + /* store an element at the given position */ static inline void store(GdCave *cave, const int x, const int y, const GdElement element) { @@ -436,13 +564,15 @@ static inline void store_sc(GdCave *cave, const int x, const int y, const GdElem static inline void store_dir(GdCave *cave, const int x, const int y, const GdDirection dir, const GdElement element) { - store(cave, x + gd_dx[dir], y + gd_dy[dir], element|SCANNED); + store_dir_buffer(cave, x, y, dir); + store(cave, x + gd_dx[dir], y + gd_dy[dir], element | SCANNED); } /* store an element to a neighbouring cell */ static inline void store_dir_no_scanned(GdCave *cave, const int x, const int y, const GdDirection dir, const GdElement element) { + store_dir_buffer(cave, x, y, dir); store(cave, x + gd_dx[dir], y + gd_dy[dir], element); } @@ -802,7 +932,8 @@ static GdElement player_get_element(GdCave* cave, const GdElement object, int x, case O_FLYING_DIAMOND: // prevent diamond sounds for O_SKELETON (see below) if (x != -1 && y != -1) - gd_sound_play(cave, GD_S_DIAMOND_COLLECTING, object, x, y); + gd_sound_play(cave, (object == O_DIAMOND ? GD_S_DIAMOND_COLLECTING : + GD_S_FLYING_DIAMOND_COLLECTING), object, x, y); cave->score += cave->diamond_value; cave->diamonds_collected++; @@ -973,7 +1104,7 @@ static boolean do_push(GdCave *cave, int x, int y, GdDirection player_move, bool { /* if decided that he will be able to push, */ store_dir(cave, x, y, GD_MV_TWICE + player_move, what); - play_sound_of_element(cave, what, x, y); + play_sound_of_element_pushing(cave, what, x, y); result = TRUE; } } @@ -1044,7 +1175,7 @@ static boolean do_push(GdCave *cave, int x, int y, GdDirection player_move, bool } if (result) - play_sound_of_element(cave, O_BLADDER, x, y); + play_sound_of_element_pushing(cave, O_BLADDER, x, y); } break; @@ -1216,10 +1347,10 @@ static boolean do_fall_try_magic(GdCave *cave, int x, int y, { play_sound_of_element(cave, O_DIAMOND, x, y); /* always play diamond sound */ - if (cave->magic_wall_state==GD_MW_DORMANT) + if (cave->magic_wall_state == GD_MW_DORMANT) cave->magic_wall_state = GD_MW_ACTIVE; - if (cave->magic_wall_state==GD_MW_ACTIVE && + if (cave->magic_wall_state == GD_MW_ACTIVE && is_space_dir(cave, x, y, GD_MV_TWICE+fall_dir)) { /* if magic wall active and place underneath, it turns element @@ -1433,9 +1564,17 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire, /* set cave get function; to implement perfect or lineshifting borders */ if (cave->lineshift) + { cave->getp = getp_shift; + cave->getx = getx_shift; + cave->gety = gety_shift; + } else + { cave->getp = getp_perfect; + cave->getx = getx_perfect; + cave->gety = gety_perfect; + } /* increment this. if the scan routine comes across player, clears it (sets to zero). */ if (cave->player_seen_ago < 100) @@ -1470,7 +1609,7 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire, for (x = 0; x < cave->w; x++) { /* timer for the cell > 0? */ - if (cave->hammered_reappear[y][x]>0) + if (cave->hammered_reappear[y][x] > 0) { /* decrease timer */ cave->hammered_reappear[y][x]--; @@ -1516,7 +1655,7 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire, { /* if we find a scanned element, change it to the normal one, and that's all. */ /* this is required, for example for chasing stones, which have moved, always passing slime! */ - if (get(cave, x, y)&SCANNED) + if (get(cave, x, y) & SCANNED) { store(cave, x, y, get(cave, x, y) & ~SCANNED); @@ -1541,7 +1680,7 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire, cave->player_seen_ago = 0; /* bd4 intermission caves have many players. so if one of them has exited, * do not change the flag anymore. so this if () is needed */ - if (cave->player_state!=GD_PL_EXITED) + if (cave->player_state != GD_PL_EXITED) cave->player_state = GD_PL_LIVING; /* check for pneumatic hammer things */ @@ -1585,8 +1724,11 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire, /* try to push element; if successful, break */ push = do_push(cave, x, y, player_move, player_fire); if (push) + { remains = O_SPACE; + } else + { switch (what) { case O_BOMB: @@ -1634,9 +1776,10 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire, default: /* get element - process others. if cannot get, player_get_element will return the same */ - remains = player_get_element (cave, what, x, y); + remains = player_get_element(cave, what, x, y); break; } + } if (remains != what || remains == O_SPACE) { @@ -1701,7 +1844,9 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire, /* player fire is false... */ if (do_push(cave, x, y, player_move, FALSE)) + { remains = O_SPACE; + } else { switch (what) @@ -1711,10 +1856,10 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire, player_move parameter) */ /* only allow changing direction if the new dir is not diagonal */ if (cave->gravity_switch_active && - (player_move==GD_MV_LEFT || - player_move==GD_MV_RIGHT || - player_move==GD_MV_UP || - player_move==GD_MV_DOWN)) + (player_move == GD_MV_LEFT || + player_move == GD_MV_RIGHT || + player_move == GD_MV_UP || + player_move == GD_MV_DOWN)) { gd_sound_play(cave, GD_S_SWITCH_GRAVITY, what, x, y); cave->gravity_will_change = @@ -1753,7 +1898,7 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire, cave->player_seen_ago = 0; /* bd4 intermission caves have many players. so if one of them has exited, * do not change the flag anymore. so this if () is needed */ - if (cave->player_state!=GD_PL_EXITED) + if (cave->player_state != GD_PL_EXITED) cave->player_state = GD_PL_LIVING; if (player_fire) @@ -1776,7 +1921,7 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire, } cave->player_seen_ago = 0; - if (cave->player_state!=GD_PL_EXITED) + if (cave->player_state != GD_PL_EXITED) cave->player_state = GD_PL_LIVING; /* if hammering time is up, becomes a normal player again. */ @@ -2491,7 +2636,7 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire, /* is space over the bladder? */ if (is_space_dir(cave, x, y, opposite[grav_compat])) { - if (get(cave, x, y)==O_BLADDER_8) + if (get(cave, x, y) == O_BLADDER_8) { /* if it is a bladder 8, really move up */ move(cave, x, y, opposite[grav_compat], O_BLADDER_1); @@ -2609,7 +2754,7 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire, } /* if alive, check in which dir to grow (or not) */ - if (cave->amoeba_state==GD_AM_AWAKE) + if (cave->amoeba_state == GD_AM_AWAKE) { if (g_rand_int_range(cave->random, 0, 1000000) < cave->amoeba_growth_prob) { @@ -2773,8 +2918,8 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire, if (((get(cave, x, y) == O_H_EXPANDING_WALL || get(cave, x, y) == O_H_EXPANDING_STEEL_WALL) && !cave->expanding_wall_changed) || - ((get(cave, x, y)==O_V_EXPANDING_WALL || - get(cave, x, y)==O_V_EXPANDING_STEEL_WALL) && + ((get(cave, x, y) == O_V_EXPANDING_WALL || + get(cave, x, y) == O_V_EXPANDING_STEEL_WALL) && cave->expanding_wall_changed)) { if (is_space_dir(cave, x, y, GD_MV_LEFT)) @@ -2899,13 +3044,13 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire, store_dir(cave, x, y, oppos, O_BLADDER_1); play_sound_of_element(cave, O_SLIME, x, y); } - else if (get_dir(cave, x, y, grav)==O_FLYING_STONE) + else if (get_dir(cave, x, y, grav) == O_FLYING_STONE) { store_dir(cave, x, y, grav, O_SPACE); store_dir(cave, x, y, oppos, O_FLYING_STONE_F); play_sound_of_element(cave, O_SLIME, x, y); } - else if (get_dir(cave, x, y, grav)==O_FLYING_DIAMOND) + else if (get_dir(cave, x, y, grav) == O_FLYING_DIAMOND) { store_dir(cave, x, y, grav, O_SPACE); store_dir(cave, x, y, oppos, O_FLYING_DIAMOND_F); @@ -3222,7 +3367,7 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire, /* this loop finds the coordinates of the player. needed for scrolling and chasing stone.*/ /* but we only do this, if a living player was found. if not yet, the setup routine coordinates are used */ - if (cave->player_state==GD_PL_LIVING) + if (cave->player_state == GD_PL_LIVING) { if (cave->active_is_first_found) {