Skip to content
Permalink
master
Switch branches/tags
Go to file
 
 
Cannot retrieve contributors at this time
#include <genesis.h>
#include "collision.h"
#include "map.h"
#include "gamelogic.h"
#include "resmap.h"
#include "defs.h"
#include "resources.h"
s16 tileAfterHit(u16 tile_idx, u16 bullet_rotate, u16 dip);
void tileReaction(_bullet *bull, s16 *after_hit, u8 *kill_bull, s16 *x0, s16 *y0, u8 xShift, u8 yShift);
u8 moveAvailableInUnits(_tank *tank) {
u16 i = config.units_on_map;
_tank *buff;
s16 x = tank->posx;
s16 y = tank->posy;
s16 delta_x;
s16 delta_y;
while (i--) {
buff = &game_player[i];
if (tank == buff || !buff->hitpoint)
continue;
delta_x = x - buff->posx;
delta_y = y - buff->posy;
if (delta_x < 0) delta_x = -delta_x;
if (delta_y < 0) delta_y = -delta_y;
if (delta_x < 16 && delta_y < 16) {
x += speed_x[tank->rotate];
y += speed_y[tank->rotate];
s16 d = delta_x + delta_y;
delta_x = x - buff->posx;
delta_y = y - buff->posy;
if (delta_x < 0) delta_x = -delta_x;
if (delta_y < 0) delta_y = -delta_y;
return d < delta_x + delta_y;
}
}
return TRUE;
}
void detectBulletToWallCollision(_bullet *bull) {
u16 tile_idx = 0;
s16 x = bull->posx;
s16 y = bull->posy;
s16 x0 = x >> 3;
s16 y0 = y >> 3;
s16 after_hit1, after_hit2;
s16 mod = ((x | y) & 7) >> 2;
u8 kill_bull = 0;
u16 rotate = bull->rotate;
if (bull->speed == 0)
return;
if (x0 < 0 || x0 >= MAP_W || y0 < 0 || y0 >= MAP_H) {
if (mods.bul_ricochet && !bull->ricocheted) {
bull->ricocheted = TRUE;
bull->rotate += 2;
bull->rotate &= 3;
// u8 rot = (random() % 3);
// rot %= 3;
// if (rot == bull->rotate) GLog_killBullet(bull, 1);
}
else {
GLog_killBullet(bull, TRUE);
if (bull->maker == &game_player[0] || bull->maker == &game_player[1])
soundPlay(snd_bull_stop, sizeof(snd_bull_stop), SOUND_PCM_CH3, FALSE);
}
return;
}
tile_idx = mapGetTile(x0, y0);
after_hit1 = tileAfterHit(tile_idx, rotate, mod);
if (after_hit1 >= 0) {
tileReaction(bull, &after_hit1, &kill_bull, &x0, &y0, 0, 0);
}
if (rotate & 1) {
tile_idx = mapGetTile(x0, y0 + 1);
after_hit2 = tileAfterHit(tile_idx, rotate, mod);
if (after_hit2 >= 0) {
tileReaction(bull, &after_hit2, &kill_bull, &x0, &y0, 0, 1);
}
}
else {
tile_idx = mapGetTile(x0 + 1, y0);
after_hit2 = tileAfterHit(tile_idx, rotate, mod);
if (after_hit2 >= 0) {
tileReaction(bull, &after_hit2, &kill_bull, &x0, &y0, 1, 0);
}
}
if (kill_bull) {
GLog_killBullet(bull, TRUE);
if (bull->maker == &game_player[0] || bull->maker == &game_player[1]) {
if (after_hit1 == RES_TILE_STEEL || after_hit2 == RES_TILE_STEEL) {
// startPlaySample(snd_bull_stop, sizeof(snd_bull_stop), 11000, AUDIO_PAN_CENTER, 6);
soundPlay(snd_bull_stop, sizeof(snd_bull_stop), SOUND_PCM_CH3, FALSE);
}
if ((after_hit1 >= 0 && after_hit1 < 16) || (after_hit2 >= 0 && after_hit2 < 16)) {
// startPlaySample(snd_bull_stop_briks, sizeof(snd_bull_stop_briks), 11000, AUDIO_PAN_CENTER, 3);
soundPlay(snd_brick_hit, sizeof(snd_brick_hit), SOUND_PCM_CH4, FALSE);
}
}
}
}
s16 tileAfterHit(u16 tile_idx, u16 bullet_rotate, u16 dip) {
u16 mask;
if (tile_idx == RES_TILE_STEEL)
return RES_TILE_STEEL;
if (tile_idx == (RES_TILE_WOODS | TILE_ATTR(PAL0, 1, 0, 0))) {
return RES_TILE_WOODS;
}
else if (tile_idx > 16 || tile_idx == 0) {
return -1;
}
if (bullet_rotate & 1) {
mask = 10 >> dip;
} else {
mask = 12 >> (dip << 1);
}
if ((tile_idx & mask) == tile_idx)
return -1;
return tile_idx & mask;
}
void tileReaction(_bullet *bull, s16 *after_hit, u8 *kill_bull, s16 *x0, s16 *y0, u8 xShift, u8 yShift) {
switch (*after_hit) {
case RES_TILE_WOODS:
if (bull->maker->uranium_bullets && bull->maker->woods_trim) {
*after_hit = 0;
mapSetTile(0, *x0 + xShift, *y0 + yShift);
soundPlay(snd_brick_hit, sizeof(snd_brick_hit), SOUND_PCM_CH4, FALSE);
}
break;
case RES_TILE_STEEL:
if (mods.bul_ricochet) {
if (!bull->ricocheted) {
bull->ricocheted = TRUE;
bull->rotate += 2;
bull->rotate &= 3;
}
else if (!xShift && !yShift) {
*kill_bull = 1;
}
}
else {
if (bull->maker->uranium_bullets) {
*after_hit = 0;
}
*kill_bull = 1;
}
mapSetTile(*after_hit, *x0 + xShift, *y0 + yShift);
break;
// Brick
default:
if (bull->maker->uranium_bullets) {
*after_hit = 0;
}
mapSetTile(*after_hit, *x0 + xShift, *y0 + yShift);
*kill_bull = 1;
break;
}
}
u8 moveAvailableInWalls(_tank *tank) {
u16 r = tank->rotate;
s16 x1 = tank->posx + speed_x[r];
s16 y1 = tank->posy + speed_y[r];
s16 x2 = (x1 + 15) >> 3;
s16 y2 = (y1 + 15) >> 3;
x1 >>= 3;
y1 >>= 3;
if (x1 < 0 || x2 >= MAP_W || y1 < 0 || y2 >= MAP_H)
return FALSE;
u16 i1 = FALSE;
u16 i2 = FALSE;
u16 i3 = FALSE;
u16 i4 = FALSE;
u16 tile_idx = 0;
tile_idx = mapGetTile(x1, y1);
tile_idx &= 0x1FF;
if (tile_idx == 0
|| tile_idx == RES_TILE_WOODS
|| tile_idx == RES_TILE_ICE
|| (tank->ship == 1 && tile_idx == RES_TILE_RIVER)) i1 = TRUE;
tile_idx = mapGetTile(x2, y1);
tile_idx &= 0x1FF;
if (tile_idx == 0
|| tile_idx == RES_TILE_WOODS
|| tile_idx == RES_TILE_ICE
|| (tank->ship == 1 && tile_idx == RES_TILE_RIVER)) i2 = TRUE;
tile_idx = mapGetTile(x1, y2);
tile_idx &= 0x1FF;
if (tile_idx == 0
|| tile_idx == RES_TILE_WOODS
|| tile_idx == RES_TILE_ICE
|| (tank->ship == 1 && tile_idx == RES_TILE_RIVER)) i3 = TRUE;
tile_idx = mapGetTile(x2, y2);
tile_idx &= 0x1FF;
if (tile_idx == 0
|| tile_idx == RES_TILE_WOODS
|| tile_idx == RES_TILE_ICE
|| (tank->ship == 1 && tile_idx == RES_TILE_RIVER)) i4 = TRUE;
if (tank == &game_player[0] || tank == &game_player[1]) {
u16 ice = FALSE;
if (
(r == 0 && (mapGetTile(x1, y1+1) == RES_TILE_ICE || mapGetTile(x2, y1+1) == RES_TILE_ICE))
|| (r == 1 && (mapGetTile(x1+1, y2) == RES_TILE_ICE || mapGetTile(x1+1, y1) == RES_TILE_ICE))
|| (r == 2 && (mapGetTile(x2, y2-1) == RES_TILE_ICE || mapGetTile(x1, y2-1) == RES_TILE_ICE))
|| (r == 3 && (mapGetTile(x2-1, y2) == RES_TILE_ICE || mapGetTile(x2-1, y1) == RES_TILE_ICE))
) {
ice = TRUE;
}
tank->on_ice = FALSE;
if (ice && tank->speed == 0) {
tank->on_ice = TRUE;
}
if (ice && tank->speed) {
tank->ice = 32; // 28 ?
}
else if (!ice) {
tank->ice = 0;
}
}
if (i1 && i2 && i3 && i4)
return TRUE;
// i1 = 0; i2 = 0; i3 = 0; i4 = 0;
// tile_idx = mapGetTile(x1, y1);
// tile_idx &= 0x1FF;
// if ((tile_idx >= 1) && (tile_idx <= 15)) i1 = 1;
// tile_idx = mapGetTile(x2, y1);
// tile_idx &= 0x1FF;
// if ((tile_idx >= 1) && (tile_idx <= 15)) i2 = 1;
// tile_idx = mapGetTile(x1, y2);
// tile_idx &= 0x1FF;
// if ((tile_idx >= 1) && (tile_idx <= 15)) i3 = 1;
// tile_idx = mapGetTile(x2, y2);
// tile_idx &= 0x1FF;
// if ((tile_idx >= 1) && (tile_idx <= 15)) i4 = 1;
// if (i1 == 1 && i2 == 1 && i3 == 1 && i4 == 1) return 1;
if (mods.en_no_walls && tank->player == 0) {
return TRUE;
}
return FALSE;
}
void detectBulletToUnitsCollision(_bullet *bull) {
u16 i = 0;
u16 end = 2;
s16 delta_x;
s16 delta_y;
_tank *player1 = &game_player[0];
_tank *player2 = &game_player[1];
if (bull->maker == player1
|| bull->maker == player2
|| config.en_friend_fire == KILL
|| config.en_friend_fire == BULLETS_STOP)
{
i = 0;
end = config.units_on_map;
}
for (; i < end; i++) {
if (!game_player[i].hitpoint || game_player[i].birth)
continue;
if (bull->maker == &game_player[i] && (!mods.bul_ricochet || !bull->ricocheted))
continue;
s16 bx = bull->posx;
s16 by = bull->posy;
s16 margin_x = 0;
s16 margin_y = 0;
if ((game_player[i].rotate & 1) && !(bull->rotate & 1)) {
margin_x += 7;
} else if (!(game_player[i].rotate & 1) && (bull->rotate & 1)) {
margin_y += 7;
}
if (bull->rotate == 3) {
bx -= 15;
} else if (bull->rotate == 2) {
by -= 15;
}
delta_x = bx - game_player[i].posx;
delta_y = by - game_player[i].posy;
// Don't kill with ass
if ((delta_x < 0 && bull->rotate == 1)
|| (delta_x > 0 && bull->rotate == 3)
|| (delta_y < 0 && bull->rotate == 0)
|| (delta_y > 0 && bull->rotate == 2))
continue;
if (delta_x < 0) delta_x = -delta_x;
if (delta_y < 0) delta_y = -delta_y;
if (delta_x < 16 - margin_x && delta_y < 16 - margin_y) {
// Detect player to player friendly fire
if ((bull->maker == player1 || bull->maker == player2)
&& (&game_player[i] == player1 || &game_player[i] == player2)
&& (config.pl_friend_fire == OFF)) {
continue;
}
GLog_killBullet(bull, TRUE);
GLog_killPlayer(&game_player[i], bull->maker);
return;
}
}
}
void detectBulletToStaffCollision(_bullet *bull) {
u16 tile_idx = 0;
s16 x = bull->posx >> 3;
s16 y = bull->posy >> 3;
tile_idx = mapGetTile(x, y);
if (tile_idx >= RES_TILE_STAFF && tile_idx <= RES_TILE_STAFF + 4) {
GLog_killStaff();
GLog_killBullet(bull, TRUE);
}
if (bull->rotate & 1) {
tile_idx = mapGetTile(x, y + 1);
}
else {
tile_idx = mapGetTile(x + 1, y);
}
if (tile_idx >= RES_TILE_STAFF && tile_idx <= RES_TILE_STAFF + 4) {
GLog_killStaff();
GLog_killBullet(bull, TRUE);
}
}
void detectBulletToBulletCollision(_bullet *bull) {
u16 i = config.max_bullets;
_bullet *buff;
s16 delta_x;
s16 delta_y;
if (bull->maker != &game_player[0] && bull->maker != &game_player[1]) {
return;
}
while (i--) {
buff = &bullets[i];
if (!buff->speed || bull->maker == buff->maker) // (bull == buff) is included
continue;
delta_x = bull->posx - buff->posx;
delta_y = bull->posy - buff->posy;
if (bull->rotate & 1) {
delta_y += 7;
} else {
delta_x += 7;
}
if (buff->rotate & 1) {
delta_y -= 7;
} else {
delta_x -= 7;
}
if (delta_x < 0) delta_x = -delta_x;
if (delta_y < 0) delta_y = -delta_y;
if (delta_x < 6 && delta_y < 6) {
GLog_killBullet(bull, FALSE);
GLog_killBullet(buff, FALSE);
}
}
}
u8 detectBonusCollision(u8 player) {
s16 delta_x = game_player[player].posx - bonus.posx;
s16 delta_y = game_player[player].posy - bonus.posy;
if (delta_x < 0) delta_x = -delta_x;
if (delta_y < 0) delta_y = -delta_y;
if (delta_x < 16 && delta_y < 16)
return TRUE;
return FALSE;
}