diff --git a/data/levels/level620.dat b/data/levels/level620.dat index 8ae2a16..f1d2002 100644 --- a/data/levels/level620.dat +++ b/data/levels/level620.dat @@ -1,4 +1,4 @@ -bgfile snow2.png +bgfile fire1.png bg 0 hurryup 30 help @@ -7,9 +7,6 @@ monsters 0 2 16 134 37 16 163 7 28 -163 7 28 -163 7 28 -163 7 28 endmonsters exitdir 1 91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91, diff --git a/data/sprites/bigfire1.png b/data/sprites/bigfire1.png new file mode 100644 index 0000000..b054fde Binary files /dev/null and b/data/sprites/bigfire1.png differ diff --git a/data/sprites/bigfire2.png b/data/sprites/bigfire2.png new file mode 100644 index 0000000..2a3a4b2 Binary files /dev/null and b/data/sprites/bigfire2.png differ diff --git a/defs.h b/defs.h index a02fe57..ab25504 100644 --- a/defs.h +++ b/defs.h @@ -1,3 +1,4 @@ +#define KAS_WAITFORTOP 2 #ifndef __DEFS_H #define __DEFS_H @@ -22,6 +23,12 @@ #define CH_LASTCHANNEL 21 #define CH_HURRYUP 20 +// max number of regrowing tiles +#define MAXREGROW 200 + +// time a tile takes to regrow +#define REGROWTIMER_SHORT 200 +#define REGROWTIMER_LONG 400 #define MAXCREDITS 5 @@ -270,9 +277,17 @@ #define KFS_VERT 8 // king ant -#define KA_WALKTIME 200 +#define KA_WALKTIME 400 +#define KA_SHOOTTIME 100 // king ant stats #define KAS_WALK1 0 +#define KAS_JUMP1 1 +#define KAS_WAITFORTOP1 2 +#define KAS_WAITFORTOP2 3 +#define KAS_FALL1 4 +#define KAS_FALL2 5 +#define KAS_WALK2 6 +#define KAS_JUMP2 7 // bell states #define BELL_DONESOUND 1 @@ -428,7 +443,7 @@ #define S_SLOPE 2 // Sprite types -#define MAXPTYPES 165 +#define MAXPTYPES 166 #define P_PLAYER 0 #define P_RAT 1 #define P_CHEESE 2 @@ -599,6 +614,7 @@ #define P_TOPHAT 162 #define P_KINGANT 163 #define P_FLAME 164 // like mace smash but harmless +#define P_BIGFIREBALL 165 #define FLY_FLYTIME 150 @@ -1035,6 +1051,13 @@ typedef struct sprite_s { struct sprite_s *prev; } sprite_t; +typedef struct regrow_s { + int tx; + int ty; + int origid; + int timer; +} regrow_t; + typedef struct imageset_s { SDL_Surface *img[MAXFRAMES*4]; int numimages; diff --git a/rc.c b/rc.c index a68d134..8a57a1c 100644 --- a/rc.c +++ b/rc.c @@ -88,6 +88,10 @@ int gameovertime; int sprayalpha; // for spray effect + +regrow_t regrow[MAXREGROW]; // for tile regrowth +int numregrow = 0; + int gameover; int firstlevel; @@ -986,7 +990,33 @@ int main (int argc, char **argv) { * Timers */ if (!paused) { + int n; if (++timer == 100) timer = 0; + + for (n = 0 ; n < numregrow; n++) { + regrow[n].timer--; + if (regrow[n].timer <= 0) { + int nn,tx,ty; + // put original tile back + tx = regrow[n].tx; + ty = regrow[n].ty; + curlevel->map[ty * LEVELW + tx] = regrow[n].origid; + drawtile(temps, tx,ty); + puffin(-1, tx*TILEW+(TILEW/2), ty*TILEH+TILEH, "nothing", 0); + + // remove from list + for (nn = n ; nn < (numregrow-1); nn++) { + regrow[nn].tx = regrow[nn+1].tx; + regrow[nn].ty = regrow[nn+1].ty; + regrow[nn].origid = regrow[nn+1].origid; + regrow[nn].timer = regrow[nn+1].timer; + } + numregrow--; + // do this number again + n--; + } + } + } if (toggletimer > 0) toggletimer--; @@ -1001,6 +1031,7 @@ int main (int argc, char **argv) { } } + // screenshot if (autoshot && (levelcomplete == LV_INPROGRESS)) { if (shottaken) { @@ -1062,10 +1093,10 @@ void tick(void) { SDL_framerateDelay(&manager); } - if (paused) return; if (levelcomplete == LV_HELPFREEZE) return; + fpsticks = SDL_GetTicks(); if (fpsstart == 0) { fpsstart = fpsticks; @@ -1159,7 +1190,7 @@ void tick(void) { if (!levelcomplete) { // all sprites get angry and un-iced for (s = sprite; s; s = s->next) { - if (!isplayer(s) && (ismonster(s->id))) { + if (!isplayer(s) && ismonster(s->id) ) { s->angry = B_TRUE; s->iced = B_FALSE; } @@ -2266,7 +2297,9 @@ void checkcollide(sprite_t *s) { } // if a bullet hit us, it dies too if (isbullet(s2->id)) { - s2->dead = D_FINAL; + if (s2->id != P_BIGFIREBALL) { + s2->dead = D_FINAL; + } } } } @@ -4463,6 +4496,125 @@ printf("setting target to y = %d\n",ss->timer2); addsprite(P_FLAME, s->x + (rand() % s->img->w) - (s->img->w/2), s->y - (s->img->h/2) + (rand() % s->img->h/2), "antflame"); } + + // move back and forth + if ((s->timer1 == KAS_WALK1) || (s->timer1 == KAS_WALK2)) { + // move + rv = movex(s, s->dir*getspeed(s), B_TRUE); + if (rv) { + /* if we couldn't move (hit a wall), turn */ + s->dir = -s->dir; + } + + + // shoot out monsters + s->timer3--; + + if (s->timer3 <= 0) { + // reset shoot timer + s->timer3 = KA_SHOOTTIME; + + if (s->timer1 == KAS_WALK1) { + // shoot an ant out + if (countmonsters(-1) < 6) { // max 5 ants + king ant + sprite_t *newsp; + newsp = addsprite(P_ANT1, s->x, s->y-(s->img->h/2),"babant"); + // make it shoot upwards + newsp->jumping = 1; + newsp->jumpspeed = (rand() % 7) + 7; // 7 - 13 + newsp->jumpdir = (((double)(rand() % 110) - 50) / 10); // -5 to 5 + if (rand() % 2) newsp->dir = 1; + else newsp->dir = -1; + playfx(FX_WHOOSH); + } else { + // TODO enough monsters, shoot food instead + } + } + + } + + // dec walk timer + s->timer2--; + if (s->timer2 == 0) { + if (playersalive()) { + // jump to other side height + if (s->timer1 == KAS_WALK1) s->timer1 = KAS_JUMP1; + else s->timer1 = KAS_JUMP2; + } else { + // nobody alive - reset timer + s->timer2 = KA_WALKTIME; + s->timer3 = KA_SHOOTTIME; + } + } + } else if ((s->timer1 == KAS_JUMP1) || (s->timer1 == KAS_JUMP2)) { + + // jump to closest player height + if (!s->jumping) { + if (!playersalive() ) { // player below or dead + // go back to walking + s->timer1 = KAS_WALK1; + s->timer2 = KA_WALKTIME; + s->timer3 = KA_SHOOTTIME; + } else { + int jumpheight, jumptarget,nextstate; + jump(s, 0); + if (s->timer1 == KAS_JUMP1) { + jumpheight = 13; + jumptarget = TILEH*3; // jump to top + nextstate = KAS_WAITFORTOP1; + } else { + jumpheight = 3; + jumptarget = 480 - (TILEH*3); // jump to bottom + nextstate = KAS_WAITFORTOP2; + } + + s->willjumpspeed = jumpheight; + + // next state + s->timer1 = nextstate; + s->timer3 = jumptarget; + } + } + } else if (s->timer1 == KAS_WAITFORTOP1) { + if (!s->jumping) { + s->timer1 = KAS_FALL1; + } + } else if (s->timer1 == KAS_WAITFORTOP2) { + if (!s->jumping) { + s->timer1 = KAS_FALL2; + } + } else if ((s->timer1 == KAS_FALL1) || (s->timer1 == KAS_FALL2)) { + // King Ant's jump is handled specially in dogravity() + if (s->falling) { + if (!s->bullet) { + sprite_t *mytarget; + // shoot fireball if player in front! + mytarget = isplayerahead(s); + if (mytarget) { + sprite_t *ss; + // shoot! + playfx(FX_METEOR); + ss = addsprite(P_BIGFIREBALL,s->x,mytarget->y+(TILEH/2),"horzfireball" ); + ss->ys = 0; + ss->xs = s->dir * 4; + ss->dir = s->dir; + ss->owner = s; + + s->bullet = ss; + } + } + + } else { + // back to normal state + if (s->timer1 == KAS_FALL1) { + s->timer1 = KAS_WALK2; + } else { + s->timer1 = KAS_WALK1; + } + s->timer2 = KA_WALKTIME; + s->timer3 = KA_SHOOTTIME; + } + } } else if (s->id == P_PLATFORM) { // moving platform // timer1 tells whether we are at top speed double dstx,dsty; @@ -5184,6 +5336,26 @@ printf("setting target to y = %d\n",ss->timer2); if (movex(s, s->xs, B_TRUE)) { s->dead = D_FINAL; } + } else if (s->id == P_BIGFIREBALL) { + tiletype_t *tt; + int yyy,tx,ty; + // move + s->x += s->xs; + + // melt any ice bridges it touches + for (yyy = s->y - s->img->h ; yyy < s->y ; yyy += 4) { + tt = gettileat(s->x + (s->img->w/2),yyy, &tx,&ty); + if (tt->id == T_BRIDGE) { + melttile(tx,ty,REGROWTIMER_SHORT); + } + } + + // die if it leaves screen + if (s->x >= (640-TILEW)) { + s->dead = D_FINAL; + } else if (s->x <= TILEW) { + s->dead = D_FINAL; + } } else if (s->id == P_RAYGUNBULLET) { s->x += s->xs; if (s->x >= (640-TILEW)) { @@ -6316,6 +6488,8 @@ double getspeed(sprite_t *s ) { else speed = 1.5; } else if (id == P_KINGRAT) { speed = 1.5; + } else if (id == P_KINGANT) { + speed = 1.5; } else if (id == P_KINGFLY) { speed = 2; } else if (id == P_PLATFORM) { @@ -7440,14 +7614,61 @@ void dogravity(sprite_t *s) { } } + // king ant makes flames + if (s->id == P_KINGANT) { + // add flames on it + if (( timer % 2) == 0) { + addsprite(P_FLAME, s->x + (rand() % s->img->w) - (s->img->w/2), + s->y - (s->img->h/2) + (rand() % s->img->h/2), "antflame"); + } + } + + /* have we hit a roof ? */ - /* can jump through one tile, but not two or more */ - if (isroofabove(s) && isroofnabove(s,2)) { - if (s->id != P_KINGRAT) { // king rat can't hit roof - /* stop jumping */ - s->jumping = B_FALSE; - s->falling = B_TRUE; - s->fallspeed = 0; + if (isroofabove(s)) { + // king ANT destroys tiles when jumping, and shoots at players + if (s->id == P_KINGANT) { + int xxx; + int tx,ty; + + // melt roof + for (xxx = s->x - (s->img->w/2) ; xxx < s->x + (s->img->w/2) ; xxx += TILEW) { + tt = gettileat(xxx, s->y - s->img->h,&tx,&ty); + if (tt->id == T_BRIDGE) { + // melt it! + melttile(tx,ty,REGROWTIMER_LONG); + } + } + + + // shoot at players + if (!s->bullet) { + sprite_t *mytarget; + // shoot fireball if player in front! + mytarget = isplayerahead(s); + if (mytarget) { + sprite_t *ss; + // shoot! + playfx(FX_METEOR); + ss = addsprite(P_BIGFIREBALL,s->x,mytarget->y+(TILEH/2),"horzfireball" ); + ss->ys = 0; + ss->xs = s->dir * 4; + ss->dir = s->dir; + ss->owner = s; + + s->bullet = ss; + } + } + + } + /* can jump through one tile, but not two or more */ + if (isroofnabove(s,2)) { + if ((s->id != P_KINGRAT) && (s->id != P_KINGANT)) { // king rat can't hit roof + /* stop jumping */ + s->jumping = B_FALSE; + s->falling = B_TRUE; + s->fallspeed = 0; + } } } @@ -7491,6 +7712,30 @@ void dogravity(sprite_t *s) { s->falling = B_FALSE; s->climbing = B_FALSE; } + } else if ((s->id == P_KINGANT) && ((s->timer1 == KAS_FALL1) || (s->timer1 == KAS_FALL2))) { // special case + int xxx,tx,ty; + // add extra flames on it + if (( timer % 2) == 0) { + addsprite(P_FLAME, s->x + (rand() % s->img->w) - (s->img->w/2), + s->y - (s->img->h/2) + (rand() % s->img->h/2), "antflame"); + } + // king ant drops until he is at the wanted height + if (s->y >= s->timer3) { + s->dropping = B_FALSE; + s->falling = B_FALSE; + s->climbing = B_FALSE; + } else { + // keep falling through + ontheground = B_FALSE; + } + + // king ant melts ground + for (xxx = s->x - (s->img->w/2) ; xxx < s->x + (s->img->w/2) ; xxx += TILEW) { + tt = gettileat(xxx, s->y + 2 ,&tx,&ty); + if (tt->id == T_BRIDGE) { + melttile(tx,ty,REGROWTIMER_LONG); + } + } } else if ((s->id == P_KINGSNAIL) && (s->timer1 == KSS_JUMPING)) { // special case // king snail drops until he is at original height if (s->y < s->timer3) { // above orig height @@ -12942,6 +13187,36 @@ sprite_t *isplayerright(sprite_t *s) { return NULL; } +sprite_t *isplayerahead(sprite_t *s) { + sprite_t *seen = NULL; + int ydis; + + if (!playersalive()) { + seen = NULL; + } else { + if (player) { + ydis = abs((s->y - s->img->h/2) - (player->y - player->img->h/2)); + if (ydis > TILEH*2) { + seen = NULL; + } else if ((s->dir < 0) && (player->x > s->x)) { + seen = NULL; + } else if ((s->dir > 0) && (player->x < s->x)) { + seen = NULL; + } else seen = player; + } + if (!seen && (player2)) { + ydis = abs((s->y - s->img->h/2) - (player2->y - player2->img->h/2)); + if (ydis > TILEH*2) { + seen = NULL; + } else if ((s->dir < 0) && (player2->x > s->x)) { + seen = NULL; + } else if ((s->dir > 0) && (player2->x < s->x)) { + seen = NULL; + } else seen = player2; + } + } + return seen; +} SDL_Color *getcolour(int id) { @@ -13207,3 +13482,20 @@ int savebmp(SDL_Surface *which) { printf("Screenshot saved in %s\n",filename); return rv; } + +void melttile(int tx, int ty,int howlong) { + + if (numregrow >= (MAXREGROW-1)) { + return; + } + + regrow[numregrow].tx = tx; + regrow[numregrow].ty = ty; + regrow[numregrow].origid = curlevel->map[ty * LEVELW + tx ]; + regrow[numregrow].timer = howlong; + numregrow++; + + curlevel->map[ty * LEVELW + tx ] = getuniq(T_BLANK); + drawtile(temps, tx,ty); + puffin(-1, tx*TILEW+(TILEW/2), ty*TILEH+TILEH, "nothing", 0); +} diff --git a/rc.h b/rc.h index b3ae380..93c0233 100644 --- a/rc.h +++ b/rc.h @@ -119,6 +119,7 @@ int inintro(void); sprite_t *isplayerbelow(sprite_t *s); sprite_t *isplayerabove(sprite_t *s); sprite_t *isplayerright(sprite_t *s); +sprite_t *isplayerahead(sprite_t *s); SDL_Color *getcolour(int id); SDL_Color *getbgcolour(int id); void dointroseq(void); @@ -128,3 +129,4 @@ int isonplatform(double x, double y); int countbabies(sprite_t *s, int babytype); int isice(int id); int savebmp(SDL_Surface *which); +void melttile(int tx,int ty, int howlong); diff --git a/shared.c b/shared.c index f1fbe41..e43604b 100644 --- a/shared.c +++ b/shared.c @@ -859,7 +859,7 @@ void setdefaults(sprite_t *s) { } else if (s->id == P_KINGANT) { s->timer1 = KAS_WALK1; s->timer2 = KA_WALKTIME; - s->timer3 = 0; + s->timer3 = KA_SHOOTTIME; } if (isboss(s->id)) { s->lives = getbosshealth(s->id); // health @@ -1870,6 +1870,10 @@ int loadimagesets(void) { loadspriteimage(P_FIREBALL,1, "sprites/fire2.png"); imageset[P_FIREBALL].numimages = 2; + loadspriteimage(P_BIGFIREBALL,0, "sprites/bigfire1.png"); + loadspriteimage(P_BIGFIREBALL,1, "sprites/bigfire2.png"); + imageset[P_BIGFIREBALL].numimages = 2; + // manual angry image for black cloud @@ -2745,6 +2749,7 @@ int isfruit(int id) { int isbullet(int id) { if (id == P_SPIT) return B_TRUE; if (id == P_FIREBALL) return B_TRUE; + if (id == P_BIGFIREBALL) return B_TRUE; return B_FALSE; }