2011-08-24 14:14:44 +02:00
|
|
|
/*
|
|
|
|
Copyright (C) 2003 Parallel Realities
|
2015-03-01 21:37:32 +01:00
|
|
|
Copyright (C) 2011, 2012, 2013 Guus Sliepen
|
2016-01-02 22:59:48 +01:00
|
|
|
Copyright (C) 2012, 2014, 2015, 2016 onpon4 <onpon4@riseup.net>
|
2011-08-24 14:14:44 +02:00
|
|
|
|
|
|
|
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
|
2011-08-24 14:14:44 +02:00
|
|
|
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.
|
2011-08-24 14:14:44 +02:00
|
|
|
|
|
|
|
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/>.
|
2011-08-24 14:14:44 +02:00
|
|
|
*/
|
|
|
|
|
2011-08-26 21:29:04 +02:00
|
|
|
#include "Starfighter.h"
|
|
|
|
|
2015-05-21 01:41:43 +02:00
|
|
|
Game game;
|
2011-08-24 14:14:44 +02:00
|
|
|
|
2015-06-20 17:58:37 +02:00
|
|
|
static Star stars[STARS_NUM];
|
2015-11-07 03:35:07 +01:00
|
|
|
static Uint32 frameLimit = 0;
|
|
|
|
static int thirds = 0;
|
2015-06-20 17:58:37 +02:00
|
|
|
|
2015-05-21 01:41:43 +02:00
|
|
|
void game_init()
|
2011-08-24 14:14:44 +02:00
|
|
|
{
|
2015-05-21 01:41:43 +02:00
|
|
|
game.system = 0;
|
|
|
|
game.area = MISN_START;
|
|
|
|
game.sfxVolume = 0;
|
|
|
|
game.musicVolume = 0;
|
2011-08-24 14:14:44 +02:00
|
|
|
|
|
|
|
if (!engine.useAudio)
|
|
|
|
{
|
2011-08-26 22:48:52 +02:00
|
|
|
engine.useSound = false;
|
|
|
|
engine.useMusic = false;
|
2011-08-24 14:14:44 +02:00
|
|
|
}
|
|
|
|
|
2015-05-21 01:41:43 +02:00
|
|
|
game.cash = 0;
|
|
|
|
game.cashEarned = 0;
|
|
|
|
game.shots = 0;
|
|
|
|
game.hits = 0;
|
|
|
|
game.accuracy = 0;
|
|
|
|
game.totalKills = game.wingMate1Kills = game.wingMate2Kills = 0;
|
|
|
|
game.totalOtherKills = 0;
|
|
|
|
game.hasWingMate1 = game.hasWingMate2 = 0;
|
|
|
|
game.wingMate1Ejects = game.wingMate2Ejects = 0;
|
|
|
|
game.secondaryMissions = game.secondaryMissionsCompleted = 0;
|
|
|
|
game.shieldPickups = game.rocketPickups = game.cellPickups = 0;
|
|
|
|
game.powerups = game.minesKilled = game.cargoPickups = 0;
|
|
|
|
|
|
|
|
game.slavesRescued = 0;
|
|
|
|
game.experimentalShield = 1000;
|
|
|
|
|
|
|
|
game.timeTaken = 0;
|
|
|
|
|
|
|
|
game.stationedPlanet = -1;
|
|
|
|
game.destinationPlanet = -1;
|
2011-08-24 14:14:44 +02:00
|
|
|
for (int i = 0 ; i < 10 ; i++)
|
2015-05-21 01:41:43 +02:00
|
|
|
game.missionCompleted[i] = 0;
|
|
|
|
game.distanceCovered = 0;
|
|
|
|
|
|
|
|
game.minPlasmaRate = 1;
|
|
|
|
game.minPlasmaOutput = 1;
|
|
|
|
game.minPlasmaDamage = 1;
|
|
|
|
game.maxPlasmaRate = 2;
|
|
|
|
game.maxPlasmaOutput = 2;
|
|
|
|
game.maxPlasmaDamage = 2;
|
|
|
|
game.maxPlasmaAmmo = 100;
|
|
|
|
game.maxRocketAmmo = 10;
|
|
|
|
|
|
|
|
game.minPlasmaRateLimit = 2;
|
|
|
|
game.minPlasmaDamageLimit = 2;
|
|
|
|
game.minPlasmaOutputLimit = 2;
|
|
|
|
game.maxPlasmaRateLimit = 3;
|
|
|
|
game.maxPlasmaDamageLimit = 3;
|
|
|
|
game.maxPlasmaOutputLimit = 3;
|
|
|
|
game.maxPlasmaAmmoLimit = 250;
|
|
|
|
game.maxRocketAmmoLimit = 50;
|
2015-03-06 18:36:02 +01:00
|
|
|
|
2015-03-20 18:05:14 +01:00
|
|
|
player.maxShield = 50;
|
|
|
|
|
2015-05-21 01:41:43 +02:00
|
|
|
switch (game.difficulty)
|
2014-03-12 20:18:41 +01:00
|
|
|
{
|
2015-02-27 02:51:30 +01:00
|
|
|
case DIFFICULTY_EASY:
|
|
|
|
player.maxShield = 100;
|
2015-03-06 18:36:02 +01:00
|
|
|
|
2015-05-21 01:41:43 +02:00
|
|
|
game.minPlasmaRate = 2;
|
|
|
|
game.minPlasmaOutput = 2;
|
|
|
|
game.minPlasmaDamage = 2;
|
|
|
|
game.maxPlasmaRate = 3;
|
|
|
|
game.maxPlasmaOutput = 3;
|
|
|
|
game.maxPlasmaDamage = 3;
|
|
|
|
game.maxPlasmaAmmo = 150;
|
|
|
|
game.maxRocketAmmo = 20;
|
|
|
|
|
|
|
|
game.minPlasmaRateLimit = 3;
|
|
|
|
game.minPlasmaDamageLimit = 3;
|
|
|
|
game.minPlasmaOutputLimit = 3;
|
|
|
|
game.maxPlasmaRateLimit = 5;
|
|
|
|
game.maxPlasmaDamageLimit = 5;
|
|
|
|
game.maxPlasmaOutputLimit = 5;
|
2015-02-27 02:51:30 +01:00
|
|
|
break;
|
|
|
|
case DIFFICULTY_HARD:
|
|
|
|
player.maxShield = 25;
|
|
|
|
break;
|
|
|
|
case DIFFICULTY_NIGHTMARE:
|
|
|
|
player.maxShield = 1;
|
2015-05-21 01:41:43 +02:00
|
|
|
game.maxRocketAmmo = 5;
|
2015-02-27 02:51:30 +01:00
|
|
|
break;
|
2015-03-28 14:51:49 +01:00
|
|
|
case DIFFICULTY_ORIGINAL:
|
|
|
|
player.maxShield = 25;
|
|
|
|
|
2015-05-21 01:41:43 +02:00
|
|
|
game.minPlasmaRateLimit = 3;
|
|
|
|
game.minPlasmaDamageLimit = 3;
|
|
|
|
game.minPlasmaOutputLimit = 3;
|
|
|
|
game.maxPlasmaRateLimit = 5;
|
|
|
|
game.maxPlasmaDamageLimit = 5;
|
|
|
|
game.maxPlasmaOutputLimit = 5;
|
2015-03-28 14:51:49 +01:00
|
|
|
break;
|
2014-03-12 19:35:24 +01:00
|
|
|
}
|
2011-08-24 14:14:44 +02:00
|
|
|
|
2015-02-27 02:51:30 +01:00
|
|
|
player.shield = player.maxShield;
|
2011-08-24 14:14:44 +02:00
|
|
|
player.ammo[0] = 0;
|
2015-05-21 01:41:43 +02:00
|
|
|
player.ammo[1] = game.maxRocketAmmo / 2;
|
2011-08-24 14:14:44 +02:00
|
|
|
player.weaponType[0] = W_PLAYER_WEAPON;
|
|
|
|
player.weaponType[1] = W_ROCKETS;
|
|
|
|
|
2015-06-20 17:58:37 +02:00
|
|
|
for (int i = 0 ; i < STARS_NUM ; i++)
|
|
|
|
{
|
|
|
|
stars[i].x = rand() % screen->w;
|
|
|
|
stars[i].y = rand() % screen->h;
|
|
|
|
stars[i].speed = 1 + (rand() % 3);
|
|
|
|
}
|
|
|
|
|
2011-08-24 14:14:44 +02:00
|
|
|
initWeapons();
|
|
|
|
initMissions();
|
2015-05-21 01:41:43 +02:00
|
|
|
initPlanetMissions(game.system);
|
2011-08-24 14:14:44 +02:00
|
|
|
}
|
|
|
|
|
2015-04-08 01:16:46 +02:00
|
|
|
static void game_addDebris(int x, int y, int amount)
|
|
|
|
{
|
|
|
|
if ((rand() % 2) == 0)
|
|
|
|
audio_playSound(SFX_DEBRIS, x);
|
|
|
|
else
|
|
|
|
audio_playSound(SFX_DEBRIS2, x);
|
|
|
|
|
|
|
|
object *debris;
|
|
|
|
|
2015-04-14 23:15:06 +02:00
|
|
|
amount = RANDRANGE(3, amount);
|
2015-04-08 01:16:46 +02:00
|
|
|
LIMIT(amount, 3, 8);
|
|
|
|
|
|
|
|
for (int i = 0 ; i < amount ; i++)
|
|
|
|
{
|
|
|
|
debris = new object;
|
|
|
|
|
|
|
|
debris->next = NULL;
|
|
|
|
debris->x = x;
|
|
|
|
debris->y = y;
|
|
|
|
|
|
|
|
debris->thinktime = RANDRANGE(60, 180);
|
|
|
|
|
|
|
|
debris->dx = RANDRANGE(-500, 500);
|
|
|
|
debris->dy = RANDRANGE(-500, 500);
|
|
|
|
|
|
|
|
if (debris->dx != 0)
|
|
|
|
debris->dx /= 100;
|
|
|
|
|
|
|
|
if (debris->dy != 0)
|
|
|
|
debris->dy /= 100;
|
|
|
|
|
|
|
|
engine.debrisTail->next = debris;
|
|
|
|
engine.debrisTail = debris;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-20 17:58:37 +02:00
|
|
|
/*
|
|
|
|
Simply draws the stars in their positions on screen and moves
|
|
|
|
them around.
|
|
|
|
*/
|
|
|
|
void game_doStars()
|
|
|
|
{
|
|
|
|
/* Lock the screen for direct access to the pixels */
|
|
|
|
if (SDL_MUSTLOCK(screen))
|
|
|
|
{
|
2016-01-02 22:59:48 +01:00
|
|
|
if (SDL_LockSurface(screen) < 0)
|
|
|
|
engine_showError(2, "");
|
2015-06-20 17:58:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
int color = 0;
|
|
|
|
|
|
|
|
SDL_Rect r;
|
|
|
|
|
|
|
|
for (int i = 0 ; i < STARS_NUM ; i++)
|
|
|
|
{
|
|
|
|
if (stars[i].speed == 3)
|
|
|
|
color = white;
|
|
|
|
else if (stars[i].speed == 2)
|
|
|
|
color = lightGrey;
|
|
|
|
else if (stars[i].speed == 1)
|
|
|
|
color = darkGrey;
|
|
|
|
|
|
|
|
WRAP_ADD(stars[i].x, (engine.ssx + engine.smx) * stars[i].speed, 0,
|
|
|
|
screen->w - 1);
|
|
|
|
WRAP_ADD(stars[i].y, (engine.ssy + engine.smy) * stars[i].speed, 0,
|
|
|
|
screen->h - 1);
|
|
|
|
|
2015-11-07 03:35:07 +01:00
|
|
|
gfx_putPixel(screen, (int)stars[i].x, (int)stars[i].y, color);
|
2015-06-20 17:58:37 +02:00
|
|
|
r.x = (int)stars[i].x;
|
|
|
|
r.y = (int)stars[i].y;
|
|
|
|
r.w = 1;
|
|
|
|
r.h = 1;
|
|
|
|
|
2015-11-02 23:53:05 +01:00
|
|
|
screen_addBuffer(r.x, r.y, r.w, r.h);
|
2015-06-20 17:58:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (SDL_MUSTLOCK(screen))
|
|
|
|
{
|
|
|
|
SDL_UnlockSurface(screen);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-08 01:16:46 +02:00
|
|
|
/*
|
|
|
|
Loops through the currently active collectables (in a linked list). The collectable
|
|
|
|
will travel in the direction that was defined when it was made. Its life will decreased
|
|
|
|
whilst it remains active. It will be removed if the player touches it or if its life
|
|
|
|
reaches 0. When it is picked up, depending on the type of collectable it is, mission requirements
|
|
|
|
will be updated. Information will be displayed and appropriate player variables altered.
|
|
|
|
*/
|
|
|
|
static void game_doCollectables()
|
|
|
|
{
|
|
|
|
collectables *collectable = engine.collectableHead;
|
|
|
|
collectables *prevCollectable = engine.collectableHead;
|
|
|
|
engine.collectableTail = engine.collectableHead;
|
|
|
|
char temp[40];
|
|
|
|
|
|
|
|
while (collectable->next != NULL)
|
|
|
|
{
|
|
|
|
collectable = collectable->next;
|
|
|
|
|
|
|
|
if (collectable->active)
|
|
|
|
{
|
|
|
|
if ((collectable->x + collectable->image->w > 0) &&
|
|
|
|
(collectable->x < screen->w) &&
|
|
|
|
(collectable->y + collectable->image->h > 0) &&
|
|
|
|
(collectable->y < screen->h))
|
2015-09-26 14:49:21 +02:00
|
|
|
screen_blit(collectable->image, (int)collectable->x, (int)collectable->y);
|
2015-04-08 01:16:46 +02:00
|
|
|
|
|
|
|
collectable->x += engine.ssx + engine.smx;
|
|
|
|
collectable->y += engine.ssy + engine.smy;
|
|
|
|
collectable->x += collectable->dx;
|
|
|
|
collectable->y += collectable->dy;
|
|
|
|
|
|
|
|
collectable->life--;
|
|
|
|
|
2015-09-25 22:28:09 +02:00
|
|
|
if ((player.shield > 0) && (collectable_collision(collectable, &player)))
|
2015-04-08 01:16:46 +02:00
|
|
|
{
|
|
|
|
switch(collectable->type)
|
|
|
|
{
|
|
|
|
case P_CASH:
|
2015-05-21 01:41:43 +02:00
|
|
|
if (game.difficulty == DIFFICULTY_ORIGINAL)
|
2015-05-02 02:04:51 +02:00
|
|
|
collectable->value *= 2;
|
|
|
|
|
2015-05-21 01:41:43 +02:00
|
|
|
game.cash += collectable->value;
|
|
|
|
game.cashEarned += collectable->value;
|
2015-04-08 01:16:46 +02:00
|
|
|
sprintf(temp, "Got $%d ", collectable->value);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case P_ROCKET:
|
|
|
|
LIMIT_ADD(player.ammo[1], collectable->value, 0,
|
2015-05-21 01:41:43 +02:00
|
|
|
game.maxRocketAmmo);
|
|
|
|
if (player.ammo[1] == game.maxRocketAmmo)
|
2015-04-08 01:16:46 +02:00
|
|
|
sprintf(temp, "Rocket Ammo at Maximum");
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (collectable->value > 1)
|
|
|
|
sprintf(temp, "Got %d rockets", collectable->value);
|
|
|
|
else
|
|
|
|
sprintf(temp, "Got a rocket");
|
|
|
|
}
|
2015-05-21 01:41:43 +02:00
|
|
|
game.rocketPickups += collectable->value;
|
2015-04-08 01:16:46 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case P_SHIELD:
|
|
|
|
LIMIT_ADD(player.shield, 10, 0, player.maxShield);
|
2015-05-21 01:41:43 +02:00
|
|
|
game.shieldPickups ++;
|
2015-04-08 01:16:46 +02:00
|
|
|
sprintf(temp, "Restored 10 shield points");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case P_PLASMA_RATE:
|
2015-05-21 01:41:43 +02:00
|
|
|
game.powerups++;
|
|
|
|
if ((game.area != MISN_INTERCEPTION) ||
|
|
|
|
(game.difficulty == DIFFICULTY_ORIGINAL) ||
|
2015-04-08 01:16:46 +02:00
|
|
|
(player.ammo[0] > 0))
|
|
|
|
{
|
2015-05-21 01:41:43 +02:00
|
|
|
if ((game.area != MISN_INTERCEPTION) ||
|
|
|
|
(game.difficulty == DIFFICULTY_ORIGINAL))
|
2015-04-08 01:16:46 +02:00
|
|
|
LIMIT_ADD(player.ammo[0], collectable->value,
|
2015-05-21 01:41:43 +02:00
|
|
|
0, game.maxPlasmaAmmo);
|
2015-04-08 01:16:46 +02:00
|
|
|
|
2015-05-21 01:41:43 +02:00
|
|
|
if (weapon[W_PLAYER_WEAPON].reload[0] <= rate2reload[game.maxPlasmaRate])
|
2015-04-08 01:16:46 +02:00
|
|
|
sprintf(temp, "Firing rate already at maximum");
|
|
|
|
else
|
|
|
|
{
|
|
|
|
weapon[W_PLAYER_WEAPON].reload[0] -= 2;
|
|
|
|
sprintf(temp, "Firing rate increased");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sprintf(temp, "Upgrade failed (no plasma ammo)");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case P_PLASMA_SHOT:
|
2015-05-21 01:41:43 +02:00
|
|
|
game.powerups++;
|
|
|
|
if ((game.area != MISN_INTERCEPTION) ||
|
|
|
|
(game.difficulty == DIFFICULTY_ORIGINAL) ||
|
2015-04-08 01:16:46 +02:00
|
|
|
(player.ammo[0] > 0))
|
|
|
|
{
|
2015-05-21 01:41:43 +02:00
|
|
|
if ((game.area != MISN_INTERCEPTION) ||
|
|
|
|
(game.difficulty == DIFFICULTY_ORIGINAL))
|
2015-04-08 01:16:46 +02:00
|
|
|
LIMIT_ADD(player.ammo[0], collectable->value,
|
2015-05-21 01:41:43 +02:00
|
|
|
0, game.maxPlasmaAmmo);
|
2015-04-08 01:16:46 +02:00
|
|
|
|
2015-05-21 01:41:43 +02:00
|
|
|
if (weapon[W_PLAYER_WEAPON].ammo[0] >= game.maxPlasmaOutput)
|
2015-04-08 01:16:46 +02:00
|
|
|
sprintf(temp, "Plasma output already at maximum");
|
|
|
|
else
|
|
|
|
{
|
|
|
|
weapon[W_PLAYER_WEAPON].ammo[0]++;
|
|
|
|
sprintf(temp, "Plasma output increased");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sprintf(temp, "Upgrade failed (no plasma ammo)");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case P_PLASMA_DAMAGE:
|
2015-05-21 01:41:43 +02:00
|
|
|
game.powerups++;
|
|
|
|
if ((game.area != MISN_INTERCEPTION) ||
|
|
|
|
(game.difficulty == DIFFICULTY_ORIGINAL) ||
|
2015-04-08 01:16:46 +02:00
|
|
|
(player.ammo[0] > 0))
|
|
|
|
{
|
2015-05-21 01:41:43 +02:00
|
|
|
if ((game.area != MISN_INTERCEPTION) ||
|
|
|
|
(game.difficulty == DIFFICULTY_ORIGINAL))
|
2015-04-08 01:16:46 +02:00
|
|
|
LIMIT_ADD(player.ammo[0], collectable->value,
|
2015-05-21 01:41:43 +02:00
|
|
|
0, game.maxPlasmaAmmo);
|
2015-04-08 01:16:46 +02:00
|
|
|
|
2015-05-21 01:41:43 +02:00
|
|
|
if (weapon[W_PLAYER_WEAPON].damage >= game.maxPlasmaDamage)
|
2015-04-08 01:16:46 +02:00
|
|
|
sprintf(temp, "Plasma damage already at maximum");
|
2015-04-09 02:26:59 +02:00
|
|
|
else {
|
2015-04-08 01:16:46 +02:00
|
|
|
weapon[W_PLAYER_WEAPON].damage++;
|
|
|
|
sprintf(temp, "Plasma damage increased");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sprintf(temp, "Upgrade failed (no plasma ammo)");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case P_SUPER:
|
2015-05-21 01:41:43 +02:00
|
|
|
game.powerups++;
|
|
|
|
if ((game.area != MISN_INTERCEPTION) ||
|
|
|
|
(game.difficulty == DIFFICULTY_ORIGINAL) ||
|
2015-04-08 01:16:46 +02:00
|
|
|
(player.ammo[0] > 0))
|
|
|
|
{
|
2015-05-21 01:41:43 +02:00
|
|
|
if ((game.area != MISN_INTERCEPTION) ||
|
|
|
|
(game.difficulty == DIFFICULTY_ORIGINAL))
|
2015-04-08 01:16:46 +02:00
|
|
|
LIMIT_ADD(player.ammo[0], collectable->value,
|
2015-05-21 01:41:43 +02:00
|
|
|
0, game.maxPlasmaAmmo);
|
2015-04-08 01:16:46 +02:00
|
|
|
|
|
|
|
weapon[W_PLAYER_WEAPON].ammo[0] = 5;
|
|
|
|
weapon[W_PLAYER_WEAPON].damage = 5;
|
|
|
|
weapon[W_PLAYER_WEAPON].reload[0] = rate2reload[5];
|
|
|
|
weapon[W_PLAYER_WEAPON].flags |= WF_SPREAD;
|
|
|
|
|
|
|
|
sprintf(temp, "Picked up a Super Charge!!");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sprintf(temp, "Damn! Upgrade failed (no plasma ammo)");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case P_PLASMA_AMMO:
|
2015-05-21 01:41:43 +02:00
|
|
|
if (player.ammo[0] >= game.maxPlasmaAmmo)
|
2015-04-08 01:16:46 +02:00
|
|
|
sprintf(temp, "Plasma cells already at Maximum");
|
|
|
|
else
|
|
|
|
{
|
|
|
|
LIMIT_ADD(player.ammo[0], collectable->value,
|
2015-05-21 01:41:43 +02:00
|
|
|
0, game.maxPlasmaAmmo);
|
2015-04-08 01:16:46 +02:00
|
|
|
if (collectable->value > 1)
|
|
|
|
{
|
|
|
|
sprintf(temp, "Got %d plasma cells", collectable->value);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sprintf(temp, "Got a plasma cell");
|
|
|
|
if ((rand() % 25) == 0)
|
|
|
|
sprintf(temp, "Got one whole plasma cell (wahoo!)");
|
|
|
|
}
|
|
|
|
}
|
2015-05-21 01:41:43 +02:00
|
|
|
game.cellPickups += collectable->value;
|
2015-04-08 01:16:46 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case P_CARGO:
|
|
|
|
strcpy(temp, "Picked up some Cargo");
|
2015-05-21 01:41:43 +02:00
|
|
|
game.cargoPickups++;
|
2015-04-08 01:16:46 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case P_SLAVES:
|
|
|
|
sprintf(temp, "Rescued %d slaves", collectable->value);
|
2015-05-21 01:41:43 +02:00
|
|
|
game.slavesRescued += collectable->value;
|
2015-04-08 01:16:46 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case P_ESCAPEPOD:
|
|
|
|
sprintf(temp, "Picked up an Escape Pod");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case P_ORE:
|
|
|
|
sprintf(temp, "Picked up some Ore");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
updateMissionRequirements(M_COLLECT, collectable->type,
|
|
|
|
collectable->value);
|
|
|
|
|
|
|
|
collectable->active = false;
|
|
|
|
if (collectable->type != P_MINE)
|
|
|
|
{
|
|
|
|
setInfoLine(temp, FONT_WHITE);
|
|
|
|
if (collectable->type == P_SHIELD)
|
|
|
|
audio_playSound(SFX_SHIELDUP, player.x);
|
|
|
|
else
|
|
|
|
audio_playSound(SFX_PICKUP, player.x);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// stop people from exploiting a weapon check condition
|
|
|
|
if (player.ammo[0] == 0)
|
|
|
|
{
|
2015-05-21 01:41:43 +02:00
|
|
|
weapon[W_PLAYER_WEAPON].ammo[0] = game.minPlasmaOutput;
|
|
|
|
weapon[W_PLAYER_WEAPON].damage = game.minPlasmaDamage;
|
|
|
|
weapon[W_PLAYER_WEAPON].reload[0] = rate2reload[game.minPlasmaRate];
|
2015-04-08 01:16:46 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (collectable->life < 1)
|
|
|
|
{
|
|
|
|
collectable->active = false;
|
|
|
|
if ((collectable->type == P_CARGO) ||
|
|
|
|
(collectable->type == P_ESCAPEPOD) ||
|
|
|
|
(collectable->type == P_SLAVES))
|
|
|
|
updateMissionRequirements(M_PROTECT_PICKUP, collectable->type, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (collectable->active)
|
|
|
|
{
|
|
|
|
prevCollectable = collectable;
|
|
|
|
engine.collectableTail = collectable;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (collectable->type == P_MINE)
|
2015-04-24 22:27:07 +02:00
|
|
|
collectable_explode(collectable);
|
2015-04-08 01:16:46 +02:00
|
|
|
prevCollectable->next = collectable->next;
|
|
|
|
delete collectable;
|
|
|
|
collectable = prevCollectable;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-07 22:09:17 +02:00
|
|
|
/*
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
static void game_doBullets()
|
|
|
|
{
|
|
|
|
object *bullet = engine.bulletHead;
|
|
|
|
object *prevBullet = engine.bulletHead;
|
|
|
|
|
2015-04-24 22:37:55 +02:00
|
|
|
collectables *collectable;
|
|
|
|
collectables *prevCollectable;
|
2015-04-07 22:09:17 +02:00
|
|
|
|
|
|
|
bool okayToHit = false;
|
|
|
|
int old_shield;
|
|
|
|
float homingMissileSpeed = 0;
|
2015-06-09 07:06:26 +02:00
|
|
|
int charger_num;
|
2015-04-07 22:09:17 +02:00
|
|
|
|
2015-04-24 22:37:55 +02:00
|
|
|
bullet = engine.bulletHead;
|
|
|
|
prevBullet = engine.bulletHead;
|
2015-04-24 22:27:07 +02:00
|
|
|
engine.bulletTail = engine.bulletHead;
|
|
|
|
|
2015-04-07 22:09:17 +02:00
|
|
|
while (bullet->next != NULL)
|
|
|
|
{
|
|
|
|
bullet = bullet->next;
|
|
|
|
|
|
|
|
if (bullet->active)
|
|
|
|
{
|
|
|
|
if (bullet->flags & WF_HOMING)
|
|
|
|
{
|
|
|
|
if (bullet->target == NULL)
|
|
|
|
bullet->target = bullet_getTarget(bullet);
|
|
|
|
|
|
|
|
if (bullet->owner->flags & FL_FRIEND)
|
|
|
|
homingMissileSpeed = 0.25;
|
|
|
|
else
|
|
|
|
homingMissileSpeed = 0.05;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bullet->id == WT_ROCKET)
|
|
|
|
{
|
2015-05-01 00:51:26 +02:00
|
|
|
explosion_add(bullet->x, bullet->y, E_SMALL_EXPLOSION);
|
2015-04-07 22:09:17 +02:00
|
|
|
}
|
|
|
|
else if (bullet->id == WT_MICROROCKET)
|
|
|
|
{
|
2015-05-01 00:51:26 +02:00
|
|
|
explosion_add(bullet->x, bullet->y, E_TINY_EXPLOSION);
|
2015-04-07 22:09:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if ((bullet->flags & WF_AIMED))
|
|
|
|
{
|
2015-09-26 14:49:21 +02:00
|
|
|
screen_blit(bullet->image[0], (int)(bullet->x - bullet->dx),
|
2015-04-07 22:09:17 +02:00
|
|
|
(int)(bullet->y - bullet->dy));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bullet->id == WT_CHARGER)
|
|
|
|
{
|
2015-06-09 07:06:26 +02:00
|
|
|
if (game.difficulty == DIFFICULTY_ORIGINAL)
|
|
|
|
charger_num = bullet->damage;
|
|
|
|
else
|
|
|
|
charger_num = bullet->damage * 2;
|
|
|
|
|
|
|
|
for (int i = 0 ; i < charger_num ; i++)
|
2015-09-26 14:49:21 +02:00
|
|
|
screen_blit(bullet->image[0],
|
2015-06-09 07:06:26 +02:00
|
|
|
(int)(bullet->x - RANDRANGE(
|
|
|
|
-(charger_num / 6), charger_num / 6)),
|
2015-04-07 22:09:17 +02:00
|
|
|
(int)(bullet->y + RANDRANGE(-3, 3)));
|
|
|
|
}
|
|
|
|
|
2015-09-26 14:49:21 +02:00
|
|
|
screen_blit(bullet->image[0], (int)bullet->x, (int)bullet->y);
|
2015-04-07 22:09:17 +02:00
|
|
|
bullet->x += bullet->dx;
|
|
|
|
bullet->y += bullet->dy;
|
|
|
|
|
|
|
|
if (bullet->target != NULL)
|
|
|
|
{
|
|
|
|
if (bullet->x < bullet->target->x)
|
|
|
|
LIMIT_ADD(bullet->dx, homingMissileSpeed, -15, 15);
|
|
|
|
else if (bullet->x > bullet->target->x)
|
|
|
|
LIMIT_ADD(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)
|
|
|
|
LIMIT_ADD(bullet->dy, homingMissileSpeed, -15, 15);
|
|
|
|
else if (bullet->y > bullet->target->y)
|
|
|
|
LIMIT_ADD(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 + engine.smx;
|
|
|
|
bullet->y += engine.ssy + engine.smy;
|
|
|
|
|
|
|
|
for (int i = 0 ; i < ALIEN_MAX ; i++)
|
|
|
|
{
|
2015-04-24 22:27:07 +02:00
|
|
|
if ((aliens[i].shield < 1) || (!aliens[i].active))
|
2015-04-07 22:09:17 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
okayToHit = false;
|
|
|
|
|
2015-04-24 22:27:07 +02:00
|
|
|
if ((bullet->flags & WF_FRIEND) && (aliens[i].flags & FL_WEAPCO))
|
2015-04-07 22:09:17 +02:00
|
|
|
okayToHit = true;
|
2015-04-24 22:27:07 +02:00
|
|
|
if ((bullet->flags & WF_WEAPCO) && (aliens[i].flags & FL_FRIEND))
|
2015-04-07 22:09:17 +02:00
|
|
|
okayToHit = true;
|
|
|
|
if ((bullet->id == WT_ROCKET) || (bullet->id == WT_LASER) ||
|
|
|
|
(bullet->id == WT_CHARGER))
|
|
|
|
okayToHit = true;
|
|
|
|
|
2015-04-24 22:27:07 +02:00
|
|
|
if (bullet->owner == aliens[i].owner)
|
2015-04-07 22:09:17 +02:00
|
|
|
okayToHit = false;
|
|
|
|
|
|
|
|
if (okayToHit)
|
|
|
|
{
|
2015-09-25 22:28:09 +02:00
|
|
|
if ((bullet->active) && (bullet_collision(bullet, &aliens[i])))
|
2015-04-07 22:09:17 +02:00
|
|
|
{
|
2015-04-24 22:27:07 +02:00
|
|
|
old_shield = aliens[i].shield;
|
2015-04-07 22:09:17 +02:00
|
|
|
|
|
|
|
if (bullet->owner == &player)
|
|
|
|
{
|
2015-05-21 01:41:43 +02:00
|
|
|
game.hits++;
|
2015-04-24 22:27:07 +02:00
|
|
|
if ((aliens[i].classDef == CD_PHOEBE) ||
|
|
|
|
(aliens[i].classDef == CD_URSULA))
|
|
|
|
getMissFireMessage(&aliens[i]);
|
2015-04-07 22:09:17 +02:00
|
|
|
}
|
|
|
|
|
2015-04-24 22:27:07 +02:00
|
|
|
if (!(aliens[i].flags & FL_IMMORTAL))
|
2015-04-07 22:09:17 +02:00
|
|
|
{
|
2015-04-24 22:27:07 +02:00
|
|
|
alien_hurt(&aliens[i], bullet->owner,
|
|
|
|
bullet->damage, (bullet->flags & WF_DISABLE));
|
2015-04-07 22:09:17 +02:00
|
|
|
|
2015-04-24 22:27:07 +02:00
|
|
|
aliens[i].hit = 5;
|
2015-04-07 22:09:17 +02:00
|
|
|
}
|
2015-06-02 18:43:06 +02:00
|
|
|
else if (aliens[i].flags & FL_DAMAGEOWNER)
|
|
|
|
{
|
|
|
|
alien_hurt(aliens[i].owner, bullet->owner,
|
|
|
|
bullet->damage, (bullet->flags & WF_DISABLE));
|
|
|
|
|
|
|
|
aliens[i].owner->hit = 5;
|
|
|
|
}
|
2015-04-07 22:09:17 +02:00
|
|
|
|
|
|
|
if (bullet->id == WT_CHARGER)
|
|
|
|
{
|
|
|
|
bullet->damage -= old_shield;
|
|
|
|
if (bullet->damage <= 0)
|
|
|
|
{
|
|
|
|
bullet->active = false;
|
|
|
|
bullet->shield = 0;
|
|
|
|
audio_playSound(SFX_EXPLOSION, bullet->x);
|
|
|
|
for (int i = 0 ; i < 10 ; i++)
|
2015-05-01 00:51:26 +02:00
|
|
|
explosion_add(bullet->x + RANDRANGE(-35, 35),
|
2015-04-07 22:09:17 +02:00
|
|
|
bullet->y + RANDRANGE(-35, 35),
|
|
|
|
E_BIG_EXPLOSION);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
bullet->active = false;
|
|
|
|
bullet->shield = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bullet->id == WT_ROCKET)
|
2015-05-01 00:51:26 +02:00
|
|
|
explosion_add(bullet->x, bullet->y, E_BIG_EXPLOSION);
|
2015-04-07 22:09:17 +02:00
|
|
|
else
|
2015-05-01 00:51:26 +02:00
|
|
|
explosion_add(bullet->x, bullet->y, E_SMALL_EXPLOSION);
|
2015-04-07 22:09:17 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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 && (player.shield > 0) &&
|
2015-09-25 22:28:09 +02:00
|
|
|
(bullet->owner != &player) && bullet_collision(bullet, &player))
|
2015-04-07 22:09:17 +02:00
|
|
|
{
|
|
|
|
old_shield = player.shield;
|
|
|
|
|
|
|
|
if ((!engine.cheatShield) || (engine.missionCompleteTimer != 0))
|
|
|
|
{
|
|
|
|
if ((player.shield > engine.lowShield) &&
|
|
|
|
(player.shield - bullet->damage <= engine.lowShield))
|
|
|
|
setInfoLine("!!! WARNING: SHIELD LOW !!!", FONT_RED);
|
|
|
|
|
|
|
|
player.shield -= bullet->damage;
|
|
|
|
LIMIT(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->damage -= old_shield;
|
|
|
|
if (bullet->damage <= 0)
|
|
|
|
{
|
|
|
|
bullet->active = false;
|
|
|
|
bullet->shield = 0;
|
|
|
|
audio_playSound(SFX_EXPLOSION, bullet->x);
|
|
|
|
for (int i = 0 ; i < 10 ; i++)
|
2015-05-01 00:51:26 +02:00
|
|
|
explosion_add(bullet->x + RANDRANGE(-35, 35),
|
2015-04-07 22:09:17 +02:00
|
|
|
bullet->y + RANDRANGE(-35, 35), E_BIG_EXPLOSION);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
bullet->active = false;
|
|
|
|
bullet->shield = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
audio_playSound(SFX_HIT, player.x);
|
|
|
|
|
|
|
|
if (bullet->id == WT_ROCKET)
|
2015-05-01 00:51:26 +02:00
|
|
|
explosion_add(bullet->x, bullet->y, E_BIG_EXPLOSION);
|
2015-04-07 22:09:17 +02:00
|
|
|
else
|
2015-05-01 00:51:26 +02:00
|
|
|
explosion_add(bullet->x, bullet->y, E_SMALL_EXPLOSION);
|
2015-04-07 22:09:17 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-21 01:41:43 +02:00
|
|
|
if ((game.difficulty != DIFFICULTY_EASY) &&
|
2015-04-07 22:09:17 +02:00
|
|
|
((bullet->owner == &player) || (bullet->id == WT_ROCKET)))
|
|
|
|
{
|
|
|
|
for (int j = 0 ; j < 20 ; j++)
|
|
|
|
{
|
2015-04-24 22:27:07 +02:00
|
|
|
if (cargo[j].active)
|
2015-04-07 22:09:17 +02:00
|
|
|
{
|
2015-09-25 22:28:09 +02:00
|
|
|
if (bullet_collision(bullet, &cargo[j]))
|
2015-04-07 22:09:17 +02:00
|
|
|
{
|
|
|
|
bullet->active = false;
|
2015-05-01 00:51:26 +02:00
|
|
|
explosion_add(bullet->x, bullet->y, E_SMALL_EXPLOSION);
|
2015-04-24 22:27:07 +02:00
|
|
|
audio_playSound(SFX_HIT, cargo[j].x);
|
|
|
|
if (cargo[j].collectType != P_PHOEBE)
|
2015-04-07 22:09:17 +02:00
|
|
|
{
|
2015-04-24 22:27:07 +02:00
|
|
|
cargo[j].active = false;
|
|
|
|
audio_playSound(SFX_EXPLOSION, cargo[j].x);
|
2015-04-07 22:09:17 +02:00
|
|
|
for (int i = 0 ; i < 10 ; i++)
|
2015-05-01 00:51:26 +02:00
|
|
|
explosion_add(cargo[j].x + RANDRANGE(-15, 15),
|
2015-04-24 22:27:07 +02:00
|
|
|
cargo[j].y + RANDRANGE(-15, 15),
|
2015-04-07 22:09:17 +02:00
|
|
|
E_BIG_EXPLOSION);
|
|
|
|
updateMissionRequirements(M_PROTECT_PICKUP,
|
|
|
|
P_CARGO, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// check to see if a bullet (on any side) hits a mine
|
2015-04-24 22:37:55 +02:00
|
|
|
collectable = engine.collectableHead;
|
|
|
|
prevCollectable = engine.collectableHead;
|
2015-04-24 22:27:07 +02:00
|
|
|
engine.collectableTail = engine.collectableHead;
|
|
|
|
while (collectable->next != NULL)
|
|
|
|
{
|
|
|
|
collectable = collectable->next;
|
|
|
|
|
|
|
|
if (collectable->type == P_MINE)
|
|
|
|
{
|
2015-09-25 22:28:09 +02:00
|
|
|
if (collectable_collision(collectable, bullet))
|
2015-04-24 22:27:07 +02:00
|
|
|
{
|
|
|
|
collectable->active = false;
|
|
|
|
|
|
|
|
if (bullet->id != WT_CHARGER)
|
|
|
|
{
|
|
|
|
bullet->active = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
bullet->shield--;
|
|
|
|
if (bullet->shield < 0)
|
|
|
|
bullet->active = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bullet->owner == &player)
|
|
|
|
{
|
2015-05-21 01:41:43 +02:00
|
|
|
game.minesKilled++;
|
|
|
|
game.hits++;
|
2015-04-24 22:27:07 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (collectable->active)
|
|
|
|
{
|
|
|
|
prevCollectable = collectable;
|
|
|
|
engine.collectableTail = collectable;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
collectable_explode(collectable);
|
|
|
|
prevCollectable->next = collectable->next;
|
|
|
|
delete collectable;
|
|
|
|
collectable = prevCollectable;
|
|
|
|
}
|
|
|
|
}
|
2015-04-07 22:09:17 +02:00
|
|
|
|
|
|
|
bullet->shield--;
|
|
|
|
|
|
|
|
if (bullet->shield < 1)
|
|
|
|
{
|
|
|
|
if (bullet->flags & WF_TIMEDEXPLOSION)
|
|
|
|
{
|
|
|
|
audio_playSound(SFX_EXPLOSION, bullet->x);
|
|
|
|
for (int i = 0 ; i < 10 ; i++)
|
2015-05-01 00:51:26 +02:00
|
|
|
explosion_add(bullet->x + RANDRANGE(-35, 35),
|
2015-04-07 22:09:17 +02:00
|
|
|
bullet->y + RANDRANGE(-35, 35), E_BIG_EXPLOSION);
|
|
|
|
|
2015-04-24 22:37:55 +02:00
|
|
|
player_checkShockDamage(bullet->x, bullet->y);
|
2015-04-07 22:09:17 +02:00
|
|
|
}
|
|
|
|
bullet->active = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bullet->active)
|
|
|
|
{
|
|
|
|
prevBullet = bullet;
|
|
|
|
engine.bulletTail = bullet;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
prevBullet->next = bullet->next;
|
|
|
|
delete bullet;
|
|
|
|
bullet = prevBullet;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void game_doAliens()
|
2011-08-24 14:14:44 +02:00
|
|
|
{
|
2015-03-07 05:18:31 +01:00
|
|
|
static float barrierLoop = 0;
|
|
|
|
|
|
|
|
int shapeToUse;
|
2015-04-07 22:09:17 +02:00
|
|
|
bool canFire;
|
|
|
|
int n;
|
|
|
|
|
|
|
|
barrierLoop += 0.2;
|
|
|
|
|
|
|
|
// A global variable for checking if all the aliens are dead
|
|
|
|
engine.allAliensDead = 1;
|
|
|
|
|
|
|
|
for (int i = 0 ; i < ALIEN_MAX ; i++)
|
|
|
|
{
|
|
|
|
if (aliens[i].active)
|
|
|
|
{
|
|
|
|
if (aliens[i].shield > 0)
|
|
|
|
{
|
|
|
|
if ((aliens[i].flags & FL_WEAPCO) && (!(aliens[i].flags & FL_DISABLED)))
|
|
|
|
engine.allAliensDead = 0;
|
|
|
|
|
|
|
|
// Set part attributes
|
|
|
|
if (aliens[i].owner != &aliens[i])
|
|
|
|
{
|
|
|
|
aliens[i].face = aliens[i].owner->face;
|
|
|
|
|
|
|
|
if (aliens[i].face == 0)
|
|
|
|
aliens[i].x = aliens[i].owner->x - aliens[i].dx;
|
|
|
|
else
|
|
|
|
aliens[i].x = aliens[i].owner->x + aliens[i].owner->image[0]->w + aliens[i].dx - aliens[i].image[0]->w;
|
|
|
|
|
|
|
|
aliens[i].y = (aliens[i].owner->y + aliens[i].dy);
|
|
|
|
|
|
|
|
if (aliens[i].owner->shield < 1)
|
|
|
|
{
|
|
|
|
if ((aliens[i].classDef != CD_URANUSBOSSWING1) &&
|
|
|
|
(aliens[i].classDef != CD_URANUSBOSSWING2))
|
|
|
|
{
|
|
|
|
aliens[i].shield = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
aliens[i].flags &= ~FL_IMMORTAL;
|
|
|
|
aliens[i].owner = &aliens[i];
|
|
|
|
aliens[i].chance[0] = 25;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
canFire = true; // The alien is allowed to fire
|
|
|
|
|
|
|
|
LIMIT_ADD(aliens[i].thinktime, -1, 0, 250);
|
|
|
|
|
|
|
|
if (aliens[i].target->shield < 1)
|
|
|
|
aliens[i].target = &aliens[i];
|
|
|
|
|
|
|
|
// Specific to Sid to stop him pissing about(!)
|
|
|
|
if ((aliens[i].classDef == CD_SID) &&
|
|
|
|
(aliens[i].target->flags & FL_DISABLED))
|
|
|
|
aliens[i].target = &aliens[i];
|
|
|
|
|
|
|
|
if (aliens[i].target == &aliens[i])
|
|
|
|
{
|
|
|
|
if (engine.missionCompleteTimer == 0)
|
|
|
|
{
|
|
|
|
alien_searchForTarget(&aliens[i]);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (aliens[i].flags & FL_FRIEND)
|
|
|
|
{
|
|
|
|
aliens[i].target = &player;
|
|
|
|
aliens[i].thinktime = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((!(aliens[i].flags & FL_DISABLED)) &&
|
|
|
|
(aliens[i].thinktime == 0) && (aliens[i].target != &aliens[i]) &&
|
|
|
|
(aliens[i].owner == &aliens[i]))
|
|
|
|
{
|
|
|
|
if (aliens[i].classDef == CD_KLINE)
|
|
|
|
alien_setKlineAI(&aliens[i]);
|
|
|
|
else
|
|
|
|
alien_setAI(&aliens[i]);
|
|
|
|
|
|
|
|
aliens[i].thinktime = (rand() % 25) * 10;
|
|
|
|
|
|
|
|
// Face direction of movement unless you always face
|
|
|
|
// your target(!)
|
|
|
|
if (!(aliens[i].flags & FL_ALWAYSFACE))
|
|
|
|
{
|
|
|
|
aliens[i].face = (aliens[i].dx > 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
LIMIT(aliens[i].dx, -aliens[i].speed, aliens[i].speed);
|
|
|
|
LIMIT(aliens[i].dy, -aliens[i].speed, aliens[i].speed);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aliens[i].flags & FL_ALWAYSFACE)
|
|
|
|
{
|
|
|
|
aliens[i].face = 0;
|
|
|
|
if (aliens[i].x > aliens[i].target->x) aliens[i].face = 1;
|
|
|
|
}
|
|
|
|
|
2015-05-21 01:41:43 +02:00
|
|
|
if ((game.area == MISN_ELLESH) &&
|
2015-06-02 02:09:33 +02:00
|
|
|
((aliens[i].classDef == CD_BOSS) ||
|
|
|
|
game.difficulty != DIFFICULTY_ORIGINAL))
|
2015-04-07 22:09:17 +02:00
|
|
|
aliens[i].face = 0;
|
|
|
|
|
|
|
|
if ((aliens[i].flags & FL_DEPLOYDRONES) && ((rand() % 300) == 0))
|
|
|
|
alien_addDrone(&aliens[i]);
|
|
|
|
|
|
|
|
if (aliens[i].flags & FL_LEAVESECTOR)
|
|
|
|
{
|
|
|
|
// Note: The original version of this line incorrectly
|
|
|
|
// specified -15 as the *maximum* instead of the
|
|
|
|
// *minimum*, which at the time was equivalent to
|
|
|
|
// ``aliens[i].dx = -15``.
|
|
|
|
LIMIT_ADD(aliens[i].dx, -0.5, -15, 0);
|
|
|
|
aliens[i].dy = 0;
|
|
|
|
aliens[i].thinktime = 999;
|
|
|
|
aliens[i].face = 0;
|
|
|
|
|
|
|
|
if (aliens[i].x >= 5000)
|
|
|
|
{
|
|
|
|
aliens[i].flags -= FL_LEAVESECTOR;
|
|
|
|
aliens[i].flags += FL_ESCAPED;
|
|
|
|
aliens[i].active = false;
|
|
|
|
|
|
|
|
if (aliens[i].classDef == CD_CLOAKFIGHTER)
|
|
|
|
{
|
2015-05-21 01:41:43 +02:00
|
|
|
game.experimentalShield = aliens[i].shield;
|
2015-04-07 22:09:17 +02:00
|
|
|
setInfoLine("Experimental Fighter has fled",
|
|
|
|
FONT_CYAN);
|
|
|
|
}
|
|
|
|
|
|
|
|
aliens[i].shield = 0;
|
|
|
|
updateMissionRequirements(M_ESCAPE_TARGET,
|
|
|
|
aliens[i].classDef, 1);
|
|
|
|
|
|
|
|
if (aliens[i].classDef != CD_CLOAKFIGHTER)
|
|
|
|
updateMissionRequirements(M_DESTROY_TARGET_TYPE,
|
|
|
|
aliens[i].classDef, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// This deals with the Experimental Fighter in Mordor
|
|
|
|
// (and Kline on the final mission)
|
|
|
|
// It can cloak and uncloak at random. When cloaked,
|
|
|
|
// its sprite is not displayed. However the engine
|
|
|
|
// trail is still visible!
|
|
|
|
if ((aliens[i].flags & FL_CANCLOAK) && ((rand() % 500) == 0))
|
|
|
|
{
|
|
|
|
if (aliens[i].flags & FL_ISCLOAKED)
|
|
|
|
aliens[i].flags -= FL_ISCLOAKED;
|
|
|
|
else
|
|
|
|
aliens[i].flags += FL_ISCLOAKED;
|
|
|
|
audio_playSound(SFX_CLOAK, aliens[i].x);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aliens[i].classDef == CD_BARRIER)
|
|
|
|
{
|
|
|
|
aliens[i].dx = -10 + (sinf(barrierLoop + aliens[i].speed) * 60);
|
|
|
|
aliens[i].dy = 20 + (cosf(barrierLoop + aliens[i].speed) * 40);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aliens[i].classDef == CD_MOBILESHIELD)
|
|
|
|
{
|
|
|
|
LIMIT_ADD(aliens[ALIEN_BOSS].shield, 1, 0,
|
|
|
|
aliens[ALIEN_BOSS].maxShield);
|
|
|
|
}
|
|
|
|
|
|
|
|
LIMIT_ADD(aliens[i].reload[0], -1, 0, 999);
|
|
|
|
LIMIT_ADD(aliens[i].reload[1], -1, 0, 999);
|
|
|
|
|
|
|
|
if ((!(aliens[i].flags & FL_DISABLED)) &&
|
|
|
|
(!(aliens[i].flags & FL_NOFIRE)))
|
|
|
|
{
|
|
|
|
if ((aliens[i].target->shield > 0))
|
|
|
|
canFire = alien_checkTarget(&aliens[i]);
|
|
|
|
|
|
|
|
if (((aliens[i].thinktime % 2) == 0) &&
|
|
|
|
(aliens[i].flags & FL_FRIEND))
|
|
|
|
canFire = alien_enemiesInFront(&aliens[i]);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
canFire = false;
|
|
|
|
}
|
|
|
|
|
2015-05-21 01:41:43 +02:00
|
|
|
if (canFire)
|
2015-04-07 22:09:17 +02:00
|
|
|
{
|
|
|
|
if ((aliens[i].reload[0] == 0) &&
|
|
|
|
((rand() % 1000 < aliens[i].chance[0]) ||
|
|
|
|
(aliens[i].flags & FL_CONTINUOUS_FIRE)))
|
|
|
|
{
|
|
|
|
ship_fireBullet(&aliens[i], 0);
|
|
|
|
}
|
|
|
|
if ((aliens[i].reload[1] == 0) &&
|
|
|
|
((rand() % 1000 < aliens[i].chance[1]) ||
|
|
|
|
(aliens[i].flags & FL_CONTINUOUS_FIRE)))
|
|
|
|
{
|
|
|
|
if ((aliens[i].weaponType[1] != W_ENERGYRAY) &&
|
|
|
|
(aliens[i].weaponType[1] != W_LASER))
|
|
|
|
{
|
|
|
|
if (aliens[i].weaponType[1] == W_CHARGER)
|
|
|
|
aliens[i].ammo[1] = 50 + rand() % 150;
|
|
|
|
ship_fireBullet(&aliens[i], 1);
|
|
|
|
}
|
|
|
|
else if (aliens[i].weaponType[1] == W_LASER)
|
|
|
|
{
|
|
|
|
aliens[i].flags += FL_FIRELASER;
|
|
|
|
}
|
|
|
|
else if ((aliens[i].weaponType[1] == W_ENERGYRAY) &&
|
|
|
|
(aliens[i].ammo[0] == 250))
|
|
|
|
{
|
|
|
|
aliens[i].flags += FL_FIRERAY;
|
|
|
|
audio_playSound(SFX_ENERGYRAY, aliens[i].x);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aliens[i].flags & FL_FIRERAY)
|
|
|
|
{
|
|
|
|
ship_fireRay(&aliens[i]);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
LIMIT_ADD(aliens[i].ammo[0], 1, 0, 250);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aliens[i].flags & FL_FIRELASER)
|
|
|
|
{
|
|
|
|
ship_fireBullet(&aliens[i], 1);
|
|
|
|
if ((rand() % 25) == 0)
|
|
|
|
aliens[i].flags -= FL_FIRELASER;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aliens[i].flags & FL_DROPMINES)
|
|
|
|
{
|
|
|
|
if ((rand() % 150) == 0)
|
2015-04-24 22:27:07 +02:00
|
|
|
collectable_add(aliens[i].x, aliens[i].y, P_MINE, 25,
|
2015-04-07 22:09:17 +02:00
|
|
|
600 + rand() % 2400);
|
|
|
|
|
|
|
|
// Kline drops mines a lot more often
|
|
|
|
if ((&aliens[i] == &aliens[ALIEN_KLINE]))
|
|
|
|
{
|
|
|
|
if ((rand() % 10) == 0)
|
2015-04-24 22:27:07 +02:00
|
|
|
collectable_add(aliens[i].x, aliens[i].y, P_MINE, 25,
|
2015-04-07 22:09:17 +02:00
|
|
|
600 + rand() % 2400);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
shapeToUse = aliens[i].imageIndex[aliens[i].face];
|
|
|
|
|
|
|
|
if (aliens[i].hit)
|
|
|
|
shapeToUse += SHIP_HIT_INDEX;
|
|
|
|
|
|
|
|
LIMIT_ADD(aliens[i].hit, -1, 0, 100);
|
|
|
|
|
|
|
|
if ((aliens[i].x + aliens[i].image[0]->w > 0) &&
|
|
|
|
(aliens[i].x < screen->w) &&
|
|
|
|
(aliens[i].y + aliens[i].image[0]->h > 0) &&
|
|
|
|
(aliens[i].y < screen->h))
|
|
|
|
{
|
|
|
|
if ((!(aliens[i].flags & FL_DISABLED)) &&
|
|
|
|
(aliens[i].classDef != CD_ASTEROID) &&
|
|
|
|
(aliens[i].classDef != CD_ASTEROID2))
|
2015-05-01 00:51:26 +02:00
|
|
|
explosion_addEngine(&aliens[i]);
|
2015-04-07 22:09:17 +02:00
|
|
|
if ((!(aliens[i].flags & FL_ISCLOAKED)) || (aliens[i].hit > 0))
|
2015-09-26 14:49:21 +02:00
|
|
|
screen_blit(shipShape[shapeToUse], (int)aliens[i].x,
|
2015-04-07 22:09:17 +02:00
|
|
|
(int)aliens[i].y);
|
|
|
|
if (aliens[i].flags & FL_DISABLED)
|
|
|
|
{
|
|
|
|
if ((rand() % 10) == 0)
|
2015-05-01 00:51:26 +02:00
|
|
|
explosion_add(aliens[i].x + (rand() % aliens[i].image[0]->w),
|
2015-04-07 22:09:17 +02:00
|
|
|
aliens[i].y + (rand() % aliens[i].image[0]->h),
|
|
|
|
E_ELECTRICAL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-21 01:41:43 +02:00
|
|
|
if ((game.area == MISN_MARS) && (aliens[i].x < -60))
|
2015-04-07 22:09:17 +02:00
|
|
|
aliens[i].active = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
aliens[i].shield--;
|
|
|
|
if ((aliens[i].x > 0) && (aliens[i].x < screen->w) &&
|
|
|
|
(aliens[i].y > 0) && (aliens[i].y < screen->h))
|
|
|
|
{
|
2015-09-26 14:49:21 +02:00
|
|
|
screen_blit(aliens[i].image[aliens[i].face], (int)aliens[i].x,
|
2015-04-07 22:09:17 +02:00
|
|
|
(int)aliens[i].y);
|
2015-05-01 00:51:26 +02:00
|
|
|
explosion_add(aliens[i].x + (rand() % aliens[i].image[0]->w),
|
2015-04-07 22:09:17 +02:00
|
|
|
aliens[i].y + (rand() % aliens[i].image[0]->h),
|
|
|
|
E_BIG_EXPLOSION);
|
|
|
|
}
|
|
|
|
if (aliens[i].shield < aliens[i].deathCounter)
|
|
|
|
{
|
|
|
|
aliens[i].active = false;
|
|
|
|
if ((aliens[i].classDef == CD_BOSS) ||
|
|
|
|
(aliens[i].owner == &aliens[ALIEN_BOSS]) ||
|
|
|
|
(aliens[i].flags & FL_FRIEND) ||
|
|
|
|
(aliens[i].classDef == CD_ASTEROID) ||
|
|
|
|
(aliens[i].classDef == CD_KLINE))
|
2015-04-08 01:16:46 +02:00
|
|
|
game_addDebris((int)aliens[i].x, (int)aliens[i].y,
|
2015-04-07 22:09:17 +02:00
|
|
|
aliens[i].maxShield);
|
|
|
|
|
|
|
|
if (aliens[i].classDef == CD_ASTEROID)
|
|
|
|
{
|
|
|
|
n = 1 + (rand() % 3);
|
2015-04-15 00:50:07 +02:00
|
|
|
for (int j = 0 ; j < n ; j++)
|
|
|
|
{
|
2015-04-07 22:09:17 +02:00
|
|
|
alien_addSmallAsteroid(&aliens[i]);
|
2015-04-15 00:50:07 +02:00
|
|
|
}
|
2015-04-07 22:09:17 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Adjust the movement even whilst exploding
|
2015-05-21 01:41:43 +02:00
|
|
|
if ((!(aliens[i].flags & FL_NOMOVE)) &&
|
2015-04-07 22:09:17 +02:00
|
|
|
(!(aliens[i].flags & FL_DISABLED)))
|
|
|
|
alien_move(&aliens[i]);
|
|
|
|
|
2015-05-21 01:41:43 +02:00
|
|
|
if ((game.area != MISN_ELLESH) || (aliens[i].shield < 0))
|
2015-04-07 22:09:17 +02:00
|
|
|
aliens[i].x += engine.ssx;
|
|
|
|
|
|
|
|
aliens[i].x += engine.smx;
|
|
|
|
aliens[i].y += engine.ssy + engine.smy;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-08 01:16:46 +02:00
|
|
|
static void game_doPlayer()
|
2015-04-07 22:09:17 +02:00
|
|
|
{
|
2015-04-08 01:16:46 +02:00
|
|
|
// This causes the motion to slow
|
|
|
|
engine.ssx *= 0.99;
|
|
|
|
engine.ssy *= 0.99;
|
2011-08-24 14:14:44 +02:00
|
|
|
|
2015-04-08 01:16:46 +02:00
|
|
|
engine.smx = 0;
|
|
|
|
engine.smy = 0;
|
2011-08-24 14:14:44 +02:00
|
|
|
|
2015-04-08 01:16:46 +02:00
|
|
|
int shapeToUse;
|
|
|
|
float cd;
|
|
|
|
float cc;
|
|
|
|
bool xmoved = false;
|
|
|
|
bool ymoved = false;
|
2015-03-07 05:18:31 +01:00
|
|
|
|
2015-04-08 01:16:46 +02:00
|
|
|
if (player.shield > -100)
|
2015-03-07 05:18:31 +01:00
|
|
|
{
|
2015-04-08 01:16:46 +02:00
|
|
|
if (player.shield > 0)
|
|
|
|
{
|
|
|
|
if ((engine.keyState[KEY_FIRE]))
|
|
|
|
ship_fireBullet(&player, 0);
|
2015-03-07 05:18:31 +01:00
|
|
|
|
2015-04-08 01:16:46 +02:00
|
|
|
if ((engine.keyState[KEY_ALTFIRE]) && (player.weaponType[1] != W_NONE))
|
|
|
|
{
|
|
|
|
if ((player.weaponType[1] != W_CHARGER) &&
|
|
|
|
(player.weaponType[1] != W_LASER) && (player.ammo[1] > 0))
|
|
|
|
{
|
|
|
|
ship_fireBullet(&player, 1);
|
|
|
|
}
|
2015-03-07 05:18:31 +01:00
|
|
|
|
2015-04-08 01:16:46 +02:00
|
|
|
if (player.weaponType[1] == W_LASER)
|
|
|
|
{
|
|
|
|
if (player.ammo[1] < 100)
|
|
|
|
{
|
|
|
|
ship_fireBullet(&player, 1);
|
2015-05-20 16:39:30 +02:00
|
|
|
|
|
|
|
if (!engine.cheatAmmo)
|
|
|
|
player.ammo[1] += 2;
|
|
|
|
|
2015-04-08 01:16:46 +02:00
|
|
|
if (player.ammo[1] >= 100)
|
|
|
|
{
|
|
|
|
player.ammo[1] = 200;
|
|
|
|
setInfoLine("Laser Overheat!!", FONT_WHITE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-03-07 05:18:31 +01:00
|
|
|
|
2015-04-08 01:16:46 +02:00
|
|
|
if (player.weaponType[1] == W_CHARGER)
|
|
|
|
{
|
|
|
|
if (engine.keyState[KEY_ALTFIRE] &&
|
2015-05-21 01:41:43 +02:00
|
|
|
((game.difficulty == DIFFICULTY_ORIGINAL) ||
|
2015-04-08 01:16:46 +02:00
|
|
|
!(engine.keyState[KEY_FIRE])))
|
|
|
|
{
|
|
|
|
if (!player_chargerFired)
|
|
|
|
{
|
2015-05-20 16:39:30 +02:00
|
|
|
// With ammo cheat, cause the charge cannon to
|
|
|
|
// fire at full blast immediately.
|
|
|
|
if (engine.cheatAmmo)
|
|
|
|
player.ammo[1] = 200;
|
|
|
|
|
2015-05-21 01:41:43 +02:00
|
|
|
if (game.difficulty == DIFFICULTY_ORIGINAL)
|
2015-04-08 01:16:46 +02:00
|
|
|
{
|
|
|
|
LIMIT_ADD(player.ammo[1], 1, 0, 200);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
LIMIT_ADD(player.ammo[1], 1, 0, 150);
|
|
|
|
if (player.ammo[1] >= 150)
|
|
|
|
{
|
|
|
|
ship_fireBullet(&player, 1);
|
|
|
|
player.ammo[1] = 0;
|
|
|
|
player_chargerFired = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (player.ammo[1] > 0)
|
|
|
|
ship_fireBullet(&player, 1);
|
|
|
|
player.ammo[1] = 0;
|
|
|
|
player_chargerFired = false;
|
|
|
|
}
|
|
|
|
}
|
2015-03-07 05:18:31 +01:00
|
|
|
|
2015-04-08 01:16:46 +02:00
|
|
|
if ((engine.keyState[KEY_SWITCH]))
|
2015-03-07 05:18:31 +01:00
|
|
|
{
|
2015-04-08 01:16:46 +02:00
|
|
|
if ((weapon[W_PLAYER_WEAPON].ammo[0] >= 3) &&
|
2015-05-21 01:41:43 +02:00
|
|
|
(weapon[W_PLAYER_WEAPON].ammo[0] <= game.maxPlasmaOutput))
|
2015-04-08 01:16:46 +02:00
|
|
|
{
|
|
|
|
weapon[W_PLAYER_WEAPON].flags ^= WF_SPREAD;
|
2015-03-07 05:18:31 +01:00
|
|
|
|
2015-04-08 01:16:46 +02:00
|
|
|
if (weapon[W_PLAYER_WEAPON].flags & WF_SPREAD)
|
|
|
|
{
|
|
|
|
setInfoLine("Weapon set to Spread", FONT_WHITE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
setInfoLine("Weapon set to Concentrate", FONT_WHITE);
|
|
|
|
}
|
|
|
|
}
|
2015-03-07 05:18:31 +01:00
|
|
|
|
2015-04-08 01:16:46 +02:00
|
|
|
engine.keyState[KEY_SWITCH] = 0;
|
2015-03-07 05:18:31 +01:00
|
|
|
}
|
|
|
|
|
2015-04-08 01:16:46 +02:00
|
|
|
LIMIT_ADD(player.reload[0], -1, 0, 999);
|
|
|
|
LIMIT_ADD(player.reload[1], -1, 0, 999);
|
2015-03-07 05:18:31 +01:00
|
|
|
|
2015-04-08 01:16:46 +02:00
|
|
|
if (engine.keyState[KEY_UP])
|
2015-03-07 05:18:31 +01:00
|
|
|
{
|
2015-04-08 01:16:46 +02:00
|
|
|
player.y -= player.speed;
|
|
|
|
engine.ssy += 0.1;
|
|
|
|
ymoved = true;
|
2015-03-07 05:18:31 +01:00
|
|
|
}
|
|
|
|
|
2015-04-08 01:16:46 +02:00
|
|
|
if (engine.keyState[KEY_DOWN])
|
2015-03-07 05:18:31 +01:00
|
|
|
{
|
2015-04-08 01:16:46 +02:00
|
|
|
player.y += player.speed;
|
|
|
|
engine.ssy -= 0.1;
|
|
|
|
ymoved = true;
|
2015-03-07 05:18:31 +01:00
|
|
|
}
|
|
|
|
|
2015-04-08 01:16:46 +02:00
|
|
|
if (engine.keyState[KEY_LEFT])
|
2015-03-07 05:18:31 +01:00
|
|
|
{
|
2015-04-08 01:16:46 +02:00
|
|
|
player.x -= player.speed;
|
|
|
|
engine.ssx += 0.1;
|
|
|
|
player.face = 1;
|
|
|
|
xmoved = true;
|
2015-03-07 05:18:31 +01:00
|
|
|
}
|
|
|
|
|
2015-04-08 01:16:46 +02:00
|
|
|
if (engine.keyState[KEY_RIGHT])
|
2015-03-07 05:18:31 +01:00
|
|
|
{
|
2015-04-08 01:16:46 +02:00
|
|
|
player.x += player.speed;
|
|
|
|
engine.ssx -= 0.1;
|
|
|
|
player.face = 0;
|
|
|
|
xmoved = true;
|
2015-03-07 05:18:31 +01:00
|
|
|
}
|
|
|
|
|
2015-04-08 01:16:46 +02:00
|
|
|
if (engine.keyState[KEY_ESCAPE])
|
2015-03-07 05:18:31 +01:00
|
|
|
{
|
2015-04-08 01:16:46 +02:00
|
|
|
if ((engine.done == 0) && (engine.gameSection == SECTION_GAME) &&
|
|
|
|
(currentMission.remainingObjectives1 == 0))
|
|
|
|
{
|
|
|
|
audio_playSound(SFX_FLY, screen->w / 2);
|
|
|
|
engine.done = 2;
|
|
|
|
engine.missionCompleteTimer = (SDL_GetTicks() - 1);
|
|
|
|
}
|
2015-03-07 05:18:31 +01:00
|
|
|
}
|
|
|
|
|
2015-04-08 01:16:46 +02:00
|
|
|
if (engine.keyState[KEY_PAUSE])
|
2015-03-07 05:18:31 +01:00
|
|
|
{
|
2015-04-08 01:16:46 +02:00
|
|
|
engine.paused = true;
|
|
|
|
engine.keyState[KEY_PAUSE] = 0;
|
2015-03-07 05:18:31 +01:00
|
|
|
}
|
|
|
|
|
2015-05-21 01:41:43 +02:00
|
|
|
if (((game.area == MISN_ELLESH) &&
|
2015-04-08 01:16:46 +02:00
|
|
|
(aliens[ALIEN_BOSS].shield > 0)) ||
|
2015-05-21 01:41:43 +02:00
|
|
|
(game.area == MISN_MARS))
|
2015-04-08 01:16:46 +02:00
|
|
|
{
|
|
|
|
player.face = 0;
|
|
|
|
xmoved = true;
|
|
|
|
ymoved = true;
|
|
|
|
}
|
2015-03-07 05:18:31 +01:00
|
|
|
|
2015-04-08 01:16:46 +02:00
|
|
|
if (engine.done == 0)
|
2015-03-07 05:18:31 +01:00
|
|
|
{
|
2015-05-21 01:41:43 +02:00
|
|
|
if ((game.difficulty != DIFFICULTY_ORIGINAL) ||
|
|
|
|
((game.area != MISN_ELLESH) &&
|
|
|
|
(game.area != MISN_MARS)))
|
2015-04-08 01:16:46 +02:00
|
|
|
{
|
2015-05-20 16:27:21 +02:00
|
|
|
if (xmoved)
|
2015-04-08 01:16:46 +02:00
|
|
|
{
|
2015-05-20 16:27:21 +02:00
|
|
|
if (player.x < xViewBorder)
|
|
|
|
{
|
|
|
|
engine.smx += xViewBorder - player.x;
|
|
|
|
player.x = xViewBorder;
|
|
|
|
}
|
|
|
|
else if (player.x > screen->w - xViewBorder)
|
|
|
|
{
|
|
|
|
engine.smx += (screen->w - xViewBorder) - player.x;
|
|
|
|
player.x = screen->w - xViewBorder;
|
|
|
|
}
|
2015-04-08 01:16:46 +02:00
|
|
|
}
|
2015-05-21 01:41:43 +02:00
|
|
|
else if (game.difficulty != DIFFICULTY_ORIGINAL)
|
2015-04-08 01:16:46 +02:00
|
|
|
{
|
2015-05-20 16:27:21 +02:00
|
|
|
cd = player.x - screen->w / 2;
|
|
|
|
if (cd < 0)
|
|
|
|
{
|
|
|
|
cc = MAX(cd / 10, MAX(0, engine.ssx) - cameraMaxSpeed);
|
|
|
|
player.x -= cc;
|
|
|
|
engine.smx -= cc;
|
|
|
|
}
|
|
|
|
else if (cd > 0)
|
|
|
|
{
|
|
|
|
cc = MIN(cd / 10, cameraMaxSpeed + MIN(0, engine.ssx));
|
|
|
|
player.x -= cc;
|
|
|
|
engine.smx -= cc;
|
|
|
|
}
|
2015-04-08 01:16:46 +02:00
|
|
|
}
|
|
|
|
|
2015-05-20 16:27:21 +02:00
|
|
|
if (ymoved)
|
2015-04-08 01:16:46 +02:00
|
|
|
{
|
2015-05-20 16:27:21 +02:00
|
|
|
if (player.y < yViewBorder)
|
|
|
|
{
|
|
|
|
engine.smy += yViewBorder - player.y;
|
|
|
|
player.y = yViewBorder;
|
|
|
|
}
|
|
|
|
else if (player.y > screen->h - yViewBorder)
|
|
|
|
{
|
|
|
|
engine.smy += (screen->h - yViewBorder) - player.y;
|
|
|
|
player.y = screen->h - yViewBorder;
|
|
|
|
}
|
2015-04-08 01:16:46 +02:00
|
|
|
}
|
2015-05-21 01:41:43 +02:00
|
|
|
else if (game.difficulty != DIFFICULTY_ORIGINAL)
|
2015-04-08 01:16:46 +02:00
|
|
|
{
|
2015-05-20 16:27:21 +02:00
|
|
|
cd = player.y - screen->h / 2;
|
|
|
|
if (cd < 0)
|
|
|
|
{
|
|
|
|
cc = MAX(cd / 10, MAX(0, engine.ssy) - cameraMaxSpeed);
|
|
|
|
player.y -= cc;
|
|
|
|
engine.smy -= cc;
|
|
|
|
}
|
|
|
|
else if (cd > 0)
|
|
|
|
{
|
|
|
|
cc = MIN(cd / 10, cameraMaxSpeed + MIN(0, engine.ssy));
|
|
|
|
player.y -= cc;
|
|
|
|
engine.smy -= cc;
|
|
|
|
}
|
2015-04-08 01:16:46 +02:00
|
|
|
}
|
|
|
|
}
|
2015-05-20 16:27:21 +02:00
|
|
|
else
|
2015-04-08 01:16:46 +02:00
|
|
|
{
|
2015-05-20 16:27:21 +02:00
|
|
|
LIMIT(player.x, xViewBorder, screen->w - xViewBorder);
|
|
|
|
LIMIT(player.y, yViewBorder, screen->h - yViewBorder);
|
2015-04-08 01:16:46 +02:00
|
|
|
}
|
2015-03-07 05:18:31 +01:00
|
|
|
}
|
|
|
|
|
2015-04-08 01:16:46 +02:00
|
|
|
if ((player.maxShield <= 1) || (player.shield > engine.lowShield))
|
2015-05-01 00:51:26 +02:00
|
|
|
explosion_addEngine(&player);
|
2015-03-07 05:18:31 +01:00
|
|
|
|
2015-04-08 01:16:46 +02:00
|
|
|
shapeToUse = player.face;
|
|
|
|
|
|
|
|
if (player.hit)
|
|
|
|
shapeToUse += SHIP_HIT_INDEX;
|
|
|
|
|
|
|
|
LIMIT_ADD(player.hit, -1, 0, 100);
|
|
|
|
|
2015-09-26 14:49:21 +02:00
|
|
|
screen_blit(shipShape[shapeToUse], (int)player.x, (int)player.y);
|
2015-04-08 01:16:46 +02:00
|
|
|
if ((player.maxShield > 1) && (player.shield <= engine.lowShield) &&
|
|
|
|
(rand() % 5 < 1))
|
2015-05-01 00:51:26 +02:00
|
|
|
explosion_add(player.x + RANDRANGE(-10, 10),
|
2015-04-08 01:16:46 +02:00
|
|
|
player.y + RANDRANGE(-10, 20), E_SMOKE);
|
2015-03-07 05:18:31 +01:00
|
|
|
}
|
2015-04-08 01:16:46 +02:00
|
|
|
else
|
2015-03-07 05:18:31 +01:00
|
|
|
{
|
2015-04-08 01:16:46 +02:00
|
|
|
player.active = false;
|
|
|
|
player.shield--;
|
|
|
|
if (player.shield == -1)
|
2015-03-07 05:18:31 +01:00
|
|
|
{
|
2015-05-21 01:41:43 +02:00
|
|
|
if ((game.hasWingMate1) || (aliens[ALIEN_KLINE].active))
|
2015-04-08 01:16:46 +02:00
|
|
|
getPlayerDeathMessage();
|
2015-03-07 05:18:31 +01:00
|
|
|
|
2015-04-08 01:16:46 +02:00
|
|
|
// Make it look like the ships are all still moving...
|
2015-05-21 01:41:43 +02:00
|
|
|
if (game.area == MISN_ELLESH)
|
2015-03-07 05:18:31 +01:00
|
|
|
{
|
2015-04-08 01:16:46 +02:00
|
|
|
for (int i = 0 ; i < ALIEN_MAX ; i++)
|
|
|
|
aliens[i].flags |= FL_LEAVESECTOR;
|
2015-03-07 05:18:31 +01:00
|
|
|
}
|
2015-04-08 01:16:46 +02:00
|
|
|
|
|
|
|
audio_playSound(SFX_DEATH, player.x);
|
|
|
|
audio_playSound(SFX_EXPLOSION, player.x);
|
|
|
|
}
|
|
|
|
|
|
|
|
engine.keyState[KEY_UP] = engine.keyState[KEY_DOWN] = engine.keyState[KEY_LEFT] = engine.keyState[KEY_RIGHT] = 0;
|
|
|
|
if ((rand() % 3) == 0)
|
2015-05-01 00:51:26 +02:00
|
|
|
explosion_add(player.x + RANDRANGE(-10, 10),
|
2015-04-08 01:16:46 +02:00
|
|
|
player.y + RANDRANGE(-10, 10), E_BIG_EXPLOSION);
|
|
|
|
if (player.shield == -99)
|
|
|
|
game_addDebris((int)player.x, (int)player.y, player.maxShield);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
LIMIT(engine.ssx, -cameraMaxSpeed, cameraMaxSpeed);
|
|
|
|
LIMIT(engine.ssy, -cameraMaxSpeed, cameraMaxSpeed);
|
|
|
|
|
|
|
|
// Specific for the mission were you have to chase the Executive Transport
|
2015-05-21 01:41:43 +02:00
|
|
|
if ((game.area == MISN_ELLESH) && (aliens[ALIEN_BOSS].shield > 0) &&
|
2015-04-08 01:16:46 +02:00
|
|
|
(player.shield > 0))
|
|
|
|
{
|
|
|
|
engine.ssx = -6;
|
|
|
|
engine.ssy = 0;
|
|
|
|
}
|
|
|
|
|
2015-05-21 01:41:43 +02:00
|
|
|
if (game.area == MISN_MARS)
|
2015-04-08 01:16:46 +02:00
|
|
|
{
|
|
|
|
engine.ssx = -6;
|
|
|
|
engine.ssy = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
player.dx = engine.ssx;
|
|
|
|
player.dy = engine.ssy;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void game_doCargo()
|
|
|
|
{
|
|
|
|
float dx, dy, chainX, chainY;
|
|
|
|
|
|
|
|
for (int i = 0 ; i < MAX_CARGO ; i++)
|
|
|
|
{
|
|
|
|
if (cargo[i].active)
|
|
|
|
{
|
|
|
|
if (!cargo[i].owner->active)
|
|
|
|
{
|
|
|
|
cargo_becomeCollectable(i);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2015-09-26 14:49:21 +02:00
|
|
|
screen_blit(cargo[i].image[0], (int)cargo[i].x, (int)cargo[i].y);
|
2015-04-08 01:16:46 +02:00
|
|
|
|
|
|
|
cargo[i].x += engine.ssx + engine.smx;
|
|
|
|
cargo[i].y += engine.ssy + engine.smy;
|
|
|
|
|
|
|
|
LIMIT(cargo[i].x, cargo[i].owner->x - 50, cargo[i].owner->x + 50);
|
|
|
|
LIMIT(cargo[i].y, cargo[i].owner->y - 50, cargo[i].owner->y + 50);
|
|
|
|
|
|
|
|
dx = (cargo[i].x - cargo[i].owner->x) / 10;
|
|
|
|
dy = (cargo[i].y - cargo[i].owner->y) / 10;
|
|
|
|
chainX = cargo[i].x - cargo[i].dx;
|
|
|
|
chainY = cargo[i].y - cargo[i].dy;
|
|
|
|
|
|
|
|
// draw the chain link line
|
|
|
|
for (int j = 0 ; j < 10 ; j++)
|
|
|
|
{
|
2015-09-26 14:49:21 +02:00
|
|
|
screen_blit(shape[30], (int)chainX, (int)chainY);
|
2015-04-08 01:16:46 +02:00
|
|
|
chainX -= dx;
|
|
|
|
chainY -= dy;
|
2015-03-07 05:18:31 +01:00
|
|
|
}
|
|
|
|
}
|
2015-04-08 01:16:46 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void game_doDebris()
|
|
|
|
{
|
|
|
|
object *prevDebris = engine.debrisHead;
|
|
|
|
object *debris = engine.debrisHead;
|
|
|
|
engine.debrisTail = engine.debrisHead;
|
|
|
|
|
|
|
|
while (debris->next != NULL)
|
|
|
|
{
|
|
|
|
debris = debris->next;
|
|
|
|
|
|
|
|
if (debris->thinktime > 0)
|
2015-03-07 05:18:31 +01:00
|
|
|
{
|
2015-04-08 01:16:46 +02:00
|
|
|
debris->thinktime--;
|
|
|
|
|
|
|
|
debris->x += engine.ssx + engine.smx;
|
|
|
|
debris->y += engine.ssy + engine.smy;
|
|
|
|
debris->x += debris->dx;
|
|
|
|
debris->y += debris->dy;
|
2015-03-07 05:18:31 +01:00
|
|
|
|
2015-05-01 00:51:26 +02:00
|
|
|
explosion_add(debris->x + RANDRANGE(-10, 10), debris->y + RANDRANGE(-10, 10), E_BIG_EXPLOSION);
|
2015-04-08 01:16:46 +02:00
|
|
|
}
|
2015-03-07 05:18:31 +01:00
|
|
|
|
2015-04-08 01:16:46 +02:00
|
|
|
if (debris->thinktime < 1)
|
|
|
|
{
|
|
|
|
prevDebris->next = debris->next;
|
|
|
|
delete debris;
|
|
|
|
debris = prevDebris;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
prevDebris = debris;
|
|
|
|
engine.debrisTail = debris;
|
2015-03-07 05:18:31 +01:00
|
|
|
}
|
2015-04-08 01:16:46 +02:00
|
|
|
|
2015-03-07 05:18:31 +01:00
|
|
|
}
|
2015-04-08 01:16:46 +02:00
|
|
|
}
|
|
|
|
|
2015-05-01 00:51:26 +02:00
|
|
|
/*
|
|
|
|
Loops through active explosions and decrements their think time.
|
|
|
|
If their thinktime is divisable by 5, then the frame is changed to
|
|
|
|
the next one up (for example 0->1->2-3). When their think time is 0,
|
|
|
|
the explosion is killed off.
|
|
|
|
*/
|
|
|
|
void game_doExplosions()
|
|
|
|
{
|
|
|
|
object *prevExplosion = engine.explosionHead;
|
|
|
|
object *explosion = engine.explosionHead;
|
|
|
|
engine.explosionTail = engine.explosionHead;
|
|
|
|
|
|
|
|
while (explosion->next != NULL)
|
|
|
|
{
|
|
|
|
explosion = explosion->next;
|
|
|
|
|
|
|
|
if (explosion->active)
|
|
|
|
{
|
|
|
|
explosion->x += engine.ssx + engine.smx;
|
|
|
|
explosion->y += engine.ssy + engine.smy;
|
|
|
|
|
2015-09-26 14:49:21 +02:00
|
|
|
screen_blit(explosion->image[0], (int)explosion->x, (int)explosion->y);
|
2015-05-01 00:51:26 +02:00
|
|
|
|
|
|
|
if(rand() % 7 == 0)
|
|
|
|
{
|
|
|
|
explosion->thinktime -= 7;
|
|
|
|
|
|
|
|
if(explosion->thinktime < 1)
|
|
|
|
{
|
|
|
|
explosion->active = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
explosion->face++;
|
|
|
|
explosion->image[0] = shape[explosion->face];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (explosion->active)
|
|
|
|
{
|
|
|
|
prevExplosion = explosion;
|
|
|
|
engine.explosionTail = explosion;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
prevExplosion->next = explosion->next;
|
|
|
|
delete explosion;
|
|
|
|
explosion = prevExplosion;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-28 12:51:45 +02:00
|
|
|
/*
|
|
|
|
Draw an arrow at the edge of the screen for each enemy ship that is not visible.
|
|
|
|
*/
|
|
|
|
static void game_doArrow(int i)
|
|
|
|
{
|
|
|
|
if (i < 0 || !aliens[i].active || aliens[i].shield <= 0 || aliens[i].flags & FL_ISCLOAKED)
|
|
|
|
return;
|
|
|
|
|
|
|
|
int x = aliens[i].x + aliens[i].image[0]->w / 2;
|
|
|
|
int y = aliens[i].y + aliens[i].image[0]->h / 2;
|
|
|
|
|
|
|
|
float sx = fabsf((x - (screen->w / 2)) / (screen->w / 2.0));
|
|
|
|
float sy = fabsf((y - (screen->h / 2)) / (screen->h / 2.0));
|
|
|
|
float sxy = MAX(sx, sy);
|
|
|
|
|
|
|
|
if (sxy < 1)
|
|
|
|
return;
|
|
|
|
|
|
|
|
x = screen->w / 2 + (x - screen->w / 2) / sxy;
|
|
|
|
y = screen->h / 2 + (y - screen->h / 2) / sxy;
|
|
|
|
|
|
|
|
int arrow;
|
|
|
|
|
|
|
|
if (sxy == sx) {
|
|
|
|
arrow = x < screen->w / 2 ? 42 : 38;
|
|
|
|
x -= x > screen->w / 2 ? shape[arrow]->w : 0;
|
|
|
|
y -= shape[arrow]->h / 2;
|
|
|
|
} else {
|
|
|
|
arrow = y < screen->h / 2 ? 36 : 40;
|
|
|
|
x -= shape[arrow]->w / 2;
|
|
|
|
y -= y > screen->h / 2 ? shape[arrow]->h : 0;
|
|
|
|
}
|
|
|
|
|
2015-09-26 14:49:21 +02:00
|
|
|
screen_blit(shape[arrow], x, y);
|
2015-05-28 12:51:45 +02:00
|
|
|
|
|
|
|
if (i != engine.targetIndex)
|
|
|
|
return;
|
|
|
|
|
2015-12-31 16:47:27 +01:00
|
|
|
if (gfx_text[TS_RADIO].life > 0)
|
2015-05-28 12:51:45 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (sxy == sx) {
|
|
|
|
x -= x > screen->w / 2 ? 5 + shape[44]->w : -5 - shape[arrow]->w;
|
|
|
|
y -= (shape[44]->h - shape[arrow]->h) / 2;
|
|
|
|
} else {
|
|
|
|
x -= (shape[44]->w - shape[arrow]->w) / 2;
|
|
|
|
y -= y > screen->h / 2 ? 5 + shape[44]->h : -5 - shape[arrow]->h;
|
|
|
|
}
|
|
|
|
|
2015-09-26 14:49:21 +02:00
|
|
|
screen_blit(shape[44], x, y);
|
2015-05-28 12:51:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void game_doHud()
|
|
|
|
{
|
|
|
|
int shieldColor = 0;
|
|
|
|
SDL_Rect bar;
|
|
|
|
signed char fontColor;
|
|
|
|
char text[25];
|
|
|
|
|
2015-11-02 23:53:05 +01:00
|
|
|
screen_addBuffer(0, 20, 800, 25);
|
|
|
|
screen_addBuffer(0, 550, 800, 34);
|
2015-05-28 12:51:45 +02:00
|
|
|
|
|
|
|
if (engine.minutes > -1)
|
|
|
|
{
|
|
|
|
if ((engine.minutes == 0) && (engine.seconds <= 29))
|
|
|
|
fontColor = FONT_RED;
|
|
|
|
else if ((engine.minutes == 0) && (engine.seconds > 29))
|
|
|
|
fontColor = FONT_YELLOW;
|
|
|
|
else
|
|
|
|
fontColor = FONT_WHITE;
|
2015-12-31 16:47:27 +01:00
|
|
|
screen_blitText(TS_TIME_T);
|
2015-05-28 12:51:45 +02:00
|
|
|
sprintf(text, "%.2d:%.2d", engine.minutes, engine.seconds);
|
2015-12-31 16:47:27 +01:00
|
|
|
gfx_createTextObject(TS_TIME, text, 410, 21, fontColor);
|
|
|
|
screen_blitText(TS_TIME);
|
2015-05-28 12:51:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (game.area != MISN_INTERCEPTION)
|
|
|
|
{
|
2015-12-31 16:47:27 +01:00
|
|
|
screen_blitText(TS_OBJECTIVES_T);
|
2015-05-28 12:51:45 +02:00
|
|
|
sprintf(text, "%d", (currentMission.remainingObjectives1 + currentMission.remainingObjectives2));
|
2015-12-31 16:47:27 +01:00
|
|
|
gfx_createTextObject(TS_OBJECTIVES, text, 745, 21, FONT_WHITE);
|
|
|
|
screen_blitText(TS_OBJECTIVES);
|
2015-05-28 12:51:45 +02:00
|
|
|
}
|
|
|
|
|
2015-12-31 16:47:27 +01:00
|
|
|
screen_blitText(TS_CASH_T); // cash
|
2015-05-28 12:51:45 +02:00
|
|
|
sprintf(text, "%.6d", game.cash);
|
2015-12-31 16:47:27 +01:00
|
|
|
gfx_createTextObject(TS_CASH, text, 90, 21, FONT_WHITE);
|
|
|
|
screen_blitText(TS_CASH);
|
2015-05-28 12:51:45 +02:00
|
|
|
|
|
|
|
for (int i = 0; i < ALIEN_MAX; i++)
|
|
|
|
game_doArrow(i);
|
|
|
|
|
|
|
|
fontColor = FONT_WHITE;
|
|
|
|
if (player.ammo[0] > 0)
|
|
|
|
{
|
|
|
|
if (player.ammo[0] <= 25) fontColor = FONT_YELLOW;
|
|
|
|
if (player.ammo[0] <= 10) fontColor = FONT_RED;
|
|
|
|
}
|
2015-12-31 16:47:27 +01:00
|
|
|
screen_blitText(TS_PLASMA_T);
|
2015-05-28 12:51:45 +02:00
|
|
|
sprintf(text, "%.3d", player.ammo[0]);
|
2015-12-31 16:47:27 +01:00
|
|
|
gfx_createTextObject(TS_PLASMA, text, 320, 551, fontColor);
|
|
|
|
screen_blitText(TS_PLASMA);
|
2015-05-28 12:51:45 +02:00
|
|
|
|
2015-12-31 16:47:27 +01:00
|
|
|
screen_blitText(TS_AMMO_T);
|
2015-05-28 12:51:45 +02:00
|
|
|
|
|
|
|
if ((player.weaponType[1] != W_CHARGER) && (player.weaponType[1] != W_LASER))
|
|
|
|
{
|
|
|
|
if (player.ammo[1] == 1)
|
|
|
|
fontColor = FONT_RED;
|
|
|
|
else
|
|
|
|
fontColor = FONT_WHITE;
|
|
|
|
sprintf(text, "%.3d", player.ammo[1]); // rocket ammo
|
2015-12-31 16:47:27 +01:00
|
|
|
gfx_createTextObject(TS_AMMO, text, 465, 551, fontColor);
|
|
|
|
screen_blitText(TS_AMMO);
|
2015-05-28 12:51:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (((player.weaponType[1] == W_CHARGER) || (player.weaponType[1] == W_LASER)) && (player.ammo[1] > 0))
|
|
|
|
{
|
|
|
|
int c = white;
|
|
|
|
if (player.ammo[1] > 100)
|
|
|
|
c = red;
|
|
|
|
|
|
|
|
bar.x = 450;
|
|
|
|
bar.y = 550;
|
|
|
|
bar.h = 12;
|
|
|
|
|
|
|
|
for (int i = 0 ; i < (player.ammo[1] / 5) ; i++)
|
|
|
|
{
|
|
|
|
bar.w = 1;
|
|
|
|
SDL_FillRect(screen, &bar, c);
|
|
|
|
bar.x += 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((!allMissionsCompleted()) && (SDL_GetTicks() >= engine.counter2))
|
|
|
|
{
|
|
|
|
engine.timeTaken++;
|
|
|
|
engine.counter2 = SDL_GetTicks() + 1000;
|
|
|
|
if (engine.missionCompleteTimer == 0)
|
2016-01-03 20:31:39 +01:00
|
|
|
events_check();
|
2015-05-28 12:51:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if ((engine.timeMission) && (!engine.cheatTime) && (player.shield > 0))
|
|
|
|
{
|
|
|
|
if (SDL_GetTicks() >= engine.counter)
|
|
|
|
{
|
|
|
|
if ((engine.seconds > 1) && (engine.seconds <= 11) && (engine.minutes == 0))
|
|
|
|
{
|
|
|
|
audio_playSound(SFX_CLOCK, screen->w / 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (engine.seconds > 0)
|
|
|
|
{
|
|
|
|
engine.seconds--;
|
|
|
|
engine.counter = (SDL_GetTicks() + 1000);
|
|
|
|
}
|
|
|
|
else if ((engine.seconds == 0) && (engine.minutes > 0))
|
|
|
|
{
|
|
|
|
engine.minutes--;
|
|
|
|
engine.seconds = 59;
|
|
|
|
engine.counter = (SDL_GetTicks() + 1000);
|
|
|
|
for (int i = 0 ; i < 3 ; i++)
|
|
|
|
{
|
|
|
|
if (currentMission.timeLimit1[i] > -1)
|
|
|
|
currentMission.timeLimit1[i]--;
|
|
|
|
if (currentMission.timeLimit2[i] > -1)
|
|
|
|
currentMission.timeLimit2[i]--;
|
|
|
|
}
|
|
|
|
checkTimer();
|
2016-01-03 20:31:39 +01:00
|
|
|
events_check();
|
2015-05-28 12:51:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if ((engine.seconds == 0) && (engine.minutes == 0))
|
|
|
|
{
|
|
|
|
for (int i = 0 ; i < 3 ; i++)
|
|
|
|
{
|
|
|
|
if (currentMission.timeLimit1[i] > -1)
|
|
|
|
currentMission.timeLimit1[i]--;
|
|
|
|
if (currentMission.timeLimit2[i] > -1)
|
|
|
|
currentMission.timeLimit2[i]--;
|
|
|
|
}
|
|
|
|
checkTimer();
|
2016-01-03 20:31:39 +01:00
|
|
|
events_check();
|
2015-05-28 12:51:45 +02:00
|
|
|
engine.counter = (SDL_GetTicks() + 1000);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-31 16:47:27 +01:00
|
|
|
for (int i = 0 ; i < MAX_INFOLINES ; i++)
|
2015-05-28 12:51:45 +02:00
|
|
|
{
|
2015-10-11 18:04:52 +02:00
|
|
|
if (gfx_text[i].life > 0)
|
2015-05-28 12:51:45 +02:00
|
|
|
{
|
2015-10-11 18:04:52 +02:00
|
|
|
gfx_text[i].y = (525 - (i * 20));
|
|
|
|
screen_blitText(i);
|
|
|
|
gfx_text[i].life--;
|
2015-05-28 12:51:45 +02:00
|
|
|
|
2015-10-11 18:04:52 +02:00
|
|
|
if (gfx_text[i].life == 0)
|
2015-05-28 12:51:45 +02:00
|
|
|
{
|
2015-12-31 16:47:27 +01:00
|
|
|
for (int j = i ; j < MAX_INFOLINES - 1 ; j++)
|
|
|
|
{
|
|
|
|
copyInfoLine(j + 1, j);
|
|
|
|
}
|
|
|
|
gfx_text[MAX_INFOLINES - 1].life = 0;
|
2015-05-28 12:51:45 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Show the radio message if there is one
|
2015-12-31 16:47:27 +01:00
|
|
|
if (gfx_text[TS_RADIO].life > 0)
|
2015-05-28 12:51:45 +02:00
|
|
|
{
|
2015-12-31 16:47:27 +01:00
|
|
|
screen_blit(messageBox, (screen->w - messageBox->w) / 2, 50);
|
|
|
|
gfx_text[TS_RADIO].life--;
|
2015-05-28 12:51:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Do the target's remaining shield (if required)
|
|
|
|
if (game.area != MISN_DORIM)
|
|
|
|
{
|
|
|
|
if ((engine.targetIndex > -1) && (aliens[engine.targetIndex].shield > 0) && (engine.targetIndex > 9))
|
|
|
|
{
|
2015-12-31 16:47:27 +01:00
|
|
|
screen_blitText(TS_TARGET);
|
2015-05-28 12:51:45 +02:00
|
|
|
bar.w = 1;
|
|
|
|
bar.h = 12;
|
|
|
|
bar.x = 620;
|
|
|
|
bar.y = 550;
|
|
|
|
|
|
|
|
for (float i = 0 ; i < (engine.targetShield * aliens[engine.targetIndex].shield) ; i++)
|
|
|
|
{
|
|
|
|
if (i > 50)
|
|
|
|
shieldColor = green;
|
|
|
|
else if ((i >= 25) && (i <= 50))
|
|
|
|
shieldColor = yellow;
|
|
|
|
else
|
|
|
|
shieldColor = red;
|
|
|
|
SDL_FillRect(screen, &bar, shieldColor);
|
|
|
|
bar.x += 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-31 16:47:27 +01:00
|
|
|
screen_blitText(TS_POWER);
|
2015-05-28 12:51:45 +02:00
|
|
|
|
|
|
|
bar.w = 25;
|
|
|
|
bar.h = 12;
|
|
|
|
bar.x = 80;
|
|
|
|
bar.y = 571;
|
|
|
|
|
|
|
|
for (int i = 1 ; i <= 5 ; i++)
|
|
|
|
{
|
|
|
|
if (weapon[W_PLAYER_WEAPON].damage >= i) {
|
|
|
|
if(i <= game.maxPlasmaDamage || (SDL_GetTicks() % 1000 > (unsigned)i * 100))
|
|
|
|
{
|
|
|
|
SDL_FillRect(screen, &bar, green);
|
|
|
|
}
|
|
|
|
} else if (i <= game.maxPlasmaDamage)
|
|
|
|
SDL_FillRect(screen, &bar, darkGreen);
|
|
|
|
bar.x += 30;
|
|
|
|
}
|
|
|
|
|
2015-12-31 16:47:27 +01:00
|
|
|
screen_blitText(TS_OUTPUT);
|
2015-05-28 12:51:45 +02:00
|
|
|
|
|
|
|
bar.w = 25;
|
|
|
|
bar.h = 12;
|
|
|
|
bar.x = 315;
|
|
|
|
bar.y = 571;
|
|
|
|
SDL_FillRect(screen, &bar, yellow);
|
|
|
|
|
|
|
|
for (int i = 1 ; i <= 5 ; i++)
|
|
|
|
{
|
|
|
|
if (weapon[W_PLAYER_WEAPON].ammo[0] >= i) {
|
|
|
|
if(i <= game.maxPlasmaOutput || (SDL_GetTicks() % 1000 > (unsigned)i * 100))
|
|
|
|
{
|
|
|
|
SDL_FillRect(screen, &bar, yellow);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (i <= game.maxPlasmaOutput)
|
|
|
|
SDL_FillRect(screen, &bar, darkYellow);
|
|
|
|
bar.x += 30;
|
|
|
|
}
|
|
|
|
|
2015-12-31 16:47:27 +01:00
|
|
|
screen_blitText(TS_COOLER);
|
2015-05-28 12:51:45 +02:00
|
|
|
|
|
|
|
bar.w = 25;
|
|
|
|
bar.h = 12;
|
|
|
|
bar.x = 550;
|
|
|
|
bar.y = 571;
|
|
|
|
|
|
|
|
for (int i = 1 ; i <= 5 ; i++)
|
|
|
|
{
|
|
|
|
if (weapon[W_PLAYER_WEAPON].reload[0] <= rate2reload[i]) {
|
|
|
|
if(i <= game.maxPlasmaRate || (SDL_GetTicks() % 1000 > (unsigned)i * 100))
|
|
|
|
{
|
|
|
|
SDL_FillRect(screen, &bar, blue);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (i <= game.maxPlasmaRate)
|
|
|
|
SDL_FillRect(screen, &bar, darkerBlue);
|
|
|
|
bar.x += 30;
|
|
|
|
}
|
|
|
|
|
2015-12-31 16:47:27 +01:00
|
|
|
screen_blitText(TS_SHIELD);
|
2015-05-28 12:51:45 +02:00
|
|
|
if (player.shield < 1)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if ((!engine.keyState[KEY_ALTFIRE]) && (player.weaponType[1] == W_LASER) && (engine.eventTimer % 8 == 1))
|
|
|
|
LIMIT_ADD(player.ammo[1], -1, 1, 255);
|
|
|
|
|
|
|
|
if ((engine.eventTimer < 30) && (player.shield <= engine.lowShield))
|
|
|
|
return;
|
|
|
|
|
|
|
|
signed char blockSize = 1;
|
|
|
|
|
|
|
|
bar.w = blockSize;
|
|
|
|
bar.h = 12;
|
|
|
|
bar.x = 95;
|
|
|
|
bar.y = 550;
|
|
|
|
|
|
|
|
for (int i = 0 ; i < player.shield ; i += blockSize)
|
|
|
|
{
|
|
|
|
if (i >= engine.averageShield)
|
|
|
|
shieldColor = green;
|
|
|
|
else if ((i >= engine.lowShield) && (i < engine.averageShield))
|
|
|
|
shieldColor = yellow;
|
|
|
|
else
|
|
|
|
shieldColor = red;
|
|
|
|
SDL_FillRect(screen, &bar, shieldColor);
|
|
|
|
bar.x += blockSize;
|
|
|
|
if (player.maxShield < 75)
|
|
|
|
bar.x++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-07 03:35:07 +01:00
|
|
|
/*
|
|
|
|
* Delay until the next 60 Hz frame
|
|
|
|
*/
|
|
|
|
void game_delayFrame()
|
|
|
|
{
|
|
|
|
Uint32 now = SDL_GetTicks();
|
|
|
|
|
|
|
|
// Add 16 2/3 (= 1000 / 60) to frameLimit
|
|
|
|
frameLimit += 16;
|
|
|
|
thirds += 2;
|
|
|
|
while (thirds >= 3)
|
|
|
|
{
|
|
|
|
thirds -= 3;
|
|
|
|
frameLimit++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(now < frameLimit)
|
|
|
|
SDL_Delay(frameLimit - now);
|
|
|
|
else
|
|
|
|
frameLimit = now;
|
|
|
|
}
|
|
|
|
|
2015-04-26 13:36:25 +02:00
|
|
|
/*
|
|
|
|
Checked during the main game loop. When the game is paused
|
|
|
|
it goes into a constant loop checking this routine. If escape is
|
|
|
|
pressed, the game automatically ends and goes back to the title screen
|
|
|
|
*/
|
|
|
|
static bool game_checkPauseRequest()
|
|
|
|
{
|
|
|
|
getPlayerInput();
|
|
|
|
|
|
|
|
if (engine.keyState[KEY_ESCAPE])
|
|
|
|
{
|
|
|
|
engine.paused = false;
|
|
|
|
engine.done = 1;
|
|
|
|
player.shield = 0;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (engine.keyState[KEY_PAUSE])
|
|
|
|
{
|
|
|
|
engine.paused = false;
|
|
|
|
engine.keyState[KEY_PAUSE] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-09-25 22:28:09 +02:00
|
|
|
bool game_collision(float x0, float y0, int w0, int h0, float x2, float y2, int w1, int h1)
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2015-05-21 01:41:43 +02:00
|
|
|
int game_mainLoop()
|
2015-04-08 01:16:46 +02:00
|
|
|
{
|
|
|
|
resetLists();
|
|
|
|
|
2015-05-21 01:41:43 +02:00
|
|
|
setMission(game.area);
|
2015-04-08 01:16:46 +02:00
|
|
|
missionBriefScreen();
|
|
|
|
|
2015-04-24 22:27:07 +02:00
|
|
|
cargo_init();
|
2015-04-08 01:16:46 +02:00
|
|
|
initPlayer();
|
|
|
|
aliens_init();
|
2015-03-07 05:18:31 +01:00
|
|
|
|
|
|
|
// specific for Phoebe being captured!
|
2015-05-21 01:41:43 +02:00
|
|
|
if (game.area == MISN_NEROD)
|
|
|
|
game.hasWingMate1 = 1;
|
2015-03-07 05:18:31 +01:00
|
|
|
|
2015-05-21 01:41:43 +02:00
|
|
|
if (game.area == MISN_ELAMALE)
|
2015-03-09 01:59:33 +01:00
|
|
|
aliens[ALIEN_KLINE].active = false;
|
2015-03-07 05:18:31 +01:00
|
|
|
|
|
|
|
for (int i = 0 ; i < engine.maxAliens ; i++)
|
|
|
|
alien_add();
|
|
|
|
|
2015-05-21 01:41:43 +02:00
|
|
|
if (game.hasWingMate1)
|
2015-03-09 01:59:33 +01:00
|
|
|
alien_addFriendly(ALIEN_PHOEBE);
|
2015-03-07 05:18:31 +01:00
|
|
|
|
2015-05-21 01:41:43 +02:00
|
|
|
if (game.hasWingMate2)
|
2015-03-09 01:59:33 +01:00
|
|
|
alien_addFriendly(ALIEN_URSULA);
|
2015-03-07 05:18:31 +01:00
|
|
|
|
2015-05-21 01:41:43 +02:00
|
|
|
if ((game.area == MISN_URUSOR) ||
|
|
|
|
(game.area == MISN_POSWIC) ||
|
|
|
|
(game.area == MISN_EARTH))
|
2015-03-09 01:59:33 +01:00
|
|
|
alien_addFriendly(ALIEN_SID);
|
2015-03-07 05:18:31 +01:00
|
|
|
|
|
|
|
// Disable Wingmates for certain missions
|
2015-05-21 01:41:43 +02:00
|
|
|
switch (game.area)
|
2015-03-07 05:18:31 +01:00
|
|
|
{
|
2015-03-29 19:11:12 +02:00
|
|
|
case MISN_NEROD:
|
|
|
|
case MISN_URUSOR:
|
|
|
|
case MISN_DORIM:
|
|
|
|
case MISN_SIVEDI:
|
|
|
|
case MISN_ALMARTHA:
|
|
|
|
case MISN_ELLESH:
|
|
|
|
case MISN_MARS:
|
|
|
|
case MISN_VENUS:
|
2015-03-09 01:59:33 +01:00
|
|
|
aliens[ALIEN_PHOEBE].active = false;
|
|
|
|
aliens[ALIEN_URSULA].active = false;
|
2015-03-07 05:18:31 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-05-21 01:41:43 +02:00
|
|
|
if (game.area == MISN_DORIM)
|
2015-03-07 05:18:31 +01:00
|
|
|
{
|
2015-03-07 15:42:24 +01:00
|
|
|
aliens[0].collectChance = 100;
|
|
|
|
aliens[0].collectType = P_ESCAPEPOD;
|
2015-03-07 05:18:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Some specifics for interception missions
|
2015-05-21 01:41:43 +02:00
|
|
|
if (game.area == MISN_INTERCEPTION)
|
2015-03-07 05:18:31 +01:00
|
|
|
{
|
2015-05-21 01:41:43 +02:00
|
|
|
if ((game.system > 1) && ((rand() % 5) == 0))
|
2015-03-07 05:18:31 +01:00
|
|
|
{
|
2015-03-09 01:59:33 +01:00
|
|
|
aliens[ALIEN_KLINE] = alien_defs[CD_KLINE];
|
|
|
|
aliens[ALIEN_KLINE].owner = &aliens[ALIEN_KLINE];
|
|
|
|
aliens[ALIEN_KLINE].target = &player;
|
|
|
|
aliens[ALIEN_KLINE].active = true;
|
|
|
|
aliens[ALIEN_KLINE].x = player.x + 1000;
|
|
|
|
aliens[ALIEN_KLINE].y = player.y;
|
|
|
|
player_setTarget(ALIEN_KLINE);
|
2015-03-07 05:18:31 +01:00
|
|
|
}
|
|
|
|
|
2015-05-21 01:41:43 +02:00
|
|
|
if ((game.system == 2) && (game.experimentalShield > 0))
|
2015-03-07 05:18:31 +01:00
|
|
|
{
|
2015-03-18 03:09:00 +01:00
|
|
|
if ((rand() % 5) > 0)
|
2015-03-07 05:18:31 +01:00
|
|
|
{
|
2015-03-07 15:42:24 +01:00
|
|
|
aliens[10] = alien_defs[CD_CLOAKFIGHTER];
|
|
|
|
aliens[10].owner = &aliens[10];
|
|
|
|
aliens[10].target = &aliens[10];
|
|
|
|
aliens[10].shield = 1000;
|
|
|
|
aliens[10].active = true;
|
|
|
|
aliens[10].x = player.x - 1000;
|
|
|
|
aliens[10].y = player.y;
|
2015-03-07 05:18:31 +01:00
|
|
|
player_setTarget(10);
|
2015-05-21 01:41:43 +02:00
|
|
|
aliens[10].shield = game.experimentalShield;
|
2015-03-07 05:18:31 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-21 01:41:43 +02:00
|
|
|
if (game.area == MISN_VENUS)
|
2015-03-07 05:18:31 +01:00
|
|
|
{
|
2015-03-09 01:59:33 +01:00
|
|
|
aliens[ALIEN_KLINE].x = player.x + 1000;
|
|
|
|
aliens[ALIEN_KLINE].y = player.y;
|
2015-03-07 05:18:31 +01:00
|
|
|
}
|
|
|
|
|
2015-03-09 01:59:33 +01:00
|
|
|
for (int i = 0 ; i < ALIEN_MAX ; i++)
|
2015-03-07 05:18:31 +01:00
|
|
|
{
|
2015-03-07 15:42:24 +01:00
|
|
|
aliens[i].systemPower = aliens[i].maxShield;
|
|
|
|
aliens[i].deathCounter = 0 - (aliens[i].maxShield * 3);
|
2015-03-18 00:00:13 +01:00
|
|
|
LIMIT(aliens[i].deathCounter, -350, 0);
|
2015-03-07 05:18:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Set target energy meter
|
2015-05-21 01:41:43 +02:00
|
|
|
switch (game.area)
|
2015-03-07 05:18:31 +01:00
|
|
|
{
|
2015-03-29 19:11:12 +02:00
|
|
|
case MISN_MOEBO:
|
|
|
|
case MISN_ELAMALE:
|
|
|
|
case MISN_ODEON:
|
|
|
|
case MISN_FELLON:
|
|
|
|
case MISN_POSWIC:
|
|
|
|
case MISN_ELLESH:
|
|
|
|
case MISN_PLUTO:
|
|
|
|
case MISN_NEPTUNE:
|
|
|
|
case MISN_URANUS:
|
|
|
|
case MISN_JUPITER:
|
2015-03-09 01:59:33 +01:00
|
|
|
player_setTarget(ALIEN_BOSS);
|
2015-03-07 05:18:31 +01:00
|
|
|
break;
|
2015-03-29 19:11:12 +02:00
|
|
|
case MISN_NEROD:
|
2015-03-09 01:59:33 +01:00
|
|
|
player_setTarget(ALIEN_PHOEBE);
|
2015-03-07 05:18:31 +01:00
|
|
|
break;
|
2015-03-29 19:11:12 +02:00
|
|
|
case MISN_ALLEZ:
|
2015-03-09 01:59:33 +01:00
|
|
|
player_setTarget(ALIEN_GOODTRANSPORT);
|
2015-03-07 05:18:31 +01:00
|
|
|
break;
|
2015-03-29 19:11:12 +02:00
|
|
|
case MISN_URUSOR:
|
2015-03-09 01:59:33 +01:00
|
|
|
player_setTarget(ALIEN_SID);
|
2015-03-07 05:18:31 +01:00
|
|
|
break;
|
2015-03-29 19:11:12 +02:00
|
|
|
case MISN_EARTH:
|
|
|
|
case MISN_VENUS:
|
2015-03-09 01:59:33 +01:00
|
|
|
player_setTarget(ALIEN_KLINE);
|
2015-03-07 05:18:31 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2011-08-24 14:14:44 +02:00
|
|
|
clearInfoLines();
|
|
|
|
|
2016-01-03 20:14:31 +01:00
|
|
|
events_init();
|
2011-08-24 14:14:44 +02:00
|
|
|
|
|
|
|
engine.ssx = 0;
|
|
|
|
engine.ssy = 0;
|
2015-02-27 05:23:08 +01:00
|
|
|
engine.smx = 0;
|
|
|
|
engine.smy = 0;
|
2011-08-24 14:14:44 +02:00
|
|
|
|
|
|
|
engine.done = 0;
|
|
|
|
|
|
|
|
engine.counter = (SDL_GetTicks() + 1000);
|
|
|
|
engine.counter2 = (SDL_GetTicks() + 1000);
|
|
|
|
|
|
|
|
engine.missionCompleteTimer = 0;
|
|
|
|
engine.musicVolume = 100;
|
|
|
|
|
|
|
|
int rtn = 0;
|
|
|
|
|
|
|
|
int allowableAliens = 999999999;
|
|
|
|
|
|
|
|
for (int i = 0 ; i < 3 ; i++)
|
|
|
|
{
|
2015-03-07 15:42:24 +01:00
|
|
|
if ((currentMission.primaryType[i] == M_DESTROY_TARGET_TYPE) &&
|
|
|
|
(currentMission.target1[i] == CD_ANY))
|
2011-08-24 14:14:44 +02:00
|
|
|
allowableAliens = currentMission.targetValue1[i];
|
|
|
|
|
|
|
|
if (currentMission.primaryType[i] == M_DESTROY_ALL_TARGETS)
|
|
|
|
allowableAliens = 999999999;
|
|
|
|
}
|
|
|
|
|
2015-03-09 01:59:33 +01:00
|
|
|
for (int i = 0 ; i < ALIEN_MAX ; i++)
|
2011-08-24 14:14:44 +02:00
|
|
|
{
|
2015-03-07 15:42:24 +01:00
|
|
|
if ((aliens[i].active) && (aliens[i].flags & FL_WEAPCO))
|
2011-08-24 14:14:44 +02:00
|
|
|
{
|
|
|
|
allowableAliens--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-07 01:43:34 +01:00
|
|
|
screen_drawBackground();
|
2015-11-02 23:53:05 +01:00
|
|
|
screen_flushBuffer();
|
2011-08-24 14:14:44 +02:00
|
|
|
|
|
|
|
// Default to no aliens dead...
|
|
|
|
engine.allAliensDead = 0;
|
|
|
|
|
2015-03-07 05:18:31 +01:00
|
|
|
engine.keyState[KEY_FIRE] = 0;
|
|
|
|
engine.keyState[KEY_ALTFIRE] = 0;
|
2011-08-24 14:14:44 +02:00
|
|
|
flushInput();
|
|
|
|
|
|
|
|
while (engine.done != 1)
|
|
|
|
{
|
2015-10-27 01:07:31 +01:00
|
|
|
renderer_update();
|
2011-08-24 14:14:44 +02:00
|
|
|
|
|
|
|
if ((allMissionsCompleted()) && (engine.missionCompleteTimer == 0))
|
|
|
|
{
|
|
|
|
engine.missionCompleteTimer = SDL_GetTicks() + 4000;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((missionFailed()) && (engine.missionCompleteTimer == 0))
|
|
|
|
{
|
2015-05-21 01:41:43 +02:00
|
|
|
if (game.area != MISN_MOEBO)
|
2011-08-24 14:14:44 +02:00
|
|
|
engine.missionCompleteTimer = SDL_GetTicks() + 4000;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (engine.missionCompleteTimer != 0)
|
|
|
|
{
|
|
|
|
engine.gameSection = SECTION_INTERMISSION;
|
|
|
|
if (player.shield > 0)
|
|
|
|
{
|
|
|
|
if (SDL_GetTicks() >= engine.missionCompleteTimer)
|
|
|
|
{
|
2015-05-21 01:41:43 +02:00
|
|
|
if ((!missionFailed()) && (game.area != MISN_VENUS))
|
2011-08-24 14:14:44 +02:00
|
|
|
{
|
|
|
|
leaveSector();
|
2015-03-29 19:11:12 +02:00
|
|
|
if ((engine.done == 2) &&
|
2015-05-21 01:41:43 +02:00
|
|
|
(game.area != MISN_DORIM) &&
|
|
|
|
(game.area != MISN_SIVEDI))
|
2011-08-24 14:14:44 +02:00
|
|
|
{
|
2015-03-09 01:59:33 +01:00
|
|
|
if ((aliens[ALIEN_PHOEBE].shield > 0) &&
|
2015-05-21 01:41:43 +02:00
|
|
|
(game.area != MISN_EARTH))
|
2011-08-24 14:14:44 +02:00
|
|
|
{
|
2015-03-09 01:59:33 +01:00
|
|
|
aliens[ALIEN_PHOEBE].x = player.x - 40;
|
|
|
|
aliens[ALIEN_PHOEBE].y = player.y - 35;
|
|
|
|
aliens[ALIEN_PHOEBE].face = 0;
|
2011-08-24 14:14:44 +02:00
|
|
|
}
|
|
|
|
|
2015-03-09 01:59:33 +01:00
|
|
|
if ((aliens[ALIEN_URSULA].shield > 0) &&
|
2015-05-21 01:41:43 +02:00
|
|
|
(game.area != MISN_EARTH))
|
2011-08-24 14:14:44 +02:00
|
|
|
{
|
2015-03-09 01:59:33 +01:00
|
|
|
aliens[ALIEN_URSULA].x = player.x - 40;
|
|
|
|
aliens[ALIEN_URSULA].y = player.y + 45;
|
|
|
|
aliens[ALIEN_URSULA].face = 0;
|
2011-08-24 14:14:44 +02:00
|
|
|
}
|
|
|
|
|
2015-05-21 01:41:43 +02:00
|
|
|
if ((game.area == MISN_URUSOR) ||
|
|
|
|
(game.area == MISN_POSWIC))
|
2011-08-24 14:14:44 +02:00
|
|
|
{
|
2015-03-09 01:59:33 +01:00
|
|
|
aliens[ALIEN_SID].x = player.x - 100;
|
|
|
|
aliens[ALIEN_SID].y = player.y;
|
|
|
|
aliens[ALIEN_SID].face = 0;
|
2011-08-24 14:14:44 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-05-21 01:41:43 +02:00
|
|
|
else if ((game.area == MISN_VENUS) &&
|
2015-03-29 19:11:12 +02:00
|
|
|
(engine.musicVolume > 0))
|
2011-08-24 14:14:44 +02:00
|
|
|
{
|
2015-03-29 22:49:33 +02:00
|
|
|
engine.keyState[KEY_UP] = 0;
|
|
|
|
engine.keyState[KEY_DOWN] = 0;
|
|
|
|
engine.keyState[KEY_LEFT] = 0;
|
|
|
|
engine.keyState[KEY_RIGHT] = 0;
|
|
|
|
engine.keyState[KEY_FIRE] = 0;
|
|
|
|
engine.keyState[KEY_ALTFIRE] = 0;
|
2015-03-18 00:00:13 +01:00
|
|
|
LIMIT_ADD(engine.musicVolume, -0.2, 0, 100);
|
2015-03-31 21:23:17 +02:00
|
|
|
audio_setMusicVolume(engine.musicVolume);
|
2011-08-24 14:14:44 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
engine.done = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
getPlayerInput();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-03-18 00:00:13 +01:00
|
|
|
LIMIT_ADD(engine.musicVolume, -0.2, 0, 100);
|
2015-03-31 21:23:17 +02:00
|
|
|
audio_setMusicVolume(engine.musicVolume);
|
2011-08-24 14:14:44 +02:00
|
|
|
if (SDL_GetTicks() >= engine.missionCompleteTimer)
|
|
|
|
{
|
|
|
|
engine.done = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
getPlayerInput();
|
|
|
|
}
|
|
|
|
|
2015-11-02 23:53:05 +01:00
|
|
|
screen_unBuffer();
|
2015-06-20 17:58:37 +02:00
|
|
|
game_doStars();
|
2015-04-08 01:16:46 +02:00
|
|
|
game_doCollectables();
|
2015-04-07 22:09:17 +02:00
|
|
|
game_doBullets();
|
|
|
|
game_doAliens();
|
2015-04-08 01:16:46 +02:00
|
|
|
game_doPlayer();
|
|
|
|
game_doCargo();
|
|
|
|
game_doDebris();
|
2015-05-01 00:51:26 +02:00
|
|
|
game_doExplosions();
|
2015-05-28 12:51:45 +02:00
|
|
|
game_doHud();
|
2011-08-24 14:14:44 +02:00
|
|
|
|
2015-03-24 23:51:12 +01:00
|
|
|
WRAP_ADD(engine.eventTimer, -1, 0, 60);
|
2011-08-24 14:14:44 +02:00
|
|
|
|
2011-09-05 11:40:35 +02:00
|
|
|
if (engine.paused)
|
2011-08-24 14:14:44 +02:00
|
|
|
{
|
2015-12-31 16:47:27 +01:00
|
|
|
gfx_createTextObject(TS_PAUSED, "PAUSED", -1, screen->h / 2, FONT_WHITE);
|
|
|
|
screen_blitText(TS_PAUSED);
|
2015-10-27 01:07:31 +01:00
|
|
|
renderer_update();
|
2015-04-26 13:45:58 +02:00
|
|
|
audio_pauseMusic();
|
2011-09-05 11:40:35 +02:00
|
|
|
|
|
|
|
while (engine.paused)
|
|
|
|
{
|
2015-04-26 13:36:25 +02:00
|
|
|
engine.done = game_checkPauseRequest();
|
2015-11-07 03:35:07 +01:00
|
|
|
game_delayFrame();
|
2011-09-05 11:40:35 +02:00
|
|
|
}
|
2015-04-26 13:45:58 +02:00
|
|
|
|
|
|
|
audio_resumeMusic();
|
2011-08-24 14:14:44 +02:00
|
|
|
}
|
|
|
|
|
2015-05-21 01:41:43 +02:00
|
|
|
if ((game.area == MISN_MARS) && (engine.addAliens > -1))
|
2011-08-24 14:14:44 +02:00
|
|
|
{
|
2015-03-29 20:27:29 +02:00
|
|
|
if ((rand() % 5) == 0)
|
2015-03-29 16:19:53 +02:00
|
|
|
// XXX: The originally specified range for x was [800, 100],
|
|
|
|
// which with the original rrand function caused the result
|
|
|
|
// returned to be `800 + rand() % -699`. Clearly a mistake,
|
|
|
|
// but I'm not entirely sure what the original intention was.
|
|
|
|
// For now, I've set the range to [800, 1500], which
|
|
|
|
// approximately replicates the original's results.
|
2015-04-24 22:27:07 +02:00
|
|
|
collectable_add(RANDRANGE(800, 1500),
|
2015-03-29 20:27:29 +02:00
|
|
|
RANDRANGE(-screen->h / 3, (4 * screen->h) / 3), P_MINE, 25,
|
2015-03-07 05:18:31 +01:00
|
|
|
180 + rand() % 60);
|
2011-08-24 14:14:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (engine.addAliens > -1)
|
|
|
|
{
|
2015-03-28 18:18:37 +01:00
|
|
|
WRAP_ADD(engine.addAliens, -1, 0, currentMission.addAliens);
|
2011-08-24 14:14:44 +02:00
|
|
|
if ((engine.addAliens == 0) && (allowableAliens > 0))
|
|
|
|
{
|
2015-03-05 03:30:23 +01:00
|
|
|
allowableAliens -= alien_add();
|
2011-08-24 14:14:44 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((player.shield <= 0) && (engine.missionCompleteTimer == 0))
|
|
|
|
engine.missionCompleteTimer = SDL_GetTicks() + 7000;
|
|
|
|
|
|
|
|
// specific to Boss 1
|
2015-05-21 01:41:43 +02:00
|
|
|
if ((game.area == MISN_MOEBO) &&
|
2015-03-29 19:11:12 +02:00
|
|
|
(aliens[ALIEN_BOSS].flags & FL_ESCAPED))
|
2011-08-24 14:14:44 +02:00
|
|
|
{
|
2015-03-09 01:59:33 +01:00
|
|
|
audio_playSound(SFX_DEATH, aliens[ALIEN_BOSS].x);
|
2015-11-07 03:35:07 +01:00
|
|
|
screen_clear(white);
|
2015-10-27 01:07:31 +01:00
|
|
|
renderer_update();
|
2011-08-24 14:14:44 +02:00
|
|
|
for (int i = 0 ; i < 300 ; i++)
|
|
|
|
{
|
|
|
|
SDL_Delay(10);
|
|
|
|
if ((rand() % 25) == 0)
|
2015-03-09 01:59:33 +01:00
|
|
|
audio_playSound(SFX_EXPLOSION, aliens[ALIEN_BOSS].x);
|
2011-08-24 14:14:44 +02:00
|
|
|
}
|
|
|
|
SDL_Delay(1000);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-11-07 03:35:07 +01:00
|
|
|
game_delayFrame();
|
2011-08-24 14:14:44 +02:00
|
|
|
}
|
|
|
|
|
2015-11-02 23:53:05 +01:00
|
|
|
screen_flushBuffer();
|
2011-08-24 14:14:44 +02:00
|
|
|
|
|
|
|
if ((player.shield > 0) && (!missionFailed()))
|
|
|
|
{
|
2015-05-21 01:41:43 +02:00
|
|
|
if (game.area < MISN_VENUS)
|
2011-08-24 14:14:44 +02:00
|
|
|
missionFinishedScreen();
|
|
|
|
|
2015-05-21 01:41:43 +02:00
|
|
|
switch (game.area)
|
2011-08-24 14:14:44 +02:00
|
|
|
{
|
2015-03-29 19:11:12 +02:00
|
|
|
case MISN_MOEBO:
|
2011-08-24 14:14:44 +02:00
|
|
|
doCutscene(1);
|
|
|
|
doCutscene(2);
|
|
|
|
break;
|
2015-03-29 19:11:12 +02:00
|
|
|
case MISN_NEROD:
|
2011-08-24 14:14:44 +02:00
|
|
|
doCutscene(3);
|
|
|
|
break;
|
2015-03-29 19:11:12 +02:00
|
|
|
case MISN_ELAMALE:
|
2011-08-24 14:14:44 +02:00
|
|
|
doCutscene(4);
|
|
|
|
break;
|
2015-03-29 19:11:12 +02:00
|
|
|
case MISN_ODEON:
|
2011-08-24 14:14:44 +02:00
|
|
|
doCutscene(5);
|
|
|
|
break;
|
2015-03-29 19:11:12 +02:00
|
|
|
case MISN_ELLESH:
|
2011-08-24 14:14:44 +02:00
|
|
|
doCutscene(6);
|
|
|
|
break;
|
2015-03-29 19:11:12 +02:00
|
|
|
case MISN_VENUS:
|
2015-03-04 14:20:11 +01:00
|
|
|
doCredits();
|
2011-08-24 14:14:44 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-05-21 01:41:43 +02:00
|
|
|
if (game.area < MISN_VENUS)
|
2011-08-24 14:14:44 +02:00
|
|
|
{
|
|
|
|
updateSystemStatus();
|
2015-03-03 05:32:48 +01:00
|
|
|
saveGame(0);
|
2011-08-24 14:14:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
rtn = 1;
|
|
|
|
|
2015-05-21 01:41:43 +02:00
|
|
|
if (game.area == MISN_VENUS)
|
2011-08-24 14:14:44 +02:00
|
|
|
rtn = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gameover();
|
|
|
|
rtn = 0;
|
|
|
|
}
|
|
|
|
|
2011-08-29 09:10:50 +02:00
|
|
|
exitPlayer();
|
|
|
|
|
2011-08-24 14:14:44 +02:00
|
|
|
return rtn;
|
|
|
|
}
|