X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame.c;h=fd58165902daf1fb29f4b49747943b541fb28d9b;hb=5e8d9d0308f76bb35e7578a8859d6f01977d0f69;hp=15c379531fc488fc94a14f84cc5b0c02b7d6cc5e;hpb=cf5b3a1e9077e88eb40ce2fb59e985a0ae037c84;p=rocksndiamonds.git diff --git a/src/game.c b/src/game.c index 15c37953..fd581659 100644 --- a/src/game.c +++ b/src/game.c @@ -23,64 +23,111 @@ #include "tape.h" #include "joystick.h" -extern int Gamespeed; -extern int Movemethod; -extern int Movespeed[2]; - void GetPlayerConfig() { int old_joystick_nr = joystick_nr; if (sound_status==SOUND_OFF) - player.setup &= ~SETUP_SOUND; + local_player->setup &= ~SETUP_SOUND; if (!sound_loops_allowed) { - player.setup &= ~SETUP_SOUND_LOOPS; - player.setup &= ~SETUP_SOUND_MUSIC; + local_player->setup &= ~SETUP_SOUND_LOOPS; + local_player->setup &= ~SETUP_SOUND_MUSIC; } - sound_on = sound_simple_on = SETUP_SOUND_ON(player.setup); - sound_loops_on = SETUP_SOUND_LOOPS_ON(player.setup); - sound_music_on = SETUP_SOUND_MUSIC_ON(player.setup); - toons_on = SETUP_TOONS_ON(player.setup); - direct_draw_on = SETUP_DIRECT_DRAW_ON(player.setup); - fading_on = SETUP_FADING_ON(player.setup); - autorecord_on = SETUP_AUTO_RECORD_ON(player.setup); - joystick_nr = SETUP_2ND_JOYSTICK_ON(player.setup); - quick_doors = SETUP_QUICK_DOORS_ON(player.setup); - scroll_delay_on = SETUP_SCROLL_DELAY_ON(player.setup); + sound_on = sound_simple_on = SETUP_SOUND_ON(local_player->setup); + sound_loops_on = SETUP_SOUND_LOOPS_ON(local_player->setup); + sound_music_on = SETUP_SOUND_MUSIC_ON(local_player->setup); + toons_on = SETUP_TOONS_ON(local_player->setup); + direct_draw_on = SETUP_DIRECT_DRAW_ON(local_player->setup); + fading_on = SETUP_FADING_ON(local_player->setup); + autorecord_on = SETUP_AUTO_RECORD_ON(local_player->setup); + joystick_nr = SETUP_2ND_JOYSTICK_ON(local_player->setup); + quick_doors = SETUP_QUICK_DOORS_ON(local_player->setup); + scroll_delay_on = SETUP_SCROLL_DELAY_ON(local_player->setup); + soft_scrolling_on = SETUP_SOFT_SCROLL_ON(local_player->setup); +#ifndef MSDOS if (joystick_nr != old_joystick_nr) { if (joystick_device) close(joystick_device); InitJoystick(); } +#endif } void InitGame() { - int i,x,y; + int i, x,y; BOOL emulate_bd = TRUE; /* unless non-BOULDERDASH elements found */ BOOL emulate_sb = TRUE; /* unless non-SOKOBAN elements found */ - Dynamite = Score = 0; - Gems = level.edelsteine; - SokobanFields = Lights = Friends = 0; - DynaBombCount = DynaBombSize = DynaBombsLeft = 0; - DynaBombXL = FALSE; - Key[0] = Key[1] = Key[2] = Key[3] = FALSE; + for(i=0; inr = 1; + local_player->active = TRUE; + local_player->local = TRUE; + + player = local_player; + + player->score = 0; + player->gems_still_needed = level.edelsteine; + player->sokobanfields_still_needed = 0; + player->lights_still_needed = 0; + player->friends_still_needed = 0; + + for(i=0; i<4; i++) + player->key[i] = FALSE; + + player->dynamite = 0; + player->dynabomb_count = 0; + player->dynabomb_size = 0; + player->dynabombs_left = 0; + player->dynabomb_xl = FALSE; + MampferNr = 0; FrameCounter = 0; TimeFrames = 0; TimeLeft = level.time; - PlayerMovDir = MV_NO_MOVING; - PlayerFrame = 0; - PlayerPushing = FALSE; - PlayerGone = LevelSolved = GameOver = SiebAktiv = FALSE; + ScreenMovPos = 0; + + player->MovDir = MV_NO_MOVING; + player->MovPos = 0; + player->Pushing = FALSE; + player->GfxPos = 0; + player->Frame = 0; + + player->frame_reset_delay = 0; + + player->push_delay = 0; + player->push_delay_value = 5; + + player->move_delay = 0; + player->last_move_dir = MV_NO_MOVING; + + player->lastJX = player->lastJY = 0; + player->JX = player->JY = 0; + + lastJX = lastJY = 0; JX = JY = 0; ZX = ZY = -1; + + /* test */ + for(i=1; iJX = JX; + player->JY = JY; + player->lastJX = lastJX; + player->lastJY = lastJY; + break; case EL_SPIELER2: + case EL_SPIELER3: + case EL_SPIELER4: + StorePlayer[x][y] = Feld[x][y]; Feld[x][y] = EL_LEERRAUM; + + stored_player[StorePlayer[x][y] - EL_SPIELER1].JX = x; + stored_player[StorePlayer[x][y] - EL_SPIELER1].JY = y; + stored_player[StorePlayer[x][y] - EL_SPIELER1].lastJX = x; + stored_player[StorePlayer[x][y] - EL_SPIELER1].lastJY = y; + break; case EL_BADEWANNE: if (xlights_still_needed++; break; case EL_SOKOBAN_FELD_LEER: - SokobanFields++; + local_player->sokobanfields_still_needed++; break; case EL_MAULWURF: case EL_PINGUIN: - Friends++; + local_player->friends_still_needed++; break; case EL_SCHWEIN: case EL_DRACHE: @@ -210,13 +275,13 @@ void InitGame() int2str(level_nr,2),FS_SMALL,FC_YELLOW); DrawTextExt(pix[PIX_DB_DOOR],gc, DOOR_GFX_PAGEX1+XX_EMERALDS,DOOR_GFX_PAGEY1+YY_EMERALDS, - int2str(Gems,3),FS_SMALL,FC_YELLOW); + int2str(local_player->gems_still_needed,3),FS_SMALL,FC_YELLOW); DrawTextExt(pix[PIX_DB_DOOR],gc, DOOR_GFX_PAGEX1+XX_DYNAMITE,DOOR_GFX_PAGEY1+YY_DYNAMITE, - int2str(Dynamite,3),FS_SMALL,FC_YELLOW); + int2str(local_player->dynamite,3),FS_SMALL,FC_YELLOW); DrawTextExt(pix[PIX_DB_DOOR],gc, DOOR_GFX_PAGEX1+XX_SCORE,DOOR_GFX_PAGEY1+YY_SCORE, - int2str(Score,5),FS_SMALL,FC_YELLOW); + int2str(local_player->score,5),FS_SMALL,FC_YELLOW); DrawTextExt(pix[PIX_DB_DOOR],gc, DOOR_GFX_PAGEX1+XX_TIME,DOOR_GFX_PAGEY1+YY_TIME, int2str(TimeLeft,3),FS_SMALL,FC_YELLOW); @@ -359,21 +424,21 @@ void GameWon() if (TimeLeft) { if (sound_loops_on) - PlaySoundExt(SND_SIRR,PSND_MAX_VOLUME,PSND_MAX_RIGHT,PSND_LOOP); + PlaySoundExt(SND_SIRR, PSND_MAX_VOLUME, PSND_MAX_RIGHT, PSND_LOOP); - while(TimeLeft>0) + while(TimeLeft > 0) { if (!sound_loops_on) - PlaySoundStereo(SND_SIRR,PSND_MAX_RIGHT); + PlaySoundStereo(SND_SIRR, PSND_MAX_RIGHT); if (TimeLeft && !(TimeLeft % 10)) RaiseScore(level.score[SC_ZEITBONUS]); if (TimeLeft > 100 && !(TimeLeft % 10)) TimeLeft -= 10; else TimeLeft--; - DrawText(DX_TIME,DY_TIME,int2str(TimeLeft,3),FS_SMALL,FC_YELLOW); + DrawText(DX_TIME, DY_TIME, int2str(TimeLeft,3), FS_SMALL, FC_YELLOW); BackToFront(); - Delay(10000); + Delay(10); } if (sound_loops_on) @@ -383,7 +448,7 @@ void GameWon() FadeSounds(); /* Hero disappears */ - DrawLevelElement(ExitX,ExitY,Feld[ExitX][ExitY]); + DrawLevelField(ExitX, ExitY); BackToFront(); if (tape.playing) @@ -397,15 +462,15 @@ void GameWon() SaveLevelTape(tape.level_nr); /* Ask to save tape */ } - if (level_nr==player.handicap && - level_nrhandicap && + level_nr < leveldir[leveldir_nr].levels-1) { - player.handicap++; + local_player->handicap++; bumplevel = TRUE; SavePlayerInfo(PLAYER_LEVEL); } - if ((hi_pos=NewHiScore())>=0) + if ((hi_pos=NewHiScore()) >= 0) { game_status = HALLOFFAME; DrawHallOfFame(hi_pos); @@ -430,21 +495,23 @@ BOOL NewHiScore() LoadScore(level_nr); - if (!strcmp(player.alias_name,EMPTY_ALIAS) || - Scorealias_name,EMPTY_ALIAS) || + local_player->score < highscore[MAX_SCORE_ENTRIES-1].Score) return(-1); for(k=0;khighscore[k].Score) /* Spieler kommt in Highscore-Liste */ + if (local_player->score > highscore[k].Score) { + /* Spieler kommt in Highscore-Liste */ + if (kalias_name,highscore[l].Name)) m = l; if (m==k) /* Spieler überschreibt seine alte Position */ goto put_into_list; @@ -460,14 +527,14 @@ BOOL NewHiScore() #ifdef ONE_PER_NAME put_into_list: #endif - sprintf(highscore[k].Name,player.alias_name); - highscore[k].Score = Score; + sprintf(highscore[k].Name,local_player->alias_name); + highscore[k].Score = local_player->score; position = k; break; } #ifdef ONE_PER_NAME - else if (!strcmp(player.alias_name,highscore[k].Name)) + else if (!strcmp(local_player->alias_name,highscore[k].Name)) break; /* Spieler schon mit besserer Punktzahl in der Liste */ #endif @@ -486,7 +553,7 @@ void InitMovingField(int x, int y, int direction) MovDir[x][y] = direction; MovDir[newx][newy] = direction; - if (Feld[newx][newy]==EL_LEERRAUM) + if (Feld[newx][newy] == EL_LEERRAUM) Feld[newx][newy] = EL_BLOCKED; } @@ -587,12 +654,12 @@ void DrawDynamite(int x, int y) if (Feld[x][y]==EL_DYNAMIT) { - if ((phase = (48-MovDelay[x][y])/6) > 6) + if ((phase = (96-MovDelay[x][y])/12) > 6) phase = 6; } else { - if ((phase = ((48-MovDelay[x][y])/3) % 8) > 3) + if ((phase = ((96-MovDelay[x][y])/6) % 8) > 3) phase = 7-phase; } @@ -609,12 +676,12 @@ void CheckDynamite(int x, int y) MovDelay[x][y]--; if (MovDelay[x][y]) { - if (!(MovDelay[x][y] % 6)) + if (!(MovDelay[x][y] % 12)) PlaySoundLevel(x,y,SND_ZISCH); - if (Feld[x][y]==EL_DYNAMIT && !(MovDelay[x][y] % 6)) + if (Feld[x][y]==EL_DYNAMIT && !(MovDelay[x][y] % 12)) DrawDynamite(x,y); - else if (Feld[x][y]==EL_DYNABOMB && !(MovDelay[x][y] % 3)) + else if (Feld[x][y]==EL_DYNABOMB && !(MovDelay[x][y] % 6)) DrawDynamite(x,y); return; @@ -628,7 +695,7 @@ void CheckDynamite(int x, int y) void Explode(int ex, int ey, int phase, int mode) { int x,y; - int num_phase = 9, delay = 1; + int num_phase = 9, delay = 2; int last_phase = num_phase*delay; int half_phase = (num_phase/2)*delay; @@ -790,12 +857,12 @@ void DynaExplode(int ex, int ey, int size) if (element != EL_LEERRAUM && element != EL_ERDREICH && element != EL_EXPLODING && - !DynaBombXL) + !player->dynabomb_xl) break; } } - DynaBombsLeft++; + player->dynabombs_left++; } void Bang(int x, int y) @@ -821,7 +888,7 @@ void Bang(int x, int y) case EL_DYNABOMB_NR: case EL_DYNABOMB_SZ: case EL_DYNABOMB_XL: - DynaExplode(x,y,DynaBombSize); + DynaExplode(x,y,player->dynabomb_size); break; case EL_BIRNE_AUS: case EL_BIRNE_EIN: @@ -858,13 +925,13 @@ void Blurb(int x, int y) int graphic = (element==EL_BLURB_LEFT ? GFX_BLURB_LEFT : GFX_BLURB_RIGHT); if (!MovDelay[x][y]) /* neue Phase / noch nicht gewartet */ - MovDelay[x][y] = 5; + MovDelay[x][y] = 9; if (MovDelay[x][y]) /* neue Phase / in Wartezustand */ { MovDelay[x][y]--; - if (MovDelay[x][y] && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y))) - DrawGraphic(SCROLLX(x),SCROLLY(y),graphic+4-MovDelay[x][y]); + if (MovDelay[x][y]/2 && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y))) + DrawGraphic(SCROLLX(x),SCROLLY(y),graphic+4-MovDelay[x][y]/2); if (!MovDelay[x][y]) { @@ -1083,7 +1150,7 @@ void TurnRound(int x, int y) MovDir[x][y] = left_dir; if (element==EL_KAEFER && MovDir[x][y] != old_move_dir) - MovDelay[x][y] = 5; + MovDelay[x][y] = 9; else if (element==EL_BUTTERFLY) /* && MovDir[x][y]==left_dir) */ MovDelay[x][y] = 1; } @@ -1099,7 +1166,7 @@ void TurnRound(int x, int y) MovDir[x][y] = right_dir; if (element==EL_FLIEGER && MovDir[x][y] != old_move_dir) - MovDelay[x][y] = 5; + MovDelay[x][y] = 9; else if (element==EL_FIREFLY) /* && MovDir[x][y]==right_dir) */ MovDelay[x][y] = 1; } @@ -1125,7 +1192,7 @@ void TurnRound(int x, int y) else MovDir[x][y] = back_dir; - MovDelay[x][y] = 8+8*RND(3); + MovDelay[x][y] = 16+16*RND(3); } else if (element==EL_MAMPFER2) { @@ -1149,7 +1216,7 @@ void TurnRound(int x, int y) else MovDir[x][y] = back_dir; - MovDelay[x][y] = 8+8*RND(3); + MovDelay[x][y] = 16+16*RND(3); } else if (element==EL_PACMAN) { @@ -1173,7 +1240,7 @@ void TurnRound(int x, int y) else MovDir[x][y] = back_dir; - MovDelay[x][y] = 3+RND(20); + MovDelay[x][y] = 6+RND(40); } else if (element==EL_SCHWEIN) { @@ -1336,9 +1403,9 @@ void TurnRound(int x, int y) Moving2Blocked(x,y,&newx,&newy); if (IN_LEV_FIELD(newx,newy) && IS_FREE_OR_PLAYER(newx,newy)) - MovDelay[x][y] = 4+4*!RND(3); + MovDelay[x][y] = 8+8*!RND(3); else - MovDelay[x][y] = 8; + MovDelay[x][y] = 16; } else { @@ -1389,6 +1456,26 @@ void StartMoving(int x, int y) if (CAN_FALL(element) && y0 && IS_PLAYER(x-1,y)) || (xactive && pl->Pushing && pl->MovPos) + { + int nextJX = pl->JX + (pl->JX - pl->lastJX); + int nextJY = pl->JY + (pl->JY - pl->lastJY); + + if (x == nextJX && y == nextJY) + return; + } + } + } + if (element==EL_MORAST_VOLL) { if (IS_FREE(x,y+1)) @@ -1400,7 +1487,7 @@ void StartMoving(int x, int y) else if (Feld[x][y+1]==EL_MORAST_LEER) { if (!MovDelay[x][y]) - MovDelay[x][y] = 16; + MovDelay[x][y] = TILEY + 1; if (MovDelay[x][y]) { @@ -1429,7 +1516,7 @@ void StartMoving(int x, int y) else if (Feld[x][y+1]==EL_SIEB_LEER) { if (!MovDelay[x][y]) - MovDelay[x][y] = 2; + MovDelay[x][y] = TILEY/4 + 1; if (MovDelay[x][y]) { @@ -1455,7 +1542,7 @@ void StartMoving(int x, int y) else if (Feld[x][y+1]==EL_SIEB2_LEER) { if (!MovDelay[x][y]) - MovDelay[x][y] = 2; + MovDelay[x][y] = TILEY/4 + 1; if (MovDelay[x][y]) { @@ -1636,8 +1723,8 @@ void StartMoving(int x, int y) if (IN_SCR_FIELD(SCROLLX(newx),SCROLLY(newy))) DrawGraphicThruMask(SCROLLX(newx),SCROLLY(newy),el2gfx(element)); - Friends--; - if (!Friends && PlayerGone && !GameOver) + local_player->friends_still_needed--; + if (!local_player->friends_still_needed && PlayerGone && !GameOver) LevelSolved = GameOver = TRUE; return; @@ -1652,7 +1739,7 @@ void StartMoving(int x, int y) else if (!IS_FREE(newx,newy)) { if (IS_PLAYER(x,y)) - DrawPlayerField(); + DrawPlayerField(x,y); else DrawLevelField(x,y); return; @@ -1673,7 +1760,7 @@ void StartMoving(int x, int y) else if (!IS_FREE(newx,newy)) { if (IS_PLAYER(x,y)) - DrawPlayerField(); + DrawPlayerField(x,y); else DrawLevelField(x,y); return; @@ -1684,7 +1771,7 @@ void StartMoving(int x, int y) if (!IS_FREE(newx,newy)) { if (IS_PLAYER(x,y)) - DrawPlayerField(); + DrawPlayerField(x,y); else DrawLevelField(x,y); return; @@ -1705,11 +1792,11 @@ void StartMoving(int x, int y) element1 != EL_BURNING && element2 != EL_BURNING) { if (IS_PLAYER(x,y)) - DrawPlayerField(); + DrawPlayerField(x,y); else DrawLevelField(x,y); - MovDelay[x][y] = 25; + MovDelay[x][y] = 50; Feld[newx][newy] = EL_BURNING; if (IN_LEV_FIELD(newx1,newy1) && Feld[newx1][newy1] == EL_LEERRAUM) Feld[newx1][newy1] = EL_BURNING; @@ -1768,9 +1855,28 @@ void StartMoving(int x, int y) if (element == EL_KAEFER || element == EL_FLIEGER) DrawLevelField(x,y); else if (element == EL_BUTTERFLY || element == EL_FIREFLY) - DrawGraphicAnimation(x,y, el2gfx(element), 2, 2, ANIM_NORMAL); + DrawGraphicAnimation(x,y, el2gfx(element), 2, 4, ANIM_NORMAL); else if (element==EL_SONDE) - DrawGraphicAnimation(x,y, GFX_SONDE_START, 8, 1, ANIM_NORMAL); + { + int i; + + /* check if this element is just being pushed */ + for(i=0; iactive && pl->Pushing && pl->GfxPos) + { + int nextJX = pl->JX + (pl->JX - pl->lastJX); + int nextJY = pl->JY + (pl->JY - pl->lastJY); + + if (x == nextJX && y == nextJY) + return; + } + } + + DrawGraphicAnimation(x,y, GFX_SONDE_START, 8, 2, ANIM_NORMAL); + } return; } @@ -1793,7 +1899,7 @@ void ContinueMoving(int x, int y) int dy = (direction==MV_UP ? -1 : direction==MV_DOWN ? +1 : 0); int horiz_move = (dx!=0); int newx = x + dx, newy = y + dy; - int step = (horiz_move ? dx : dy)*TILEX/4; + int step = (horiz_move ? dx : dy) * TILEX/8; if (CAN_FALL(element) && horiz_move) step*=2; @@ -2022,9 +2128,9 @@ void AmoebeWaechst(int x, int y) if (!MovDelay[x][y]) /* neue Phase / noch nicht gewartet */ { - MovDelay[x][y] = 4; + MovDelay[x][y] = 7; - if (DelayReached(&sound_delay,sound_delay_value)) + if (DelayReached(&sound_delay, sound_delay_value)) { PlaySoundLevel(x,y,SND_AMOEBE); sound_delay_value = 30; @@ -2034,8 +2140,8 @@ void AmoebeWaechst(int x, int y) if (MovDelay[x][y]) /* neue Phase / in Wartezustand */ { MovDelay[x][y]--; - if (MovDelay[x][y] && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y))) - DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_AMOEBING+3-MovDelay[x][y]); + if (MovDelay[x][y]/2 && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y))) + DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_AMOEBING+3-MovDelay[x][y]/2); if (!MovDelay[x][y]) { @@ -2179,7 +2285,7 @@ void Life(int ax, int ay) { int x1,y1,x2,y2; static int life[4] = { 2,3,3,3 }; /* "Life"-Parameter */ - int life_time = 20; + int life_time = 40; int element = Feld[ax][ay]; if (Stop[ax][ay]) @@ -2267,7 +2373,7 @@ void Ablenk(int x, int y) void Birne(int x, int y) { if (!MovDelay[x][y]) /* neue Phase / noch nicht gewartet */ - MovDelay[x][y] = 400; + MovDelay[x][y] = 800; if (MovDelay[x][y]) /* neue Phase / in Wartezustand */ { @@ -2295,19 +2401,22 @@ void Birne(int x, int y) void Blubber(int x, int y) { - DrawGraphicAnimation(x,y, GFX_GEBLUBBER, 4, 5, ANIM_NORMAL); + if (y > 0 && IS_MOVING(x,y-1) && MovDir[x][y-1] == MV_DOWN) + DrawLevelField(x,y-1); + else + DrawGraphicAnimation(x,y, GFX_GEBLUBBER, 4, 10, ANIM_NORMAL); } void NussKnacken(int x, int y) { if (!MovDelay[x][y]) /* neue Phase / noch nicht gewartet */ - MovDelay[x][y] = 4; + MovDelay[x][y] = 7; if (MovDelay[x][y]) /* neue Phase / in Wartezustand */ { MovDelay[x][y]--; - if (MovDelay[x][y] && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y))) - DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_CRACKINGNUT+3-MovDelay[x][y]); + if (MovDelay[x][y]/2 && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y))) + DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_CRACKINGNUT+3-MovDelay[x][y]/2); if (!MovDelay[x][y]) { @@ -2319,34 +2428,40 @@ void NussKnacken(int x, int y) void SiebAktivieren(int x, int y, int typ) { - if (SiebAktiv%2 && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y))) + if (!(SiebAktiv % 4) && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y))) DrawGraphic(SCROLLX(x),SCROLLY(y), - (typ==1 ? GFX_SIEB_VOLL : GFX_SIEB2_VOLL)+3-(SiebAktiv%8)/2); + (typ==1 ? GFX_SIEB_VOLL : GFX_SIEB2_VOLL)+3-(SiebAktiv%16)/4); } void AusgangstuerPruefen(int x, int y) { - if (!Gems && !SokobanFields && !Lights) + if (!local_player->gems_still_needed && + !local_player->sokobanfields_still_needed && + !local_player->lights_still_needed) { Feld[x][y] = EL_AUSGANG_ACT; - PlaySoundLevel(x,y,SND_OEFFNEN); + + if (IN_SCR_FIELD(SCROLLX(x),SCROLLY(y))) + PlaySoundLevel(x,y,SND_OEFFNEN); + else + PlaySoundLevel(JX,JY,SND_OEFFNEN); } } void AusgangstuerOeffnen(int x, int y) { - int speed = 3; + int delay = 6; if (!MovDelay[x][y]) /* neue Phase / noch nicht gewartet */ - MovDelay[x][y] = 5*speed; + MovDelay[x][y] = 5*delay; if (MovDelay[x][y]) /* neue Phase / in Wartezustand */ { int tuer; MovDelay[x][y]--; - tuer = MovDelay[x][y]/speed; - if (!(MovDelay[x][y]%speed) && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y))) + tuer = MovDelay[x][y]/delay; + if (!(MovDelay[x][y]%delay) && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y))) DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_AUSGANG_AUF-tuer); if (!MovDelay[x][y]) @@ -2359,7 +2474,7 @@ void AusgangstuerOeffnen(int x, int y) void AusgangstuerBlinken(int x, int y) { - DrawGraphicAnimation(x,y, GFX_AUSGANG_AUF, 4, 2, ANIM_OSCILLATE); + DrawGraphicAnimation(x,y, GFX_AUSGANG_AUF, 4, 4, ANIM_OSCILLATE); } void EdelsteinFunkeln(int x, int y) @@ -2368,47 +2483,51 @@ void EdelsteinFunkeln(int x, int y) return; if (Feld[x][y] == EL_EDELSTEIN_BD) - { - const int delay = 2; - const int frames = 4; - int phase = (FrameCounter % (delay*frames)) / delay; - - if (!(FrameCounter % delay)) - DrawGraphic(SCROLLX(x),SCROLLY(y), GFX_EDELSTEIN_BD - phase); - } + DrawGraphicAnimation(x,y, GFX_EDELSTEIN_BD, 4, 4, ANIM_REVERSE); else { if (!MovDelay[x][y]) /* neue Phase / noch nicht gewartet */ - MovDelay[x][y] = 6*!SimpleRND(500); + MovDelay[x][y] = 11 * !SimpleRND(500); if (MovDelay[x][y]) /* neue Phase / in Wartezustand */ { MovDelay[x][y]--; if (direct_draw_on && MovDelay[x][y]) - drawto_field = backbuffer; + SetDrawtoField(DRAW_BUFFERED); DrawGraphic(SCROLLX(x),SCROLLY(y), el2gfx(Feld[x][y])); if (MovDelay[x][y]) { int src_x,src_y, dest_x,dest_y; - int phase = MovDelay[x][y]-1; + int phase = (MovDelay[x][y]-1)/2; + + if (phase > 2) + phase = 4-phase; - src_x = SX+GFX_PER_LINE*TILEX; - src_y = SY+(phase > 2 ? 4-phase : phase)*TILEY; - dest_x = SX+SCROLLX(x)*TILEX; - dest_y = SY+SCROLLY(y)*TILEY; + src_x = SX + GFX_PER_LINE*TILEX; + src_y = SY + phase*TILEY; + dest_x = FX + SCROLLX(x)*TILEX; + dest_y = FY + SCROLLY(y)*TILEY; + /* XSetClipOrigin(display,clip_gc[PIX_BACK],dest_x-src_x,dest_y-src_y); XCopyArea(display,pix[PIX_BACK],drawto_field,clip_gc[PIX_BACK], src_x,src_y, TILEX,TILEY, dest_x,dest_y); + */ + + XSetClipMask(display, tile_clip_gc, + tile_clipmask[GFX_MASK_SPARKLING + phase]); + XSetClipOrigin(display, tile_clip_gc, dest_x,dest_y); + XCopyArea(display, pix[PIX_BACK], drawto_field, tile_clip_gc, + src_x,src_y, TILEX,TILEY, dest_x,dest_y); if (direct_draw_on) { - XCopyArea(display,backbuffer,window,gc, + XCopyArea(display,drawto_field,window,gc, dest_x,dest_y, TILEX,TILEY, dest_x,dest_y); - drawto_field = window; + SetDrawtoField(DRAW_DIRECT); } } } @@ -2417,18 +2536,18 @@ void EdelsteinFunkeln(int x, int y) void MauerWaechst(int x, int y) { - int speed = 3; + int delay = 6; if (!MovDelay[x][y]) /* neue Phase / noch nicht gewartet */ - MovDelay[x][y] = 3*speed; + MovDelay[x][y] = 3*delay; if (MovDelay[x][y]) /* neue Phase / in Wartezustand */ { int phase; MovDelay[x][y]--; - phase = 2-MovDelay[x][y]/speed; - if (!(MovDelay[x][y]%speed) && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y))) + phase = 2-MovDelay[x][y]/delay; + if (!(MovDelay[x][y]%delay) && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y))) DrawGraphic(SCROLLX(x),SCROLLY(y), (Store[x][y]==MV_LEFT ? GFX_MAUER_L1 : GFX_MAUER_R1)+phase); @@ -2458,7 +2577,7 @@ void MauerAbleger(int ax, int ay) BOOL links_massiv = FALSE, rechts_massiv = FALSE; if (!MovDelay[ax][ay]) /* neue Mauer / noch nicht gewartet */ - MovDelay[ax][ay] = 3; + MovDelay[ax][ay] = 6; if (MovDelay[ax][ay]) /* neue Mauer / in Wartezustand */ { @@ -2548,157 +2667,245 @@ void CheckForDragon(int x, int y) } } -void GameActions() +void PlayerActions(int player_action) +{ + BOOL moved = FALSE, snapped = FALSE, bombed = FALSE; + int left = player_action & JOY_LEFT; + int right = player_action & JOY_RIGHT; + int up = player_action & JOY_UP; + int down = player_action & JOY_DOWN; + int button1 = player_action & JOY_BUTTON_1; + int button2 = player_action & JOY_BUTTON_2; + int dx = (left ? -1 : right ? 1 : 0); + int dy = (up ? -1 : down ? 1 : 0); + + if (player_action) + { + player->frame_reset_delay = 0; + + if (button1) + snapped = SnapField(dx,dy); + else + { + if (button2) + bombed = PlaceBomb(); + moved = MoveFigure(dx,dy); + } + + if (tape.recording && (moved || snapped || bombed)) + { + if (bombed && !moved) + player_action &= JOY_BUTTON; + TapeRecordAction(player_action); + } + else if (tape.playing && snapped) + SnapField(0,0); /* stop snapping */ + } + else + { + DigField(0,0,0,0,DF_NO_PUSH); + SnapField(0,0); + if (++player->frame_reset_delay > MoveSpeed) + player->Frame = 0; + } + + if (tape.playing && !tape.pausing && !player_action && + tape.counter < tape.length) + { + int next_joy = tape.pos[tape.counter].joystickdata & (JOY_LEFT|JOY_RIGHT); + + if (next_joy == JOY_LEFT || next_joy == JOY_RIGHT) + { + int dx = (next_joy == JOY_LEFT ? -1 : +1); + + if (IN_LEV_FIELD(JX+dx,JY) && IS_PUSHABLE(Feld[JX+dx][JY])) + { + int el = Feld[JX+dx][JY]; + int push_delay = (IS_SB_ELEMENT(el) || el==EL_SONDE ? 2 : 10); + + if (tape.delay_played + push_delay >= tape.pos[tape.counter].delay) + { + player->MovDir = next_joy; + player->Frame = FrameCounter % 4; + player->Pushing = TRUE; + } + } + } + } +} + +void GameActions(int player_action) { - static long action_delay=0; + static long action_delay = 0; long action_delay_value; + int sieb_x = 0, sieb_y = 0; + int i, x,y, element; if (game_status != PLAYING) return; -/* +#ifdef DEBUG + action_delay_value = + (tape.playing && tape.fast_forward ? FFWD_FRAME_DELAY : GameFrameDelay); +#else action_delay_value = (tape.playing && tape.fast_forward ? FFWD_FRAME_DELAY : GAME_FRAME_DELAY); -*/ +#endif - action_delay_value = - (tape.playing && tape.fast_forward ? FFWD_FRAME_DELAY : Gamespeed); + /* main game synchronization point */ + WaitUntilDelayReached(&action_delay, action_delay_value); - if (DelayReached(&action_delay, action_delay_value)) + for(i=0; iJX; + JY = player->JY; + lastJX = player->lastJX; + lastJY = player->lastJY; - if (tape.pausing || (tape.playing && !TapePlayDelay())) - return; - else if (tape.recording) - TapeRecordDelay(); + if (!player->active) + continue; - FrameCounter++; - TimeFrames++; + PlayerActions(player_action); - for(y=0;y0) - JustHit[x][y]--; + if (player->MovPos) + ScrollFigure(0); + } + + player = local_player; + JX = player->JX; + JY = player->JY; + lastJX = player->lastJX; + lastJY = player->lastJY; + + if (tape.pausing || (tape.playing && !TapePlayDelay())) + return; + else if (tape.recording) + TapeRecordDelay(); + + FrameCounter++; + TimeFrames++; + + for(y=0;y0) + JustHit[x][y]--; #if DEBUG - if (IS_BLOCKED(x,y)) - { - int oldx,oldy; + if (IS_BLOCKED(x,y)) + { + int oldx,oldy; - Blocked2Moving(x,y,&oldx,&oldy); - if (!IS_MOVING(oldx,oldy)) - { - printf("GameActions(): (BLOCKED=>MOVING) context corrupted!\n"); - printf("GameActions(): BLOCKED: x = %d, y = %d\n",x,y); - printf("GameActions(): !MOVING: oldx = %d, oldy = %d\n",oldx,oldy); - printf("GameActions(): This should never happen!\n"); - } + Blocked2Moving(x,y,&oldx,&oldy); + if (!IS_MOVING(oldx,oldy)) + { + printf("GameActions(): (BLOCKED=>MOVING) context corrupted!\n"); + printf("GameActions(): BLOCKED: x = %d, y = %d\n",x,y); + printf("GameActions(): !MOVING: oldx = %d, oldy = %d\n",oldx,oldy); + printf("GameActions(): This should never happen!\n"); } + } #endif + } - } + for(y=0;y0 && TimeFrames>=25 && !tape.pausing) + if (TimeLeft>0 && TimeFrames>=(1000/GameFrameDelay) && !tape.pausing) { TimeFrames = 0; TimeLeft--; @@ -2715,57 +2922,78 @@ void GameActions() KillHero(); } - BackToFront(); + + + + for(i=0; iJX; + JY = player->JY; + lastJX = player->lastJX; + lastJY = player->lastJY; + + if (!player->active) + continue; + + DrawPlayerField(player->JX,player->JY); + } + + player = local_player; + JX = player->JX; + JY = player->JY; + lastJX = player->lastJX; + lastJY = player->lastJY; + + /* + DrawPlayerField(JX,JY); + */ } void ScrollLevel(int dx, int dy) { + int softscroll_offset = (soft_scrolling_on ? TILEX : 0); int x,y; + ScreenMovPos = player->GfxPos; + XCopyArea(display,drawto_field,drawto_field,gc, - SX+TILEX*(dx==-1),SY+TILEY*(dy==-1), - SXSIZE-TILEX*(dx!=0),SYSIZE-TILEY*(dy!=0), - SX+TILEX*(dx==1),SY+TILEY*(dy==1)); + FX + TILEX*(dx==-1) - softscroll_offset, + FY + TILEY*(dy==-1) - softscroll_offset, + SXSIZE - TILEX*(dx!=0) + 2*softscroll_offset, + SYSIZE - TILEY*(dy!=0) + 2*softscroll_offset, + FX + TILEX*(dx==1) - softscroll_offset, + FY + TILEY*(dy==1) - softscroll_offset); if (dx) { - x = (dx==1 ? 0 : SCR_FIELDX-1); - for(y=0;y 0 ? MV_RIGHT : - dy < 0 ? MV_UP : - dy > 0 ? MV_DOWN : MV_NO_MOVING); -/* - if (old_move_dir != PlayerMovDir) - PlayerFrame = 0; - else - PlayerFrame = (PlayerFrame + 1) % 4; -*/ + player->MovDir = (dx < 0 ? MV_LEFT : + dx > 0 ? MV_RIGHT : + dy < 0 ? MV_UP : + dy > 0 ? MV_DOWN : MV_NO_MOVING); if (!IN_LEV_FIELD(newJX,newJY)) return(MF_NO_ACTION); @@ -2793,112 +3021,84 @@ BOOL MoveFigureOneStep(int dx, int dy, int real_dx, int real_dy) if (can_move != MF_MOVING) return(can_move); - oldJX = JX; - oldJY = JY; - JX = newJX; - JY = newJY; - + lastJX = player->lastJX = JX; + lastJY = player->lastJY = JY; + JX = player->JX = newJX; + JY = player->JY = newJY; - JX2 = oldJX; - JY2 = oldJY; + StorePlayer[lastJX][lastJY] = EL_LEERRAUM; + StorePlayer[JX][JY] = EL_SPIELER1; - PlayerMovPos = TILEX/4; - PlayerMovPos = (dx > 0 || dy > 0 ? -1 : 1) * 3*TILEX/4; + player->MovPos = (dx > 0 || dy > 0 ? -1 : 1) * 7*TILEX/8; ScrollFigure(-1); - if (Store[oldJX][oldJY]) - { - DrawGraphic(SCROLLX(oldJX),SCROLLY(oldJY),el2gfx(Store[oldJX][oldJY])); - DrawGraphicThruMask(SCROLLX(oldJX),SCROLLY(oldJY), - el2gfx(Feld[oldJX][oldJY])); - } - else if (Feld[oldJX][oldJY]==EL_DYNAMIT) - DrawDynamite(oldJX,oldJY); - else - DrawLevelField(oldJX,oldJY); - return(MF_MOVING); } BOOL MoveFigure(int dx, int dy) { - static long move_delay = 0; int moved = MF_NO_ACTION; int oldJX = JX, oldJY = JY; if (PlayerGone || (!dx && !dy)) return(FALSE); -/* - if (!DelayReached(&move_delay,8) && !tape.playing) - return(FALSE); -*/ - -/* - if (!DelayReached(&move_delay,10) && !tape.playing) + if (!FrameReached(&player->move_delay,MoveSpeed) && !tape.playing) return(FALSE); -*/ -/* - if (!FrameReached(&move_delay,2) && !tape.playing) - return(FALSE); -*/ - - if (Movemethod == 0) + if (player->last_move_dir & (MV_LEFT | MV_RIGHT)) { - if (!DelayReached(&move_delay,Movespeed[0]) && !tape.playing) - return(FALSE); + if (!(moved |= MoveFigureOneStep(0,dy, dx,dy))) + moved |= MoveFigureOneStep(dx,0, dx,dy); } else { - if (!FrameReached(&move_delay,Movespeed[1]) && !tape.playing) - return(FALSE); + if (!(moved |= MoveFigureOneStep(dx,0, dx,dy))) + moved |= MoveFigureOneStep(0,dy, dx,dy); } - if (moved |= MoveFigureOneStep(dx,0, dx,dy)) - moved |= MoveFigureOneStep(0,dy, dx,dy); - else - { - moved |= MoveFigureOneStep(0,dy, dx,dy); - moved |= MoveFigureOneStep(dx,0, dx,dy); - } - if (moved & MF_MOVING) + /* + player->last_move_dir = MV_NO_MOVING; + */ + + + if (moved & MF_MOVING && player == local_player) { - int old_scroll_x=scroll_x, old_scroll_y=scroll_y; + int old_scroll_x = scroll_x, old_scroll_y = scroll_y; int offset = (scroll_delay_on ? 3 : 0); if ((scroll_x < JX-MIDPOSX-offset || scroll_x > JX-MIDPOSX+offset) && - JX>=MIDPOSX-1-offset && JX<=lev_fieldx-(MIDPOSX-offset)) + JX >= MIDPOSX-1-offset && JX <= lev_fieldx-(MIDPOSX-offset)) scroll_x = JX-MIDPOSX + (scroll_x < JX-MIDPOSX ? -offset : offset); if ((scroll_y < JY-MIDPOSY-offset || scroll_y > JY-MIDPOSY+offset) && - JY>=MIDPOSY-1-offset && JY<=lev_fieldy-(MIDPOSY-offset)) + JY >= MIDPOSY-1-offset && JY <= lev_fieldy-(MIDPOSY-offset)) scroll_y = JY-MIDPOSY + (scroll_y < JY-MIDPOSY ? -offset : offset); - if (scroll_x!=old_scroll_x || scroll_y!=old_scroll_y) - ScrollLevel(old_scroll_x-scroll_x,old_scroll_y-scroll_y); + if (scroll_x != old_scroll_x || scroll_y != old_scroll_y) + ScrollLevel(old_scroll_x - scroll_x, old_scroll_y - scroll_y); } - if (!(moved & MF_MOVING) && !PlayerPushing) - PlayerFrame = 0; + if (!(moved & MF_MOVING) && !player->Pushing) + player->Frame = 0; else - PlayerFrame = (PlayerFrame + 1) % 4; + player->Frame = (player->Frame + 1) % 4; if (moved & MF_MOVING) { if (oldJX != JX && oldJY == JY) - PlayerMovDir = (oldJX < JX ? MV_RIGHT : MV_LEFT); + player->MovDir = (oldJX < JX ? MV_RIGHT : MV_LEFT); else if (oldJX == JX && oldJY != JY) - PlayerMovDir = (oldJY < JY ? MV_DOWN : MV_UP); + player->MovDir = (oldJY < JY ? MV_DOWN : MV_UP); DrawLevelField(JX,JY); /* für "ErdreichAnbroeckeln()" */ + + player->last_move_dir = player->MovDir; } TestIfHeroHitsBadThing(); - BackToFront(); - if (PlayerGone) RemoveHero(); @@ -2907,20 +3107,42 @@ BOOL MoveFigure(int dx, int dy) void ScrollFigure(int init) { - static long actual_frame_counter; + static long actual_frame_counter = 0; if (init) { actual_frame_counter = FrameCounter; + + player->GfxPos = ScrollStepSize * (player->MovPos / ScrollStepSize); + + if (Feld[lastJX][lastJY] == EL_LEERRAUM) + Feld[lastJX][lastJY] = EL_PLAYER_IS_LEAVING; + + DrawPlayerField(JX,JY); return; } else if (!FrameReached(&actual_frame_counter,1)) return; - PlayerMovPos += (PlayerMovPos > 0 ? -1 : 1) * TILEX/4; + player->MovPos += (player->MovPos > 0 ? -1 : 1) * TILEX/8; + player->GfxPos = ScrollStepSize * (player->MovPos / ScrollStepSize); + + if (ScreenMovPos && ScreenMovPos != local_player->GfxPos) + { + ScreenMovPos = local_player->GfxPos; + redraw_mask |= REDRAW_FIELD; + } + + if (Feld[lastJX][lastJY] == EL_PLAYER_IS_LEAVING) + Feld[lastJX][lastJY] = EL_LEERRAUM; - DrawLevelElement(JX2,JY2, Feld[JX2][JY2]); - DrawPlayerField(); + DrawPlayerField(JX,JY); + + if (!player->MovPos) + { + lastJX = JX; + lastJY = JY; + } } void TestIfGoodThingHitsBadThing(int goodx, int goody) @@ -3108,18 +3330,17 @@ int DigField(int x, int y, int real_dx, int real_dy, int mode) { int dx = x-JX, dy = y-JY; int element; - static long push_delay = 0; - static int push_delay_value = 5; - PlayerPushing = FALSE; + if (!player->MovPos) + player->Pushing = FALSE; if (mode == DF_NO_PUSH) { - push_delay = 0; + player->push_delay = 0; return(MF_NO_ACTION); } - if (IS_MOVING(x,y)) + if (IS_MOVING(x,y) || IS_PLAYER(x,y)) return(MF_NO_ACTION); element = Feld[x][y]; @@ -3140,49 +3361,55 @@ int DigField(int x, int y, int real_dx, int real_dy, int mode) case EL_EDELSTEIN_LILA: Feld[x][y] = EL_LEERRAUM; MovDelay[x][y] = 0; /* wegen EDELSTEIN_BD-Funkeln! */ - if (Gems>0) - Gems--; + if (local_player->gems_still_needed > 0) + local_player->gems_still_needed--; RaiseScoreElement(EL_EDELSTEIN); - DrawText(DX_EMERALDS,DY_EMERALDS,int2str(Gems,3),FS_SMALL,FC_YELLOW); - PlaySoundLevel(x,y,SND_PONG); + DrawText(DX_EMERALDS, DY_EMERALDS, + int2str(local_player->gems_still_needed, 3), + FS_SMALL, FC_YELLOW); + PlaySoundLevel(x, y, SND_PONG); break; case EL_DIAMANT: Feld[x][y] = EL_LEERRAUM; - Gems -= 3; - if (Gems<0) - Gems=0; + local_player->gems_still_needed -= 3; + if (local_player->gems_still_needed < 0) + local_player->gems_still_needed = 0; RaiseScoreElement(EL_DIAMANT); - DrawText(DX_EMERALDS,DY_EMERALDS,int2str(Gems,3),FS_SMALL,FC_YELLOW); - PlaySoundLevel(x,y,SND_PONG); + DrawText(DX_EMERALDS, DY_EMERALDS, + int2str(local_player->gems_still_needed, 3), + FS_SMALL, FC_YELLOW); + PlaySoundLevel(x, y, SND_PONG); break; case EL_DYNAMIT_AUS: Feld[x][y] = EL_LEERRAUM; - Dynamite++; + player->dynamite++; RaiseScoreElement(EL_DYNAMIT); - DrawText(DX_DYNAMITE,DY_DYNAMITE,int2str(Dynamite,3),FS_SMALL,FC_YELLOW); + DrawText(DX_DYNAMITE, DY_DYNAMITE, + int2str(local_player->dynamite, 3), + FS_SMALL, FC_YELLOW); PlaySoundLevel(x,y,SND_PONG); break; case EL_DYNABOMB_NR: Feld[x][y] = EL_LEERRAUM; - DynaBombCount++; - DynaBombsLeft++; + player->dynabomb_count++; + player->dynabombs_left++; RaiseScoreElement(EL_DYNAMIT); PlaySoundLevel(x,y,SND_PONG); break; case EL_DYNABOMB_SZ: Feld[x][y] = EL_LEERRAUM; - DynaBombSize++; + player->dynabomb_size++; RaiseScoreElement(EL_DYNAMIT); PlaySoundLevel(x,y,SND_PONG); break; case EL_DYNABOMB_XL: Feld[x][y] = EL_LEERRAUM; - DynaBombXL = TRUE; + player->dynabomb_xl = TRUE; RaiseScoreElement(EL_DYNAMIT); PlaySoundLevel(x,y,SND_PONG); break; @@ -3195,14 +3422,14 @@ int DigField(int x, int y, int real_dx, int real_dy, int mode) int key_nr = element-EL_SCHLUESSEL1; Feld[x][y] = EL_LEERRAUM; - Key[key_nr] = TRUE; + player->key[key_nr] = TRUE; RaiseScoreElement(EL_SCHLUESSEL); - DrawMiniGraphicExtHiRes(drawto,gc, - DX_KEYS+key_nr*MINI_TILEX,DY_KEYS, - GFX_SCHLUESSEL1+key_nr); - DrawMiniGraphicExtHiRes(window,gc, - DX_KEYS+key_nr*MINI_TILEX,DY_KEYS, - GFX_SCHLUESSEL1+key_nr); + DrawMiniGraphicExt(drawto,gc, + DX_KEYS+key_nr*MINI_TILEX,DY_KEYS, + GFX_SCHLUESSEL1+key_nr); + DrawMiniGraphicExt(window,gc, + DX_KEYS+key_nr*MINI_TILEX,DY_KEYS, + GFX_SCHLUESSEL1+key_nr); PlaySoundLevel(x,y,SND_PONG); break; } @@ -3222,7 +3449,7 @@ int DigField(int x, int y, int real_dx, int real_dy, int mode) if (dy || mode==DF_SNAP) return(MF_NO_ACTION); - PlayerPushing = TRUE; + player->Pushing = TRUE; if (!IN_LEV_FIELD(x+dx,y+dy) || Feld[x+dx][y+dy] != EL_LEERRAUM) return(MF_NO_ACTION); @@ -3233,15 +3460,16 @@ int DigField(int x, int y, int real_dx, int real_dy, int mode) return(MF_NO_ACTION); } - if (push_delay == 0) - push_delay = FrameCounter; - if (!FrameReached(&push_delay,push_delay_value) && !tape.playing) + if (player->push_delay == 0) + player->push_delay = FrameCounter; + if (!FrameReached(&player->push_delay, player->push_delay_value) && + !tape.playing) return(MF_NO_ACTION); Feld[x][y] = EL_LEERRAUM; Feld[x+dx][y+dy] = element; - push_delay_value = 2+RND(8); + player->push_delay_value = 2+RND(8); DrawLevelField(x+dx,y+dy); if (element==EL_FELSBROCKEN) @@ -3256,7 +3484,7 @@ int DigField(int x, int y, int real_dx, int real_dy, int mode) case EL_PFORTE2: case EL_PFORTE3: case EL_PFORTE4: - if (!Key[element-EL_PFORTE1]) + if (!player->key[element-EL_PFORTE1]) return(MF_NO_ACTION); break; @@ -3264,7 +3492,7 @@ int DigField(int x, int y, int real_dx, int real_dy, int mode) case EL_PFORTE2X: case EL_PFORTE3X: case EL_PFORTE4X: - if (!Key[element-EL_PFORTE1X]) + if (!player->key[element-EL_PFORTE1X]) return(MF_NO_ACTION); break; @@ -3281,14 +3509,14 @@ int DigField(int x, int y, int real_dx, int real_dy, int mode) PlayerGone = TRUE; PlaySoundLevel(x,y,SND_BUING); - if (!Friends) + if (!local_player->friends_still_needed) LevelSolved = GameOver = TRUE; break; case EL_BIRNE_AUS: Feld[x][y] = EL_BIRNE_EIN; - Lights--; + local_player->lights_still_needed--; DrawLevelField(x,y); PlaySoundLevel(x,y,SND_DENG); return(MF_ACTION); @@ -3312,7 +3540,7 @@ int DigField(int x, int y, int real_dx, int real_dy, int mode) if (mode==DF_SNAP) return(MF_NO_ACTION); - PlayerPushing = TRUE; + player->Pushing = TRUE; if (!IN_LEV_FIELD(x+dx,y+dy) || (Feld[x+dx][y+dy] != EL_LEERRAUM @@ -3331,9 +3559,10 @@ int DigField(int x, int y, int real_dx, int real_dy, int mode) return(MF_NO_ACTION); } - if (push_delay == 0) - push_delay = FrameCounter; - if (!FrameReached(&push_delay,push_delay_value) && !tape.playing) + if (player->push_delay == 0) + player->push_delay = FrameCounter; + if (!FrameReached(&player->push_delay, player->push_delay_value) && + !tape.playing) return(MF_NO_ACTION); if (IS_SB_ELEMENT(element)) @@ -3341,7 +3570,7 @@ int DigField(int x, int y, int real_dx, int real_dy, int mode) if (element == EL_SOKOBAN_FELD_VOLL) { Feld[x][y] = EL_SOKOBAN_FELD_LEER; - SokobanFields++; + local_player->sokobanfields_still_needed++; } else Feld[x][y] = EL_LEERRAUM; @@ -3349,7 +3578,7 @@ int DigField(int x, int y, int real_dx, int real_dy, int mode) if (Feld[x+dx][y+dy] == EL_SOKOBAN_FELD_LEER) { Feld[x+dx][y+dy] = EL_SOKOBAN_FELD_VOLL; - SokobanFields--; + local_player->sokobanfields_still_needed--; if (element == EL_SOKOBAN_OBJEKT) PlaySoundLevel(x,y,SND_DENG); } @@ -3362,14 +3591,15 @@ int DigField(int x, int y, int real_dx, int real_dy, int mode) Feld[x+dx][y+dy] = element; } - push_delay_value = 2; + player->push_delay_value = 2; DrawLevelField(x,y); DrawLevelField(x+dx,y+dy); PlaySoundLevel(x+dx,y+dy,SND_PUSCH); if (IS_SB_ELEMENT(element) && - SokobanFields == 0 && game_emulation == EMU_SOKOBAN) + local_player->sokobanfields_still_needed == 0 && + game_emulation == EMU_SOKOBAN) { LevelSolved = GameOver = TRUE; PlaySoundLevel(x,y,SND_BUING); @@ -3388,7 +3618,7 @@ int DigField(int x, int y, int real_dx, int real_dy, int mode) break; } - push_delay = 0; + player->push_delay = 0; return(MF_MOVING); } @@ -3410,10 +3640,10 @@ BOOL SnapField(int dx, int dy) if (snapped) return(FALSE); - PlayerMovDir = (dx < 0 ? MV_LEFT : - dx > 0 ? MV_RIGHT : - dy < 0 ? MV_UP : - dy > 0 ? MV_DOWN : MV_NO_MOVING); + player->MovDir = (dx < 0 ? MV_LEFT : + dx > 0 ? MV_RIGHT : + dy < 0 ? MV_UP : + dy > 0 ? MV_DOWN : MV_NO_MOVING); if (!DigField(x,y, 0,0, DF_SNAP)) return(FALSE); @@ -3429,31 +3659,32 @@ BOOL PlaceBomb(void) { int element; - if (PlayerGone) + if (PlayerGone || player->MovPos) return(FALSE); element = Feld[JX][JY]; - if ((Dynamite==0 && DynaBombsLeft==0) || + if ((player->dynamite==0 && player->dynabombs_left==0) || element==EL_DYNAMIT || element==EL_DYNABOMB || element==EL_EXPLODING) return(FALSE); if (element != EL_LEERRAUM) Store[JX][JY] = element; - if (Dynamite) + if (player->dynamite) { Feld[JX][JY] = EL_DYNAMIT; - MovDelay[JX][JY] = 48; - Dynamite--; - DrawText(DX_DYNAMITE,DY_DYNAMITE,int2str(Dynamite,3),FS_SMALL,FC_YELLOW); + MovDelay[JX][JY] = 96; + player->dynamite--; + DrawText(DX_DYNAMITE, DY_DYNAMITE, int2str(local_player->dynamite, 3), + FS_SMALL, FC_YELLOW); DrawGraphicThruMask(SCROLLX(JX),SCROLLY(JY),GFX_DYNAMIT); } else { Feld[JX][JY] = EL_DYNABOMB; - MovDelay[JX][JY] = 48; - DynaBombsLeft--; + MovDelay[JX][JY] = 96; + player->dynabombs_left--; DrawGraphicThruMask(SCROLLX(JX),SCROLLY(JY),GFX_DYNABOMB); } @@ -3476,7 +3707,13 @@ void PlaySoundLevel(int x, int y, int sound_nr) return; volume = PSND_MAX_VOLUME; +#ifndef MSDOS stereo = (sx-SCR_FIELDX/2)*12; +#else + stereo = PSND_MIDDLE+(2*sx-(SCR_FIELDX-1))*5; + if(stereo > PSND_MAX_RIGHT) stereo = PSND_MAX_RIGHT; + if(stereo < PSND_MAX_LEFT) stereo = PSND_MAX_LEFT; +#endif if (!IN_SCR_FIELD(sx,sy)) { @@ -3491,9 +3728,9 @@ void PlaySoundLevel(int x, int y, int sound_nr) void RaiseScore(int value) { - Score += value; - DrawText(DX_SCORE,DY_SCORE,int2str(Score,5),FS_SMALL,FC_YELLOW); - BackToFront(); + local_player->score += value; + DrawText(DX_SCORE, DY_SCORE, int2str(local_player->score, 5), + FS_SMALL, FC_YELLOW); } void RaiseScoreElement(int element)