You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
811 lines
22 KiB
811 lines
22 KiB
/* player.c - everything what have to do with the player */
|
|
|
|
#include <SDL.h>
|
|
#include "bomberclone.h"
|
|
#include "network.h"
|
|
#include "sound.h"
|
|
|
|
void
|
|
draw_player (_player * player)
|
|
{
|
|
SDL_Rect src,
|
|
dest;
|
|
int i;
|
|
|
|
if ((int)player->pos.x < 0 || (int)player->pos.x >= map.size.x ||
|
|
(int)player->pos.y < 0 || (int)player->pos.y >= map.size.y) {
|
|
d_printf ("FATAL: Draw Player out of range : [%f,%f]\n", player->pos.x,
|
|
player->pos.y);
|
|
return;
|
|
}
|
|
|
|
if (PS_IS_alife (player->state)) {
|
|
/* player is alife */
|
|
dest.w = src.w = player->gfx->ani.w;
|
|
dest.h = src.h = player->gfx->ani.h;
|
|
dest.x =
|
|
gfx.offset.x + player->gfx->offset.x + player->pos.x * gfx.block.x;
|
|
dest.y =
|
|
gfx.offset.y + player->gfx->offset.y + player->pos.y * gfx.block.y;
|
|
src.x = player->d * player->gfx->ani.w;
|
|
src.y = (int)player->frame * player->gfx->ani.h;
|
|
|
|
gfx_blit (player->gfx->ani.image, &src, gfx.screen, &dest, (player->pos.y * 256) + 128);
|
|
|
|
/* if the player is ill, draw this image above him */
|
|
for (i = PI_max - 1; (i >= 0) && (player->ill[i].to <= 0.0f); i--);
|
|
if (i >= 0) {
|
|
player->illframe += timefactor;
|
|
if (player->illframe > gfx.ill.frames)
|
|
player->illframe = 0.0f;
|
|
|
|
dest.w = src.w = gfx.block.x * 2;
|
|
dest.h = src.h = gfx.block.y * 2;
|
|
src.x = 0;
|
|
src.y = (2 * gfx.block.y) * (int)player->illframe;
|
|
dest.x =
|
|
gfx.offset.x + ((player->pos.x-0.5f) * gfx.block.x);
|
|
dest.y =
|
|
gfx.offset.y + ((player->pos.y - 1.0f) * gfx.block.y);
|
|
gfx_blit (gfx.ill.image, &src, gfx.screen, &dest, (player->pos.y*256) + 129);
|
|
}
|
|
}
|
|
|
|
else {
|
|
/* player is dead */
|
|
dest.w = src.w = gfx.dead.image->w;
|
|
dest.h = src.h = player->gfx->ani.h;
|
|
|
|
dest.x =
|
|
gfx.offset.x + player->gfx->offset.x + player->pos.x * gfx.block.x;
|
|
dest.y =
|
|
gfx.offset.y + player->gfx->offset.y + player->pos.y * gfx.block.y;
|
|
|
|
src.x = 0;
|
|
src.y = (2 * gfx.block.y) * (int)player->frame;
|
|
|
|
gfx_blit (gfx.dead.image, &src, gfx.screen, &dest, 0xFFFF);
|
|
}
|
|
player->old = player->pos; // save this position
|
|
};
|
|
|
|
|
|
void
|
|
restore_players_screen ()
|
|
{
|
|
int i,
|
|
x,
|
|
xs,
|
|
xe,
|
|
y,
|
|
ys,
|
|
ye;
|
|
|
|
for (i = 0; i < MAX_PLAYERS; i++)
|
|
if ((PS_IS_used (players[i].state)) && players[i].old.x >= 0.0f ) {
|
|
|
|
if (players[i].old.x < 0.0f || players[i].old.x >= map.size.x
|
|
|| players[i].old.y < 0.0f || players[i].old.y >= map.size.y)
|
|
d_printf ("FATAL: Restore Player out of range : playernr %d [%f,%f]\n", i,
|
|
players[i].old.x, players[i].old.y);
|
|
else {
|
|
// start and end position for the stones to redraw X Position
|
|
if (CUTINT(players[i].old.x) > 0.5f) {
|
|
x = players[i].old.x;
|
|
xe = players[i].old.x + 2;
|
|
}
|
|
else {
|
|
x = players[i].old.x - 1;
|
|
xe = players[i].old.x + 1;
|
|
}
|
|
if (x < 0)
|
|
x = 0;
|
|
if (xe >= map.size.x)
|
|
xe = map.size.x - 1;
|
|
// start and end position for the stones to redraw X Position
|
|
ys = players[i].old.y - 1;
|
|
ye = players[i].old.y + 1;
|
|
if (ys < 0)
|
|
ys = 0;
|
|
if (ye >= map.size.y)
|
|
ye = map.size.y - 1;
|
|
// redrawing of the stone
|
|
xs = x;
|
|
for (; x <= xe; x++)
|
|
for (y = ys; y <= ye; y++)
|
|
stonelist_add (x, y);
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
void
|
|
player_check_powerup (int p_nr)
|
|
{
|
|
_player *p = &players[p_nr];
|
|
int fx = p->pos.x;
|
|
int fy = p->pos.y;
|
|
int ft,
|
|
i;
|
|
|
|
if (PS_IS_netplayer (p->state))
|
|
return;
|
|
|
|
/* Get the right field position */
|
|
if (CUTINT(p->pos.x) > 0.5)
|
|
fx = fx + 1;
|
|
if (CUTINT(p->pos.y) > 0.5)
|
|
fy = fy + 1;
|
|
ft = map.field[fx][fy].type;
|
|
|
|
/* we found a mixed powerup */
|
|
if (ft == FT_mixed) {
|
|
i = s_random (6);
|
|
switch (i) {
|
|
case 0:
|
|
ft = FT_bomb;
|
|
break;
|
|
case 1:
|
|
ft = FT_fire;
|
|
break;
|
|
case 2:
|
|
ft = FT_shoe;
|
|
break;
|
|
case 3:
|
|
case 4:
|
|
case 5:
|
|
ft = FT_death;
|
|
break;
|
|
}
|
|
}
|
|
|
|
switch (ft) {
|
|
/* we found a bomb powerup */
|
|
case FT_bomb:
|
|
if (p->bombs_n < MAX_BOMBS && p->ill[PI_nobomb].to <= 0) {
|
|
p->bombs_n++;
|
|
bman.updatestatusbar = 1;
|
|
}
|
|
field_clear (fx, fy);
|
|
break;
|
|
/* we found a fire powerup */
|
|
case FT_fire:
|
|
if (p->range < MAX_RANGE && p->ill[PI_range].to <= 0) {
|
|
p->range++;
|
|
bman.updatestatusbar = 1;
|
|
}
|
|
field_clear (fx, fy);
|
|
break;
|
|
/* we found a shoe powerup */
|
|
case FT_shoe:
|
|
if (p->speed < MAX_SPEED && p->ill[PI_slow].to <= 0) {
|
|
p->speed *= SPEEDMUL;
|
|
bman.updatestatusbar = 1;
|
|
}
|
|
field_clear (fx, fy);
|
|
break;
|
|
/* we found a death ?powerup? */
|
|
case FT_death:
|
|
player_set_ilness (p, -1);
|
|
bman.updatestatusbar = 1;
|
|
if (GT_MP)
|
|
net_game_send_ill (bman.p_nr);
|
|
field_clear (fx, fy);
|
|
break;
|
|
/* we found a special */
|
|
case FT_sp_trigger:
|
|
case FT_sp_row:
|
|
case FT_sp_push:
|
|
case FT_sp_moved:
|
|
case FT_sp_liquid:
|
|
special_pickup (p_nr, ft - FT_sp_trigger + 1);
|
|
bman.updatestatusbar = 1;
|
|
field_clear (fx, fy);
|
|
break;
|
|
}
|
|
};
|
|
|
|
|
|
/*
|
|
check the givin field. if we are able to move on it
|
|
fx,fy = position on the field
|
|
*/
|
|
int
|
|
check_field (short int x, short int y)
|
|
{
|
|
int res = 0;
|
|
|
|
if (map.field[x][y].type != FT_stone && map.field[x][y].type != FT_block)
|
|
res = 1;
|
|
|
|
return res;
|
|
}
|
|
|
|
|
|
/* make only a smal step until i can go around the corner
|
|
return the rest speed for this move */
|
|
int
|
|
stepmove_player (int pl_nr)
|
|
{
|
|
_point bomb1[MAX_PLAYERS * MAX_BOMBS],
|
|
bomb2[MAX_PLAYERS * MAX_BOMBS];
|
|
_player *p = &players[pl_nr];
|
|
int i,
|
|
j,
|
|
f;
|
|
_pointf _pos, // position inside the field
|
|
d; // distance to move
|
|
float speed = 0.0f;
|
|
|
|
|
|
if (p->m == 1) {
|
|
_pos.x = CUTINT(p->pos.x);
|
|
_pos.y = CUTINT(p->pos.y);
|
|
|
|
// do direction correction for going up/down
|
|
if (_pos.x > 0.0f && _pos.x <= 0.5f && (p->d == up || p->d == down))
|
|
p->d = left;
|
|
if (_pos.x > 0.5f && _pos.x < 1.0f && (p->d == up || p->d == down))
|
|
p->d = right;
|
|
// do direction correction for left/right
|
|
if (_pos.y > 0.0f && _pos.y <= 0.5f && (p->d == left || p->d == right))
|
|
p->d = up;
|
|
if (_pos.y > 0.5f && _pos.y < 1.0f && (p->d == left || p->d == right))
|
|
p->d = down;
|
|
|
|
/* get the distance/speed until we reach the next position */
|
|
if (p->d == left)
|
|
speed = _pos.x;
|
|
else if (p->d == right)
|
|
speed = 1.0f - _pos.x;
|
|
else if (p->d == up)
|
|
speed = _pos.y;
|
|
else
|
|
speed = 1.0f - _pos.y;
|
|
|
|
if (speed > (p->speed * timefactor) || speed == 0)
|
|
speed = p->speed * timefactor;
|
|
|
|
// check the new field position
|
|
d.x = d.y = 0.0f;
|
|
if (p->d == left && _pos.y == 0.0f
|
|
&& ((_pos.x == 0.0f && check_field (p->pos.x - 1.0f, p->pos.y)) || (_pos.x > 0.0f)))
|
|
d.x = -speed;
|
|
if (p->d == right && _pos.y == 0.0f
|
|
&& ((_pos.x == 0.0f && check_field (p->pos.x + 1.0f, p->pos.y)) || (_pos.x > 0.0f)))
|
|
d.x = speed;
|
|
if (p->d == up && _pos.x == 0.0f
|
|
&& ((_pos.y == 0.0f && check_field (p->pos.x, p->pos.y - 1.0f)) || (_pos.y > 0.0f)))
|
|
d.y = -speed;
|
|
if (p->d == down && _pos.x == 0.0f
|
|
&& ((_pos.y == 0.0f && check_field (p->pos.x, p->pos.y + 1.0f)) || (_pos.y > 0.0f)))
|
|
d.y = speed;
|
|
|
|
// check if we can move and if there is any bomb
|
|
if (d.y != 0 || d.x != 0) {
|
|
get_bomb_on (p->pos.x, p->pos.y, bomb1);
|
|
get_bomb_on (p->pos.x + d.x, p->pos.y + d.y, bomb2);
|
|
|
|
if (bomb1[0].x == -1 && bomb2[0].x != -1)
|
|
/* old pos no bomb, new pos no bomb */
|
|
d.x = d.y = 0.0f;
|
|
else if (bomb2[0].x != -1) {
|
|
/* new pos bomb, old pos bomb... check if it's the same
|
|
use f to save if we found the bomb or not
|
|
f == 0 no bomb found, f == 1 bomb found */
|
|
for (i = 0, f = 1; (bomb2[i].x != -1 && f == 1); i++)
|
|
for (f = 0, j = 0; (bomb1[j].x != -1 && f == 0); j++)
|
|
if (bomb1[j].x == bomb2[i].x && bomb1[j].y == bomb2[i].y)
|
|
/* identical bomb found ... f = 1 */
|
|
f = 1;
|
|
if (f == 0)
|
|
d.x = d.y = 0.0f;
|
|
}
|
|
}
|
|
|
|
p->pos.x += d.x;
|
|
p->pos.y += d.y;
|
|
|
|
player_check_powerup (pl_nr);
|
|
|
|
_pos.x = CUTINT(p->pos.x);
|
|
_pos.y = CUTINT(p->pos.y);
|
|
|
|
/* check if we can go though a tunnel */
|
|
if (_pos.x == 0.0f && _pos.y == 0.0f && map.field[(int)p->pos.x][(int)p->pos.y].type == FT_tunnel
|
|
&& p->tunnelto <= 0.0f) {
|
|
|
|
int tunnelnr = map.field[(int)p->pos.x][(int)p->pos.y].special;
|
|
d_printf ("Tunnel [%d] Player %s is going to (%d,%d)\n", tunnelnr, p->name,
|
|
map.tunnel[tunnelnr].x, map.tunnel[tunnelnr].y);
|
|
d.x = d.y = 0.0f;
|
|
if (map.bfield[map.tunnel[tunnelnr].x][map.tunnel[tunnelnr].y])
|
|
d_printf (" *** End of tunnel is with an bomb.\n");
|
|
else {
|
|
p->pos.x = map.tunnel[tunnelnr].x;
|
|
p->pos.y = map.tunnel[tunnelnr].y;
|
|
p->tunnelto = GAME_TUNNEL_TO;
|
|
speed = p->speed * timefactor;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (d.x == 0.0f && d.y == 0.0f)
|
|
return 0;
|
|
|
|
return (p->speed - (speed/timefactor));
|
|
};
|
|
|
|
|
|
/* check if the givin position is oky
|
|
1 = ok, 0 = bad */
|
|
int
|
|
player_checkpos (int x, int y)
|
|
{
|
|
int i,
|
|
d;
|
|
|
|
for (i = 0, d = 0; d < 4; d++)
|
|
if (map.field[x][y].ex[d].count > 0)
|
|
i++;
|
|
|
|
if (map.field[x][y].type == FT_block || i > 0)
|
|
return 0;
|
|
else
|
|
return 1;
|
|
};
|
|
|
|
|
|
/* move the player if he have to move AND check if we are on a block
|
|
or over fire */
|
|
void
|
|
move_player (int pl_nr)
|
|
{
|
|
|
|
int oldd,
|
|
stepsleft,
|
|
speed;
|
|
_player *p = &players[pl_nr];
|
|
|
|
oldd = p->d;
|
|
|
|
if (p->tunnelto > 0.0f) {
|
|
p->tunnelto -= timediff;
|
|
p->m = 0;
|
|
if (p->tunnelto <= 0.0f && GT_MP)
|
|
net_game_send_playermove (bman.p_nr, 1);
|
|
}
|
|
else {
|
|
if (p->m) {
|
|
player_animation (p);
|
|
if ((stepsleft = stepmove_player (pl_nr)) > 0) {
|
|
/* save the speed and go the rest of the step */
|
|
p->d = oldd;
|
|
speed = p->speed;
|
|
p->speed = stepsleft;
|
|
stepmove_player (pl_nr);
|
|
p->speed = speed;
|
|
}
|
|
|
|
/* network packet send control - send data if it's time to send or if we need to */
|
|
if (GT_MP)
|
|
net_game_send_playermove (pl_nr, (p->old_m == 0));
|
|
}
|
|
|
|
/* the player just stopt moving so send data */
|
|
if (GT_MP && p->m == 0 && p->old_m != 0)
|
|
net_game_send_playermove (pl_nr, 1);
|
|
p->old_m = p->m; // save the old state
|
|
p->m = 0;
|
|
|
|
/* check the players position */
|
|
if ((CUTINT(p->pos.x) > EXPLOSION_SAVE_DISTANCE && (p->d == left || p->d == right))
|
|
&& (!check_field (p->pos.x + 1.0f, p->pos.y)))
|
|
player_died (p, -1);
|
|
if ((CUTINT(p->pos.y) > EXPLOSION_SAVE_DISTANCE && (p->d == up || p->d == down))
|
|
&& (!check_field (p->pos.x, p->pos.y + 1.0f)))
|
|
player_died (p, -1);
|
|
if (((CUTINT(p->pos.x) < (1.0f - EXPLOSION_SAVE_DISTANCE) && (p->d == left || p->d == right))
|
|
|| (CUTINT(p->pos.y) < (1.0f - EXPLOSION_SAVE_DISTANCE)
|
|
&& (p->d == up || p->d == down)))
|
|
&& (!check_field (p->pos.x, p->pos.y)))
|
|
player_died (p, -1);
|
|
}
|
|
};
|
|
|
|
|
|
void
|
|
player_drop_bomb (int pl_nr)
|
|
{
|
|
|
|
_player *player = &players[pl_nr];
|
|
_bomb *bomb = NULL;
|
|
int i;
|
|
_point bombs[MAX_PLAYERS * MAX_BOMBS];
|
|
|
|
i = player_findfreebomb (player);
|
|
|
|
if (i >= 0 && i < MAX_BOMBS && PS_IS_alife (player->state)) { // free bomb found
|
|
// get the best position for the bomb.
|
|
bomb = &player->bombs[i];
|
|
bomb->pos.x = rintf (player->pos.x);
|
|
bomb->pos.y = rintf (player->pos.y);
|
|
|
|
get_bomb_on (bomb->pos.x, bomb->pos.y, bombs);
|
|
if (bombs[0].x != -1) // is there already a bomb
|
|
return;
|
|
|
|
d_printf ("Player %d Dropped Bomb %d\n", pl_nr, i);
|
|
bomb->r = player->range;
|
|
if (player->special.type == SP_trigger) {
|
|
bomb->state = BS_trigger;
|
|
bomb->to = SPECIAL_TRIGGER_TIMEOUT;
|
|
}
|
|
else {
|
|
bomb->state = BS_ticking;
|
|
bomb->to = BOMB_TIMEOUT;
|
|
}
|
|
bomb->mode = BM_normal;
|
|
bomb->ex_nr = -1;
|
|
map.bfield[(int)bomb->pos.x][(int)bomb->pos.y] = 1;
|
|
if (GT_MP) {
|
|
net_game_send_bomb (pl_nr, i);
|
|
if (GT_MP_PTPS)
|
|
bomb->to = bomb->to + 2 * RESENDCACHE_RETRY;
|
|
}
|
|
|
|
snd_play (SND_bombdrop);
|
|
}
|
|
};
|
|
|
|
|
|
/*
|
|
check the field - 4 pixels from every side.. so it's not anymore that tricky to get
|
|
away from bombs.. */
|
|
void
|
|
get_player_on (float x, float y, int pl_nr[])
|
|
{
|
|
int i,
|
|
p;
|
|
|
|
for (i = 0, p = 0; p < MAX_PLAYERS; p++)
|
|
if (PS_IS_alife (players[p].state) && players[p].tunnelto <= 0) {
|
|
if ((players[p].pos.x - EXPLOSION_SAVE_DISTANCE) > x - 1.0f
|
|
&& (players[p].pos.x + EXPLOSION_SAVE_DISTANCE) < x + 1.0f
|
|
&& (players[p].pos.y - EXPLOSION_SAVE_DISTANCE) > y - 1.0f
|
|
&& (players[p].pos.y + EXPLOSION_SAVE_DISTANCE) < y + 1.0f) {
|
|
pl_nr[i] = p;
|
|
i++;
|
|
}
|
|
}
|
|
pl_nr[i] = -1;
|
|
};
|
|
|
|
|
|
void
|
|
player_died (_player * player, signed char dead_by)
|
|
{
|
|
// player die !
|
|
|
|
d_printf ("player_died (%10s)\n", player->name);
|
|
|
|
bman.updatestatusbar = 1; // force an update
|
|
if (PS_IS_alife (player->state) && dead_by >= 0 && dead_by < MAX_PLAYERS)
|
|
if (bman.p_nr != dead_by)
|
|
players[dead_by].points++;
|
|
player->frame = 0;
|
|
player->state &= (0xFF - PSF_alife);
|
|
player->dead_by = dead_by;
|
|
if (GT_MP)
|
|
net_game_send_player (player - &players[0]);
|
|
snd_play (SND_dead);
|
|
};
|
|
|
|
|
|
void
|
|
draw_players ()
|
|
{
|
|
int p;
|
|
for (p = 0; p < MAX_PLAYERS; p++) {
|
|
if (PS_IS_playing (players[p].state) && players[p].tunnelto <= 0)
|
|
draw_player (&players[p]);
|
|
}
|
|
};
|
|
|
|
|
|
void
|
|
player_animation (_player * player)
|
|
{
|
|
if (player->gfx == NULL)
|
|
return;
|
|
|
|
if (PS_IS_alife (player->state)) {
|
|
player->frame += timefactor;
|
|
if ((int)player->frame >= player->gfx->ani.frames)
|
|
player->frame = 0.0f;
|
|
}
|
|
|
|
if (PS_IS_dead (player->state)) {
|
|
if ((int)player->frame < gfx.dead.frames)
|
|
player->frame += timefactor;
|
|
}
|
|
};
|
|
|
|
|
|
int
|
|
dead_playerani ()
|
|
{
|
|
int i,
|
|
b = 0;
|
|
|
|
for (i = 0; i < MAX_PLAYERS; i++)
|
|
if (PS_IS_dead (players[i].state)) {
|
|
player_animation (&players[i]);
|
|
b++;
|
|
}
|
|
|
|
return b;
|
|
};
|
|
|
|
|
|
void
|
|
player_calcstep (_player * pl)
|
|
{
|
|
_pointf d;
|
|
|
|
player_animation (pl);
|
|
d.x = 0;
|
|
d.y = 0;
|
|
if (pl->d == left)
|
|
d.x = -pl->speed * timefactor;
|
|
else if (pl->d == right)
|
|
d.x = pl->speed * timefactor;
|
|
else if (pl->d == up)
|
|
d.y = -pl->speed * timefactor;
|
|
else if (pl->d == down)
|
|
d.y = pl->speed * timefactor;
|
|
|
|
if (map.field[postofield(pl->pos.x+d.x)][postofield(pl->pos.y+d.y)].type != FT_block
|
|
&& map.field[postofield(pl->pos.x+d.x)][postofield(pl->pos.y+d.y)].type != FT_stone) {
|
|
pl->pos.x += d.x;
|
|
pl->pos.y += d.y;
|
|
}
|
|
};
|
|
|
|
|
|
/*
|
|
calc the position on the screen for moving network players
|
|
*/
|
|
void
|
|
player_calcpos ()
|
|
{
|
|
_player *pl;
|
|
int oldm,
|
|
oldd,
|
|
p;
|
|
|
|
for (p = 0; p < MAX_PLAYERS; p++) {
|
|
pl = &players[p];
|
|
if (PS_IS_netplayer (pl->state) && PS_IS_alife (pl->state) && pl->m != 0) {
|
|
|
|
oldm = pl->m;
|
|
oldd = pl->d;
|
|
if (pl->speed > 0.0)
|
|
stepmove_player (p);
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
void
|
|
player_ilness_loop (int pl_nr)
|
|
{
|
|
_player *p;
|
|
int type,
|
|
pnr,
|
|
i,
|
|
send;
|
|
float tmpf;
|
|
int pl[MAX_PLAYERS + 1];
|
|
|
|
/* do the illness for the network players */
|
|
if (GT_MP) {
|
|
for (pnr = 0; pnr < MAX_PLAYERS; pnr++)
|
|
if (pnr != pl_nr && PS_IS_alife (players[pnr].state)) {
|
|
p = &players[pnr];
|
|
for (type = 0; type < PI_max; type++)
|
|
if (p->ill[type].to > 0.0f) {
|
|
p->ill[type].to -= timediff;
|
|
p->illframe += timefactor;
|
|
if (p->illframe < 0 || p->illframe >= gfx.ill.frames)
|
|
p->illframe = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* check if we have contact with an other ill player */
|
|
p = &players[pl_nr];
|
|
get_player_on (p->pos.x, p->pos.y, pl);
|
|
for (i = 0; (pl[i] != -1 && i < MAX_PLAYERS); i++)
|
|
if (pl[i] != pl_nr) {
|
|
send = 0;
|
|
for (type = 0; type < PI_max; type++) {
|
|
if (players[pl[i]].ill[type].to > p->ill[type].to) {
|
|
tmpf = p->ill[type].to;
|
|
player_set_ilness (p, type);
|
|
p->ill[type].to = players[pl[i]].ill[type].to;
|
|
if (tmpf <= 0.0f)
|
|
send = 1;
|
|
}
|
|
}
|
|
if (send != 0 && GT_MP)
|
|
net_game_send_ill (pl_nr);
|
|
}
|
|
|
|
/* do the illness for the givin player */
|
|
for (type = 0; type < PI_max; type++)
|
|
if (p->ill[type].to > 0.0f) {
|
|
p->ill[type].to -= timediff;
|
|
if (p->ill[type].to <= 0.0f)
|
|
player_clear_ilness (p, type);
|
|
else {
|
|
p->illframe += timediff;
|
|
if (p->illframe < 0 || p->illframe >= gfx.ill.frames)
|
|
p->illframe = 0.0f;
|
|
|
|
if (type == PI_keys) {
|
|
/* switch direction for player key illness */
|
|
if (p->m > 0)
|
|
switch (p->d) {
|
|
case (left):
|
|
p->d = right;
|
|
break;
|
|
case (right):
|
|
p->d = left;
|
|
break;
|
|
case (up):
|
|
p->d = down;
|
|
break;
|
|
case (down):
|
|
p->d = up;
|
|
break;
|
|
}
|
|
}
|
|
else if (type == PI_bomb)
|
|
/* player is dropping bombs */
|
|
player_drop_bomb (pl_nr);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* player picked up the death powerup, add timeout for
|
|
this illness to the maybe excisting timeout */
|
|
void
|
|
player_set_ilness (_player * p, int t)
|
|
{
|
|
int type;
|
|
if (t == -1)
|
|
type = s_random (PI_max);
|
|
else
|
|
type = t;
|
|
|
|
d_printf ("Ilness : %d\n", type);
|
|
switch (type) {
|
|
case PI_slow:
|
|
if (p->ill[type].to <= 0.0f) {
|
|
if (p->ill[PI_fast].to > 0.0f) {
|
|
p->ill[type].dataf = p->ill[PI_fast].dataf;
|
|
p->ill[PI_fast].to = 0.0f;
|
|
}
|
|
else
|
|
p->ill[type].dataf = p->speed;
|
|
}
|
|
p->speed = ILL_SLOWSPEED;
|
|
break;
|
|
case PI_fast:
|
|
if (p->ill[type].to <= 0.0f) {
|
|
if (p->ill[PI_slow].to > 0.0f) {
|
|
p->ill[type].dataf = p->ill[PI_slow].dataf;
|
|
p->ill[PI_slow].to = 0.0f;
|
|
}
|
|
else
|
|
p->ill[type].dataf = p->speed;
|
|
}
|
|
|
|
p->speed = ILL_FASTSPEED;
|
|
break;
|
|
case PI_range:
|
|
if (p->ill[type].to == 0)
|
|
p->ill[type].datai = p->range;
|
|
p->range = 1;
|
|
break;
|
|
case PI_nobomb:
|
|
if (p->ill[type].to == 0)
|
|
p->ill[type].datai = p->bombs_n;
|
|
p->bombs_n = s_random (2);
|
|
break;
|
|
}
|
|
bman.updatestatusbar = 1;
|
|
p->ill[type].to += ILL_TIMEOUT;
|
|
};
|
|
|
|
|
|
/* players ilness is over now */
|
|
void
|
|
player_clear_ilness (_player * p, int type)
|
|
{
|
|
if (type < 0 || type >= PI_max)
|
|
return;
|
|
switch (type) {
|
|
case PI_slow:
|
|
case PI_fast:
|
|
p->speed = p->ill[type].dataf;
|
|
break;
|
|
case PI_range:
|
|
p->range = p->ill[type].datai;
|
|
break;
|
|
case PI_nobomb:
|
|
p->bombs_n = p->ill[type].datai;
|
|
break;
|
|
}
|
|
p->ill[type].to = 0;
|
|
if (GT_MP)
|
|
net_game_send_ill (bman.p_nr);
|
|
bman.updatestatusbar = 1;
|
|
};
|
|
|
|
|
|
void
|
|
player_set_gfx (_player * p, signed char gfx_nr)
|
|
{
|
|
p->gfx_nr = gfx_nr;
|
|
if (p->gfx_nr < 0 || p->gfx_nr >= MAX_PLAYERS)
|
|
p->gfx_nr = -1;
|
|
if (p->gfx_nr == -1) {
|
|
p->gfx = NULL;
|
|
p->state &= (0xFF - (PSF_alife + PSF_playing));
|
|
}
|
|
else {
|
|
p->gfx = &gfx.players[gfx_nr];
|
|
p->state |= PSF_playing;
|
|
}
|
|
};
|
|
|
|
|
|
/* find a free bomb */
|
|
int
|
|
player_findfreebomb (_player * player)
|
|
{
|
|
int i,
|
|
bombused = 0,
|
|
res = -1,
|
|
nr;
|
|
|
|
/* check every free bomb from next entry of the last
|
|
exploded bomb to the last exploded bomb */
|
|
if (player->bomb_lastex < 0 || player->bomb_lastex >= MAX_BOMBS)
|
|
player->bomb_lastex = 0;
|
|
|
|
for (i = 0; i < MAX_BOMBS; i++) {
|
|
nr = player->bomb_lastex + 1 + i;
|
|
if (nr < 0 || nr >= MAX_BOMBS) // i out of range .. restart at bomb 0
|
|
nr -= MAX_BOMBS;
|
|
|
|
if (player->bombs[i].state == BS_off) { /* check if this bomb is free */
|
|
if (res == -1)
|
|
res = i;
|
|
}
|
|
else
|
|
bombused++; // count number of used bombs
|
|
}
|
|
|
|
if (res == -1 && i == player->bomb_lastex && player->bombs[i].state == BS_off)
|
|
res = i;
|
|
|
|
if (bombused >= player->bombs_n)
|
|
res = -1; /* all max number of bombs lay */
|
|
|
|
return res;
|
|
};
|