starfighter/src/bullet.cpp

205 lines
4.8 KiB
C++
Raw Normal View History

/*
Copyright (C) 2003 Parallel Realities
Copyright (C) 2011, 2012 Guus Sliepen
2016-11-17 01:43:03 +01:00
Copyright (C) 2015, 2016 Julie Marchant <onpon4@riseup.net>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
2015-02-26 17:20:36 +01:00
as published by the Free Software Foundation; either version 3
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
2015-02-26 17:20:36 +01:00
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
2015-02-26 17:20:36 +01:00
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Starfighter.h"
2015-03-11 20:36:42 +01:00
void bullet_add(object *theWeapon, object *attacker, int y, int dy)
{
object *bullet;
int imageIndex;
int tempX, tempY, steps;
bullet = new object;
if (attacker == &player)
game.shots++;
bullet->next = NULL;
bullet->active = 1;
bullet->x = attacker->x + (attacker->image[0]->w / 2) -
(theWeapon->image[0]->w * attacker->face);
bullet->y = attacker->y + y;
bullet->flags = theWeapon->flags;
bullet->shield = 300; // bullets live for (approximately) 5 seconds
// Timed explosions live between 1 and 3 seconds
if (bullet->flags & WF_TIMEDEXPLOSION)
bullet->shield = 60 + ((rand() % 3) * 60);
if (attacker->face == 0)
{
bullet->dx = theWeapon->speed;
if ((game.area == MISN_ELLESH) ||
(game.area == MISN_MARS))
bullet->dx += fabsf(engine.ssx + engine.smx);
}
else
{
bullet->dx = -theWeapon->speed;
}
if (bullet->flags & WF_VARIABLE_SPEED)
{
bullet->dx = RANDRANGE(100, 200) / 10;
if (attacker->face == 1)
bullet->dx = -bullet->dx;
}
bullet->dy = dy;
if (bullet->flags & WF_SCATTER)
{
bullet->dy = RANDRANGE(-200, 200) / 200;
}
if (attacker->flags & FL_WEAPCO)
2011-09-04 14:23:31 +02:00
bullet->flags |= WF_WEAPCO;
else
2011-09-04 14:23:31 +02:00
bullet->flags |= WF_FRIEND;
bullet->owner = attacker->owner;
bullet->id = theWeapon->id;
bullet->damage = theWeapon->damage;
if (bullet->id == WT_CHARGER)
{
if (game.difficulty == DIFFICULTY_ORIGINAL)
bullet->damage = attacker->ammo[1];
else
bullet->damage = attacker->ammo[1] / 2;
if (bullet->damage < 15)
{
bullet->damage = 1;
bullet->id = WT_PLASMA;
}
}
bullet->target = NULL;
if (attacker->flags & FL_FRIEND)
imageIndex = 0;
else
imageIndex = 1;
// Use the enemy's images if applicable
if (bullet->id != WT_ROCKET)
bullet->image[0] = theWeapon->image[imageIndex];
else
bullet->image[0] = theWeapon->image[attacker->face];
if (bullet->flags & WF_AIMED)
{
tempX = (int)fabsf(attacker->target->x - attacker->x);
tempY = (int)fabsf(attacker->target->y - attacker->y);
2015-03-17 21:54:00 +01:00
steps = MAX(tempX, tempY);
if (steps < 12)
steps = 12;
if (!(bullet->flags & WF_TIMEDEXPLOSION))
steps /= 8;
else
steps /= 6 + (rand() % 6);
tempX = (int)(attacker->target->x - attacker->x);
tempY = (int)(attacker->target->y - attacker->y);
bullet->dx = tempX / steps;
bullet->dy = tempY / steps;
}
if (attacker->classDef == CD_ASTEROID)
{
bullet->dx = RANDRANGE(-20, 20);
bullet->dy = RANDRANGE(-20, 20);
bullet->image[0] = gfx_sprites[SP_SMALL_EXPLOSION];
}
engine.bulletTail->next = bullet;
engine.bulletTail = bullet;
}
/*
Used for homing missiles. When a missile is active and it is told to home in
on an enemy, it will attempt to randomly grab one every frame if it does not
already have a target. If the target it is currently chasing is killed, it will
begin to look for a new one (done in doBullets()). The homing missile will make
one attempt per call (one call per frame) to find a suitable target. If the target
it picks is dead or outside the screen range, then it returns NULL. A suitable
target will be returned as the object address.
*/
2015-04-07 22:09:17 +02:00
object *bullet_getTarget(object *bullet)
{
int i;
if (bullet->owner->flags & FL_WEAPCO)
{
i = (rand() % 10);
if (i < 1)
return &player;
}
i = rand() % ALIEN_MAX;
if ((aliens[i].shield < 1) || (!aliens[i].active))
return NULL;
if (aliens[i].flags & FL_IMMORTAL)
return NULL;
if ((bullet->owner->flags & FL_WEAPCO) && (aliens[i].flags & FL_WEAPCO))
return NULL;
if ((bullet->owner->flags & FL_FRIEND) && (aliens[i].flags & FL_FRIEND))
return NULL;
if (abs((int)bullet->x - (int)aliens[i].target->x) > 800)
return NULL;
if (abs((int)bullet->y - (int)aliens[i].target->y) > 200)
return NULL;
return &aliens[i];
}
int bullet_collision(object *bullet, object *ship)
{
float x0 = bullet->x;
float y0 = bullet->y;
float w0 = bullet->image[0]->w;
float h0 = bullet->image[0]->h;
float x2 = ship->x;
float y2 = ship->y;
float w1 = ship->image[0]->w;
float h1 = ship->image[0]->h;
float x1 = x0 + w0;
float y1 = y0 + h0;
float x3 = x2 + w1;
float y3 = y2 + h1;
return !(x1<x2 || x3<x0 || y1<y2 || y3<y0);
}