|
|
|
@ -1,4 +1,4 @@
|
|
|
|
|
/* $Id: bomb.c,v 1.57 2004/05/20 16:55:30 stpohle Exp $ */
|
|
|
|
|
/* $Id: bomb.c,v 1.58 2004/08/08 23:18:46 stpohle Exp $ */
|
|
|
|
|
/* everything what have to do with the bombs */
|
|
|
|
|
|
|
|
|
|
#include "bomberclone.h"
|
|
|
|
@ -25,7 +25,9 @@ draw_bomb (_bomb * bomb)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (bomb->state != BS_trigger || ((bomb->state == BS_trigger) && (bomb->to < bman.bomb_tickingtime))) {
|
|
|
|
|
/* check the framenumber */
|
|
|
|
|
/*
|
|
|
|
|
* check the framenumber
|
|
|
|
|
*/
|
|
|
|
|
bomb->frame += (timefactor / 3.0);
|
|
|
|
|
if (bomb->frame < 0 || bomb->frame >= gfx.bomb.frames)
|
|
|
|
|
bomb->frame = 0.0f;
|
|
|
|
@ -34,7 +36,9 @@ draw_bomb (_bomb * bomb)
|
|
|
|
|
dest.w = src.w = gfx.bomb.image->w;
|
|
|
|
|
dest.h = src.h = gfx.block.y;
|
|
|
|
|
if (bomb->mode == BM_kicked) {
|
|
|
|
|
/* draw the kicked bomb */
|
|
|
|
|
/*
|
|
|
|
|
* draw the kicked bomb
|
|
|
|
|
*/
|
|
|
|
|
w = sqrt (bomb->speed);
|
|
|
|
|
w *= absol (sin (w));
|
|
|
|
|
x1 = bomb->dest.x - bomb->pos.x;
|
|
|
|
@ -89,23 +93,50 @@ draw_bomb (_bomb * bomb)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* the bomb is going to explode, prepare all values,
|
|
|
|
|
* set: ex_nr - explosion number for the bomb, and all resulting explosions
|
|
|
|
|
* to - timeout
|
|
|
|
|
* firer[d] - range of the bomb.
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
bomb_explode (_bomb *bomb, int net)
|
|
|
|
|
{
|
|
|
|
|
int d;
|
|
|
|
|
int d,
|
|
|
|
|
ftype,
|
|
|
|
|
dx,
|
|
|
|
|
dy;
|
|
|
|
|
_point dir_ch [] ={ { -1, 0 },
|
|
|
|
|
{ 1, 0 },
|
|
|
|
|
{ 0, -1 },
|
|
|
|
|
{ 0, 1 } };
|
|
|
|
|
|
|
|
|
|
d_printf ("Bomb Explode p:%d, b:%d [%f,%f]\n", bomb->id.p, bomb->id.b, bomb->pos.x, bomb->pos.y);
|
|
|
|
|
|
|
|
|
|
if (bomb->ex_nr == -1)
|
|
|
|
|
bomb->ex_nr = bman.last_ex_nr++; // set bomb explosion id
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
players[bomb->id.p].bomb_lastex = bomb->id.b;
|
|
|
|
|
|
|
|
|
|
bomb->to = EXPLOSIONTIMEOUT; /* set the timeout for the fireexplosion */
|
|
|
|
|
bomb->state = BS_exploding;
|
|
|
|
|
for (d = 0; d < 4; d++) {
|
|
|
|
|
bomb->firer[d] = 0;
|
|
|
|
|
bomb->firerst[d] = -1;
|
|
|
|
|
dx = bomb->pos.x;
|
|
|
|
|
dy = bomb->pos.y;
|
|
|
|
|
bomb->firer[d] = 0;
|
|
|
|
|
ftype = map.field[dx][dy].type;
|
|
|
|
|
|
|
|
|
|
while ((ftype == FT_nothing || ftype == FT_tunnel) && bomb->firer[d] < bomb->r) {
|
|
|
|
|
bomb->firer[d]++;
|
|
|
|
|
dx += dir_ch[d].x;
|
|
|
|
|
dy += dir_ch[d].y;
|
|
|
|
|
ftype = explosion_check_field (dx, dy, bomb);
|
|
|
|
|
if (ftype == FT_nothing || ftype == FT_tunnel) {
|
|
|
|
|
map.field[dx][dy].ex[d].count++;
|
|
|
|
|
map.field[dx][dy].ex[d].frame = bomb->firer[d];
|
|
|
|
|
stonelist_add (dx, dy);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (GT_MP_PTPM && net) /* from now on only the server let the bomb explode */
|
|
|
|
@ -268,10 +299,10 @@ bomb_loop ()
|
|
|
|
|
|
|
|
|
|
case BS_exploding:
|
|
|
|
|
if (bomb->to > 0.0f) {
|
|
|
|
|
do_explosion (bomb);
|
|
|
|
|
explosion_do (bomb);
|
|
|
|
|
}
|
|
|
|
|
if (bomb->to <= 0.0f) { // explosion done
|
|
|
|
|
restore_explosion (bomb);
|
|
|
|
|
explosion_restore (bomb);
|
|
|
|
|
bomb->to = 0.0f;
|
|
|
|
|
bomb->state = BS_off;
|
|
|
|
|
}
|
|
|
|
@ -314,50 +345,42 @@ get_bomb_on (float x, float y, _point bombs[])
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
restore_explosion (_bomb * bomb)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* restore the bombexplosion,
|
|
|
|
|
* will be excecuted after a explosion has finished.
|
|
|
|
|
* delete all old explosion data from the field.
|
|
|
|
|
*/
|
|
|
|
|
void explosion_restore (_bomb *bomb) {
|
|
|
|
|
int i,
|
|
|
|
|
d,
|
|
|
|
|
dx = 0,
|
|
|
|
|
dy = 0,
|
|
|
|
|
_x,
|
|
|
|
|
_y;
|
|
|
|
|
_x,
|
|
|
|
|
_y;
|
|
|
|
|
_point dir_ch [] ={ { -1, 0 },
|
|
|
|
|
{ 1, 0 },
|
|
|
|
|
{ 0, -1 },
|
|
|
|
|
{ 0, 1 } };
|
|
|
|
|
|
|
|
|
|
for (d = 0; d < 4; d++) {
|
|
|
|
|
switch (d) {
|
|
|
|
|
case (left):
|
|
|
|
|
dx = -1;
|
|
|
|
|
dy = 0;
|
|
|
|
|
break;
|
|
|
|
|
case (right):
|
|
|
|
|
dx = 1;
|
|
|
|
|
dy = 0;
|
|
|
|
|
break;
|
|
|
|
|
case (up):
|
|
|
|
|
dx = 0;
|
|
|
|
|
dy = -1;
|
|
|
|
|
break;
|
|
|
|
|
case (down):
|
|
|
|
|
dx = 0;
|
|
|
|
|
dy = 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_x = bomb->pos.x;
|
|
|
|
|
_y = bomb->pos.y;
|
|
|
|
|
|
|
|
|
|
if (map.field[_x][_y].ex[d].count > 0)
|
|
|
|
|
map.field[_x][_y].ex[d].count--;
|
|
|
|
|
if (map.field[_x][_y].ex[d].count == 0)
|
|
|
|
|
map.field[_x][_y].ex[d].frame = 0; // reset the framenumber
|
|
|
|
|
|
|
|
|
|
/* with every field where was an fire on it decrease the ex[].count value
|
|
|
|
|
* and force an drawing of this field */
|
|
|
|
|
for (i = 0; i < bomb->firer[d]; i++) {
|
|
|
|
|
if (--map.field[_x][_y].ex[d].count == 0) // there was only one explosion so
|
|
|
|
|
map.field[_x][_y].ex[d].frame = 0; // reset the framenumber
|
|
|
|
|
for (i = 0; i < bomb->firer[d]; i++) { // lower the number of explosions
|
|
|
|
|
_x = _x + dir_ch[d].x;
|
|
|
|
|
_y = _y + dir_ch[d].y;
|
|
|
|
|
|
|
|
|
|
stonelist_add (_x, _y);
|
|
|
|
|
if (map.field[_x][_y].ex[d].count > 0)
|
|
|
|
|
map.field[_x][_y].ex[d].count--;
|
|
|
|
|
if (map.field[_x][_y].ex[d].count == 0)
|
|
|
|
|
map.field[_x][_y].ex[d].frame = 0; // reset the framenumber
|
|
|
|
|
|
|
|
|
|
_x = _x + dx;
|
|
|
|
|
_y = _y + dy;
|
|
|
|
|
stonelist_add (_x, _y);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* delete the stone completly if there was any in the way
|
|
|
|
@ -370,10 +393,10 @@ restore_explosion (_bomb * bomb)
|
|
|
|
|
if (map.field[_x][_y].special != FT_nothing) {
|
|
|
|
|
map.field[_x][_y].type = map.field[_x][_y].special;
|
|
|
|
|
map.field[_x][_y].special = FT_nothing;
|
|
|
|
|
d_printf ("field_explode (%d,%d) ex_nr = %d\n", _x, _y, map.field[_x][_y].ex_nr);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
map.field[_x][_y].type = FT_nothing;
|
|
|
|
|
d_printf ("field_explode (%d,%d) ex_nr = %d\n", _x, _y, map.field[_x][_y].ex_nr);
|
|
|
|
|
|
|
|
|
|
stonelist_add (_x, _y);
|
|
|
|
|
|
|
|
|
@ -392,59 +415,12 @@ restore_explosion (_bomb * bomb)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* check the field if there is another bomb stone or wathever
|
|
|
|
|
* if a bomb is found let this one explode, on a player well this player
|
|
|
|
|
* will die and if a stone was found, start with the stone explosion
|
|
|
|
|
* RETURN: value of the stonetype (FT_*) */
|
|
|
|
|
int explosion_check_field (int x, int y, _bomb *bomb)
|
|
|
|
|
{
|
|
|
|
|
int pl[MAX_PLAYERS];
|
|
|
|
|
int i;
|
|
|
|
|
_point bo[MAX_PLAYERS * MAX_BOMBS];
|
|
|
|
|
_bomb *tmpbomb;
|
|
|
|
|
_player *tmpplayer;
|
|
|
|
|
|
|
|
|
|
if (x < 0 || x >= map.size.x || y < 0 || y >= map.size.y)
|
|
|
|
|
return FT_block;
|
|
|
|
|
|
|
|
|
|
get_player_on (x, y, pl);
|
|
|
|
|
get_bomb_on (x, y, bo);
|
|
|
|
|
|
|
|
|
|
/* check if any bomb have to explode.. */
|
|
|
|
|
for (i = 0; bo[i].x != -1; i++) {
|
|
|
|
|
tmpbomb = &players[bo[i].x].bombs[bo[i].y];
|
|
|
|
|
if (tmpbomb != bomb && tmpbomb->state != BS_exploding) {
|
|
|
|
|
tmpbomb->ex_nr = bomb->ex_nr; // set the ex_nr to identify explosions
|
|
|
|
|
bomb_explode (&players[bo[i].x].bombs[bo[i].y], 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// check if any player is in the explosion
|
|
|
|
|
for (i = 0; pl[i] != -1; i++) {
|
|
|
|
|
tmpplayer = &players[pl[i]];
|
|
|
|
|
if (((tmpplayer->state & PSF_alife) != 0)
|
|
|
|
|
&& (GT_SP
|
|
|
|
|
|| (GT_MP && (&players[bman.p_nr] == tmpplayer || (IS_LPLAYER2 && &players[bman.p2_nr] == tmpplayer)))
|
|
|
|
|
|| (GT_MP_PTPM && PS_IS_aiplayer (tmpplayer->state))))
|
|
|
|
|
player_died (tmpplayer, bomb->id.p);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// let the stones right beside explode
|
|
|
|
|
if (map.field[x][y].type != FT_nothing && map.field[x][y].type != FT_tunnel
|
|
|
|
|
&& map.field[x][y].type != FT_block && bomb->ex_nr != map.field[x][y].ex_nr)
|
|
|
|
|
if (map.field[x][y].frame <= 0.0f) {
|
|
|
|
|
map.field[x][y].frame = 1.0f;
|
|
|
|
|
|
|
|
|
|
stonelist_add (x, y);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return map.field[x][y].type;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* draw the explosion as far as she got */
|
|
|
|
|
/*
|
|
|
|
|
* draw the explosion as far as she got
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
draw_explosion (_bomb * bomb)
|
|
|
|
|
explosion_draw (_bomb * bomb)
|
|
|
|
|
{
|
|
|
|
|
int d,
|
|
|
|
|
r,
|
|
|
|
@ -487,62 +463,74 @@ draw_explosion (_bomb * bomb)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* do the bombexplosion itself, with every loop for one explosion
|
|
|
|
|
* add one more distance from the bomb if no stones are in the way */
|
|
|
|
|
void
|
|
|
|
|
do_explosion (_bomb *bomb)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* calculate the explosion itself,
|
|
|
|
|
* check the direction of the explosion and and and
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
void explosion_do (_bomb *bomb) {
|
|
|
|
|
/* with a slow pc disable this --- maybe option over a config menu */
|
|
|
|
|
if (bomb->state == BS_exploding)
|
|
|
|
|
explosion_draw (bomb);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* check the field if there is another bomb stone or wathever
|
|
|
|
|
* if a bomb is found let this one explode, on a player well this player
|
|
|
|
|
* will die and if a stone was found, start with the stone explosion
|
|
|
|
|
* RETURN: value of the stonetype (FT_*) */
|
|
|
|
|
int explosion_check_field (int x, int y, _bomb *bomb)
|
|
|
|
|
{
|
|
|
|
|
int dx = 0,
|
|
|
|
|
dy = 0,
|
|
|
|
|
d;
|
|
|
|
|
int pl[MAX_PLAYERS];
|
|
|
|
|
int i;
|
|
|
|
|
_point bo[MAX_PLAYERS * MAX_BOMBS];
|
|
|
|
|
_bomb *tmpbomb;
|
|
|
|
|
_player *tmpplayer;
|
|
|
|
|
|
|
|
|
|
for (d = 0; d < 4; d++) {
|
|
|
|
|
switch (d) {
|
|
|
|
|
case (left):
|
|
|
|
|
dx = -1;
|
|
|
|
|
dy = 0;
|
|
|
|
|
break;
|
|
|
|
|
case (right):
|
|
|
|
|
dx = 1;
|
|
|
|
|
dy = 0;
|
|
|
|
|
break;
|
|
|
|
|
case (up):
|
|
|
|
|
dx = 0;
|
|
|
|
|
dy = -1;
|
|
|
|
|
break;
|
|
|
|
|
case (down):
|
|
|
|
|
dx = 0;
|
|
|
|
|
dy = 1;
|
|
|
|
|
break;
|
|
|
|
|
if (x < 0 || x >= map.size.x || y < 0 || y >= map.size.y)
|
|
|
|
|
return FT_block;
|
|
|
|
|
|
|
|
|
|
get_player_on (x, y, pl);
|
|
|
|
|
get_bomb_on (x, y, bo);
|
|
|
|
|
|
|
|
|
|
/* check if any bomb have to explode.. */
|
|
|
|
|
for (i = 0; bo[i].x != -1; i++) {
|
|
|
|
|
tmpbomb = &players[bo[i].x].bombs[bo[i].y];
|
|
|
|
|
if (tmpbomb != bomb && tmpbomb->state != BS_exploding) {
|
|
|
|
|
tmpbomb->ex_nr = bomb->ex_nr; // set the ex_nr to identify explosions
|
|
|
|
|
bomb_explode (tmpbomb, 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (bomb->firer[d] <= bomb->r) {
|
|
|
|
|
int checkfield;
|
|
|
|
|
// check if any player is in the explosion
|
|
|
|
|
for (i = 0; pl[i] != -1; i++) {
|
|
|
|
|
tmpplayer = &players[pl[i]];
|
|
|
|
|
if (((tmpplayer->state & PSF_alife) != 0)
|
|
|
|
|
&& (GT_SP
|
|
|
|
|
|| (GT_MP && (&players[bman.p_nr] == tmpplayer || (IS_LPLAYER2 && &players[bman.p2_nr] == tmpplayer)))
|
|
|
|
|
|| (GT_MP_PTPM && PS_IS_aiplayer (tmpplayer->state))))
|
|
|
|
|
player_died (tmpplayer, bomb->id.p);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dx = bomb->firer[d] * dx;
|
|
|
|
|
dy = bomb->firer[d] * dy;
|
|
|
|
|
// let the stones right beside explode
|
|
|
|
|
if (map.field[x][y].type != FT_nothing && map.field[x][y].type != FT_tunnel
|
|
|
|
|
&& map.field[x][y].type != FT_block && bomb->ex_nr != map.field[x][y].ex_nr)
|
|
|
|
|
if (map.field[x][y].frame <= 0.0f) {
|
|
|
|
|
map.field[x][y].frame = 1.0f;
|
|
|
|
|
|
|
|
|
|
checkfield = explosion_check_field (bomb->pos.x + dx, bomb->pos.y + dy, bomb);
|
|
|
|
|
if ((checkfield == FT_nothing || checkfield == FT_tunnel)
|
|
|
|
|
&& bomb->firerst[d] == -1) {
|
|
|
|
|
bomb->firer[d]++;
|
|
|
|
|
map.field[(int) bomb->pos.x + dx][(int) bomb->pos.y + dy].ex[d].count++;
|
|
|
|
|
map.field[(int) bomb->pos.x + dx][(int) bomb->pos.y + dy].ex[d].frame =
|
|
|
|
|
bomb->firer[d];
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
bomb->firerst[d] = bomb->firer[d];
|
|
|
|
|
stonelist_add (bomb->pos.x + dx, bomb->pos.y + dy);
|
|
|
|
|
}
|
|
|
|
|
stonelist_add (x, y);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* with a slow pc disable this --- maybe option over a config menu */
|
|
|
|
|
if (bomb->state == BS_exploding)
|
|
|
|
|
draw_explosion (bomb);
|
|
|
|
|
return map.field[x][y].type;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inline void
|
|
|
|
|
bomb_action (_bomb * bomb)
|
|
|
|
|
{
|
|
|
|
|