📄 bullets.cpp
字号:
return 1;
}
return 0;
}
/*
Fill in later...
*/
void fireRay(object *attacker)
{
SDL_Rect ray;
if (attacker->face == 0)
{
ray.x = (int)(attacker->x + attacker->image[0]->w);
}
else
{
ray.x = (int)(attacker->x - 800);
}
ray.y = (int)(attacker->y + attacker->engineY - 1);
ray.h = 3;
ray.w = 800;
int red = SDL_MapRGB(graphics.screen->format, rand() % 256, 0x00, 0x00);
SDL_FillRect(graphics.screen, &ray, red);
graphics.addBuffer(ray.x, ray.y, ray.w, ray.h);
if (attacker != &player)
{
if (player.shield > 0)
{
if (Collision::collision(player.x, player.y, player.image[0]->w, player.image[0]->h, ray.x, ray.y, ray.w, ray.h) && (!engine.cheatShield))
{
if (player.shield > engine.lowShield)
{
if (player.shield - 1 <= engine.lowShield)
{
setInfoLine("!!! WARNING: SHIELD LOW !!!", FONT_RED);
}
}
player.shield--;
addExplosion(player.x, player.y, E_SMALL_EXPLOSION);
playSound(SFX_HIT);
if (player.shield < 1)
{
playSound(SFX_DEATH);
playSound(SFX_EXPLOSION);
}
}
}
}
object *anEnemy = enemy;
for (int i = 0 ; i < MAX_ALIENS ; i++)
{
if (anEnemy->flags & FL_IMMORTAL)
continue;
if ((anEnemy->shield > 0) && (attacker != anEnemy) && (attacker->classDef != anEnemy->classDef))
{
if (Collision::collision(anEnemy->x, anEnemy->y, anEnemy->image[0]->w, anEnemy->image[0]->h, ray.x, ray.y, ray.w, ray.h))
{
anEnemy->shield--;
addExplosion(anEnemy->x, anEnemy->y, E_SMALL_EXPLOSION);
playSound(SFX_HIT);
if (anEnemy->shield < 1)
{
destroyAlien(attacker, anEnemy);
}
}
}
*anEnemy++;
}
attacker->ammo[0]--;
if (attacker->ammo[0] < 1)
attacker->flags -= FL_FIRERAY;
}
/*
This handles active bullets in a linked list. The current bullet and
previous bullet pointers are first assigned to the main header bullet
and each successive bullet is pulled out. Bullets are moved in their
delta coordinates, with rockets having fire trails added to them. Seperate
collision checks are done for a bullet that belongs to the enemy and one
that belongs to a player. However rockets can hit anyone. Upon an enemy
being killed, mission requirements are checked and collectables are randomly
spawned.
*/
void doBullets()
{
object *bullet = engine.bulletHead;
object *prevBullet = engine.bulletHead;
engine.bulletTail = engine.bulletHead;
object *theEnemy, *theCargo;
signed char okayToHit = 0;
float homingMissileSpeed = 0;
while (bullet->next != NULL)
{
bullet = bullet->next;
if (bullet->active == 1)
{
if (bullet->flags & WF_HOMING)
{
if (bullet->target == NULL)
bullet->target = getRandomEnemy(bullet);
if (bullet->owner->flags & FL_FRIEND)
homingMissileSpeed = 0.25;
else
homingMissileSpeed = 0.05;
}
if (bullet->id == WT_ROCKET)
{
addExplosion(bullet->x, bullet->y, E_SMALL_EXPLOSION);
}
else if (bullet->id == WT_MICROROCKET)
{
addExplosion(bullet->x, bullet->y, E_TINY_EXPLOSION);
}
if ((bullet->flags & WF_AIMED) || (bullet->flags & WF_THIN_SPREAD))
{
graphics.blit(bullet->image[0], (int)(bullet->x - bullet->dx), (int)(bullet->y - bullet->dy));
}
if (bullet->id == WT_CHARGER)
{
for (int i = 0 ; i < bullet->damage ; i++)
graphics.blit(bullet->image[0], (int)(bullet->x - Math::rrand(-(bullet->damage / 3), 0)), (int)(bullet->y + Math::rrand(-3, 3)));
}
graphics.blit(bullet->image[0], (int)bullet->x, (int)bullet->y);
bullet->x += bullet->dx;
bullet->y += bullet->dy;
if (bullet->target != NULL)
{
if (bullet->x < bullet->target->x)
Math::limitFloat(&(bullet->dx += homingMissileSpeed), -15, 15);
if (bullet->x > bullet->target->x)
Math::limitFloat(&(bullet->dx -= homingMissileSpeed), -15, 15);
//Rocket is (more or less) inline with target. Fly straight
if ((bullet->x > bullet->target->x - 1) && (bullet->x < bullet->target->x + 5))
bullet->dx = 0;
if (bullet->y < bullet->target->y)
Math::limitFloat(&(bullet->dy += homingMissileSpeed), -15, 15);
if (bullet->y > bullet->target->y)
Math::limitFloat(&(bullet->dy -= homingMissileSpeed), -15, 15);
//Rocket is (more or less) inline with target. Fly straight
if ((bullet->y > bullet->target->y - 1) && (bullet->y < bullet->target->y + 5))
bullet->dy = 0;
if ((bullet->target->shield < 1) || (bullet->target->flags & FL_ISCLOAKED))
bullet->target = NULL;
}
bullet->x += engine.ssx;
bullet->y += engine.ssy;
for (int i = 0 ; i < MAX_ALIENS ; i++)
{
theEnemy = &enemy[i];
if ((theEnemy->shield < 1) || (!theEnemy->active))
continue;
okayToHit = 0;
if ((bullet->flags & WF_FRIEND) && (theEnemy->flags & FL_WEAPCO))
okayToHit = 1;
if ((bullet->flags & WF_WEAPCO) && (theEnemy->flags & FL_FRIEND))
okayToHit = 1;
if ((bullet->id == WT_ROCKET) || (bullet->id == WT_LASER) || (bullet->id == WT_CHARGER))
okayToHit = 1;
if (bullet->owner == theEnemy->owner)
okayToHit = 0;
if (okayToHit)
{
if ((bullet->active == 1) && (Collision::collision(bullet, theEnemy)))
{
if (bullet->owner == &player)
{
currentGame.hits++;
if ((theEnemy->classDef == CD_PHOEBE) || (theEnemy->classDef == CD_URSULA))
getMissFireMessage(theEnemy);
}
if (!(theEnemy->flags & FL_IMMORTAL))
{
if (!(bullet->flags & WF_DISABLE))
theEnemy->shield -= bullet->damage;
else
theEnemy->systemPower -= bullet->damage;
theEnemy->hit = 5;
}
if (theEnemy->flags & FL_CANNOTDIE)
{
Math::limitInt(&theEnemy->shield, 1, theEnemy->maxShield);
if (theEnemy->shield == 1)
{
if (currentGame.area != 26)
{
if (!(theEnemy->flags & FL_LEAVESECTOR))
{
theEnemy->flags += FL_LEAVESECTOR;
if (theEnemy->flags & FL_CIRCLES)
theEnemy->flags -= FL_CIRCLES;
if (currentGame.area == 11)
setRadioMessage(FACE_KLINE, "Seems I underestimated you, Bainfield! We'll meet again!", 1);
else if (currentGame.area == 25)
setRadioMessage(FACE_SID, "Chris, Kethlan is getting away!", 1);
}
}
else
{
setKlineAttackMethod(theEnemy);
}
}
}
if ((theEnemy->flags & FL_RUNSAWAY) && ((rand() % 50) == 0))
{
if (!(theEnemy->flags & FL_LEAVESECTOR))
theEnemy->flags += FL_LEAVESECTOR;
}
if (bullet->id != WT_CHARGER)
{
bullet->active = 0;
bullet->shield = 0;
}
else if (bullet->id == WT_CHARGER)
{
bullet->shield -= theEnemy->shield;
if (bullet->shield < 0)
bullet->active = 0;
}
playSound(SFX_HIT);
if (theEnemy->AIType == AI_EVASIVE)
theEnemy->thinktime = 0;
if (theEnemy->shield < 1)
destroyAlien(bullet, theEnemy);
if (theEnemy->systemPower < 1)
{
if (!(theEnemy->flags & FL_DISABLED))
{
theEnemy->flags += FL_DISABLED;
updateMissionRequirements(M_DISABLE_TARGET, theEnemy->classDef, 1);
}
theEnemy->systemPower = 0;
if (theEnemy->classDef == CD_KLINE)
theEnemy->systemPower = theEnemy->maxShield;
}
if (bullet->id == WT_ROCKET)
addExplosion(bullet->x, bullet->y, E_BIG_EXPLOSION);
else
addExplosion(bullet->x, bullet->y, E_SMALL_EXPLOSION);
}
}
}
// Check for bullets hitting player
if ((bullet->flags & WF_WEAPCO) || (bullet->id == WT_ROCKET) || (bullet->id == WT_LASER) || (bullet->id == WT_CHARGER))
{
if ((bullet->active == 1) && (player.shield > 0) && (Collision::collision(bullet, &player)) && (bullet->owner != &player))
{
if ((!engine.cheatShield) || (engine.missionCompleteTimer != 0))
{
if (player.shield > engine.lowShield)
{
if (player.shield - bullet->damage <= engine.lowShield)
{
setInfoLine("!!! WARNING: SHIELD LOW !!!", FONT_RED);
}
}
player.shield -= bullet->damage;
Math::limitInt(&player.shield, 0, player.maxShield);
player.hit = 5;
}
if ((bullet->owner->classDef == CD_PHOEBE) || (bullet->owner->classDef == CD_URSULA))
getPlayerHitMessage(bullet->owner);
if (bullet->id != WT_CHARGER)
{
bullet->active = 0;
bullet->shield = 0;
}
else if (bullet->id == WT_CHARGER)
{
bullet->shield -= theEnemy->shield;
if (bullet->shield < 0)
bullet->active = 0;
}
playSound(SFX_HIT);
if (bullet->id == WT_ROCKET)
addExplosion(bullet->x, bullet->y, E_BIG_EXPLOSION);
else
addExplosion(bullet->x, bullet->y, E_SMALL_EXPLOSION);
}
}
}
if (((bullet->owner == &player)) || (bullet->id == WT_ROCKET))
{
for (int j = 0 ; j < 20 ; j++)
{
theCargo = &cargo[j];
if (theCargo->active)
{
if (Collision::collision(bullet, theCargo))
{
bullet->active = 0;
addExplosion(bullet->x, bullet->y, E_SMALL_EXPLOSION);
playSound(SFX_HIT);
if (theCargo->collectType != P_PHOEBE)
{
theCargo->active = 0;
playSound(SFX_EXPLOSION);
for (int i = 0 ; i < 10 ; i++)
addExplosion(theCargo->x + Math::rrand(-15, 15), theCargo->y + Math::rrand(-15, 15), E_BIG_EXPLOSION);
updateMissionRequirements(M_PROTECT_PICKUP, P_CARGO, 1);
}
}
}
}
}
// check to see if a bullet (on any side) hits a mine
checkMineBulletCollisions(bullet);
bullet->shield--;
if (bullet->shield < 1)
{
if ((bullet->flags & WF_TIMEDEXPLOSION) || (bullet->id == WT_CHARGER))
{
playSound(SFX_EXPLOSION);
for (int i = 0 ; i < 10 ; i++)
addExplosion(bullet->x + Math::rrand(-35, 35), bullet->y + Math::rrand(-35, 35), E_BIG_EXPLOSION);
if (bullet->flags & WF_TIMEDEXPLOSION)
if (checkPlayerShockDamage(bullet->x, bullet->y, 75))
setInfoLine("Warning: Missile Shockwave Damage!!", FONT_RED);
}
bullet->active = 0;
}
if (bullet->active == 1)
{
prevBullet = bullet;
engine.bulletTail = bullet;
}
else
{
prevBullet->next = bullet->next;
delete bullet;
bullet = prevBullet;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -