From: Holger Schemel Date: Sun, 10 Oct 1999 03:31:09 +0000 (+0200) Subject: rnd-19991010-1-src X-Git-Tag: 1.4.0^2~6 X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=commitdiff_plain;h=f806f2ad0dfa82c3abd3d027250a549ca22f4374 rnd-19991010-1-src --- diff --git a/src/editor.c b/src/editor.c index 5b77b1fc..379da414 100644 --- a/src/editor.c +++ b/src/editor.c @@ -1057,6 +1057,11 @@ int editor_element[] = EL_CHAR('I'), EL_CHAR('I'), + EL_PEARL, + EL_CRYSTAL, + EL_WALL_PEARL, + EL_WALL_CRYSTAL, + EL_BELT1_LEFT, EL_BELT1_MIDDLE, EL_BELT1_RIGHT, @@ -1112,6 +1117,46 @@ int editor_element[] = EL_EXTRA_TIME, EL_LEERRAUM, + EL_CHAR('D'), + EL_CHAR('X'), + EL_CHAR('-'), + EL_CHAR(' '), + + EL_CHAR('B'), + EL_CHAR('O'), + EL_CHAR('U'), + EL_CHAR('L'), + + EL_CHAR('-'), + EL_CHAR('D'), + EL_CHAR('E'), + EL_CHAR('R'), + + EL_CHAR('D'), + EL_CHAR('A'), + EL_CHAR('S'), + EL_CHAR('H'), + + EL_SPRING, + EL_TUBE_RIGHT_DOWN, + EL_TUBE_HORIZ_DOWN, + EL_TUBE_LEFT_DOWN, + + EL_TUBE_HORIZONTAL, + EL_TUBE_VERT_RIGHT, + EL_TUBE_CROSS, + EL_TUBE_VERT_LEFT, + + EL_TUBE_VERTICAL, + EL_TUBE_RIGHT_UP, + EL_TUBE_HORIZ_UP, + EL_TUBE_LEFT_UP, + + EL_TRAP_INACTIVE, + EL_LEERRAUM, + EL_LEERRAUM, + EL_LEERRAUM, + /* EL_CHAR('D'), EL_CHAR('Y'), diff --git a/src/files.c b/src/files.c index e0d444b1..fa40845e 100644 --- a/src/files.c +++ b/src/files.c @@ -421,22 +421,22 @@ static void setLevelInfoToDefaults() switch (LEVELCLASS(leveldir_current)) { case LEVELCLASS_TUTORIAL: - strcpy(level.author, PROGRAM_AUTHOR_STRING); - break; + strcpy(level.author, PROGRAM_AUTHOR_STRING); + break; case LEVELCLASS_CONTRIBUTION: - strncpy(level.author, leveldir_current->name,MAX_LEVEL_AUTHOR_LEN); - level.author[MAX_LEVEL_AUTHOR_LEN] = '\0'; - break; + strncpy(level.author, leveldir_current->name,MAX_LEVEL_AUTHOR_LEN); + level.author[MAX_LEVEL_AUTHOR_LEN] = '\0'; + break; case LEVELCLASS_USER: - strncpy(level.author, getRealName(), MAX_LEVEL_AUTHOR_LEN); - level.author[MAX_LEVEL_AUTHOR_LEN] = '\0'; - break; + strncpy(level.author, getRealName(), MAX_LEVEL_AUTHOR_LEN); + level.author[MAX_LEVEL_AUTHOR_LEN] = '\0'; + break; default: - /* keep default value */ - break; + /* keep default value */ + break; } } } @@ -1431,6 +1431,42 @@ static void setLevelDirInfoToDefaults(struct LevelDirInfo *ldi) ldi->next = NULL; } +static void setLevelDirInfoToDefaultsFromParent(struct LevelDirInfo *ldi, + struct LevelDirInfo *parent) +{ + if (parent == NULL) + { + setLevelDirInfoToDefaults(ldi); + return; + } + + /* first copy all values from the parent structure ... */ + *ldi = *parent; + + /* ... then set all fields to default that cannot be inherited from parent. + This is especially important for all those fields that can be set from + the 'levelinfo.conf' config file, because the function 'setSetupInfo()' + calls 'free()' for all already set token values which requires that no + other structure's pointer may point to them! + */ + + ldi->filename = NULL; + ldi->fullpath = NULL; + ldi->basepath = NULL; + ldi->name = getStringCopy(ANONYMOUS_NAME); + ldi->name_short = NULL; + ldi->name_sorting = NULL; + ldi->author = getStringCopy(parent->author); + ldi->imported_from = getStringCopy(parent->imported_from); + + ldi->level_group = FALSE; + ldi->parent_link = FALSE; + + ldi->node_parent = parent; + ldi->node_group = NULL; + ldi->next = NULL; +} + static void setSetupInfoToDefaults(struct SetupInfo *si) { int i; @@ -1636,9 +1672,7 @@ static void LoadLevelInfoFromLevelDir(struct LevelDirInfo **node_first, int i; checkSetupFileListIdentifier(setup_file_list, LEVELINFO_COOKIE); - setLevelDirInfoToDefaults(leveldir_new); - - leveldir_new->node_parent = node_parent; + setLevelDirInfoToDefaultsFromParent(leveldir_new, node_parent); /* set all structure fields according to the token/value pairs */ ldi = *leveldir_new; diff --git a/src/game.c b/src/game.c index da36f241..b732e32c 100644 --- a/src/game.c +++ b/src/game.c @@ -103,7 +103,7 @@ /* forward declaration for internal use */ static void CloseAllOpenTimegates(void); static void CheckGravityMovement(struct PlayerInfo *); -static void KillHeroUnlessShield(struct PlayerInfo *); +static void KillHeroUnlessProtected(int, int); static void MapGameButtons(); static void HandleGameButtons(struct GadgetInfo *); @@ -1290,7 +1290,7 @@ void Explode(int ex, int ey, int phase, int mode) if (element == EL_EXPLODING) element = Store2[x][y]; - if (IS_PLAYER(ex, ey) && !SHIELD_ON(PLAYERINFO(ex, ey))) + if (IS_PLAYER(ex, ey) && !PLAYER_PROTECTED(ex, ey)) { switch(StorePlayer[ex][ey]) { @@ -1338,6 +1338,10 @@ void Explode(int ex, int ey, int phase, int mode) Store[x][y] = EL_EDELSTEIN_ROT; else if (element == EL_ERZ_EDEL_LILA) Store[x][y] = EL_EDELSTEIN_LILA; + else if (element == EL_WALL_PEARL) + Store[x][y] = EL_PEARL; + else if (element == EL_WALL_CRYSTAL) + Store[x][y] = EL_CRYSTAL; else if (!IS_PFORTE(Store[x][y])) Store[x][y] = EL_LEERRAUM; @@ -1391,7 +1395,7 @@ void Explode(int ex, int ey, int phase, int mode) int element = Store2[x][y]; if (IS_PLAYER(x, y)) - KillHeroUnlessShield(PLAYERINFO(x, y)); + KillHeroUnlessProtected(x, y); else if (IS_EXPLOSIVE(element)) { Feld[x][y] = Store2[x][y]; @@ -1774,11 +1778,17 @@ void Impact(int x, int y) Bang(x, y); return; } + else if (element == EL_PEARL) + { + Feld[x][y] = EL_PEARL_BREAKING; + PlaySoundLevel(x, y, SND_KNACK); + return; + } if (element == EL_TROPFEN && (lastline || object_hit)) /* acid drop */ { if (object_hit && IS_PLAYER(x, y+1)) - KillHeroUnlessShield(PLAYERINFO(x, y+1)); + KillHeroUnlessProtected(x, y+1); else if (object_hit && smashed == EL_PINGUIN) Bang(x, y+1); else @@ -1811,7 +1821,7 @@ void Impact(int x, int y) if (IS_PLAYER(x, y+1)) { - KillHeroUnlessShield(PLAYERINFO(x, y+1)); + KillHeroUnlessProtected(x, y+1); return; } else if (smashed == EL_PINGUIN) @@ -1851,6 +1861,12 @@ void Impact(int x, int y) RaiseScoreElement(EL_KOKOSNUSS); return; } + else if (smashed == EL_PEARL) + { + Feld[x][y+1] = EL_PEARL_BREAKING; + PlaySoundLevel(x, y, SND_KNACK); + return; + } else if (smashed == EL_DIAMANT) { Feld[x][y+1] = EL_LEERRAUM; @@ -2626,7 +2642,7 @@ void StartMoving(int x, int y) Moving2Blocked(x, y, &newx, &newy); /* get next screen position */ if (IS_ENEMY(element) && IS_PLAYER(newx, newy) && - !SHIELD_ON(PLAYERINFO(newx, newy))) + !PLAYER_PROTECTED(newx, newy)) { #if 1 @@ -3503,7 +3519,8 @@ void NussKnacken(int x, int y) { MovDelay[x][y]--; if (MovDelay[x][y]/2 && IN_SCR_FIELD(SCREENX(x), SCREENY(y))) - DrawGraphic(SCREENX(x), SCREENY(y), GFX_CRACKINGNUT+3-MovDelay[x][y]/2); + DrawGraphic(SCREENX(x), SCREENY(y), + GFX_CRACKINGNUT + 3 - MovDelay[x][y]/2); if (!MovDelay[x][y]) { @@ -3513,6 +3530,26 @@ void NussKnacken(int x, int y) } } +void BreakingPearl(int x, int y) +{ + if (!MovDelay[x][y]) /* next animation frame */ + MovDelay[x][y] = 9; + + if (MovDelay[x][y]) /* wait some time before next frame */ + { + MovDelay[x][y]--; + if (MovDelay[x][y]/2 && IN_SCR_FIELD(SCREENX(x), SCREENY(y))) + DrawGraphic(SCREENX(x), SCREENY(y), + GFX_PEARL_BREAKING + 4 - MovDelay[x][y]/2); + + if (!MovDelay[x][y]) + { + Feld[x][y] = EL_LEERRAUM; + DrawLevelField(x, y); + } + } +} + void SiebAktivieren(int x, int y, int typ) { int graphic = (typ == 1 ? GFX_SIEB_VOLL : GFX_SIEB2_VOLL) + 3; @@ -3919,10 +3956,10 @@ static void CheckBuggyBase(int x, int y) if (element == EL_SP_BUG) { - if (!MovDelay[x][y]) /* start activating buggy base */ + if (!MovDelay[x][y]) /* wait some time before activating base */ MovDelay[x][y] = 2 * FRAMES_PER_SECOND + RND(5 * FRAMES_PER_SECOND); - if (MovDelay[x][y]) /* wait some time before activating base */ + if (MovDelay[x][y]) { MovDelay[x][y]--; if (MovDelay[x][y] < 5 && IN_SCR_FIELD(SCREENX(x), SCREENY(y))) @@ -3938,7 +3975,7 @@ static void CheckBuggyBase(int x, int y) if (!MovDelay[x][y]) /* start activating buggy base */ MovDelay[x][y] = 1 * FRAMES_PER_SECOND + RND(1 * FRAMES_PER_SECOND); - if (MovDelay[x][y]) /* wait some time before activating base */ + if (MovDelay[x][y]) { MovDelay[x][y]--; if (MovDelay[x][y]) @@ -3975,6 +4012,61 @@ static void CheckBuggyBase(int x, int y) } } +static void CheckTrap(int x, int y) +{ + int element = Feld[x][y]; + + if (element == EL_TRAP_INACTIVE) + { + if (!MovDelay[x][y]) /* wait some time before activating trap */ + MovDelay[x][y] = 2 * FRAMES_PER_SECOND + RND(5 * FRAMES_PER_SECOND); + + if (MovDelay[x][y]) + { + MovDelay[x][y]--; + if (MovDelay[x][y]) + return; + + Feld[x][y] = EL_TRAP_ACTIVE; + } + } + else if (element == EL_TRAP_ACTIVE) + { + int delay = 4; + int num_frames = 8; + + if (!MovDelay[x][y]) /* start activating trap */ + MovDelay[x][y] = num_frames * delay; + + if (MovDelay[x][y]) + { + MovDelay[x][y]--; + + if (MovDelay[x][y]) + { + if (!(MovDelay[x][y] % delay)) + { + int phase = MovDelay[x][y]/delay; + + if (phase >= num_frames/2) + phase = num_frames - phase; + + if (IN_SCR_FIELD(SCREENX(x), SCREENY(y))) + { + DrawGraphic(SCREENX(x),SCREENY(y), GFX_TRAP_INACTIVE + phase - 1); + ErdreichAnbroeckeln(SCREENX(x), SCREENY(y)); + } + } + + return; + } + + Feld[x][y] = EL_TRAP_INACTIVE; + DrawLevelField(x, y); + } + } +} + static void DrawBeltAnimation(int x, int y, int element) { int belt_nr = getBeltNrFromElement(element); @@ -4260,6 +4352,8 @@ void GameActions() Blurb(x, y); else if (element == EL_CRACKINGNUT) NussKnacken(x, y); + else if (element == EL_PEARL_BREAKING) + BreakingPearl(x, y); else if (element == EL_AUSGANG_ZU) AusgangstuerPruefen(x, y); else if (element == EL_AUSGANG_ACT) @@ -4277,6 +4371,8 @@ void GameActions() CheckForDragon(x, y); else if (element == EL_SP_BUG || element == EL_SP_BUG_ACTIVE) CheckBuggyBase(x, y); + else if (element == EL_TRAP_INACTIVE || element == EL_TRAP_ACTIVE) + CheckTrap(x, y); else if (element == EL_SP_TERMINAL) DrawGraphicAnimation(x, y, GFX2_SP_TERMINAL, 7, 12, ANIM_NORMAL); else if (element == EL_SP_TERMINAL_ACTIVE) @@ -4560,14 +4656,7 @@ boolean MoveFigureOneStep(struct PlayerInfo *player, BuryHero(player); } else - { -#if 1 TestIfBadThingHitsHero(new_jx, new_jy); -#else - if (player->shield_time_left == 0) - KillHero(player); -#endif - } return MF_MOVING; } @@ -4886,7 +4975,7 @@ void TestIfGoodThingHitsBadThing(int goodx, int goody) if (player->shield_active_time_left > 0) Bang(killx, killy); - else if (player->shield_passive_time_left == 0) + else if (!PLAYER_PROTECTED(goodx, goody)) KillHero(player); } else @@ -4951,7 +5040,7 @@ void TestIfBadThingHitsGoodThing(int badx, int bady) if (player->shield_active_time_left > 0) Bang(badx, bady); - else if (player->shield_passive_time_left == 0) + else if (!PLAYER_PROTECTED(killx, killy)) KillHero(player); } else @@ -5031,10 +5120,10 @@ void KillHero(struct PlayerInfo *player) BuryHero(player); } -static void KillHeroUnlessShield(struct PlayerInfo *player) +static void KillHeroUnlessProtected(int x, int y) { - if (!SHIELD_ON(player)) - KillHero(player); + if (!PLAYER_PROTECTED(x, y)) + KillHero(PLAYERINFO(x, y)); } void BuryHero(struct PlayerInfo *player) @@ -5096,6 +5185,36 @@ int DigField(struct PlayerInfo *player, if (IS_MOVING(x, y) || IS_PLAYER(x, y)) return MF_NO_ACTION; + if (IS_TUBE(Feld[jx][jy])) + { + int i = 0; + int tube_leave_directions[][2] = + { + { EL_TUBE_CROSS, MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN }, + { EL_TUBE_VERTICAL, MV_UP | MV_DOWN }, + { EL_TUBE_HORIZONTAL, MV_LEFT | MV_RIGHT }, + { EL_TUBE_VERT_LEFT, MV_LEFT | MV_UP | MV_DOWN }, + { EL_TUBE_VERT_RIGHT, MV_RIGHT | MV_UP | MV_DOWN }, + { EL_TUBE_HORIZ_UP, MV_LEFT | MV_RIGHT | MV_UP }, + { EL_TUBE_HORIZ_DOWN, MV_LEFT | MV_RIGHT | MV_DOWN }, + { EL_TUBE_LEFT_UP, MV_LEFT | MV_UP }, + { EL_TUBE_LEFT_DOWN, MV_LEFT | MV_DOWN }, + { EL_TUBE_RIGHT_UP, MV_RIGHT | MV_UP }, + { EL_TUBE_RIGHT_DOWN, MV_RIGHT | MV_DOWN }, + { -1, MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN } + }; + + while (tube_leave_directions[i][0] != Feld[jx][jy]) + { + i++; + if (tube_leave_directions[i][0] == -1) /* should not happen */ + break; + } + + if (!(tube_leave_directions[i][1] & move_direction)) + return MF_NO_ACTION; /* tube has no opening in this direction */ + } + element = Feld[x][y]; switch (element) @@ -5106,6 +5225,7 @@ int DigField(struct PlayerInfo *player, case EL_ERDREICH: case EL_SAND_INVISIBLE: + case EL_TRAP_INACTIVE: Feld[x][y] = EL_LEERRAUM; PlaySoundLevel(x, y, SND_SCHLURF); break; @@ -5123,8 +5243,12 @@ int DigField(struct PlayerInfo *player, case EL_EDELSTEIN_LILA: case EL_DIAMANT: case EL_SP_INFOTRON: + case EL_PEARL: + case EL_CRYSTAL: RemoveField(x, y); - local_player->gems_still_needed -= (element == EL_DIAMANT ? 3 : 1); + local_player->gems_still_needed -= (element == EL_DIAMANT ? 3 : + element == EL_PEARL ? 5 : + element == EL_CRYSTAL ? 8 : 1); if (local_player->gems_still_needed < 0) local_player->gems_still_needed = 0; RaiseScoreElement(element); @@ -5490,7 +5614,47 @@ int DigField(struct PlayerInfo *player, DOUBLE_PLAYER_SPEED(player); PlaySoundLevel(x, y, SND_GATE); + break; + + case EL_TUBE_CROSS: + case EL_TUBE_VERTICAL: + case EL_TUBE_HORIZONTAL: + case EL_TUBE_VERT_LEFT: + case EL_TUBE_VERT_RIGHT: + case EL_TUBE_HORIZ_UP: + case EL_TUBE_HORIZ_DOWN: + case EL_TUBE_LEFT_UP: + case EL_TUBE_LEFT_DOWN: + case EL_TUBE_RIGHT_UP: + case EL_TUBE_RIGHT_DOWN: + { + int i = 0; + int tube_enter_directions[][2] = + { + { EL_TUBE_CROSS, MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN }, + { EL_TUBE_VERTICAL, MV_UP | MV_DOWN }, + { EL_TUBE_HORIZONTAL, MV_LEFT | MV_RIGHT }, + { EL_TUBE_VERT_LEFT, MV_RIGHT | MV_UP | MV_DOWN }, + { EL_TUBE_VERT_RIGHT, MV_LEFT | MV_UP | MV_DOWN }, + { EL_TUBE_HORIZ_UP, MV_LEFT | MV_RIGHT | MV_DOWN }, + { EL_TUBE_HORIZ_DOWN, MV_LEFT | MV_RIGHT | MV_UP }, + { EL_TUBE_LEFT_UP, MV_RIGHT | MV_DOWN }, + { EL_TUBE_LEFT_DOWN, MV_RIGHT | MV_UP }, + { EL_TUBE_RIGHT_UP, MV_LEFT | MV_DOWN }, + { EL_TUBE_RIGHT_DOWN, MV_LEFT | MV_UP }, + { -1, MV_NO_MOVING } + }; + while (tube_enter_directions[i][0] != element) + { + i++; + if (tube_enter_directions[i][0] == -1) /* should not happen */ + break; + } + + if (!(tube_enter_directions[i][1] & move_direction)) + return MF_NO_ACTION; /* tube has no opening in this direction */ + } break; case EL_AUSGANG_ZU: @@ -5532,6 +5696,7 @@ int DigField(struct PlayerInfo *player, case EL_SONDE: case EL_SP_DISK_YELLOW: case EL_BALLOON: + case EL_SPRING: if (mode == DF_SNAP) return MF_NO_ACTION; diff --git a/src/init.c b/src/init.c index 64b0ae4e..5a43f577 100644 --- a/src/init.c +++ b/src/init.c @@ -875,7 +875,18 @@ void InitElementProperties() EL_SWITCHGATE_OPEN, EL_SWITCHGATE_CLOSED, EL_TIMEGATE_OPEN, - EL_TIMEGATE_CLOSED + EL_TIMEGATE_CLOSED, + EL_TUBE_CROSS, + EL_TUBE_VERTICAL, + EL_TUBE_HORIZONTAL, + EL_TUBE_VERT_LEFT, + EL_TUBE_VERT_RIGHT, + EL_TUBE_HORIZ_UP, + EL_TUBE_HORIZ_DOWN, + EL_TUBE_LEFT_UP, + EL_TUBE_LEFT_DOWN, + EL_TUBE_RIGHT_UP, + EL_TUBE_RIGHT_DOWN }; static int ep_pforte_num = sizeof(ep_pforte)/sizeof(int); @@ -974,7 +985,21 @@ void InitElementProperties() EL_EMC_WALL_5, EL_EMC_WALL_6, EL_EMC_WALL_7, - EL_EMC_WALL_8 + EL_EMC_WALL_8, + EL_CRYSTAL, + EL_WALL_PEARL, + EL_WALL_CRYSTAL, + EL_TUBE_CROSS, + EL_TUBE_VERTICAL, + EL_TUBE_HORIZONTAL, + EL_TUBE_VERT_LEFT, + EL_TUBE_VERT_RIGHT, + EL_TUBE_HORIZ_UP, + EL_TUBE_HORIZ_DOWN, + EL_TUBE_LEFT_UP, + EL_TUBE_LEFT_DOWN, + EL_TUBE_RIGHT_UP, + EL_TUBE_RIGHT_DOWN }; static int ep_solid_num = sizeof(ep_solid)/sizeof(int); @@ -1049,7 +1074,19 @@ void InitElementProperties() EL_EMC_STEEL_WALL_1, EL_EMC_STEEL_WALL_2, EL_EMC_STEEL_WALL_3, - EL_EMC_STEEL_WALL_4 + EL_EMC_STEEL_WALL_4, + EL_CRYSTAL, + EL_TUBE_CROSS, + EL_TUBE_VERTICAL, + EL_TUBE_HORIZONTAL, + EL_TUBE_VERT_LEFT, + EL_TUBE_VERT_RIGHT, + EL_TUBE_HORIZ_UP, + EL_TUBE_HORIZ_DOWN, + EL_TUBE_LEFT_UP, + EL_TUBE_LEFT_DOWN, + EL_TUBE_RIGHT_UP, + EL_TUBE_RIGHT_DOWN }; static int ep_massive_num = sizeof(ep_massive)/sizeof(int); @@ -1082,7 +1119,9 @@ void InitElementProperties() EL_SP_CHIP_UPPER, EL_SP_CHIP_LOWER, EL_SPEED_PILL, - EL_STEEL_SLANTED + EL_STEEL_SLANTED, + EL_PEARL, + EL_CRYSTAL }; static int ep_slippery_num = sizeof(ep_slippery)/sizeof(int); @@ -1184,7 +1223,10 @@ void InitElementProperties() EL_ZEIT_LEER, EL_SP_ZONK, EL_SP_INFOTRON, - EL_SP_DISK_ORANGE + EL_SP_DISK_ORANGE, + EL_PEARL, + EL_CRYSTAL, + EL_SPRING }; static int ep_can_fall_num = sizeof(ep_can_fall)/sizeof(int); @@ -1212,7 +1254,9 @@ void InitElementProperties() EL_ZEIT_LEER, EL_SP_ZONK, EL_SP_INFOTRON, - EL_SP_DISK_ORANGE + EL_SP_DISK_ORANGE, + EL_PEARL, + EL_CRYSTAL }; static int ep_can_smash_num = sizeof(ep_can_smash)/sizeof(int); @@ -1298,6 +1342,7 @@ void InitElementProperties() EL_SP_SNIKSNAK, EL_SP_ELECTRON, EL_SP_BUG_ACTIVE, + EL_TRAP_ACTIVE, EL_LANDMINE }; static int ep_dont_go_to_num = sizeof(ep_dont_go_to)/sizeof(int); @@ -1323,7 +1368,9 @@ void InitElementProperties() EL_EDELSTEIN_GELB, EL_EDELSTEIN_ROT, EL_EDELSTEIN_LILA, - EL_DIAMANT + EL_DIAMANT, + EL_PEARL, + EL_CRYSTAL }; static int ep_mampf2_num = sizeof(ep_mampf2)/sizeof(int); @@ -1547,7 +1594,9 @@ void InitElementProperties() EL_EDELSTEIN_GELB, EL_EDELSTEIN_ROT, EL_EDELSTEIN_LILA, - EL_DIAMANT + EL_DIAMANT, + EL_PEARL, + EL_CRYSTAL }; static int ep_mampf3_num = sizeof(ep_mampf3)/sizeof(int); @@ -1563,7 +1612,8 @@ void InitElementProperties() EL_SP_ZONK, EL_SP_DISK_ORANGE, EL_SP_DISK_YELLOW, - EL_BALLOON + EL_BALLOON, + EL_SPRING }; static int ep_pushable_num = sizeof(ep_pushable)/sizeof(int); @@ -1592,6 +1642,7 @@ void InitElementProperties() EL_ERDREICH, EL_SP_BASE, EL_SP_BUG, + EL_TRAP_INACTIVE, EL_SAND_INVISIBLE }; static int ep_eatable_num = sizeof(ep_eatable)/sizeof(int); @@ -1681,7 +1732,18 @@ void InitElementProperties() EL_SP_PORT2_DOWN, EL_SP_PORT_X, EL_SP_PORT_Y, - EL_SP_PORT_XY + EL_SP_PORT_XY, + EL_TUBE_CROSS, + EL_TUBE_VERTICAL, + EL_TUBE_HORIZONTAL, + EL_TUBE_VERT_LEFT, + EL_TUBE_VERT_RIGHT, + EL_TUBE_HORIZ_UP, + EL_TUBE_HORIZ_DOWN, + EL_TUBE_LEFT_UP, + EL_TUBE_LEFT_DOWN, + EL_TUBE_RIGHT_UP, + EL_TUBE_RIGHT_DOWN }; static int ep_over_player_num = sizeof(ep_over_player)/sizeof(int); @@ -1729,6 +1791,22 @@ void InitElementProperties() }; static int ep_belt_switch_num = sizeof(ep_belt_switch)/sizeof(int); + static int ep_tube[] = + { + EL_TUBE_CROSS, + EL_TUBE_VERTICAL, + EL_TUBE_HORIZONTAL, + EL_TUBE_VERT_LEFT, + EL_TUBE_VERT_RIGHT, + EL_TUBE_HORIZ_UP, + EL_TUBE_HORIZ_DOWN, + EL_TUBE_LEFT_UP, + EL_TUBE_LEFT_DOWN, + EL_TUBE_RIGHT_UP, + EL_TUBE_RIGHT_DOWN + }; + static int ep_tube_num = sizeof(ep_tube)/sizeof(int); + static long ep1_bit[] = { EP_BIT_AMOEBALIVE, @@ -1766,7 +1844,8 @@ void InitElementProperties() static long ep2_bit[] = { EP_BIT_BELT, - EP_BIT_BELT_SWITCH + EP_BIT_BELT_SWITCH, + EP_BIT_TUBE }; static int *ep1_array[] = { @@ -1805,7 +1884,8 @@ void InitElementProperties() static int *ep2_array[] = { ep_belt, - ep_belt_switch + ep_belt_switch, + ep_tube }; static int *ep1_num[] = { @@ -1844,7 +1924,8 @@ void InitElementProperties() static int *ep2_num[] = { &ep_belt_num, - &ep_belt_switch_num + &ep_belt_switch_num, + &ep_tube_num }; static int num_properties1 = sizeof(ep1_num)/sizeof(int *); static int num_properties2 = sizeof(ep2_num)/sizeof(int *); diff --git a/src/main.c b/src/main.c index 78ce1be2..6d4ece73 100644 --- a/src/main.c +++ b/src/main.c @@ -395,8 +395,8 @@ char *element_info[] = "letter ''", "letter ''", "letter ''", - "growing wall (horizontally)", /* 200 */ - "growing wall (vertically)", + "growing wall (horizontal)", /* 200 */ + "growing wall (vertical)", "growing wall (all directions)", "unused", "unused", @@ -426,8 +426,8 @@ char *element_info[] = "yellow disk", "terminal", "red disk", /* 230 */ - "port (vertically)", - "port (horizontally)", + "port (vertical)", + "port (horizontal)", "port (all directions)", "electron", "buggy base", @@ -542,6 +542,19 @@ char *element_info[] = "normal wall", "normal wall", "normal wall", + "tube (all directions)", + "tube (vertical)", + "tube (horizontal)", + "tube (vertical & left)", + "tube (vertical & right)", + "tube (horizontal & up)", + "tube (horizontal & down)", /* 350 */ + "tube (left & up)", + "tube (left & down)", + "tube (right & up)", + "tube (right & down)", + "spring", + "trap", "-" /* diff --git a/src/main.h b/src/main.h index 9a58655c..66c7d05f 100644 --- a/src/main.h +++ b/src/main.h @@ -132,6 +132,7 @@ typedef unsigned char byte; /* values for 'Elementeigenschaften2' */ #define EP_BIT_BELT (1 << 0) #define EP_BIT_BELT_SWITCH (1 << 1) +#define EP_BIT_TUBE (1 << 2) #define IS_AMOEBALIVE(e) (Elementeigenschaften1[e] & EP_BIT_AMOEBALIVE) #define IS_AMOEBOID(e) (Elementeigenschaften1[e] & EP_BIT_AMOEBOID) @@ -167,6 +168,7 @@ typedef unsigned char byte; #define IS_ACTIVE_BOMB(e) (Elementeigenschaften1[e] & EP_BIT_ACTIVE_BOMB) #define IS_BELT(e) (Elementeigenschaften2[e] & EP_BIT_BELT) #define IS_BELT_SWITCH(e) (Elementeigenschaften2[e] & EP_BIT_BELT_SWITCH) +#define IS_TUBE(e) (Elementeigenschaften2[e] & EP_BIT_TUBE) #define IS_PLAYER(x,y) (ELEM_IS_PLAYER(StorePlayer[x][y])) @@ -192,6 +194,9 @@ typedef unsigned char byte; #define PLAYERINFO(x,y) (&stored_player[StorePlayer[x][y]-EL_SPIELER1]) #define SHIELD_ON(p) ((p)->shield_passive_time_left > 0) +#define PROTECTED_FIELD(x,y) (IS_TUBE(Feld[x][y])) +#define PLAYER_PROTECTED(x,y) (SHIELD_ON(PLAYERINFO(x, y)) || \ + PROTECTED_FIELD(x, y)) /* Pixmaps with graphic file */ #define PIX_BACK 0 @@ -968,6 +973,19 @@ extern char *element_info[]; #define EL_EMC_WALL_7 342 #define EL_EMC_WALL_8 343 +#define EL_TUBE_CROSS 344 +#define EL_TUBE_VERTICAL 345 +#define EL_TUBE_HORIZONTAL 346 +#define EL_TUBE_VERT_LEFT 347 +#define EL_TUBE_VERT_RIGHT 348 +#define EL_TUBE_HORIZ_UP 349 +#define EL_TUBE_HORIZ_DOWN 350 +#define EL_TUBE_LEFT_UP 351 +#define EL_TUBE_LEFT_DOWN 352 +#define EL_TUBE_RIGHT_UP 353 +#define EL_TUBE_RIGHT_DOWN 354 +#define EL_SPRING 355 +#define EL_TRAP_INACTIVE 356 /* "real" (and therefore drawable) runtime elements */ #define EL_FIRST_RUNTIME_EL 500 @@ -993,6 +1011,8 @@ extern char *element_info[]; #define EL_SWITCHGATE_CLOSING 518 #define EL_TIMEGATE_OPENING 519 #define EL_TIMEGATE_CLOSING 520 +#define EL_PEARL_BREAKING 521 +#define EL_TRAP_ACTIVE 522 /* "unreal" (and therefore not drawable) runtime elements */ #define EL_BLOCKED 600 @@ -1437,6 +1457,26 @@ extern char *element_info[]; #define GFX_ARROW_RED_DOWN (GFX_START_ROCKSMORE + 1 * MORE_PER_LINE + 3) #define GFX_SCROLLBAR_BLUE (GFX_START_ROCKSMORE + 2 * MORE_PER_LINE + 0) #define GFX_SCROLLBAR_RED (GFX_START_ROCKSMORE + 2 * MORE_PER_LINE + 1) +#define GFX_PEARL (GFX_START_ROCKSMORE + 3 * MORE_PER_LINE + 0) +#define GFX_CRYSTAL (GFX_START_ROCKSMORE + 3 * MORE_PER_LINE + 1) +#define GFX_WALL_PEARL (GFX_START_ROCKSMORE + 3 * MORE_PER_LINE + 2) +#define GFX_WALL_CRYSTAL (GFX_START_ROCKSMORE + 3 * MORE_PER_LINE + 3) +#define GFX_PEARL_BREAKING (GFX_START_ROCKSMORE + 4 * MORE_PER_LINE + 0) +#define GFX_SPRING (GFX_START_ROCKSMORE + 5 * MORE_PER_LINE + 0) +#define GFX_TUBE_RIGHT_DOWN (GFX_START_ROCKSMORE + 5 * MORE_PER_LINE + 1) +#define GFX_TUBE_HORIZ_DOWN (GFX_START_ROCKSMORE + 5 * MORE_PER_LINE + 2) +#define GFX_TUBE_LEFT_DOWN (GFX_START_ROCKSMORE + 5 * MORE_PER_LINE + 3) +#define GFX_TUBE_HORIZONTAL (GFX_START_ROCKSMORE + 6 * MORE_PER_LINE + 0) +#define GFX_TUBE_VERT_RIGHT (GFX_START_ROCKSMORE + 6 * MORE_PER_LINE + 1) +#define GFX_TUBE_CROSS (GFX_START_ROCKSMORE + 6 * MORE_PER_LINE + 2) +#define GFX_TUBE_VERT_LEFT (GFX_START_ROCKSMORE + 6 * MORE_PER_LINE + 3) +#define GFX_TUBE_VERTICAL (GFX_START_ROCKSMORE + 7 * MORE_PER_LINE + 0) +#define GFX_TUBE_RIGHT_UP (GFX_START_ROCKSMORE + 7 * MORE_PER_LINE + 1) +#define GFX_TUBE_HORIZ_UP (GFX_START_ROCKSMORE + 7 * MORE_PER_LINE + 2) +#define GFX_TUBE_LEFT_UP (GFX_START_ROCKSMORE + 7 * MORE_PER_LINE + 3) + +#define GFX_TRAP_INACTIVE (GFX_START_ROCKSMORE + 0 * MORE_PER_LINE + 4) +#define GFX_TRAP_ACTIVE (GFX_START_ROCKSMORE + 0 * MORE_PER_LINE + 7) /* graphics from "RocksFont" */ #define GFX_CHAR_START (GFX_START_ROCKSFONT) @@ -1471,10 +1511,6 @@ extern char *element_info[]; #define GFX_CHAR_END (GFX_CHAR_START + 79) /* new elements which still have no graphic */ -#define GFX_PEARL GFX_CHAR_FRAGE -#define GFX_CRYSTAL GFX_CHAR_FRAGE -#define GFX_WALL_PEARL GFX_CHAR_FRAGE -#define GFX_WALL_CRYSTAL GFX_CHAR_FRAGE #define GFX_DOOR_WHITE GFX_CHAR_FRAGE #define GFX_DOOR_WHITE_GRAY GFX_CHAR_FRAGE #define GFX_KEY_WHITE GFX_CHAR_FRAGE diff --git a/src/misc.c b/src/misc.c index 40bfad4b..b6f8f940 100644 --- a/src/misc.c +++ b/src/misc.c @@ -334,7 +334,12 @@ char *getPath3(char *path1, char *path2, char *path3) char *getStringCopy(char *s) { - char *s_copy = checked_malloc(strlen(s) + 1); + char *s_copy; + + if (s == NULL) + return NULL; + + s_copy = checked_malloc(strlen(s) + 1); strcpy(s_copy, s); return s_copy; diff --git a/src/tools.c b/src/tools.c index b2815d94..57fb652d 100644 --- a/src/tools.c +++ b/src/tools.c @@ -928,6 +928,13 @@ void getMiniGraphicSource(int graphic, Pixmap *pixmap, int *x, int *y) *x = MINI_DC_STARTX + (graphic % MINI_DC_PER_LINE) * MINI_TILEX; *y = MINI_DC_STARTY + (graphic / MINI_DC_PER_LINE) * MINI_TILEY; } + else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE) + { + graphic -= GFX_START_ROCKSMORE; + *pixmap = pix[PIX_MORE]; + *x = MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX; + *y = MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY; + } else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT) { graphic -= GFX_START_ROCKSFONT; @@ -1278,7 +1285,10 @@ void ErdreichAnbroeckeln(int x, int y) element = Feld[ux][uy]; - if (element == EL_ERDREICH || element == EL_LANDMINE) + if (element == EL_ERDREICH || + element == EL_LANDMINE || + element == EL_TRAP_INACTIVE || + element == EL_TRAP_ACTIVE) { if (!IN_SCR_FIELD(x, y)) return; @@ -1296,7 +1306,10 @@ void ErdreichAnbroeckeln(int x, int y) else element = Feld[uxx][uyy]; - if (element == EL_ERDREICH || element == EL_LANDMINE) + if (element == EL_ERDREICH || + element == EL_LANDMINE || + element == EL_TRAP_INACTIVE || + element == EL_TRAP_ACTIVE) continue; if (i == 1 || i == 2) @@ -1336,7 +1349,10 @@ void ErdreichAnbroeckeln(int x, int y) uyy = uy + xy[i][1]; if (!IN_LEV_FIELD(uxx, uyy) || - (Feld[uxx][uyy] != EL_ERDREICH && Feld[uxx][uyy] != EL_LANDMINE) || + (Feld[uxx][uyy] != EL_ERDREICH && + Feld[uxx][uyy] != EL_LANDMINE && + Feld[uxx][uyy] != EL_TRAP_INACTIVE && + Feld[uxx][uyy] != EL_TRAP_ACTIVE) || !IN_SCR_FIELD(xx, yy)) continue; @@ -1552,6 +1568,14 @@ void DrawMicroElement(int xpos, int ypos, int element) MICRO_DC_STARTY + (graphic / MICRO_DC_PER_LINE) * MICRO_TILEY, MICRO_TILEX, MICRO_TILEY, xpos, ypos); } + else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE) + { + graphic -= GFX_START_ROCKSMORE; + XCopyArea(display, pix[PIX_MORE], drawto, gc, + MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE) *MICRO_TILEX, + MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE) *MICRO_TILEY, + MICRO_TILEX, MICRO_TILEY, xpos, ypos); + } else XCopyArea(display, pix[PIX_BACK], drawto, gc, MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX, @@ -2614,6 +2638,20 @@ int el2gfx(int element) case EL_EMC_WALL_6: return GFX_EMC_WALL_6; case EL_EMC_WALL_7: return GFX_EMC_WALL_7; case EL_EMC_WALL_8: return GFX_EMC_WALL_8; + case EL_TUBE_CROSS: return GFX_TUBE_CROSS; + case EL_TUBE_VERTICAL: return GFX_TUBE_VERTICAL; + case EL_TUBE_HORIZONTAL: return GFX_TUBE_HORIZONTAL; + case EL_TUBE_VERT_LEFT: return GFX_TUBE_VERT_LEFT; + case EL_TUBE_VERT_RIGHT: return GFX_TUBE_VERT_RIGHT; + case EL_TUBE_HORIZ_UP: return GFX_TUBE_HORIZ_UP; + case EL_TUBE_HORIZ_DOWN: return GFX_TUBE_HORIZ_DOWN; + case EL_TUBE_LEFT_UP: return GFX_TUBE_LEFT_UP; + case EL_TUBE_LEFT_DOWN: return GFX_TUBE_LEFT_DOWN; + case EL_TUBE_RIGHT_UP: return GFX_TUBE_RIGHT_UP; + case EL_TUBE_RIGHT_DOWN: return GFX_TUBE_RIGHT_DOWN; + case EL_SPRING: return GFX_SPRING; + case EL_TRAP_INACTIVE: return GFX_TRAP_INACTIVE; + case EL_TRAP_ACTIVE: return GFX_TRAP_ACTIVE; default: {