From a476bb35e8b7a41f8bef49d6ffd7ec9478ece646 Mon Sep 17 00:00:00 2001 From: Holger Schemel Date: Fri, 24 Feb 2023 01:08:56 +0100 Subject: [PATCH] improved handling laser on two diagonally adjacent elements in MM engine --- src/game_mm/mm_game.c | 64 +++++++++++++++++++++++++++++++------------ src/game_mm/mm_main.h | 9 ++++++ 2 files changed, 55 insertions(+), 18 deletions(-) diff --git a/src/game_mm/mm_game.c b/src/game_mm/mm_game.c index 78f0f954..d4a69181 100644 --- a/src/game_mm/mm_game.c +++ b/src/game_mm/mm_game.c @@ -1049,24 +1049,44 @@ static void ScanLaser(void) break; } - if (hit_mask == (HIT_MASK_TOPRIGHT | HIT_MASK_BOTTOMLEFT)) + if (hit_mask == HIT_MASK_DIAGONAL_1 || hit_mask == HIT_MASK_DIAGONAL_2) { - /* we have hit the top-right and bottom-left element -- - choose the bottom-left one */ - /* !!! THIS CAN BE DONE MORE INTELLIGENTLY, FOR EXAMPLE, IF ONE - ELEMENT WAS STEEL AND THE OTHER ONE WAS ICE => ALWAYS CHOOSE - THE ICE AND MELT IT AWAY INSTEAD OF OVERLOADING LASER !!! */ - ELX = (LX - 2) / TILEX; - ELY = (LY + 2) / TILEY; - } + // we have hit two diagonally adjacent elements -- compare them + boolean dia_1 = (hit_mask == HIT_MASK_DIAGONAL_1); + int xoffset = 2; + int yoffset = 2 * (dia_1 ? -1 : +1); + int elx1 = (LX - xoffset) / TILEX; + int ely1 = (LY + yoffset) / TILEY; + int elx2 = (LX + xoffset) / TILEX; + int ely2 = (LY - yoffset) / TILEY; + int e1 = Tile[elx1][ely1]; + int e2 = Tile[elx2][ely2]; + boolean use_element_1 = FALSE; + + if (IS_WALL_ICE(e1) || IS_WALL_ICE(e2)) + { + if (IS_WALL_ICE(e1) && IS_WALL_ICE(e2)) + use_element_1 = (RND(2) ? TRUE : FALSE); + else if (IS_WALL_ICE(e1)) + use_element_1 = TRUE; + } + else if (IS_WALL_AMOEBA(e1) || IS_WALL_AMOEBA(e2)) + { + if (IS_WALL_AMOEBA(e1) && IS_WALL_AMOEBA(e2)) + use_element_1 = (RND(2) ? TRUE : FALSE); + else if (IS_WALL_AMOEBA(e1)) + use_element_1 = TRUE; + } + else if (IS_ABSORBING_BLOCK(e1) || IS_ABSORBING_BLOCK(e2)) + { + if (IS_ABSORBING_BLOCK(e1) && IS_ABSORBING_BLOCK(e2)) + use_element_1 = (RND(2) ? TRUE : FALSE); + else if (IS_ABSORBING_BLOCK(e1)) + use_element_1 = TRUE; + } - if (hit_mask == (HIT_MASK_TOPLEFT | HIT_MASK_BOTTOMRIGHT)) - { - /* we have hit the top-left and bottom-right element -- - choose the top-left one */ - // !!! SEE ABOVE !!! - ELX = (LX - 2) / TILEX; - ELY = (LY - 2) / TILEY; + ELX = (use_element_1 ? elx1 : elx2); + ELY = (use_element_1 ? ely1 : ely2); } #if 0 @@ -2405,10 +2425,18 @@ static boolean HitAbsorbingWalls(int element, int hit_mask) if (IS_WALL_ICE(element)) { + int lx = LX + XS; + int ly = LY + YS; int mask; - mask = (LX + XS) / MINI_TILEX - ELX * 2 + 1; // Quadrant (horizontal) - mask <<= (((LY + YS) / MINI_TILEY - ELY * 2) > 0) * 2; // || (vertical) + // check if laser hit adjacent edges of two diagonal tiles + if (ELX != lx / TILEX) + lx = LX - XS; + if (ELY != ly / TILEY) + ly = LY - YS; + + mask = lx / MINI_TILEX - ELX * 2 + 1; // Quadrant (horizontal) + mask <<= ((ly / MINI_TILEY - ELY * 2) > 0 ? 2 : 0); // || (vertical) // check if laser hits wall with an angle of 90° if (IS_90_ANGLE(laser.current_angle)) diff --git a/src/game_mm/mm_main.h b/src/game_mm/mm_main.h index cf99e635..7350890b 100644 --- a/src/game_mm/mm_main.h +++ b/src/game_mm/mm_main.h @@ -124,6 +124,13 @@ (e) == EL_BOMB || \ IS_WALL_AMOEBA(e)) +#define IS_ABSORBING_BLOCK(e) (IS_WALL_WOOD(e) || \ + IS_DF_WALL_WOOD(e) || \ + (e) == EL_BLOCK_WOOD || \ + (e) == EL_GATE_WOOD || \ + (e) == EL_EXIT_CLOSED || \ + (e) == EL_EXIT_OPEN) + #define IS_ENVELOPE_OPENING(e) ((e) >= EL_ENVELOPE_OPENING_START && \ (e) <= EL_ENVELOPE_OPENING_END) @@ -712,6 +719,8 @@ extern int num_element_info; #define HIT_MASK_RIGHT (HIT_MASK_TOPRIGHT | HIT_MASK_BOTTOMRIGHT) #define HIT_MASK_TOP (HIT_MASK_TOPLEFT | HIT_MASK_TOPRIGHT) #define HIT_MASK_BOTTOM (HIT_MASK_BOTTOMLEFT | HIT_MASK_BOTTOMRIGHT) +#define HIT_MASK_DIAGONAL_1 (HIT_MASK_TOPLEFT | HIT_MASK_BOTTOMRIGHT) +#define HIT_MASK_DIAGONAL_2 (HIT_MASK_TOPRIGHT | HIT_MASK_BOTTOMLEFT) #define HIT_MASK_ALL (HIT_MASK_LEFT | HIT_MASK_RIGHT) // step values for rotating elements -- 2.34.1