From 695b9e3d2e2ee94c93d2e804aa3c23dd34f68a25 Mon Sep 17 00:00:00 2001 From: Holger Schemel Date: Tue, 22 Jan 2008 01:01:22 +0100 Subject: [PATCH] rnd-20080122-1-src * added condition "deadly when " for custom elements that behaves a bit like the existing "deadly when ", but with the following differences: - it only kills players or friends when it was moving before it hits - it does not kill players or friends that try to run into it --- ChangeLog | 7 +++++ src/conftime.h | 2 +- src/editor.c | 5 ++++ src/game.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++- src/main.h | 2 ++ 5 files changed, 88 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index d9b14c6f..9940b396 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2008-01-22 + * added condition "deadly when " for custom elements + that behaves a bit like the existing "deadly when ", + but with the following differences: + - it only kills players or friends when it was moving before it hits + - it does not kill players or friends that try to run into it + 2008-01-21 * fixed the following change conditions where a player element is used as the "element that is triggering the custom element change": diff --git a/src/conftime.h b/src/conftime.h index 2ea92065..fa795ebb 100644 --- a/src/conftime.h +++ b/src/conftime.h @@ -1 +1 @@ -#define COMPILE_DATE_STRING "2008-01-21 23:05" +#define COMPILE_DATE_STRING "2008-01-22 01:00" diff --git a/src/editor.c b/src/editor.c index 084a2d58..57331cfc 100644 --- a/src/editor.c +++ b/src/editor.c @@ -1515,6 +1515,7 @@ static struct ValueTextInfo options_deadliness[] = { { EP_DONT_RUN_INTO, "running into" }, { EP_DONT_COLLIDE_WITH, "colliding with" }, + { EP_DONT_GET_HIT_BY, "getting hit by" }, { EP_DONT_TOUCH, "touching" }, { -1, NULL } @@ -6771,11 +6772,13 @@ static void CopyCustomElementPropertiesToEditor(int element) /* set deadliness selectbox help value */ custom_element.deadliness = (DONT_TOUCH(element) ? EP_DONT_TOUCH : + DONT_GET_HIT_BY(element) ? EP_DONT_GET_HIT_BY : DONT_COLLIDE_WITH(element) ? EP_DONT_COLLIDE_WITH : DONT_RUN_INTO(element) ? EP_DONT_RUN_INTO : custom_element.deadliness); custom_element_properties[EP_DEADLY] = (DONT_TOUCH(element) || + DONT_GET_HIT_BY(element) || DONT_COLLIDE_WITH(element) || DONT_RUN_INTO(element)); @@ -6923,6 +6926,7 @@ static void CopyCustomElementPropertiesToGame(int element) /* set deadliness property from checkbox and selectbox */ custom_element_properties[EP_DONT_RUN_INTO] = FALSE; custom_element_properties[EP_DONT_COLLIDE_WITH] = FALSE; + custom_element_properties[EP_DONT_GET_HIT_BY] = FALSE; custom_element_properties[EP_DONT_TOUCH] = FALSE; custom_element_properties[custom_element.deadliness] = custom_element_properties[EP_DEADLY]; @@ -7714,6 +7718,7 @@ static void DrawPropertiesInfo() { EP_DONT_RUN_INTO, "- deadly when running into" }, { EP_DONT_COLLIDE_WITH, "- deadly when colliding with" }, + { EP_DONT_GET_HIT_BY, "- deadly when getting hit by" }, { EP_DONT_TOUCH, "- deadly when touching" }, { EP_INDESTRUCTIBLE, "- indestructible" }, diff --git a/src/game.c b/src/game.c index 71d83bbc..cf5441bf 100644 --- a/src/game.c +++ b/src/game.c @@ -62,7 +62,7 @@ #define USE_GFX_RESET_WHEN_NOT_MOVING (USE_NEW_STUFF * 1) -#define USE_DELAYED_GFX_REDRAW (USE_NEW_STUFF * 1) +#define USE_DELAYED_GFX_REDRAW (USE_NEW_STUFF * 0) #if USE_DELAYED_GFX_REDRAW #define TEST_DrawLevelField(x, y) \ @@ -1126,6 +1126,7 @@ void TestIfBadThingRunsIntoPlayer(int, int, int); void TestIfFriendTouchesBadThing(int, int); void TestIfBadThingTouchesFriend(int, int); void TestIfBadThingTouchesOtherBadThing(int, int); +void TestIfGoodThingGetsHitByBadThing(int, int, int); void KillPlayer(struct PlayerInfo *); void BuryPlayer(struct PlayerInfo *); @@ -5140,7 +5141,10 @@ static void RemoveField(int x, int y) GfxElement[x][y] = EL_UNDEFINED; GfxAction[x][y] = ACTION_DEFAULT; GfxDir[x][y] = MV_NONE; +#if 0 + /* !!! this would prevent the removed tile from being redrawn !!! */ GfxRedraw[x][y] = GFX_REDRAW_NONE; +#endif } void RemoveMovingField(int x, int y) @@ -8943,6 +8947,11 @@ void ContinueMoving(int x, int y) else if (element == EL_PENGUIN) TestIfFriendTouchesBadThing(newx, newy); + if (DONT_GET_HIT_BY(element)) + { + TestIfGoodThingGetsHitByBadThing(newx, newy, direction); + } + /* give the player one last chance (one more frame) to move away */ if (CAN_FALL(element) && direction == MV_DOWN && (last_line || (!IS_FREE(x, newy + 1) && @@ -12561,6 +12570,9 @@ void GameActions_RND() GfxRedraw[x][y] != GFX_REDRAW_NONE) #endif { + /* !!! PROBLEM: THIS REDRAWS THE PLAYFIELD _AFTER_ THE SCAN, BUT TILES + !!! MAY HAVE CHANGED AFTER BEING DRAWN DURING PLAYFIELD SCAN !!! */ + if (GfxRedraw[x][y] & GFX_REDRAW_TILE) DrawLevelField(x, y); @@ -13905,6 +13917,7 @@ void TestIfBadThingHitsGoodThing(int bad_x, int bad_y, int bad_move_dir) test_x = bad_x + test_xy[i][0]; test_y = bad_y + test_xy[i][1]; + if (!IN_LEV_FIELD(test_x, test_y)) continue; @@ -13935,12 +13948,14 @@ void TestIfBadThingHitsGoodThing(int bad_x, int bad_y, int bad_move_dir) kill_x = test_x; kill_y = test_y; + break; } else if (test_element == EL_PENGUIN) { kill_x = test_x; kill_y = test_y; + break; } } @@ -13963,6 +13978,63 @@ void TestIfBadThingHitsGoodThing(int bad_x, int bad_y, int bad_move_dir) } } +void TestIfGoodThingGetsHitByBadThing(int bad_x, int bad_y, int bad_move_dir) +{ + int bad_element = Feld[bad_x][bad_y]; + int dx = (bad_move_dir == MV_LEFT ? -1 : bad_move_dir == MV_RIGHT ? +1 : 0); + int dy = (bad_move_dir == MV_UP ? -1 : bad_move_dir == MV_DOWN ? +1 : 0); + int test_x = bad_x + dx, test_y = bad_y + dy; + int test_move_dir, test_element; + int kill_x = -1, kill_y = -1; + + if (!IN_LEV_FIELD(test_x, test_y)) + return; + + test_move_dir = + (IS_MOVING(test_x, test_y) ? MovDir[test_x][test_y] : MV_NONE); + + test_element = Feld[test_x][test_y]; + + if (test_move_dir != bad_move_dir) + { + /* good thing can be player or penguin that does not move away */ + if (IS_PLAYER(test_x, test_y)) + { + struct PlayerInfo *player = PLAYERINFO(test_x, test_y); + + /* (note: in comparison to DONT_RUN_TO and DONT_TOUCH, also handle the + player as being hit when he is moving towards the bad thing, because + the "get hit by" condition would be lost after the player stops) */ + if (player->MovPos != 0 && player->MovDir == bad_move_dir) + return; /* player moves away from bad thing */ + + kill_x = test_x; + kill_y = test_y; + } + else if (test_element == EL_PENGUIN) + { + kill_x = test_x; + kill_y = test_y; + } + } + + if (kill_x != -1 || kill_y != -1) + { + if (IS_PLAYER(kill_x, kill_y)) + { + struct PlayerInfo *player = PLAYERINFO(kill_x, kill_y); + + if (player->shield_deadly_time_left > 0 && + !IS_INDESTRUCTIBLE(bad_element)) + Bang(bad_x, bad_y); + else if (!PLAYER_ENEMY_PROTECTED(kill_x, kill_y)) + KillPlayer(player); + } + else + Bang(kill_x, kill_y); + } +} + void TestIfPlayerTouchesBadThing(int x, int y) { TestIfGoodThingHitsBadThing(x, y, MV_NONE); diff --git a/src/main.h b/src/main.h index 71f525fa..3f88801c 100644 --- a/src/main.h +++ b/src/main.h @@ -108,6 +108,7 @@ #define EP_THROWABLE 28 #define EP_CAN_EXPLODE 29 #define EP_GRAVITY_REACHABLE 30 +#define EP_DONT_GET_HIT_BY 31 /* values for pre-defined properties */ /* (from here on, values can be changed by inserting new values) */ @@ -548,6 +549,7 @@ #define IS_THROWABLE(e) HAS_PROPERTY(e, EP_THROWABLE) #define CAN_EXPLODE(e) HAS_PROPERTY(e, EP_CAN_EXPLODE) #define IS_GRAVITY_REACHABLE(e) HAS_PROPERTY(e, EP_GRAVITY_REACHABLE) +#define DONT_GET_HIT_BY(e) HAS_PROPERTY(e, EP_DONT_GET_HIT_BY) /* macros for special configurable properties */ #define IS_EM_SLIPPERY_WALL(e) HAS_PROPERTY(e, EP_EM_SLIPPERY_WALL) -- 2.34.1