diff --git a/Makefile b/Makefile
index f560530..a71063c 100644
--- a/Makefile
+++ b/Makefile
@@ -1,2 +1,5 @@
-rc: rc.c rc.h
+rc: rc.c rc.h shared.c shared.h defs.h
gcc -Wall -DREV=`./getsvnrev.sh` -orc -g rc.c shared.c `sdl-config --cflags --libs` -I/usr/local/include -L/usr/local/lib -lSDLmain -lSDL -lSDL_image -lSDL_gfx -lSDL_ttf -lSDL_mixer
+
+edit: edit.c edit.h shared.c shared.h defs.h
+ gcc -D__EDITOR -Wall -DREV=`./getsvnrev.sh` -oedit -g edit.c shared.c `sdl-config --cflags --libs` -I/usr/local/include -L/usr/local/lib -lSDLmain -lSDL -lSDL_image -lSDL_gfx -lSDL_ttf -lSDL_mixer
diff --git a/data/levels/level99.dat b/data/levels/level99.dat
index 786927e..fc97ed9 100644
--- a/data/levels/level99.dat
+++ b/data/levels/level99.dat
@@ -4,9 +4,9 @@ hurryup 10
help
endhelp
monsters
-134 18 15
0 17 15
-171 4 7
+134 18 15
+172 17 28
endmonsters
exitdir 1
4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,
diff --git a/data/sprites/moth.png b/data/sprites/moth.png
new file mode 100644
index 0000000..014f2a6
Binary files /dev/null and b/data/sprites/moth.png differ
diff --git a/data/sprites/moth1.png b/data/sprites/moth1.png
new file mode 100644
index 0000000..ab5a22a
Binary files /dev/null and b/data/sprites/moth1.png differ
diff --git a/data/sprites/mothcaught.png b/data/sprites/mothcaught.png
new file mode 100644
index 0000000..7e48caa
Binary files /dev/null and b/data/sprites/mothcaught.png differ
diff --git a/data/sprites/mothdead.png b/data/sprites/mothdead.png
new file mode 100644
index 0000000..da43aa2
Binary files /dev/null and b/data/sprites/mothdead.png differ
diff --git a/data/sprites/mothfire0.png b/data/sprites/mothfire0.png
new file mode 100644
index 0000000..7ab07b0
Binary files /dev/null and b/data/sprites/mothfire0.png differ
diff --git a/data/sprites/mothfire1.png b/data/sprites/mothfire1.png
new file mode 100644
index 0000000..df01442
Binary files /dev/null and b/data/sprites/mothfire1.png differ
diff --git a/data/sprites/mothfire2.png b/data/sprites/mothfire2.png
new file mode 100644
index 0000000..e862fab
Binary files /dev/null and b/data/sprites/mothfire2.png differ
diff --git a/data/sprites/mothfire3.png b/data/sprites/mothfire3.png
new file mode 100644
index 0000000..71786d9
Binary files /dev/null and b/data/sprites/mothfire3.png differ
diff --git a/defs.h b/defs.h
index 23bb84f..53c1433 100644
--- a/defs.h
+++ b/defs.h
@@ -1,4 +1,3 @@
-#define KAS_WAITFORTOP 2
#ifndef __DEFS_H
#define __DEFS_H
@@ -289,6 +288,15 @@
#define KAS_WALK2 6
#define KAS_JUMP2 7
+// moth
+#define MOTH_PAUSE 20
+#define MOTH_FIRESPACE 5 // space between shots
+// moth states
+#define MS_FLY 0
+#define MS_PAUSE1 1
+#define MS_PAUSE2 2
+
+
// bell states
#define BELL_DONESOUND 1
#define BELL_DONEFLASH 2
@@ -444,7 +452,7 @@
#define S_SLOPE 2
// Sprite types
-#define MAXPTYPES 172
+#define MAXPTYPES 174
#define P_PLAYER 0
#define P_RAT 1
#define P_CHEESE 2
@@ -622,6 +630,8 @@
#define P_LAMP 169
#define P_GOLDBAR 170
#define P_WSPIDER 171
+#define P_MOTH 172
+#define P_MOTHFIRE 173
#define FLY_FLYTIME 150
@@ -811,6 +821,7 @@
#define D_LEFT (-1)
#define D_UP (-2)
#define D_DOWN (2)
+#define D_NONE (0)
// boss health bar
#define HEALTHBARY 480-100 // y position of health bar
diff --git a/rc.c b/rc.c
index 91b7b50..b19ee6c 100644
--- a/rc.c
+++ b/rc.c
@@ -2800,12 +2800,14 @@ int movesprite(sprite_t *s) {
if (isonground(s) || ((s->id == P_KINGRAT) && (s->timer1 == KRS_WALK))) {
if ((!s->falling) && (!s->jumping)) {
if (!s->climbing && !s->dropping) {
- if (!isonladder(s)) {
+ if (!isonladder(s) ) {
if ((s->id == P_KINGFLY) || ((s->id == P_FLY) && (s->owner))) {
// don't adjust
} else {
adjustheight(s);
}
+ } else if (!s->climbing) { // on ladder but not climbing
+ adjustheight(s);
}
}
}
@@ -5029,6 +5031,133 @@ int movesprite(sprite_t *s) {
movex(s, s->jumpdir*getspeed(s), B_TRUE);
faceplayer(s);
}
+ } else if (s->id == P_MOTH) {
+ /* timer1 tracks state, timer2 tracks previous direction
+ timer3 is current direction
+ */
+ if (s->timer1 == MS_FLY) {
+ if (s->timer3 == D_NONE) {
+ int tx,ty;
+ int d;
+ int maxdist = -99;
+ int newdir = D_NONE;
+ tiletype_t *tt;
+
+ // get current pos
+ tt = gettileat(s->x,s->y-2,&tx,&ty);
+ // pick a direction
+ // scan each direction...
+ for (d = 0; d < 4; d++) {
+ int xm,ym,dir;
+ if (d == 0) {
+ dir = D_UP;
+ xm = 0; ym = -1;
+ } else if (d == 1) {
+ dir = D_RIGHT;
+ xm = 1; ym = 0;
+ } else if (d == 2) {
+ dir = D_DOWN;
+ xm = 0; ym = 1;
+ } else { // ie. d == 3
+ dir = D_LEFT;
+ xm = -1; ym = 0;
+ }
+ // are we allowed to go this dir?
+ if ((dir != s->timer2) && (dir != oppositedir(s->timer2))) {
+ int curx,cury,hitwall=B_FALSE;
+ int dist = 0;
+ curx = tx;
+ cury = ty;
+ // check distance until wall
+ while (!hitwall) {
+ curx += xm;
+ cury += ym;
+ tt = gettilexy(curx, cury);
+
+ if (tt->solid) hitwall = 1;
+ if (curx < 0) hitwall = 2;
+ if (cury < 0) hitwall = 3;
+ if (curx >= LEVELW) hitwall = 4;
+ if (cury >= LEVELH) hitwall = 5;
+ dist++;
+ }
+ if (dist > maxdist) {
+ newdir = dir;
+ maxdist = dist;
+ }
+ }
+ }
+ // update our direction
+ s->timer2 = s->timer3; // old dir
+ s->timer3 = newdir; // current dir
+ } else { // we DO have a current direction
+ tiletype_t *tt;
+ if (s->timer3 == D_UP) {
+ tt = gettileat(s->x, s->y - s->img->h - getspeed(s), NULL, NULL);
+ if (tt->solid) {
+ // hit a wall
+ s->timer1 = MS_PAUSE1;
+ s->timer2 = s->timer3; // old dir
+ s->timer3 = MOTH_PAUSE;
+ } else {
+ s->moved = MV_FLY;
+ s->y -= getspeed(s);
+ }
+ } else if (s->timer3 == D_DOWN) {
+ tt = gettileat(s->x, s->y + getspeed(s), NULL, NULL);
+ if (tt->solid) {
+ // hit a wall
+ s->timer1 = MS_PAUSE1;
+ s->timer2 = s->timer3; // old dir
+ s->timer3 = MOTH_PAUSE;
+ } else {
+ s->moved = MV_FLY;
+ s->y += getspeed(s);
+ }
+ } else { // right or left
+ s->dir = s->timer3;
+ if (movex(s, s->dir * getspeed(s), B_TRUE)) {
+ // hit a wall
+ s->timer1 = MS_PAUSE1;
+ s->timer2 = s->timer3; // old dir
+ s->timer3 = MOTH_PAUSE;
+ } else {
+ s->moved = MV_FLY;
+ }
+ }
+ }
+ } else if (s->timer1 == MS_PAUSE1) {
+ s->moved = MV_FLY;
+ // wait for countdown...
+ s->timer3--;
+ if ((s->timer3 == MOTH_FIRESPACE*2) || (s->timer3 == MOTH_FIRESPACE) || (s->timer3 == 0)) {
+ sprite_t *ss,*target = NULL;
+ // closest player
+ target = getclosestplayer(s);
+ if (target) {
+ double ang;
+ // get angle towards target
+ ang = atan2(target->y - s->y, target->x - s->x);
+ // shoot
+ ss = addsprite(P_MOTHFIRE,s->x,s->y - s->img->h/2,"mothfire" );
+ ss->xs = cos(ang) * getspeed(ss);
+ ss->ys = sin(ang) * getspeed(ss);
+ }
+ }
+ if (s->timer3 == 0) {
+ // go to next state
+ s->timer1 = MS_PAUSE2;
+ s->timer3 = MOTH_PAUSE;
+ }
+ } else if (s->timer1 == MS_PAUSE2) {
+ s->moved = MV_FLY;
+ s->timer3--;
+ if (s->timer3 == 0) {
+ // go to next state
+ s->timer1 = MS_FLY;
+ s->timer3 = D_NONE;
+ }
+ }
} else if (s->id == P_SNAKE) {
/* timer1 loopsfrom 0 - 19
@@ -5628,6 +5757,20 @@ int movesprite(sprite_t *s) {
} else if (s->x <= TILEW) {
s->dead = D_FINAL;
}
+ } else if (s->id == P_MOTHFIRE) {
+ // move
+ s->x += s->xs;
+ s->y += s->ys;
+ // 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->y >= (480-TILEH)) {
+ s->dead = D_FINAL;
+ } else if (s->y <= TILEH) {
+ s->dead = D_FINAL;
+ }
} else if (s->id == P_RAYGUNBULLET) {
s->x += s->xs;
if (s->x >= (640-TILEW)) {
@@ -6760,8 +6903,13 @@ double getspeed(sprite_t *s ) {
else speed = 1.5;
}
} else if (id == P_SPIDER) {
- if (s->angry) speed = 2;
- else speed = 1.5;
+ if (s->angry) speed = 2.5;
+ else speed = 2.5;
+ } else if (id == P_MOTH) {
+ if (s->angry) speed = 3;
+ else speed = 2.5;
+ } else if (id == P_MOTHFIRE) {
+ speed = 2.5;
} else if (id == P_KINGRAT) {
speed = 1.5;
} else if (id == P_KINGANT) {
@@ -8542,7 +8690,7 @@ int movex(sprite_t *s,double amt,int onpurpose) {
s->xs = 0;
return NM_SIDE;
}
- if (tt2->solid == S_SLOPE && (!candoslopes(s->id))) {
+ if ((tt2->solid == S_SLOPE) && (!candoslopes(s->id))) {
s->xs = 0;
return NM_SIDE;
}
@@ -13497,6 +13645,32 @@ void doplayermovement(sprite_t *pl) {
}
}
+
+sprite_t *getclosestplayer(sprite_t *s) {
+ double xdiff1,xdiff2,ydiff1,ydiff2,diff1,diff2;
+ sprite_t *closest = NULL;
+ // closest player
+ if (player && !player->dead) {
+ xdiff1 = abs(player->x - s->x);
+ ydiff1 = abs(player->y - s->y);
+ diff1 = xdiff1 + ydiff1;
+ closest = player;
+ } else {
+ diff1 = 9999;
+ }
+
+ if (player2 && !player2->dead) {
+ xdiff2 = abs(player2->x - s->x);
+ ydiff2 = abs(player2->y - s->y);
+ diff2 = xdiff2 + ydiff2;
+ if (closest == NULL) closest = player2;
+ else if (closest == player) {
+ if (diff2 > diff1) closest = player2;
+ }
+ }
+ return closest;
+}
+
double getxdisttoplayer(sprite_t *s, sprite_t **pl) {
double xdiff1,xdiff2,xdiff = 9999;
if (globpowerup == PW_CAMERA) return 9999;
diff --git a/rc.h b/rc.h
index 0d6a060..cde44f4 100644
--- a/rc.h
+++ b/rc.h
@@ -113,6 +113,7 @@ void swimup(sprite_t *pl);
void swimdown(sprite_t *pl);
double getdistance(double x1, double y1, double x2, double y2);
void doplayermovement(sprite_t *pl);
+sprite_t *getclosestplayer(sprite_t *s);
double getxdisttoplayer(sprite_t *s, sprite_t **pl);
double getydisttoplayer(sprite_t *s);
int playersalive(void);
diff --git a/shared.c b/shared.c
index f44303a..29f4eb8 100644
--- a/shared.c
+++ b/shared.c
@@ -843,7 +843,7 @@ void setdefaults(sprite_t *s) {
s->lives = 1;
}
- // special for bosses
+ // special for bosses/other monsters
if (s->id == P_KINGRAT) {
s->timer1 = 0;
s->timer2 = KR_WALKTIME;
@@ -862,6 +862,10 @@ void setdefaults(sprite_t *s) {
s->timer1 = KAS_WALK1;
s->timer2 = KA_WALKTIME;
s->timer3 = KA_SHOOTTIME;
+ } else if (s->id == P_MOTH) {
+ s->timer1 = MS_FLY;
+ s->timer2 = D_NONE;
+ s->timer3 = D_NONE;
}
if (isboss(s->id)) {
s->lives = getbosshealth(s->id); // health
@@ -875,6 +879,7 @@ void setdefaults(sprite_t *s) {
case P_BLACKCLOUD:
case P_SPIDER:
case P_KINGFLY:
+ case P_MOTH:
s->flies = B_TRUE;
break;
case P_FLY:
@@ -1046,6 +1051,36 @@ tiletype_t *gettileat(int pixx,int pixy, int *tilex,int *tiley) {
return gettile(tid);
}
+int oppositedir(int dir) {
+ if (dir == D_RIGHT) return D_LEFT;
+ if (dir == D_LEFT) return D_RIGHT;
+ if (dir == D_UP) return D_DOWN;
+ if (dir == D_DOWN) return D_UP;
+
+ return D_NONE;
+}
+
+tiletype_t *gettilexy(int tilex,int tiley) {
+ int tx,ty;
+ int tid;
+
+ tx = tilex;
+ ty = tiley;
+
+ if (tx >= LEVELW) tx = LEVELW-1;
+ if (ty >= LEVELH) ty = LEVELH-1;
+
+ if (ty < 0) ty = 0;
+ if (tx < 0) tx = 0;
+
+ // return layer2 if it exists
+ tid = curlevel->map2[ty*LEVELW+tx];
+ if (tid == T_BLANK) {
+ tid = curlevel->map[ty*LEVELW+tx];
+ }
+ return gettile(tid);
+}
+
int loadtiletypes(char *filename) {
char fullfile[BUFLEN];
tiletype_t *t = NULL;
@@ -1417,6 +1452,14 @@ int loadimagesets(void) {
loadspriteimage(P_WSPIDER,F_CLIMB2, "sprites/whitespiderclimb1.png");
imageset[P_WSPIDER].numimages = 10;
+ loadspriteimage(P_MOTH,F_WALK1, "sprites/moth.png");
+ loadspriteimage(P_MOTH,F_JUMP, "sprites/moth1.png");
+ loadspriteimage(P_MOTH,F_FALL, "sprites/moth1.png");
+ loadspriteimage(P_MOTH,F_CAUGHT, "sprites/mothcaught.png");
+ loadspriteimage(P_MOTH,F_DEAD, "sprites/mothdead.png");
+ /* next 3 are auto generated */
+ imageset[P_MOTH].numimages = 8;
+
loadspriteimage(P_SPIDER,F_WALK1, "sprites/newspider.png");
loadspriteimage(P_SPIDER,F_JUMP, "sprites/newspiderjump.png");
@@ -1906,6 +1949,14 @@ int loadimagesets(void) {
loadspriteimage(P_BIGFIREBALL,1, "sprites/bigfire2.png");
imageset[P_BIGFIREBALL].numimages = 2;
+ loadspriteimage(P_MOTHFIRE,0, "sprites/mothfire0.png");
+ loadspriteimage(P_MOTHFIRE,1, "sprites/mothfire1.png");
+ loadspriteimage(P_MOTHFIRE,2, "sprites/mothfire2.png");
+ loadspriteimage(P_MOTHFIRE,3, "sprites/mothfire3.png");
+ loadspriteimage(P_MOTHFIRE,4, "sprites/mothfire2.png");
+ loadspriteimage(P_MOTHFIRE,5, "sprites/mothfire1.png");
+ imageset[P_MOTHFIRE].numimages = 6;
+
// manual angry image for black cloud
@@ -2787,6 +2838,7 @@ 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;
+ if (id == P_MOTHFIRE) return B_TRUE;
return B_FALSE;
}
@@ -3246,6 +3298,7 @@ int ismonster(int id) {
case P_ANT1:
case P_ANT2:
case P_ANT3:
+ case P_MOTH:
return MT_MONSTER;
case P_BLACKCLOUD:
case P_KINGRAT:
@@ -3761,6 +3814,7 @@ void setfruitinfo(void) {
setinfo(P_SPIDER, "Redback", "Redback spiders will lurk quietly on the ceiling, crawling back and forth. If they notice a player nearby however they will swiftly pounce down onto their prey!", "spider.png");
setinfo(P_WSPIDER, "Whitetail", "Whitetail spiders are more intelligent than other monsters - they are aware of nearby players and will use the landscape to track them down!", "whitespider.png");
+ setinfo(P_MOTH, "Moth", "The moth moves in straight lines until it hits a wall. Although simplistic in their movement, moths have the ability to fire a burst of hypno-rays to take out an unwary player!", "moth.png");
setinfo(P_FROG, "Frog", "Green frogs will continually bounce around, making them more difficult to catch. They are also excellent swimmers.", "frog.png");
@@ -3847,6 +3901,8 @@ void dumpinfo(void) {
printf("");
} else if (i == P_WSPIDER) {
printf("");
+ } else if (i == P_MOTH) {
+ printf("");
}
printf("
%s