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
|
2019-05-22 00:47:32 +02:00
|
|
|
Copyright (C) 2012, 2014-2019 Julie Marchant <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
|
|
|
*/
|
|
|
|
|
2019-06-06 04:13:48 +02:00
|
|
|
#include <libintl.h>
|
2017-01-21 05:48:53 +01:00
|
|
|
#include <math.h>
|
2017-01-25 16:48:29 +01:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
#include "SDL.h"
|
2016-11-26 00:21:31 +01:00
|
|
|
|
2017-01-21 05:48:53 +01:00
|
|
|
#include "colors.h"
|
2016-11-26 00:21:31 +01:00
|
|
|
#include "defs.h"
|
|
|
|
#include "structs.h"
|
|
|
|
|
2017-01-21 05:48:53 +01:00
|
|
|
#include "alien.h"
|
|
|
|
#include "audio.h"
|
|
|
|
#include "bullet.h"
|
|
|
|
#include "cargo.h"
|
|
|
|
#include "collectable.h"
|
|
|
|
#include "cutscene.h"
|
|
|
|
#include "engine.h"
|
|
|
|
#include "event.h"
|
|
|
|
#include "explosion.h"
|
|
|
|
#include "game.h"
|
|
|
|
#include "gfx.h"
|
|
|
|
#include "info.h"
|
|
|
|
#include "intermission.h"
|
|
|
|
#include "mission.h"
|
|
|
|
#include "player.h"
|
2016-11-23 03:16:49 +01:00
|
|
|
#include "radio.h"
|
2017-01-21 05:48:53 +01:00
|
|
|
#include "renderer.h"
|
|
|
|
#include "save.h"
|
|
|
|
#include "screen.h"
|
|
|
|
#include "ship.h"
|
|
|
|
#include "title.h"
|
|
|
|
#include "weapons.h"
|
2011-08-26 21:29:04 +02:00
|
|
|
|
2016-11-26 00:35:25 +01:00
|
|
|
typedef struct Star_ {
|
|
|
|
|
|
|
|
float x, y, dx, dy;
|
|
|
|
int speed; // How fast the star moves
|
|
|
|
|
|
|
|
} Star;
|
|
|
|
|
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
|
|
|
|
2016-11-19 14:10:25 +01:00
|
|
|
|
2015-05-21 01:41:43 +02:00
|
|
|
void game_init()
|
2011-08-24 14:14:44 +02:00
|
|
|
{
|
2016-01-05 12:44:26 +01:00
|
|
|
game.system = SYSTEM_SPIRIT;
|
2015-05-21 01:41:43 +02:00
|
|
|
game.area = MISN_START;
|
|
|
|
game.sfxVolume = 0;
|
|
|
|
game.musicVolume = 0;
|
2011-08-24 14:14:44 +02:00
|
|
|
|
|
|
|
if (!engine.useAudio)
|
|
|
|
{
|
2016-11-19 17:43:50 +01:00
|
|
|
engine.useSound = 0;
|
|
|
|
engine.useMusic = 0;
|
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);
|
|
|
|
}
|
|
|
|
|
2016-11-25 23:10:08 +01:00
|
|
|
weapons_init();
|
2016-11-25 18:29:15 +01:00
|
|
|
mission_init();
|
|
|
|
intermission_initPlanets(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)
|
2016-01-11 05:56:26 +01:00
|
|
|
audio_playSound(SFX_DEBRIS, x, y);
|
2015-04-08 01:16:46 +02:00
|
|
|
else
|
2016-01-11 05:56:26 +01:00
|
|
|
audio_playSound(SFX_DEBRIS2, x, y);
|
2015-04-08 01:16:46 +02:00
|
|
|
|
2016-11-25 18:37:26 +01:00
|
|
|
Object *debris;
|
2019-06-06 04:13:48 +02:00
|
|
|
|
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++)
|
|
|
|
{
|
2019-05-23 17:25:54 +02:00
|
|
|
debris = malloc(sizeof(*debris));
|
|
|
|
if (debris == NULL)
|
|
|
|
{
|
|
|
|
engine_warn("Failed to allocate memory for debris");
|
|
|
|
return;
|
|
|
|
}
|
2015-04-08 01:16:46 +02:00
|
|
|
|
|
|
|
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()
|
|
|
|
{
|
2016-11-25 18:37:26 +01:00
|
|
|
Collectable *collectable = engine.collectableHead;
|
|
|
|
Collectable *prevCollectable = engine.collectableHead;
|
2015-04-08 01:16:46 +02:00
|
|
|
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
|
|
|
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++;
|
2016-01-07 12:44:03 +01:00
|
|
|
if (game.difficulty == DIFFICULTY_ORIGINAL)
|
|
|
|
{
|
|
|
|
player.ammo[0] = MAX(player.ammo[0], 50);
|
2016-11-25 19:47:12 +01:00
|
|
|
weapons[W_PLAYER_WEAPON].reload[0] = MAX(
|
2016-01-07 12:44:03 +01:00
|
|
|
rate2reload[game.maxPlasmaRate],
|
2016-11-25 19:47:12 +01:00
|
|
|
weapons[W_PLAYER_WEAPON].reload[0] - 2);
|
2016-11-26 19:08:53 +01:00
|
|
|
|
|
|
|
if (weapons[W_PLAYER_WEAPON].reload[0] <= rate2reload[game.maxPlasmaRate])
|
|
|
|
sprintf(temp, "Firing rate already at maximum");
|
|
|
|
else
|
|
|
|
{
|
|
|
|
weapons[W_PLAYER_WEAPON].reload[0] -= 2;
|
|
|
|
sprintf(temp, "Firing rate increased");
|
|
|
|
}
|
2016-01-07 12:44:03 +01:00
|
|
|
}
|
|
|
|
else if ((game.area != MISN_INTERCEPTION) ||
|
|
|
|
(player.ammo[0] > 0))
|
2015-04-08 01:16:46 +02:00
|
|
|
{
|
2016-01-07 12:44:03 +01:00
|
|
|
if (game.area != MISN_INTERCEPTION)
|
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
|
|
|
|
2016-11-25 19:47:12 +01:00
|
|
|
if (weapons[W_PLAYER_WEAPON].reload[0] <= rate2reload[game.maxPlasmaRate])
|
2015-04-08 01:16:46 +02:00
|
|
|
sprintf(temp, "Firing rate already at maximum");
|
|
|
|
else
|
|
|
|
{
|
2016-11-25 19:47:12 +01:00
|
|
|
weapons[W_PLAYER_WEAPON].reload[0] -= 2;
|
2015-04-08 01:16:46 +02:00
|
|
|
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++;
|
2016-01-07 12:44:03 +01:00
|
|
|
if (game.difficulty == DIFFICULTY_ORIGINAL)
|
2015-04-08 01:16:46 +02:00
|
|
|
{
|
2016-01-07 12:44:03 +01:00
|
|
|
player.ammo[0] = MAX(player.ammo[0], 50);
|
2016-11-25 19:47:12 +01:00
|
|
|
weapons[W_PLAYER_WEAPON].ammo[0] = MIN(
|
|
|
|
game.maxPlasmaOutput, weapons[W_PLAYER_WEAPON].ammo[0] + 1);
|
2016-11-26 19:08:53 +01:00
|
|
|
|
|
|
|
if (weapons[W_PLAYER_WEAPON].ammo[0] >= game.maxPlasmaOutput)
|
|
|
|
sprintf(temp, "Plasma output already at maximum");
|
|
|
|
else
|
|
|
|
{
|
|
|
|
weapons[W_PLAYER_WEAPON].ammo[0]++;
|
|
|
|
sprintf(temp, "Plasma output increased");
|
|
|
|
}
|
2016-01-07 12:44:03 +01:00
|
|
|
}
|
|
|
|
else if ((game.area != MISN_INTERCEPTION) ||
|
|
|
|
(player.ammo[0] > 0))
|
|
|
|
{
|
|
|
|
if (game.area != MISN_INTERCEPTION)
|
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
|
|
|
|
2016-11-25 19:47:12 +01:00
|
|
|
if (weapons[W_PLAYER_WEAPON].ammo[0] >= game.maxPlasmaOutput)
|
2015-04-08 01:16:46 +02:00
|
|
|
sprintf(temp, "Plasma output already at maximum");
|
|
|
|
else
|
|
|
|
{
|
2016-11-25 19:47:12 +01:00
|
|
|
weapons[W_PLAYER_WEAPON].ammo[0]++;
|
2015-04-08 01:16:46 +02:00
|
|
|
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++;
|
2016-01-07 12:44:03 +01:00
|
|
|
if (game.difficulty == DIFFICULTY_ORIGINAL)
|
|
|
|
{
|
|
|
|
player.ammo[0] = MAX(player.ammo[0], 50);
|
2016-11-25 19:47:12 +01:00
|
|
|
weapons[W_PLAYER_WEAPON].damage = MIN(
|
|
|
|
game.maxPlasmaDamage, weapons[W_PLAYER_WEAPON].damage + 1);
|
2016-11-26 19:08:53 +01:00
|
|
|
|
|
|
|
if (weapons[W_PLAYER_WEAPON].damage >= game.maxPlasmaDamage)
|
|
|
|
sprintf(temp, "Plasma damage already at maximum");
|
|
|
|
else
|
|
|
|
{
|
|
|
|
weapons[W_PLAYER_WEAPON].damage++;
|
|
|
|
sprintf(temp, "Plasma damage increased");
|
|
|
|
}
|
2016-01-07 12:44:03 +01:00
|
|
|
}
|
|
|
|
else if ((game.area != MISN_INTERCEPTION) ||
|
|
|
|
(player.ammo[0] > 0))
|
2015-04-08 01:16:46 +02:00
|
|
|
{
|
2016-01-07 12:44:03 +01:00
|
|
|
if (game.area != MISN_INTERCEPTION)
|
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
|
|
|
|
2016-11-25 19:47:12 +01:00
|
|
|
if (weapons[W_PLAYER_WEAPON].damage >= game.maxPlasmaDamage)
|
2015-04-08 01:16:46 +02:00
|
|
|
sprintf(temp, "Plasma damage already at maximum");
|
2016-01-07 12:44:03 +01:00
|
|
|
else
|
|
|
|
{
|
2016-11-25 19:47:12 +01:00
|
|
|
weapons[W_PLAYER_WEAPON].damage++;
|
2015-04-08 01:16:46 +02:00
|
|
|
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))
|
|
|
|
{
|
2016-01-07 12:44:03 +01:00
|
|
|
if (game.difficulty == DIFFICULTY_ORIGINAL)
|
|
|
|
player.ammo[0] = MAX(player.ammo[0], 50);
|
|
|
|
else if (game.area != MISN_INTERCEPTION)
|
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
|
|
|
|
2016-11-25 19:47:12 +01:00
|
|
|
weapons[W_PLAYER_WEAPON].ammo[0] = 5;
|
|
|
|
weapons[W_PLAYER_WEAPON].damage = 5;
|
|
|
|
weapons[W_PLAYER_WEAPON].reload[0] = rate2reload[5];
|
|
|
|
weapons[W_PLAYER_WEAPON].flags |= WF_SPREAD;
|
2015-04-08 01:16:46 +02:00
|
|
|
|
2016-11-19 14:10:25 +01:00
|
|
|
sprintf(temp, "Picked up a Super Charge!");
|
2015-04-08 01:16:46 +02:00
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2016-11-25 18:29:15 +01:00
|
|
|
mission_updateRequirements(M_COLLECT, collectable->type,
|
2015-04-08 01:16:46 +02:00
|
|
|
collectable->value);
|
|
|
|
|
2016-11-19 17:43:50 +01:00
|
|
|
collectable->active = 0;
|
2015-04-08 01:16:46 +02:00
|
|
|
if (collectable->type != P_MINE)
|
|
|
|
{
|
2016-11-23 03:16:49 +01:00
|
|
|
info_setLine(temp, FONT_WHITE);
|
2015-04-08 01:16:46 +02:00
|
|
|
if (collectable->type == P_SHIELD)
|
2016-01-11 05:56:26 +01:00
|
|
|
audio_playSound(SFX_SHIELDUP, player.x, player.y);
|
2015-04-08 01:16:46 +02:00
|
|
|
else
|
2016-01-11 05:56:26 +01:00
|
|
|
audio_playSound(SFX_PICKUP, player.x, player.y);
|
2015-04-08 01:16:46 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// stop people from exploiting a weapon check condition
|
|
|
|
if (player.ammo[0] == 0)
|
|
|
|
{
|
2016-11-25 19:47:12 +01:00
|
|
|
weapons[W_PLAYER_WEAPON].ammo[0] = game.minPlasmaOutput;
|
|
|
|
weapons[W_PLAYER_WEAPON].damage = game.minPlasmaDamage;
|
|
|
|
weapons[W_PLAYER_WEAPON].reload[0] = rate2reload[game.minPlasmaRate];
|
2015-04-08 01:16:46 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (collectable->life < 1)
|
|
|
|
{
|
2016-11-19 17:43:50 +01:00
|
|
|
collectable->active = 0;
|
2015-04-08 01:16:46 +02:00
|
|
|
if ((collectable->type == P_CARGO) ||
|
|
|
|
(collectable->type == P_ESCAPEPOD) ||
|
|
|
|
(collectable->type == P_SLAVES))
|
2016-11-25 18:29:15 +01:00
|
|
|
mission_updateRequirements(M_PROTECT_PICKUP, collectable->type, 1);
|
2015-04-08 01:16:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (collectable->active)
|
|
|
|
{
|
|
|
|
prevCollectable = collectable;
|
|
|
|
engine.collectableTail = collectable;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-01-13 22:09:06 +01:00
|
|
|
if ((collectable->type == P_MINE) && (collectable->x >= 0) &&
|
|
|
|
(collectable->x <= screen->w) && (collectable->y >= 0) &&
|
|
|
|
(collectable->y <= screen->h))
|
2015-04-24 22:27:07 +02:00
|
|
|
collectable_explode(collectable);
|
2015-04-08 01:16:46 +02:00
|
|
|
prevCollectable->next = collectable->next;
|
2019-05-20 00:22:53 +02:00
|
|
|
free(collectable);
|
2015-04-08 01:16:46 +02:00
|
|
|
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()
|
|
|
|
{
|
2016-11-25 18:37:26 +01:00
|
|
|
Object *bullet = engine.bulletHead;
|
|
|
|
Object *prevBullet = engine.bulletHead;
|
2015-04-07 22:09:17 +02:00
|
|
|
|
2016-11-25 18:37:26 +01:00
|
|
|
Collectable *collectable;
|
|
|
|
Collectable *prevCollectable;
|
2015-04-07 22:09:17 +02:00
|
|
|
|
2016-11-19 17:43:50 +01:00
|
|
|
int okayToHit = 0;
|
2015-04-07 22:09:17 +02:00
|
|
|
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
|
|
|
|
2019-06-06 04:13:48 +02:00
|
|
|
char msg[STRMAX];
|
|
|
|
|
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)
|
|
|
|
{
|
Fixed more magic numbers.
God, this one was definitely the biggest headache of all of the
magic number erasing. Never did I expect such cryptic problems.
The first problem was that the entirety of the player's weapon
struct was a part of the save file, *including the weapon's "image
indexes"*. Since the indexes have been changed, and the originally
used one is now unavailable when it's requested, this was causing
a segfault later on. Had to fix this by setting the image index
when the game is loaded.
The second problem was related to another bug I've been confused
about for years: the one that causes mobile rays to fire 5 green
shots. The entire reason those shots were green was because
the weapon's image indexes were undefined, and *that was causing
them to default to 0*. 0 was simply the index of green plasma.
Of course, though, now attempting to use that image causes a
segfault, so for now, I've fixed this by changing the image index
of the mobile rays to the red plasma bolts.
There are still some magic numbers left, related to the intermission
screen. But the hardest part is now done, thank God.
2016-01-06 04:12:29 +01:00
|
|
|
explosion_add(bullet->x, bullet->y, SP_SMALL_EXPLOSION);
|
2015-04-07 22:09:17 +02:00
|
|
|
}
|
|
|
|
else if (bullet->id == WT_MICROROCKET)
|
|
|
|
{
|
Fixed more magic numbers.
God, this one was definitely the biggest headache of all of the
magic number erasing. Never did I expect such cryptic problems.
The first problem was that the entirety of the player's weapon
struct was a part of the save file, *including the weapon's "image
indexes"*. Since the indexes have been changed, and the originally
used one is now unavailable when it's requested, this was causing
a segfault later on. Had to fix this by setting the image index
when the game is loaded.
The second problem was related to another bug I've been confused
about for years: the one that causes mobile rays to fire 5 green
shots. The entire reason those shots were green was because
the weapon's image indexes were undefined, and *that was causing
them to default to 0*. 0 was simply the index of green plasma.
Of course, though, now attempting to use that image causes a
segfault, so for now, I've fixed this by changing the image index
of the mobile rays to the red plasma bolts.
There are still some magic numbers left, related to the intermission
screen. But the hardest part is now done, thank God.
2016-01-06 04:12:29 +01:00
|
|
|
explosion_add(bullet->x, bullet->y, SP_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);
|
|
|
|
|
2017-01-27 05:05:21 +01:00
|
|
|
//Rocket is (more or less) in line with target. Fly straight
|
2015-04-07 22:09:17 +02:00
|
|
|
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);
|
|
|
|
|
2017-01-27 05:05:21 +01:00
|
|
|
//Rocket is (more or less) in line with target. Fly straight
|
2015-04-07 22:09:17 +02:00
|
|
|
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;
|
|
|
|
|
2016-11-19 17:43:50 +01:00
|
|
|
okayToHit = 0;
|
2015-04-07 22:09:17 +02:00
|
|
|
|
2015-04-24 22:27:07 +02:00
|
|
|
if ((bullet->flags & WF_FRIEND) && (aliens[i].flags & FL_WEAPCO))
|
2016-11-19 17:43:50 +01:00
|
|
|
okayToHit = 1;
|
2015-04-24 22:27:07 +02:00
|
|
|
if ((bullet->flags & WF_WEAPCO) && (aliens[i].flags & FL_FRIEND))
|
2016-11-19 17:43:50 +01:00
|
|
|
okayToHit = 1;
|
2015-04-07 22:09:17 +02:00
|
|
|
if ((bullet->id == WT_ROCKET) || (bullet->id == WT_LASER) ||
|
|
|
|
(bullet->id == WT_CHARGER))
|
2016-11-19 17:43:50 +01:00
|
|
|
okayToHit = 1;
|
2015-04-07 22:09:17 +02:00
|
|
|
|
2015-04-24 22:27:07 +02:00
|
|
|
if (bullet->owner == aliens[i].owner)
|
2016-11-19 17:43:50 +01:00
|
|
|
okayToHit = 0;
|
2015-04-07 22:09:17 +02:00
|
|
|
|
|
|
|
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++;
|
2016-11-19 14:51:26 +01:00
|
|
|
if (aliens[i].classDef == CD_PHOEBE)
|
2019-06-06 04:13:48 +02:00
|
|
|
{
|
|
|
|
radio_getRandomMessage(msg, _(
|
|
|
|
/// Chris: Phoebe Hit Messages
|
|
|
|
/// This is a list of messages separated by "\n". They are randomly
|
|
|
|
/// broadcast by Phoebe when Chris (the player) damages her.
|
|
|
|
/// Instead of directly translating these, please populate the list
|
|
|
|
/// with messages that work well in the target language,
|
|
|
|
/// following the English version only as a general guideline. Any
|
|
|
|
/// number of messages is permitted.
|
|
|
|
"OW! I hope that was an accident!\n"
|
|
|
|
"Chris, please be more careful!\n"
|
|
|
|
"Ouch! What are you shooting at me for?"
|
|
|
|
));
|
|
|
|
radio_setMessage(FS_PHOEBE, msg, 0);
|
|
|
|
}
|
2016-11-19 14:51:26 +01:00
|
|
|
else if (aliens[i].classDef == CD_URSULA)
|
2019-06-06 04:13:48 +02:00
|
|
|
{
|
|
|
|
radio_getRandomMessage(msg, _(
|
|
|
|
/// Chris: Ursula Hit Messages
|
|
|
|
/// This is a list of messages separated by "\n". They are randomly
|
|
|
|
/// broadcast by Phoebe when Chris (the player) damages her.
|
|
|
|
/// Instead of directly translating these, please populate the list
|
|
|
|
/// with messages that work well in the target language,
|
|
|
|
/// following the English version only as a general guideline. Any
|
|
|
|
/// number of messages is permitted.
|
|
|
|
"I am NOT your enemy!\n"
|
|
|
|
"Hey! Watch it!\n"
|
|
|
|
"What are you doing?! Shoot THEM!\n"
|
|
|
|
"Open your eyes!\n"
|
|
|
|
"Are you blind?!"
|
|
|
|
));
|
|
|
|
radio_setMessage(FS_URSULA, msg, 0);
|
|
|
|
}
|
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)
|
|
|
|
{
|
2016-11-19 17:43:50 +01:00
|
|
|
bullet->active = 0;
|
2015-04-07 22:09:17 +02:00
|
|
|
bullet->shield = 0;
|
2016-01-11 05:56:26 +01:00
|
|
|
audio_playSound(SFX_EXPLOSION, bullet->x, bullet->y);
|
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(bullet->x + RANDRANGE(-35, 35),
|
2015-04-07 22:09:17 +02:00
|
|
|
bullet->y + RANDRANGE(-35, 35),
|
Fixed more magic numbers.
God, this one was definitely the biggest headache of all of the
magic number erasing. Never did I expect such cryptic problems.
The first problem was that the entirety of the player's weapon
struct was a part of the save file, *including the weapon's "image
indexes"*. Since the indexes have been changed, and the originally
used one is now unavailable when it's requested, this was causing
a segfault later on. Had to fix this by setting the image index
when the game is loaded.
The second problem was related to another bug I've been confused
about for years: the one that causes mobile rays to fire 5 green
shots. The entire reason those shots were green was because
the weapon's image indexes were undefined, and *that was causing
them to default to 0*. 0 was simply the index of green plasma.
Of course, though, now attempting to use that image causes a
segfault, so for now, I've fixed this by changing the image index
of the mobile rays to the red plasma bolts.
There are still some magic numbers left, related to the intermission
screen. But the hardest part is now done, thank God.
2016-01-06 04:12:29 +01:00
|
|
|
SP_BIG_EXPLOSION);
|
2015-04-07 22:09:17 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-11-19 17:43:50 +01:00
|
|
|
bullet->active = 0;
|
2015-04-07 22:09:17 +02:00
|
|
|
bullet->shield = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bullet->id == WT_ROCKET)
|
Fixed more magic numbers.
God, this one was definitely the biggest headache of all of the
magic number erasing. Never did I expect such cryptic problems.
The first problem was that the entirety of the player's weapon
struct was a part of the save file, *including the weapon's "image
indexes"*. Since the indexes have been changed, and the originally
used one is now unavailable when it's requested, this was causing
a segfault later on. Had to fix this by setting the image index
when the game is loaded.
The second problem was related to another bug I've been confused
about for years: the one that causes mobile rays to fire 5 green
shots. The entire reason those shots were green was because
the weapon's image indexes were undefined, and *that was causing
them to default to 0*. 0 was simply the index of green plasma.
Of course, though, now attempting to use that image causes a
segfault, so for now, I've fixed this by changing the image index
of the mobile rays to the red plasma bolts.
There are still some magic numbers left, related to the intermission
screen. But the hardest part is now done, thank God.
2016-01-06 04:12:29 +01:00
|
|
|
explosion_add(bullet->x, bullet->y, SP_BIG_EXPLOSION);
|
2015-04-07 22:09:17 +02:00
|
|
|
else
|
Fixed more magic numbers.
God, this one was definitely the biggest headache of all of the
magic number erasing. Never did I expect such cryptic problems.
The first problem was that the entirety of the player's weapon
struct was a part of the save file, *including the weapon's "image
indexes"*. Since the indexes have been changed, and the originally
used one is now unavailable when it's requested, this was causing
a segfault later on. Had to fix this by setting the image index
when the game is loaded.
The second problem was related to another bug I've been confused
about for years: the one that causes mobile rays to fire 5 green
shots. The entire reason those shots were green was because
the weapon's image indexes were undefined, and *that was causing
them to default to 0*. 0 was simply the index of green plasma.
Of course, though, now attempting to use that image causes a
segfault, so for now, I've fixed this by changing the image index
of the mobile rays to the red plasma bolts.
There are still some magic numbers left, related to the intermission
screen. But the hardest part is now done, thank God.
2016-01-06 04:12:29 +01:00
|
|
|
explosion_add(bullet->x, bullet->y, SP_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;
|
|
|
|
|
2019-05-11 08:15:36 +02:00
|
|
|
player_damage(bullet->damage, 0);
|
2015-04-07 22:09:17 +02:00
|
|
|
|
2016-11-19 14:24:12 +01:00
|
|
|
if (player.shield > 0)
|
|
|
|
{
|
|
|
|
if (bullet->owner->classDef == CD_PHOEBE)
|
|
|
|
{
|
2019-06-06 04:13:48 +02:00
|
|
|
radio_getRandomMessage(msg, _(
|
|
|
|
/// Phoebe: Player Hit Messages
|
|
|
|
/// This is a list of messages separated by "\n". They are randomly
|
|
|
|
/// broadcast when Phoebe accidentally damages Chris (the player).
|
|
|
|
/// Instead of directly translating these, please populate the list
|
|
|
|
/// with messages that work well in the target language,
|
|
|
|
/// following the English version only as a general guideline. Any
|
|
|
|
/// number of messages is permitted.
|
|
|
|
"Oops! Sorry!\n"
|
|
|
|
"Whoops! Are you OK, Chris?\n"
|
|
|
|
"Oh, sorry! I didn't see you there!"
|
|
|
|
));
|
|
|
|
radio_setMessage(FS_PHOEBE, msg, 0);
|
2016-11-19 14:24:12 +01:00
|
|
|
}
|
|
|
|
else if (bullet->owner->classDef == CD_URSULA)
|
|
|
|
{
|
2019-06-06 04:13:48 +02:00
|
|
|
radio_getRandomMessage(msg, _(
|
|
|
|
/// Ursula: Player Hit Messages
|
|
|
|
/// This is a list of messages separated by "\n". They are randomly
|
|
|
|
/// broadcast when Ursula accidentally damages Chris (the player).
|
|
|
|
/// Instead of directly translating these, please populate the list
|
|
|
|
/// with messages that work well in the target language,
|
|
|
|
/// following the English version only as a general guideline. Any
|
|
|
|
/// number of messages is permitted.
|
|
|
|
"Get out of the way!\n"
|
|
|
|
"Don't fly into my missiles!\n"
|
|
|
|
"Dammit, Chris, you made me miss!"
|
|
|
|
));
|
|
|
|
radio_setMessage(FS_URSULA, msg, 0);
|
2016-11-19 14:24:12 +01:00
|
|
|
}
|
|
|
|
}
|
2015-04-07 22:09:17 +02:00
|
|
|
|
|
|
|
if (bullet->id == WT_CHARGER)
|
|
|
|
{
|
|
|
|
bullet->damage -= old_shield;
|
|
|
|
if (bullet->damage <= 0)
|
|
|
|
{
|
2016-11-19 17:43:50 +01:00
|
|
|
bullet->active = 0;
|
2015-04-07 22:09:17 +02:00
|
|
|
bullet->shield = 0;
|
2016-01-11 05:56:26 +01:00
|
|
|
audio_playSound(SFX_EXPLOSION, bullet->x, bullet->y);
|
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(bullet->x + RANDRANGE(-35, 35),
|
Fixed more magic numbers.
God, this one was definitely the biggest headache of all of the
magic number erasing. Never did I expect such cryptic problems.
The first problem was that the entirety of the player's weapon
struct was a part of the save file, *including the weapon's "image
indexes"*. Since the indexes have been changed, and the originally
used one is now unavailable when it's requested, this was causing
a segfault later on. Had to fix this by setting the image index
when the game is loaded.
The second problem was related to another bug I've been confused
about for years: the one that causes mobile rays to fire 5 green
shots. The entire reason those shots were green was because
the weapon's image indexes were undefined, and *that was causing
them to default to 0*. 0 was simply the index of green plasma.
Of course, though, now attempting to use that image causes a
segfault, so for now, I've fixed this by changing the image index
of the mobile rays to the red plasma bolts.
There are still some magic numbers left, related to the intermission
screen. But the hardest part is now done, thank God.
2016-01-06 04:12:29 +01:00
|
|
|
bullet->y + RANDRANGE(-35, 35), SP_BIG_EXPLOSION);
|
2015-04-07 22:09:17 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-11-19 17:43:50 +01:00
|
|
|
bullet->active = 0;
|
2015-04-07 22:09:17 +02:00
|
|
|
bullet->shield = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bullet->id == WT_ROCKET)
|
Fixed more magic numbers.
God, this one was definitely the biggest headache of all of the
magic number erasing. Never did I expect such cryptic problems.
The first problem was that the entirety of the player's weapon
struct was a part of the save file, *including the weapon's "image
indexes"*. Since the indexes have been changed, and the originally
used one is now unavailable when it's requested, this was causing
a segfault later on. Had to fix this by setting the image index
when the game is loaded.
The second problem was related to another bug I've been confused
about for years: the one that causes mobile rays to fire 5 green
shots. The entire reason those shots were green was because
the weapon's image indexes were undefined, and *that was causing
them to default to 0*. 0 was simply the index of green plasma.
Of course, though, now attempting to use that image causes a
segfault, so for now, I've fixed this by changing the image index
of the mobile rays to the red plasma bolts.
There are still some magic numbers left, related to the intermission
screen. But the hardest part is now done, thank God.
2016-01-06 04:12:29 +01:00
|
|
|
explosion_add(bullet->x, bullet->y, SP_BIG_EXPLOSION);
|
2015-04-07 22:09:17 +02:00
|
|
|
else
|
Fixed more magic numbers.
God, this one was definitely the biggest headache of all of the
magic number erasing. Never did I expect such cryptic problems.
The first problem was that the entirety of the player's weapon
struct was a part of the save file, *including the weapon's "image
indexes"*. Since the indexes have been changed, and the originally
used one is now unavailable when it's requested, this was causing
a segfault later on. Had to fix this by setting the image index
when the game is loaded.
The second problem was related to another bug I've been confused
about for years: the one that causes mobile rays to fire 5 green
shots. The entire reason those shots were green was because
the weapon's image indexes were undefined, and *that was causing
them to default to 0*. 0 was simply the index of green plasma.
Of course, though, now attempting to use that image causes a
segfault, so for now, I've fixed this by changing the image index
of the mobile rays to the red plasma bolts.
There are still some magic numbers left, related to the intermission
screen. But the hardest part is now done, thank God.
2016-01-06 04:12:29 +01:00
|
|
|
explosion_add(bullet->x, bullet->y, SP_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
|
|
|
{
|
2016-11-19 17:43:50 +01:00
|
|
|
bullet->active = 0;
|
Fixed more magic numbers.
God, this one was definitely the biggest headache of all of the
magic number erasing. Never did I expect such cryptic problems.
The first problem was that the entirety of the player's weapon
struct was a part of the save file, *including the weapon's "image
indexes"*. Since the indexes have been changed, and the originally
used one is now unavailable when it's requested, this was causing
a segfault later on. Had to fix this by setting the image index
when the game is loaded.
The second problem was related to another bug I've been confused
about for years: the one that causes mobile rays to fire 5 green
shots. The entire reason those shots were green was because
the weapon's image indexes were undefined, and *that was causing
them to default to 0*. 0 was simply the index of green plasma.
Of course, though, now attempting to use that image causes a
segfault, so for now, I've fixed this by changing the image index
of the mobile rays to the red plasma bolts.
There are still some magic numbers left, related to the intermission
screen. But the hardest part is now done, thank God.
2016-01-06 04:12:29 +01:00
|
|
|
explosion_add(bullet->x, bullet->y, SP_SMALL_EXPLOSION);
|
2016-01-11 05:56:26 +01:00
|
|
|
audio_playSound(SFX_HIT, cargo[j].x, cargo[j].y);
|
2015-04-24 22:27:07 +02:00
|
|
|
if (cargo[j].collectType != P_PHOEBE)
|
2015-04-07 22:09:17 +02:00
|
|
|
{
|
2016-11-19 17:43:50 +01:00
|
|
|
cargo[j].active = 0;
|
2016-01-11 05:56:26 +01:00
|
|
|
audio_playSound(SFX_EXPLOSION, cargo[j].x, cargo[j].y);
|
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),
|
Fixed more magic numbers.
God, this one was definitely the biggest headache of all of the
magic number erasing. Never did I expect such cryptic problems.
The first problem was that the entirety of the player's weapon
struct was a part of the save file, *including the weapon's "image
indexes"*. Since the indexes have been changed, and the originally
used one is now unavailable when it's requested, this was causing
a segfault later on. Had to fix this by setting the image index
when the game is loaded.
The second problem was related to another bug I've been confused
about for years: the one that causes mobile rays to fire 5 green
shots. The entire reason those shots were green was because
the weapon's image indexes were undefined, and *that was causing
them to default to 0*. 0 was simply the index of green plasma.
Of course, though, now attempting to use that image causes a
segfault, so for now, I've fixed this by changing the image index
of the mobile rays to the red plasma bolts.
There are still some magic numbers left, related to the intermission
screen. But the hardest part is now done, thank God.
2016-01-06 04:12:29 +01:00
|
|
|
SP_BIG_EXPLOSION);
|
2016-11-25 18:29:15 +01:00
|
|
|
mission_updateRequirements(M_PROTECT_PICKUP,
|
2015-04-07 22:09:17 +02:00
|
|
|
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
|
|
|
{
|
2016-11-19 17:43:50 +01:00
|
|
|
collectable->active = 0;
|
2019-06-06 04:13:48 +02:00
|
|
|
|
2015-04-24 22:27:07 +02:00
|
|
|
if (bullet->id != WT_CHARGER)
|
|
|
|
{
|
2016-11-19 17:43:50 +01:00
|
|
|
bullet->active = 0;
|
2015-04-24 22:27:07 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
bullet->shield--;
|
|
|
|
if (bullet->shield < 0)
|
2016-11-19 17:43:50 +01:00
|
|
|
bullet->active = 0;
|
2015-04-24 22:27:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
2019-05-20 00:22:53 +02:00
|
|
|
free(collectable);
|
2015-04-24 22:27:07 +02:00
|
|
|
collectable = prevCollectable;
|
|
|
|
}
|
|
|
|
}
|
2015-04-07 22:09:17 +02:00
|
|
|
|
|
|
|
bullet->shield--;
|
|
|
|
|
|
|
|
if (bullet->shield < 1)
|
|
|
|
{
|
|
|
|
if (bullet->flags & WF_TIMEDEXPLOSION)
|
|
|
|
{
|
2016-01-11 05:56:26 +01:00
|
|
|
audio_playSound(SFX_EXPLOSION, bullet->x, bullet->y);
|
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(bullet->x + RANDRANGE(-35, 35),
|
Fixed more magic numbers.
God, this one was definitely the biggest headache of all of the
magic number erasing. Never did I expect such cryptic problems.
The first problem was that the entirety of the player's weapon
struct was a part of the save file, *including the weapon's "image
indexes"*. Since the indexes have been changed, and the originally
used one is now unavailable when it's requested, this was causing
a segfault later on. Had to fix this by setting the image index
when the game is loaded.
The second problem was related to another bug I've been confused
about for years: the one that causes mobile rays to fire 5 green
shots. The entire reason those shots were green was because
the weapon's image indexes were undefined, and *that was causing
them to default to 0*. 0 was simply the index of green plasma.
Of course, though, now attempting to use that image causes a
segfault, so for now, I've fixed this by changing the image index
of the mobile rays to the red plasma bolts.
There are still some magic numbers left, related to the intermission
screen. But the hardest part is now done, thank God.
2016-01-06 04:12:29 +01:00
|
|
|
bullet->y + RANDRANGE(-35, 35), SP_BIG_EXPLOSION);
|
2015-04-07 22:09:17 +02:00
|
|
|
|
2015-04-24 22:37:55 +02:00
|
|
|
player_checkShockDamage(bullet->x, bullet->y);
|
2015-04-07 22:09:17 +02:00
|
|
|
}
|
2016-11-19 17:43:50 +01:00
|
|
|
bullet->active = 0;
|
2015-04-07 22:09:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (bullet->active)
|
|
|
|
{
|
|
|
|
prevBullet = bullet;
|
|
|
|
engine.bulletTail = bullet;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
prevBullet->next = bullet->next;
|
2019-05-19 19:40:50 +02:00
|
|
|
free(bullet);
|
2015-04-07 22:09:17 +02:00
|
|
|
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;
|
2016-11-19 17:43:50 +01:00
|
|
|
int canFire;
|
2015-04-07 22:09:17 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-19 17:43:50 +01:00
|
|
|
canFire = 1; // The alien is allowed to fire
|
2015-04-07 22:09:17 +02:00
|
|
|
|
|
|
|
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) ||
|
2019-05-20 05:46:26 +02:00
|
|
|
(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;
|
2016-11-19 17:43:50 +01:00
|
|
|
aliens[i].active = 0;
|
2015-04-07 22:09:17 +02:00
|
|
|
|
|
|
|
if (aliens[i].classDef == CD_CLOAKFIGHTER)
|
|
|
|
{
|
2015-05-21 01:41:43 +02:00
|
|
|
game.experimentalShield = aliens[i].shield;
|
2016-11-23 03:16:49 +01:00
|
|
|
info_setLine("Experimental Fighter has fled",
|
2015-04-07 22:09:17 +02:00
|
|
|
FONT_CYAN);
|
|
|
|
}
|
|
|
|
|
|
|
|
aliens[i].shield = 0;
|
2016-11-25 18:29:15 +01:00
|
|
|
mission_updateRequirements(M_ESCAPE_TARGET,
|
2015-04-07 22:09:17 +02:00
|
|
|
aliens[i].classDef, 1);
|
2019-06-06 04:13:48 +02:00
|
|
|
|
2015-04-07 22:09:17 +02:00
|
|
|
if (aliens[i].classDef != CD_CLOAKFIGHTER)
|
2016-11-25 18:29:15 +01:00
|
|
|
mission_updateRequirements(M_DESTROY_TARGET_TYPE,
|
2015-04-07 22:09:17 +02:00
|
|
|
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;
|
2016-01-11 05:56:26 +01:00
|
|
|
audio_playSound(SFX_CLOAK, aliens[i].x, aliens[i].y);
|
2015-04-07 22:09:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2019-05-27 01:49:28 +02:00
|
|
|
if ((aliens[i].classDef == CD_MOBILESHIELD) &&
|
|
|
|
(aliens[ALIEN_BOSS].active) &&
|
|
|
|
(aliens[ALIEN_BOSS].shield > 0))
|
2015-04-07 22:09:17 +02:00
|
|
|
{
|
|
|
|
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)) &&
|
2019-05-27 01:49:28 +02:00
|
|
|
(!(aliens[i].flags & FL_NOFIRE)))
|
2015-04-07 22:09:17 +02:00
|
|
|
{
|
|
|
|
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
|
|
|
|
{
|
2016-11-19 17:43:50 +01:00
|
|
|
canFire = 0;
|
2015-04-07 22:09:17 +02:00
|
|
|
}
|
|
|
|
|
2015-05-21 01:41:43 +02:00
|
|
|
if (canFire)
|
2015-04-07 22:09:17 +02:00
|
|
|
{
|
2016-01-08 01:01:25 +01:00
|
|
|
for (int j = 0 ; j < 2 ; j++)
|
2015-04-07 22:09:17 +02:00
|
|
|
{
|
2016-01-08 01:01:25 +01:00
|
|
|
if ((aliens[i].reload[j] == 0) &&
|
|
|
|
((rand() % 1000 < aliens[i].chance[j]) ||
|
|
|
|
(aliens[i].flags & FL_CONTINUOUS_FIRE)))
|
2015-04-07 22:09:17 +02:00
|
|
|
{
|
2016-01-08 01:01:25 +01:00
|
|
|
if ((aliens[i].weaponType[j] != W_ENERGYRAY) &&
|
|
|
|
(aliens[i].weaponType[j] != W_LASER))
|
|
|
|
{
|
|
|
|
if (aliens[i].weaponType[j] == W_CHARGER)
|
|
|
|
aliens[i].ammo[j] = 50 + rand() % 150;
|
|
|
|
ship_fireBullet(&aliens[i], j);
|
|
|
|
}
|
|
|
|
else if (aliens[i].weaponType[j] == W_LASER)
|
|
|
|
{
|
|
|
|
aliens[i].flags += FL_FIRELASER;
|
|
|
|
}
|
|
|
|
// XXX: This ammo check only seems to work for ammo[0],
|
|
|
|
// not ammo[1], thus necessitating using ammo[0] instead of
|
|
|
|
// ammo[j]. Should be investigated in the future.
|
|
|
|
else if ((aliens[i].weaponType[j] == W_ENERGYRAY) &&
|
|
|
|
(aliens[i].ammo[0] >= 250))
|
|
|
|
{
|
|
|
|
aliens[i].flags += FL_FIRERAY;
|
2016-01-11 05:56:26 +01:00
|
|
|
audio_playSound(SFX_ENERGYRAY, aliens[i].x, aliens[i].y);
|
2016-01-08 01:01:25 +01:00
|
|
|
}
|
2015-04-07 22:09:17 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
2016-01-04 22:34:29 +01:00
|
|
|
shapeToUse += SS_HIT_INDEX;
|
2015-04-07 22:09:17 +02:00
|
|
|
|
|
|
|
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))
|
2016-01-04 04:39:16 +01:00
|
|
|
screen_blit(gfx_shipSprites[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),
|
Fixed more magic numbers.
God, this one was definitely the biggest headache of all of the
magic number erasing. Never did I expect such cryptic problems.
The first problem was that the entirety of the player's weapon
struct was a part of the save file, *including the weapon's "image
indexes"*. Since the indexes have been changed, and the originally
used one is now unavailable when it's requested, this was causing
a segfault later on. Had to fix this by setting the image index
when the game is loaded.
The second problem was related to another bug I've been confused
about for years: the one that causes mobile rays to fire 5 green
shots. The entire reason those shots were green was because
the weapon's image indexes were undefined, and *that was causing
them to default to 0*. 0 was simply the index of green plasma.
Of course, though, now attempting to use that image causes a
segfault, so for now, I've fixed this by changing the image index
of the mobile rays to the red plasma bolts.
There are still some magic numbers left, related to the intermission
screen. But the hardest part is now done, thank God.
2016-01-06 04:12:29 +01:00
|
|
|
SP_ELECTRICAL);
|
2015-04-07 22:09:17 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-21 01:41:43 +02:00
|
|
|
if ((game.area == MISN_MARS) && (aliens[i].x < -60))
|
2016-11-19 17:43:50 +01:00
|
|
|
aliens[i].active = 0;
|
2015-04-07 22:09:17 +02:00
|
|
|
}
|
|
|
|
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),
|
Fixed more magic numbers.
God, this one was definitely the biggest headache of all of the
magic number erasing. Never did I expect such cryptic problems.
The first problem was that the entirety of the player's weapon
struct was a part of the save file, *including the weapon's "image
indexes"*. Since the indexes have been changed, and the originally
used one is now unavailable when it's requested, this was causing
a segfault later on. Had to fix this by setting the image index
when the game is loaded.
The second problem was related to another bug I've been confused
about for years: the one that causes mobile rays to fire 5 green
shots. The entire reason those shots were green was because
the weapon's image indexes were undefined, and *that was causing
them to default to 0*. 0 was simply the index of green plasma.
Of course, though, now attempting to use that image causes a
segfault, so for now, I've fixed this by changing the image index
of the mobile rays to the red plasma bolts.
There are still some magic numbers left, related to the intermission
screen. But the hardest part is now done, thank God.
2016-01-06 04:12:29 +01:00
|
|
|
SP_BIG_EXPLOSION);
|
2015-04-07 22:09:17 +02:00
|
|
|
}
|
|
|
|
if (aliens[i].shield < aliens[i].deathCounter)
|
|
|
|
{
|
2016-11-19 17:43:50 +01:00
|
|
|
aliens[i].active = 0;
|
2015-04-07 22:09:17 +02:00
|
|
|
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
|
|
|
{
|
2019-06-06 04:13:48 +02:00
|
|
|
int shapeToUse;
|
|
|
|
float cd;
|
|
|
|
float cc;
|
|
|
|
int xmoved = 0;
|
|
|
|
int ymoved = 0;
|
|
|
|
char msg[STRMAX];
|
|
|
|
|
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
|
|
|
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)
|
2016-11-25 20:20:36 +01:00
|
|
|
player.ammo[1] += 1;
|
2015-05-20 16:39:30 +02:00
|
|
|
|
2015-04-08 01:16:46 +02:00
|
|
|
if (player.ammo[1] >= 100)
|
|
|
|
{
|
|
|
|
player.ammo[1] = 200;
|
2016-11-23 03:16:49 +01:00
|
|
|
info_setLine("Laser Overheat!", FONT_WHITE);
|
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.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
|
|
|
|
{
|
2016-01-07 11:36:49 +01:00
|
|
|
LIMIT_ADD(player.ammo[1], 1, 0, 150);
|
|
|
|
if (player.ammo[1] >= 150)
|
2015-04-08 01:16:46 +02:00
|
|
|
{
|
2016-01-07 11:36:49 +01:00
|
|
|
ship_fireBullet(&player, 1);
|
|
|
|
player.ammo[1] = 0;
|
2016-11-19 17:43:50 +01:00
|
|
|
player_chargerFired = 1;
|
2015-04-08 01:16:46 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (player.ammo[1] > 0)
|
|
|
|
ship_fireBullet(&player, 1);
|
|
|
|
player.ammo[1] = 0;
|
2016-11-19 17:43:50 +01:00
|
|
|
player_chargerFired = 0;
|
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 ((engine.keyState[KEY_SWITCH]))
|
2015-03-07 05:18:31 +01:00
|
|
|
{
|
2016-11-25 19:47:12 +01:00
|
|
|
if ((weapons[W_PLAYER_WEAPON].ammo[0] >= 3) &&
|
|
|
|
(weapons[W_PLAYER_WEAPON].ammo[0] <= game.maxPlasmaOutput))
|
2015-04-08 01:16:46 +02:00
|
|
|
{
|
2016-11-25 19:47:12 +01:00
|
|
|
weapons[W_PLAYER_WEAPON].flags ^= WF_SPREAD;
|
2015-03-07 05:18:31 +01:00
|
|
|
|
2016-11-25 19:47:12 +01:00
|
|
|
if (weapons[W_PLAYER_WEAPON].flags & WF_SPREAD)
|
2015-04-08 01:16:46 +02:00
|
|
|
{
|
2016-11-23 03:16:49 +01:00
|
|
|
info_setLine("Weapon set to Spread", FONT_WHITE);
|
2015-04-08 01:16:46 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-11-23 03:16:49 +01:00
|
|
|
info_setLine("Weapon set to Concentrate", FONT_WHITE);
|
2015-04-08 01:16:46 +02:00
|
|
|
}
|
|
|
|
}
|
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;
|
2016-11-19 14:10:25 +01:00
|
|
|
ymoved = 1;
|
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;
|
2016-11-19 14:10:25 +01:00
|
|
|
ymoved = 1;
|
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;
|
2016-11-19 14:10:25 +01:00
|
|
|
xmoved = 1;
|
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;
|
2016-11-19 14:10:25 +01:00
|
|
|
xmoved = 1;
|
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) &&
|
2016-11-25 18:53:53 +01:00
|
|
|
(mission.remainingObjectives1 == 0))
|
2015-04-08 01:16:46 +02:00
|
|
|
{
|
2016-01-11 05:56:26 +01:00
|
|
|
audio_playSound(SFX_FLY, screen->w / 2, screen->h / 2);
|
2015-04-08 01:16:46 +02:00
|
|
|
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
|
|
|
{
|
2016-11-19 17:43:50 +01:00
|
|
|
engine.paused = 1;
|
2015-04-08 01:16:46 +02:00
|
|
|
engine.keyState[KEY_PAUSE] = 0;
|
2015-03-07 05:18:31 +01:00
|
|
|
}
|
|
|
|
|
2016-01-08 22:56:07 +01:00
|
|
|
if ((game.area == MISN_ELLESH) ||
|
2015-05-21 01:41:43 +02:00
|
|
|
(game.area == MISN_MARS))
|
2015-04-08 01:16:46 +02:00
|
|
|
{
|
|
|
|
player.face = 0;
|
2016-11-19 14:10:25 +01:00
|
|
|
xmoved = 1;
|
|
|
|
ymoved = 1;
|
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 (engine.done == 0)
|
2015-03-07 05:18:31 +01:00
|
|
|
{
|
2019-05-30 03:08:54 +02:00
|
|
|
if (game.difficulty == DIFFICULTY_ORIGINAL)
|
|
|
|
{
|
|
|
|
LIMIT(player.x, X_VIEW_BORDER, screen->w - X_VIEW_BORDER);
|
|
|
|
LIMIT(player.y, Y_VIEW_BORDER, screen->h - Y_VIEW_BORDER);
|
|
|
|
}
|
|
|
|
else
|
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
|
|
|
{
|
2019-05-21 07:51:39 +02:00
|
|
|
if (player.x < X_VIEW_BORDER)
|
2015-05-20 16:27:21 +02:00
|
|
|
{
|
2019-05-21 07:51:39 +02:00
|
|
|
engine.smx += X_VIEW_BORDER - player.x;
|
|
|
|
player.x = X_VIEW_BORDER;
|
2015-05-20 16:27:21 +02:00
|
|
|
}
|
2019-05-21 07:51:39 +02:00
|
|
|
else if (player.x > screen->w - X_VIEW_BORDER)
|
2015-05-20 16:27:21 +02:00
|
|
|
{
|
2019-05-21 07:51:39 +02:00
|
|
|
engine.smx += (screen->w - X_VIEW_BORDER) - player.x;
|
|
|
|
player.x = screen->w - X_VIEW_BORDER;
|
2015-05-20 16:27:21 +02:00
|
|
|
}
|
2015-04-08 01:16:46 +02:00
|
|
|
}
|
2019-05-30 02:58:12 +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)
|
|
|
|
{
|
2019-05-21 07:51:39 +02:00
|
|
|
cc = MAX(cd / 10, MAX(0, engine.ssx) - CAMERA_MAX_SPEED);
|
2015-05-20 16:27:21 +02:00
|
|
|
player.x -= cc;
|
|
|
|
engine.smx -= cc;
|
|
|
|
}
|
|
|
|
else if (cd > 0)
|
|
|
|
{
|
2019-05-21 07:51:39 +02:00
|
|
|
cc = MIN(cd / 10, CAMERA_MAX_SPEED + MIN(0, engine.ssx));
|
2015-05-20 16:27:21 +02:00
|
|
|
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
|
|
|
{
|
2019-05-21 07:51:39 +02:00
|
|
|
if (player.y < Y_VIEW_BORDER)
|
2015-05-20 16:27:21 +02:00
|
|
|
{
|
2019-05-21 07:51:39 +02:00
|
|
|
engine.smy += Y_VIEW_BORDER - player.y;
|
|
|
|
player.y = Y_VIEW_BORDER;
|
2015-05-20 16:27:21 +02:00
|
|
|
}
|
2019-05-21 07:51:39 +02:00
|
|
|
else if (player.y > screen->h - Y_VIEW_BORDER)
|
2015-05-20 16:27:21 +02:00
|
|
|
{
|
2019-05-21 07:51:39 +02:00
|
|
|
engine.smy += (screen->h - Y_VIEW_BORDER) - player.y;
|
|
|
|
player.y = screen->h - Y_VIEW_BORDER;
|
2015-05-20 16:27:21 +02:00
|
|
|
}
|
2015-04-08 01:16:46 +02:00
|
|
|
}
|
2019-05-30 02:58:12 +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)
|
|
|
|
{
|
2019-05-21 07:51:39 +02:00
|
|
|
cc = MAX(cd / 10, MAX(0, engine.ssy) - CAMERA_MAX_SPEED);
|
2015-05-20 16:27:21 +02:00
|
|
|
player.y -= cc;
|
|
|
|
engine.smy -= cc;
|
|
|
|
}
|
|
|
|
else if (cd > 0)
|
|
|
|
{
|
2019-05-21 07:51:39 +02:00
|
|
|
cc = MIN(cd / 10, CAMERA_MAX_SPEED + MIN(0, engine.ssy));
|
2015-05-20 16:27:21 +02:00
|
|
|
player.y -= cc;
|
|
|
|
engine.smy -= cc;
|
|
|
|
}
|
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)
|
2016-01-04 22:34:29 +01:00
|
|
|
shapeToUse += SS_HIT_INDEX;
|
2015-04-08 01:16:46 +02:00
|
|
|
|
|
|
|
LIMIT_ADD(player.hit, -1, 0, 100);
|
|
|
|
|
2016-01-04 04:39:16 +01:00
|
|
|
screen_blit(gfx_shipSprites[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),
|
Fixed more magic numbers.
God, this one was definitely the biggest headache of all of the
magic number erasing. Never did I expect such cryptic problems.
The first problem was that the entirety of the player's weapon
struct was a part of the save file, *including the weapon's "image
indexes"*. Since the indexes have been changed, and the originally
used one is now unavailable when it's requested, this was causing
a segfault later on. Had to fix this by setting the image index
when the game is loaded.
The second problem was related to another bug I've been confused
about for years: the one that causes mobile rays to fire 5 green
shots. The entire reason those shots were green was because
the weapon's image indexes were undefined, and *that was causing
them to default to 0*. 0 was simply the index of green plasma.
Of course, though, now attempting to use that image causes a
segfault, so for now, I've fixed this by changing the image index
of the mobile rays to the red plasma bolts.
There are still some magic numbers left, related to the intermission
screen. But the hardest part is now done, thank God.
2016-01-06 04:12:29 +01:00
|
|
|
player.y + RANDRANGE(-10, 20), SP_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
|
|
|
{
|
2019-05-11 03:09:34 +02:00
|
|
|
// Player is dead. At this point, the shield counts down to
|
|
|
|
// -100 and does death and explosion stuff along the way.
|
2016-11-19 17:43:50 +01:00
|
|
|
player.active = 0;
|
2015-04-08 01:16:46 +02:00
|
|
|
player.shield--;
|
|
|
|
if (player.shield == -1)
|
2015-03-07 05:18:31 +01:00
|
|
|
{
|
2016-11-19 14:10:25 +01:00
|
|
|
if (aliens[ALIEN_KLINE].active)
|
|
|
|
{
|
|
|
|
if (game.area == MISN_VENUS)
|
2019-06-06 04:13:48 +02:00
|
|
|
{
|
|
|
|
radio_getRandomMessage(msg, _(
|
|
|
|
/// Kline Venus insult messages
|
|
|
|
/// This is a list of insults separated by "\n". They are randomly
|
|
|
|
/// broadcast when the player dies in the Venus mission.
|
|
|
|
/// Instead of directly translating these, please populate the list
|
|
|
|
/// with insults that work well in the target language,
|
|
|
|
/// following the English version only as a general guideline. Any
|
|
|
|
/// number of insults is permitted.
|
|
|
|
"Fool.\n"
|
|
|
|
"And now you're nothing but a DEAD hero.\n"
|
|
|
|
));
|
|
|
|
radio_setMessage(FS_KLINE, msg, 1);
|
|
|
|
}
|
2016-11-19 14:10:25 +01:00
|
|
|
else
|
2019-06-06 04:13:48 +02:00
|
|
|
{
|
|
|
|
radio_getRandomMessage(msg, _(
|
|
|
|
/// Kline insult messages
|
|
|
|
/// This is a list of insults separated by "\n". They are randomly
|
|
|
|
/// broadcast when the player dies in a mission Kline is in (except Venus).
|
|
|
|
/// Instead of directly translating these, please populate the list
|
|
|
|
/// with insults that work well in the target language,
|
|
|
|
/// following the English version only as a general guideline. Any
|
|
|
|
/// number of insults is permitted.
|
|
|
|
"Pathetic.\n"
|
|
|
|
"How very disappointing...\n"
|
|
|
|
"Heroic. And stupid."
|
|
|
|
));
|
|
|
|
radio_setMessage(FS_KLINE, msg, 1);
|
|
|
|
}
|
2016-11-19 14:10:25 +01:00
|
|
|
}
|
|
|
|
else if ((aliens[ALIEN_BOSS].active) && (aliens[ALIEN_BOSS].classDef == CD_KRASS))
|
|
|
|
{
|
2019-06-06 04:13:48 +02:00
|
|
|
/// Dialog: Krass Tyler
|
|
|
|
/// Used when the player is killed in the Jupiter mission.
|
|
|
|
radio_setMessage(FS_KRASS, _("That was the easiest $90,000,000 I've ever earned! Bwah! Ha! Ha! Ha!"), 1);
|
2016-11-19 14:10:25 +01:00
|
|
|
}
|
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
|
|
|
|
2016-01-11 05:56:26 +01:00
|
|
|
audio_playSound(SFX_DEATH, player.x, player.y);
|
|
|
|
audio_playSound(SFX_EXPLOSION, player.x, player.y);
|
2015-04-08 01:16:46 +02:00
|
|
|
}
|
|
|
|
|
2019-05-30 17:32:50 +02:00
|
|
|
engine.keyState[KEY_UP] = 0;
|
|
|
|
engine.keyState[KEY_DOWN] = 0;
|
|
|
|
engine.keyState[KEY_LEFT] = 0;
|
|
|
|
engine.keyState[KEY_RIGHT] = 0;
|
2016-01-07 02:49:02 +01:00
|
|
|
if (CHANCE(1. / 3.))
|
2015-05-01 00:51:26 +02:00
|
|
|
explosion_add(player.x + RANDRANGE(-10, 10),
|
Fixed more magic numbers.
God, this one was definitely the biggest headache of all of the
magic number erasing. Never did I expect such cryptic problems.
The first problem was that the entirety of the player's weapon
struct was a part of the save file, *including the weapon's "image
indexes"*. Since the indexes have been changed, and the originally
used one is now unavailable when it's requested, this was causing
a segfault later on. Had to fix this by setting the image index
when the game is loaded.
The second problem was related to another bug I've been confused
about for years: the one that causes mobile rays to fire 5 green
shots. The entire reason those shots were green was because
the weapon's image indexes were undefined, and *that was causing
them to default to 0*. 0 was simply the index of green plasma.
Of course, though, now attempting to use that image causes a
segfault, so for now, I've fixed this by changing the image index
of the mobile rays to the red plasma bolts.
There are still some magic numbers left, related to the intermission
screen. But the hardest part is now done, thank God.
2016-01-06 04:12:29 +01:00
|
|
|
player.y + RANDRANGE(-10, 10), SP_BIG_EXPLOSION);
|
2015-04-08 01:16:46 +02:00
|
|
|
if (player.shield == -99)
|
|
|
|
game_addDebris((int)player.x, (int)player.y, player.maxShield);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-21 07:51:39 +02:00
|
|
|
LIMIT(engine.ssx, -CAMERA_MAX_SPEED, CAMERA_MAX_SPEED);
|
|
|
|
LIMIT(engine.ssy, -CAMERA_MAX_SPEED, CAMERA_MAX_SPEED);
|
2015-04-08 01:16:46 +02:00
|
|
|
|
|
|
|
// Specific for the mission were you have to chase the Executive Transport
|
2016-01-08 22:56:07 +01:00
|
|
|
if (((game.area == MISN_ELLESH) && (player.shield > 0)) ||
|
|
|
|
(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++)
|
|
|
|
{
|
Fixed more magic numbers.
God, this one was definitely the biggest headache of all of the
magic number erasing. Never did I expect such cryptic problems.
The first problem was that the entirety of the player's weapon
struct was a part of the save file, *including the weapon's "image
indexes"*. Since the indexes have been changed, and the originally
used one is now unavailable when it's requested, this was causing
a segfault later on. Had to fix this by setting the image index
when the game is loaded.
The second problem was related to another bug I've been confused
about for years: the one that causes mobile rays to fire 5 green
shots. The entire reason those shots were green was because
the weapon's image indexes were undefined, and *that was causing
them to default to 0*. 0 was simply the index of green plasma.
Of course, though, now attempting to use that image causes a
segfault, so for now, I've fixed this by changing the image index
of the mobile rays to the red plasma bolts.
There are still some magic numbers left, related to the intermission
screen. But the hardest part is now done, thank God.
2016-01-06 04:12:29 +01:00
|
|
|
screen_blit(gfx_sprites[SP_CHAIN_LINK], (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()
|
|
|
|
{
|
2016-11-25 18:37:26 +01:00
|
|
|
Object *prevDebris = engine.debrisHead;
|
|
|
|
Object *debris = engine.debrisHead;
|
2015-04-08 01:16:46 +02:00
|
|
|
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
|
|
|
|
Fixed more magic numbers.
God, this one was definitely the biggest headache of all of the
magic number erasing. Never did I expect such cryptic problems.
The first problem was that the entirety of the player's weapon
struct was a part of the save file, *including the weapon's "image
indexes"*. Since the indexes have been changed, and the originally
used one is now unavailable when it's requested, this was causing
a segfault later on. Had to fix this by setting the image index
when the game is loaded.
The second problem was related to another bug I've been confused
about for years: the one that causes mobile rays to fire 5 green
shots. The entire reason those shots were green was because
the weapon's image indexes were undefined, and *that was causing
them to default to 0*. 0 was simply the index of green plasma.
Of course, though, now attempting to use that image causes a
segfault, so for now, I've fixed this by changing the image index
of the mobile rays to the red plasma bolts.
There are still some magic numbers left, related to the intermission
screen. But the hardest part is now done, thank God.
2016-01-06 04:12:29 +01:00
|
|
|
explosion_add(debris->x + RANDRANGE(-10, 10), debris->y + RANDRANGE(-10, 10), SP_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;
|
2019-05-20 00:22:53 +02:00
|
|
|
free(debris);
|
2015-04-08 01:16:46 +02:00
|
|
|
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()
|
|
|
|
{
|
2016-11-25 18:37:26 +01:00
|
|
|
Object *prevExplosion = engine.explosionHead;
|
|
|
|
Object *explosion = engine.explosionHead;
|
2015-05-01 00:51:26 +02:00
|
|
|
engine.explosionTail = engine.explosionHead;
|
2019-06-06 04:13:48 +02:00
|
|
|
|
2015-05-01 00:51:26 +02:00
|
|
|
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
|
|
|
|
Fixed more magic numbers.
God, this one was definitely the biggest headache of all of the
magic number erasing. Never did I expect such cryptic problems.
The first problem was that the entirety of the player's weapon
struct was a part of the save file, *including the weapon's "image
indexes"*. Since the indexes have been changed, and the originally
used one is now unavailable when it's requested, this was causing
a segfault later on. Had to fix this by setting the image index
when the game is loaded.
The second problem was related to another bug I've been confused
about for years: the one that causes mobile rays to fire 5 green
shots. The entire reason those shots were green was because
the weapon's image indexes were undefined, and *that was causing
them to default to 0*. 0 was simply the index of green plasma.
Of course, though, now attempting to use that image causes a
segfault, so for now, I've fixed this by changing the image index
of the mobile rays to the red plasma bolts.
There are still some magic numbers left, related to the intermission
screen. But the hardest part is now done, thank God.
2016-01-06 04:12:29 +01:00
|
|
|
if(CHANCE(1. / 7.))
|
2015-05-01 00:51:26 +02:00
|
|
|
{
|
|
|
|
explosion->thinktime -= 7;
|
|
|
|
|
|
|
|
if(explosion->thinktime < 1)
|
|
|
|
{
|
2016-11-19 17:43:50 +01:00
|
|
|
explosion->active = 0;
|
2015-05-01 00:51:26 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
explosion->face++;
|
2016-01-04 04:39:16 +01:00
|
|
|
explosion->image[0] = gfx_sprites[explosion->face];
|
2015-05-01 00:51:26 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (explosion->active)
|
|
|
|
{
|
|
|
|
prevExplosion = explosion;
|
|
|
|
engine.explosionTail = explosion;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
prevExplosion->next = explosion->next;
|
2019-05-20 00:22:53 +02:00
|
|
|
free(explosion);
|
2015-05-01 00:51:26 +02:00
|
|
|
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)
|
|
|
|
{
|
2016-01-08 15:12:07 +01:00
|
|
|
int arrow = -1;
|
|
|
|
int arrowX;
|
|
|
|
int arrowY;
|
2015-05-28 12:51:45 +02:00
|
|
|
|
2016-01-08 15:12:07 +01:00
|
|
|
int indicator = -1;
|
|
|
|
int indicatorX;
|
|
|
|
int indicatorY;
|
2015-05-28 12:51:45 +02:00
|
|
|
|
2016-01-08 15:12:07 +01:00
|
|
|
if (i < 0 || !aliens[i].active || aliens[i].shield <= 0 || aliens[i].flags & FL_ISCLOAKED)
|
2015-05-28 12:51:45 +02:00
|
|
|
return;
|
|
|
|
|
2016-01-08 15:12:07 +01:00
|
|
|
if (aliens[i].x + aliens[i].image[0]->w < 0)
|
Fixed more magic numbers.
God, this one was definitely the biggest headache of all of the
magic number erasing. Never did I expect such cryptic problems.
The first problem was that the entirety of the player's weapon
struct was a part of the save file, *including the weapon's "image
indexes"*. Since the indexes have been changed, and the originally
used one is now unavailable when it's requested, this was causing
a segfault later on. Had to fix this by setting the image index
when the game is loaded.
The second problem was related to another bug I've been confused
about for years: the one that causes mobile rays to fire 5 green
shots. The entire reason those shots were green was because
the weapon's image indexes were undefined, and *that was causing
them to default to 0*. 0 was simply the index of green plasma.
Of course, though, now attempting to use that image causes a
segfault, so for now, I've fixed this by changing the image index
of the mobile rays to the red plasma bolts.
There are still some magic numbers left, related to the intermission
screen. But the hardest part is now done, thank God.
2016-01-06 04:12:29 +01:00
|
|
|
{
|
2016-01-08 15:12:07 +01:00
|
|
|
if (aliens[i].y + aliens[i].image[0]->h < 0)
|
2019-05-27 01:41:31 +02:00
|
|
|
arrow = (((game.difficulty != DIFFICULTY_ORIGINAL) &&
|
|
|
|
(aliens[i].flags & FL_FRIEND)) ?
|
|
|
|
SP_ARROW_FRIEND_NORTHWEST : SP_ARROW_NORTHWEST);
|
2016-01-08 15:12:07 +01:00
|
|
|
else if (aliens[i].y > screen->h)
|
2019-05-27 01:41:31 +02:00
|
|
|
arrow = (((game.difficulty != DIFFICULTY_ORIGINAL) &&
|
|
|
|
(aliens[i].flags & FL_FRIEND)) ?
|
|
|
|
SP_ARROW_FRIEND_SOUTHWEST : SP_ARROW_SOUTHWEST);
|
2016-01-08 15:12:07 +01:00
|
|
|
else
|
2019-05-27 01:41:31 +02:00
|
|
|
arrow = (((game.difficulty != DIFFICULTY_ORIGINAL) &&
|
|
|
|
(aliens[i].flags & FL_FRIEND)) ?
|
|
|
|
SP_ARROW_FRIEND_WEST : SP_ARROW_WEST);
|
Fixed more magic numbers.
God, this one was definitely the biggest headache of all of the
magic number erasing. Never did I expect such cryptic problems.
The first problem was that the entirety of the player's weapon
struct was a part of the save file, *including the weapon's "image
indexes"*. Since the indexes have been changed, and the originally
used one is now unavailable when it's requested, this was causing
a segfault later on. Had to fix this by setting the image index
when the game is loaded.
The second problem was related to another bug I've been confused
about for years: the one that causes mobile rays to fire 5 green
shots. The entire reason those shots were green was because
the weapon's image indexes were undefined, and *that was causing
them to default to 0*. 0 was simply the index of green plasma.
Of course, though, now attempting to use that image causes a
segfault, so for now, I've fixed this by changing the image index
of the mobile rays to the red plasma bolts.
There are still some magic numbers left, related to the intermission
screen. But the hardest part is now done, thank God.
2016-01-06 04:12:29 +01:00
|
|
|
}
|
2016-01-08 15:12:07 +01:00
|
|
|
else if (aliens[i].x > screen->w)
|
Fixed more magic numbers.
God, this one was definitely the biggest headache of all of the
magic number erasing. Never did I expect such cryptic problems.
The first problem was that the entirety of the player's weapon
struct was a part of the save file, *including the weapon's "image
indexes"*. Since the indexes have been changed, and the originally
used one is now unavailable when it's requested, this was causing
a segfault later on. Had to fix this by setting the image index
when the game is loaded.
The second problem was related to another bug I've been confused
about for years: the one that causes mobile rays to fire 5 green
shots. The entire reason those shots were green was because
the weapon's image indexes were undefined, and *that was causing
them to default to 0*. 0 was simply the index of green plasma.
Of course, though, now attempting to use that image causes a
segfault, so for now, I've fixed this by changing the image index
of the mobile rays to the red plasma bolts.
There are still some magic numbers left, related to the intermission
screen. But the hardest part is now done, thank God.
2016-01-06 04:12:29 +01:00
|
|
|
{
|
2016-01-08 15:12:07 +01:00
|
|
|
if (aliens[i].y + aliens[i].image[0]->h < 0)
|
2019-05-27 01:41:31 +02:00
|
|
|
arrow = (((game.difficulty != DIFFICULTY_ORIGINAL) &&
|
|
|
|
(aliens[i].flags & FL_FRIEND)) ?
|
|
|
|
SP_ARROW_FRIEND_NORTHEAST : SP_ARROW_NORTHEAST);
|
2016-01-08 15:12:07 +01:00
|
|
|
else if (aliens[i].y > screen->h)
|
2019-05-27 01:41:31 +02:00
|
|
|
arrow = (((game.difficulty != DIFFICULTY_ORIGINAL) &&
|
|
|
|
(aliens[i].flags & FL_FRIEND)) ?
|
|
|
|
SP_ARROW_FRIEND_SOUTHEAST : SP_ARROW_SOUTHEAST);
|
2016-01-08 15:12:07 +01:00
|
|
|
else
|
2019-05-27 01:41:31 +02:00
|
|
|
arrow = (((game.difficulty != DIFFICULTY_ORIGINAL) &&
|
|
|
|
(aliens[i].flags & FL_FRIEND)) ?
|
|
|
|
SP_ARROW_FRIEND_EAST : SP_ARROW_EAST);
|
2015-05-28 12:51:45 +02:00
|
|
|
}
|
2016-01-08 15:12:07 +01:00
|
|
|
else if (aliens[i].y + aliens[i].image[0]->h < 0)
|
2019-05-27 01:41:31 +02:00
|
|
|
arrow = (((game.difficulty != DIFFICULTY_ORIGINAL) &&
|
|
|
|
(aliens[i].flags & FL_FRIEND)) ?
|
|
|
|
SP_ARROW_FRIEND_NORTH : SP_ARROW_NORTH);
|
2016-01-08 15:12:07 +01:00
|
|
|
else if (aliens[i].y > screen->h)
|
2019-05-27 01:41:31 +02:00
|
|
|
arrow = (((game.difficulty != DIFFICULTY_ORIGINAL) &&
|
|
|
|
(aliens[i].flags & FL_FRIEND)) ?
|
|
|
|
SP_ARROW_FRIEND_SOUTH : SP_ARROW_SOUTH);
|
2015-05-28 12:51:45 +02:00
|
|
|
|
2016-01-08 15:12:07 +01:00
|
|
|
if (arrow != -1)
|
|
|
|
{
|
2019-05-27 01:32:52 +02:00
|
|
|
if (game.difficulty == DIFFICULTY_ORIGINAL)
|
2016-01-08 15:12:07 +01:00
|
|
|
{
|
2019-05-27 01:32:52 +02:00
|
|
|
indicator = SP_INDICATOR_TARGET;
|
|
|
|
indicatorX = (screen->w / 2) - (gfx_sprites[indicator]->w / 2);
|
|
|
|
indicatorY = 120;
|
|
|
|
arrowX = indicatorX + gfx_sprites[indicator]->w / 2 - (gfx_sprites[arrow]->w / 2);
|
|
|
|
arrowY = indicatorY + gfx_sprites[indicator]->h + 5;
|
|
|
|
screen_blit(gfx_sprites[arrow], arrowX, arrowY);
|
2016-01-08 15:12:07 +01:00
|
|
|
screen_blit(gfx_sprites[indicator], indicatorX, indicatorY);
|
2019-05-27 01:32:52 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
arrowX = aliens[i].x + aliens[i].image[0]->w / 2 - gfx_sprites[arrow]->w;
|
|
|
|
arrowX = MAX(0, MIN(arrowX, screen->w - gfx_sprites[arrow]->w));
|
|
|
|
arrowY = aliens[i].y + aliens[i].image[0]->h / 2 - gfx_sprites[arrow]->h;
|
|
|
|
arrowY = MAX(0, MIN(arrowY, screen->h - gfx_sprites[arrow]->h));
|
|
|
|
screen_blit(gfx_sprites[arrow], arrowX, arrowY);
|
|
|
|
|
|
|
|
if (i == ALIEN_SID)
|
|
|
|
indicator = SP_INDICATOR_SID;
|
|
|
|
else if (i == ALIEN_PHOEBE)
|
|
|
|
indicator = SP_INDICATOR_PHOEBE;
|
|
|
|
else if (i == ALIEN_URSULA)
|
|
|
|
indicator = SP_INDICATOR_URSULA;
|
|
|
|
else if (i == ALIEN_KLINE)
|
|
|
|
indicator = SP_INDICATOR_KLINE;
|
|
|
|
else if (i == engine.targetIndex)
|
|
|
|
indicator = SP_INDICATOR_TARGET;
|
|
|
|
|
|
|
|
if (indicator != -1)
|
|
|
|
{
|
|
|
|
indicatorX = arrowX + gfx_sprites[arrow]->w / 2 - gfx_sprites[indicator]->w / 2;
|
|
|
|
indicatorX = MAX(indicatorX, gfx_sprites[arrow]->w + 5);
|
|
|
|
indicatorX = MIN(indicatorX, screen->w - gfx_sprites[arrow]->w - gfx_sprites[indicator]->w - 5);
|
|
|
|
indicatorY = arrowY + gfx_sprites[arrow]->h / 2 - gfx_sprites[indicator]->h / 2;
|
|
|
|
indicatorY = MAX(indicatorY, gfx_sprites[arrow]->h + 5);
|
|
|
|
indicatorY = MIN(indicatorY, screen->h - gfx_sprites[arrow]->h - gfx_sprites[indicator]->h - 5);
|
|
|
|
screen_blit(gfx_sprites[indicator], indicatorX, indicatorY);
|
|
|
|
}
|
2016-01-08 15:12:07 +01:00
|
|
|
}
|
2015-05-28 12:51:45 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void game_doHud()
|
|
|
|
{
|
2019-05-27 00:22:08 +02:00
|
|
|
static int last_arrow = -1;
|
2015-05-28 12:51:45 +02:00
|
|
|
int shieldColor = 0;
|
|
|
|
SDL_Rect bar;
|
2016-01-07 02:35:37 +01:00
|
|
|
int fontColor;
|
2015-05-28 12:51:45 +02:00
|
|
|
char text[25];
|
2019-05-27 00:22:08 +02:00
|
|
|
int i;
|
2015-05-28 12:51:45 +02:00
|
|
|
|
2016-01-04 02:30:54 +01:00
|
|
|
screen_addBuffer(0, 20, screen->w, 25);
|
|
|
|
screen_addBuffer(0, screen->h - 50, screen->w, 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;
|
2019-05-31 00:33:31 +02:00
|
|
|
screen_blitText(TS_TIME_T, screen->w / 2 - 140, 20);
|
2015-05-28 12:51:45 +02:00
|
|
|
sprintf(text, "%.2d:%.2d", engine.minutes, engine.seconds);
|
2019-05-31 00:33:31 +02:00
|
|
|
gfx_createTextObject(TS_TIME, text, 0, 0, fontColor);
|
|
|
|
screen_blitText(TS_TIME, screen->w / 2 + 10, 21);
|
2015-05-28 12:51:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (game.area != MISN_INTERCEPTION)
|
|
|
|
{
|
2019-05-31 00:33:31 +02:00
|
|
|
screen_blitText(TS_OBJECTIVES_T, screen->w - 250, 20);
|
2016-11-25 18:53:53 +01:00
|
|
|
sprintf(text, "%d", (mission.remainingObjectives1 + mission.remainingObjectives2));
|
2019-05-31 00:33:31 +02:00
|
|
|
gfx_createTextObject(TS_OBJECTIVES, text, 0, 0, FONT_WHITE);
|
|
|
|
screen_blitText(TS_OBJECTIVES, screen->w - 55, 21);
|
2015-05-28 12:51:45 +02:00
|
|
|
}
|
|
|
|
|
2019-05-31 00:33:31 +02:00
|
|
|
screen_blitText(TS_CASH_T, 25, 20);
|
2015-05-28 12:51:45 +02:00
|
|
|
sprintf(text, "%.6d", game.cash);
|
2019-05-31 00:33:31 +02:00
|
|
|
gfx_createTextObject(TS_CASH, text, 0, 0, FONT_WHITE);
|
|
|
|
screen_blitText(TS_CASH, 90, 21);
|
2015-05-28 12:51:45 +02:00
|
|
|
|
2019-05-27 00:22:08 +02:00
|
|
|
if (game.difficulty == DIFFICULTY_ORIGINAL)
|
|
|
|
{
|
|
|
|
i = engine.targetIndex;
|
|
|
|
if ((i >= 0) && aliens[i].active && (aliens[i].shield > 0) && (!(aliens[i].flags & FL_ISCLOAKED)))
|
|
|
|
game_doArrow(i);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
i = last_arrow;
|
|
|
|
if ((i >= 0) && aliens[i].active && (aliens[i].shield > 0) && (!(aliens[i].flags & FL_ISCLOAKED)))
|
|
|
|
game_doArrow(i);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
last_arrow = rand() % ALIEN_MAX;
|
|
|
|
if (aliens[last_arrow].flags & FL_FRIEND)
|
|
|
|
last_arrow = 0;
|
2019-06-06 04:13:48 +02:00
|
|
|
|
2019-05-27 00:22:08 +02:00
|
|
|
game_doArrow(last_arrow);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (i = 0; i < ALIEN_MAX; i++)
|
|
|
|
game_doArrow(i);
|
|
|
|
}
|
2015-05-28 12:51:45 +02:00
|
|
|
|
|
|
|
fontColor = FONT_WHITE;
|
|
|
|
if (player.ammo[0] > 0)
|
|
|
|
{
|
|
|
|
if (player.ammo[0] <= 25) fontColor = FONT_YELLOW;
|
|
|
|
if (player.ammo[0] <= 10) fontColor = FONT_RED;
|
|
|
|
}
|
2019-05-31 04:15:51 +02:00
|
|
|
screen_blitText(TS_PLASMA_T, screen->w * 5 / 16, screen->h - 50);
|
2015-05-28 12:51:45 +02:00
|
|
|
sprintf(text, "%.3d", player.ammo[0]);
|
2019-05-31 00:42:10 +02:00
|
|
|
gfx_createTextObject(TS_PLASMA, text, 0, 0, fontColor);
|
|
|
|
screen_blitText(TS_PLASMA, screen->w * 5 / 16 + 70, screen->h - 49);
|
2015-05-28 12:51:45 +02:00
|
|
|
|
2019-05-31 04:15:51 +02:00
|
|
|
screen_blitText(TS_AMMO_T, screen->w / 2, screen->h - 50);
|
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;
|
2017-02-05 20:49:43 +01:00
|
|
|
sprintf(text, "%.2d", player.ammo[1]); // rocket ammo
|
2019-05-31 00:42:10 +02:00
|
|
|
gfx_createTextObject(TS_AMMO, text, 0, 0, fontColor);
|
|
|
|
screen_blitText(TS_AMMO, screen->w / 2 + 80, screen->h - 49);
|
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;
|
|
|
|
|
2016-01-04 02:30:54 +01:00
|
|
|
bar.x = screen->w / 2 + 65;
|
|
|
|
bar.y = screen->h - 50;
|
2015-05-28 12:51:45 +02:00
|
|
|
bar.h = 12;
|
|
|
|
|
|
|
|
for (int i = 0 ; i < (player.ammo[1] / 5) ; i++)
|
|
|
|
{
|
2016-01-04 02:30:54 +01:00
|
|
|
bar.w = MAX(screen->w / 800, 1);
|
2015-05-28 12:51:45 +02:00
|
|
|
SDL_FillRect(screen, &bar, c);
|
2016-01-04 02:30:54 +01:00
|
|
|
bar.x += bar.w + (screen->w / 800);
|
2015-05-28 12:51:45 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-25 18:29:15 +01:00
|
|
|
if ((!mission_checkCompleted()) && (SDL_GetTicks() >= engine.counter2))
|
2015-05-28 12:51:45 +02:00
|
|
|
{
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2019-05-27 02:01:16 +02:00
|
|
|
if ((engine.timeMission) && (player.shield > 0) &&
|
|
|
|
((!engine.cheatTime) || (game.area == MISN_MARS)))
|
2015-05-28 12:51:45 +02:00
|
|
|
{
|
|
|
|
if (SDL_GetTicks() >= engine.counter)
|
|
|
|
{
|
|
|
|
if ((engine.seconds > 1) && (engine.seconds <= 11) && (engine.minutes == 0))
|
|
|
|
{
|
2016-01-11 05:56:26 +01:00
|
|
|
audio_playSound(SFX_CLOCK, screen->w / 2, screen->h / 2);
|
2015-05-28 12:51:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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++)
|
|
|
|
{
|
2016-11-25 18:53:53 +01:00
|
|
|
if (mission.timeLimit1[i] > -1)
|
|
|
|
mission.timeLimit1[i]--;
|
|
|
|
if (mission.timeLimit2[i] > -1)
|
|
|
|
mission.timeLimit2[i]--;
|
2015-05-28 12:51:45 +02:00
|
|
|
}
|
2016-11-25 18:29:15 +01:00
|
|
|
mission_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++)
|
|
|
|
{
|
2016-11-25 18:53:53 +01:00
|
|
|
if (mission.timeLimit1[i] > -1)
|
|
|
|
mission.timeLimit1[i]--;
|
|
|
|
if (mission.timeLimit2[i] > -1)
|
|
|
|
mission.timeLimit2[i]--;
|
2015-05-28 12:51:45 +02:00
|
|
|
}
|
2016-11-25 18:29:15 +01:00
|
|
|
mission_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
|
|
|
{
|
2016-01-04 04:39:16 +01:00
|
|
|
if (gfx_textSprites[i].life > 0)
|
2015-05-28 12:51:45 +02:00
|
|
|
{
|
2019-06-06 04:13:48 +02:00
|
|
|
screen_blitText(i, -1, screen->h - 75 - (i * MENU_SPACING));
|
2016-01-04 04:39:16 +01:00
|
|
|
gfx_textSprites[i].life--;
|
2015-05-28 12:51:45 +02:00
|
|
|
|
2016-01-04 04:39:16 +01:00
|
|
|
if (gfx_textSprites[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++)
|
|
|
|
{
|
2016-11-23 03:16:49 +01:00
|
|
|
info_copyLine(j + 1, j);
|
2015-12-31 16:47:27 +01:00
|
|
|
}
|
2016-01-04 04:39:16 +01:00
|
|
|
gfx_textSprites[MAX_INFOLINES - 1].life = 0;
|
2015-05-28 12:51:45 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Show the radio message if there is one
|
2019-05-26 23:43:14 +02:00
|
|
|
if ((gfx_textSprites[TS_RADIO].life > 0) && (gfx_messageBox != NULL))
|
2015-05-28 12:51:45 +02:00
|
|
|
{
|
2016-01-04 04:39:16 +01:00
|
|
|
screen_blit(gfx_messageBox, (screen->w - gfx_messageBox->w) / 2, 50);
|
|
|
|
gfx_textSprites[TS_RADIO].life--;
|
2015-05-28 12:51:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Do the target's remaining shield (if required)
|
|
|
|
if (game.area != MISN_DORIM)
|
|
|
|
{
|
2016-01-08 16:52:34 +01:00
|
|
|
if ((engine.targetIndex > -1) && (aliens[engine.targetIndex].shield > 0) &&
|
|
|
|
(engine.targetIndex > engine.maxAliens))
|
2015-05-28 12:51:45 +02:00
|
|
|
{
|
2019-05-27 02:18:10 +02:00
|
|
|
if (game.difficulty == DIFFICULTY_ORIGINAL)
|
|
|
|
{
|
2019-05-31 04:15:51 +02:00
|
|
|
screen_blitText(TS_TARGET, screen->w * 11 / 16, screen->h - 50);
|
2019-05-27 02:18:10 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (engine.targetIndex == ALIEN_SID)
|
2019-05-31 04:15:51 +02:00
|
|
|
screen_blitText(TS_TARGET_SID, screen->w * 11 / 16 + 27, screen->h - 50);
|
2019-05-27 02:18:10 +02:00
|
|
|
else if (engine.targetIndex == ALIEN_PHOEBE)
|
2019-05-31 04:15:51 +02:00
|
|
|
screen_blitText(TS_TARGET_PHOEBE, screen->w * 11 / 16, screen->h - 50);
|
2019-05-27 02:18:10 +02:00
|
|
|
else if (engine.targetIndex == ALIEN_KLINE)
|
2019-05-31 04:15:51 +02:00
|
|
|
screen_blitText(TS_TARGET_KLINE, screen->w * 11 / 16 + 9, screen->h - 50);
|
2019-05-27 02:18:10 +02:00
|
|
|
else
|
2019-05-31 04:15:51 +02:00
|
|
|
screen_blitText(TS_TARGET, screen->w * 11 / 16, screen->h - 50);
|
2019-05-27 02:18:10 +02:00
|
|
|
}
|
2016-01-08 16:52:34 +01:00
|
|
|
|
2016-01-04 02:30:54 +01:00
|
|
|
bar.w = MAX(screen->w / 800, 1);
|
2015-05-28 12:51:45 +02:00
|
|
|
bar.h = 12;
|
2016-01-04 02:30:54 +01:00
|
|
|
bar.x = screen->w * 11 / 16 + 65;
|
|
|
|
bar.y = screen->h - 50;
|
2015-05-28 12:51:45 +02:00
|
|
|
|
|
|
|
for (float i = 0 ; i < (engine.targetShield * aliens[engine.targetIndex].shield) ; i++)
|
|
|
|
{
|
2016-01-04 02:30:54 +01:00
|
|
|
if (i > engine.targetShield * aliens[engine.targetIndex].maxShield * 2 / 3)
|
2015-05-28 12:51:45 +02:00
|
|
|
shieldColor = green;
|
2016-01-04 02:30:54 +01:00
|
|
|
else if ((i >= engine.targetShield * aliens[engine.targetIndex].maxShield / 3) &&
|
|
|
|
(i <= engine.targetShield * aliens[engine.targetIndex].maxShield * 2 / 3))
|
2015-05-28 12:51:45 +02:00
|
|
|
shieldColor = yellow;
|
|
|
|
else
|
|
|
|
shieldColor = red;
|
|
|
|
SDL_FillRect(screen, &bar, shieldColor);
|
2016-01-04 02:30:54 +01:00
|
|
|
bar.x += bar.w + (screen->w / 800);
|
2015-05-28 12:51:45 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-31 04:15:51 +02:00
|
|
|
screen_blitText(TS_POWER, screen->w / 32, screen->h - 30);
|
2015-05-28 12:51:45 +02:00
|
|
|
|
2016-01-04 02:30:54 +01:00
|
|
|
bar.w = screen->w / 32;
|
2015-05-28 12:51:45 +02:00
|
|
|
bar.h = 12;
|
2016-01-04 02:30:54 +01:00
|
|
|
bar.x = screen->w / 32 + 55;
|
|
|
|
bar.y = screen->h - 29;
|
2015-05-28 12:51:45 +02:00
|
|
|
|
|
|
|
for (int i = 1 ; i <= 5 ; i++)
|
|
|
|
{
|
2016-11-25 19:47:12 +01:00
|
|
|
if (weapons[W_PLAYER_WEAPON].damage >= i) {
|
2015-05-28 12:51:45 +02:00
|
|
|
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);
|
2016-01-04 02:30:54 +01:00
|
|
|
bar.x += screen->w * 3 / 80;
|
2015-05-28 12:51:45 +02:00
|
|
|
}
|
|
|
|
|
2019-05-31 04:15:51 +02:00
|
|
|
screen_blitText(TS_OUTPUT, screen->w * 5 / 16, screen->h - 30);
|
2015-05-28 12:51:45 +02:00
|
|
|
|
2016-01-04 02:30:54 +01:00
|
|
|
bar.w = screen->w / 32;
|
2015-05-28 12:51:45 +02:00
|
|
|
bar.h = 12;
|
2016-01-04 02:30:54 +01:00
|
|
|
bar.x = screen->w * 5 / 16 + 65;
|
|
|
|
bar.y = screen->h - 29;
|
2015-05-28 12:51:45 +02:00
|
|
|
SDL_FillRect(screen, &bar, yellow);
|
|
|
|
|
|
|
|
for (int i = 1 ; i <= 5 ; i++)
|
|
|
|
{
|
2016-11-25 19:47:12 +01:00
|
|
|
if (weapons[W_PLAYER_WEAPON].ammo[0] >= i) {
|
2015-05-28 12:51:45 +02:00
|
|
|
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);
|
2016-01-04 02:30:54 +01:00
|
|
|
bar.x += screen->w * 3 / 80;
|
2015-05-28 12:51:45 +02:00
|
|
|
}
|
|
|
|
|
2019-05-31 04:15:51 +02:00
|
|
|
screen_blitText(TS_COOLER, screen->w * 97 / 160, screen->h - 30);
|
2015-05-28 12:51:45 +02:00
|
|
|
|
2016-01-04 02:30:54 +01:00
|
|
|
bar.w = screen->w / 32;
|
2015-05-28 12:51:45 +02:00
|
|
|
bar.h = 12;
|
2016-01-04 02:30:54 +01:00
|
|
|
bar.x = screen->w * 97 / 160 + 65;
|
|
|
|
bar.y = screen->h - 29;
|
2015-05-28 12:51:45 +02:00
|
|
|
|
|
|
|
for (int i = 1 ; i <= 5 ; i++)
|
|
|
|
{
|
2016-11-25 19:47:12 +01:00
|
|
|
if (weapons[W_PLAYER_WEAPON].reload[0] <= rate2reload[i]) {
|
2015-05-28 12:51:45 +02:00
|
|
|
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);
|
2016-01-04 02:30:54 +01:00
|
|
|
bar.x += screen->w * 3 / 80;
|
2015-05-28 12:51:45 +02:00
|
|
|
}
|
|
|
|
|
2019-05-31 04:15:51 +02:00
|
|
|
screen_blitText(TS_SHIELD, screen->w / 32, screen->h - 50);
|
2015-05-28 12:51:45 +02:00
|
|
|
if (player.shield < 1)
|
|
|
|
return;
|
|
|
|
|
2016-11-25 20:20:36 +01:00
|
|
|
if ((player.weaponType[1] == W_LASER) && (engine.eventTimer % 8 == 1))
|
|
|
|
LIMIT_ADD(player.ammo[1], -1, 0, 200);
|
2015-05-28 12:51:45 +02:00
|
|
|
|
|
|
|
if ((engine.eventTimer < 30) && (player.shield <= engine.lowShield))
|
|
|
|
return;
|
|
|
|
|
2016-01-04 02:30:54 +01:00
|
|
|
int blockSize = MAX(screen->w / 800, 1);
|
2015-05-28 12:51:45 +02:00
|
|
|
|
|
|
|
bar.w = blockSize;
|
|
|
|
bar.h = 12;
|
2016-01-04 02:30:54 +01:00
|
|
|
bar.x = screen->w / 32 + 65;
|
|
|
|
bar.y = screen->h - 50;
|
2015-05-28 12:51:45 +02:00
|
|
|
|
|
|
|
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;
|
2016-01-04 02:30:54 +01:00
|
|
|
if (player.maxShield <= 75 || screen->w >= 1200)
|
|
|
|
bar.x += screen->w / 800;
|
2015-05-28 12:51:45 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
*/
|
2016-11-19 17:43:50 +01:00
|
|
|
static int game_checkPauseRequest()
|
2015-04-26 13:36:25 +02:00
|
|
|
{
|
2016-11-26 00:01:36 +01:00
|
|
|
player_getInput();
|
2019-06-06 04:13:48 +02:00
|
|
|
|
2015-04-26 13:36:25 +02:00
|
|
|
if (engine.keyState[KEY_ESCAPE])
|
|
|
|
{
|
2016-11-19 17:43:50 +01:00
|
|
|
engine.paused = 0;
|
2015-04-26 13:36:25 +02:00
|
|
|
player.shield = 0;
|
2016-11-19 17:43:50 +01:00
|
|
|
return 1;
|
2015-04-26 13:36:25 +02:00
|
|
|
}
|
2019-06-06 04:13:48 +02:00
|
|
|
|
2015-04-26 13:36:25 +02:00
|
|
|
if (engine.keyState[KEY_PAUSE])
|
|
|
|
{
|
2016-11-19 17:43:50 +01:00
|
|
|
engine.paused = 0;
|
2015-04-26 13:36:25 +02:00
|
|
|
engine.keyState[KEY_PAUSE] = 0;
|
|
|
|
}
|
|
|
|
|
2016-11-19 17:43:50 +01:00
|
|
|
return 0;
|
2015-04-26 13:36:25 +02:00
|
|
|
}
|
|
|
|
|
2016-11-19 17:43:50 +01:00
|
|
|
int game_collision(float x0, float y0, int w0, int h0, float x2, float y2, int w1, int h1)
|
2015-09-25 22:28:09 +02:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2016-11-25 23:10:08 +01:00
|
|
|
/*
|
|
|
|
The game over screen :(
|
|
|
|
*/
|
|
|
|
static void game_showGameOver()
|
|
|
|
{
|
|
|
|
screen_flushBuffer();
|
|
|
|
gfx_free();
|
|
|
|
SDL_FillRect(gfx_background, NULL, black);
|
|
|
|
|
|
|
|
engine.keyState[KEY_FIRE] = engine.keyState[KEY_ALTFIRE] = 0;
|
|
|
|
engine.gameSection = SECTION_INTERMISSION;
|
|
|
|
|
|
|
|
SDL_Surface *gameover = gfx_loadImage("gfx/gameover.png");
|
|
|
|
|
|
|
|
screen_clear(black);
|
|
|
|
renderer_update();
|
|
|
|
screen_clear(black);
|
|
|
|
SDL_Delay(1000);
|
|
|
|
|
|
|
|
audio_playMusic("music/death.ogg", -1);
|
|
|
|
|
|
|
|
int x = (screen->w - gameover->w) / 2;
|
|
|
|
int y = (screen->h - gameover->h) / 2;
|
|
|
|
|
|
|
|
renderer_update();
|
|
|
|
|
2016-11-26 00:01:36 +01:00
|
|
|
player_flushInput();
|
2016-11-25 23:10:08 +01:00
|
|
|
engine.keyState[KEY_FIRE] = engine.keyState[KEY_ALTFIRE] = 0;
|
|
|
|
|
|
|
|
while (1)
|
|
|
|
{
|
2016-11-26 00:01:36 +01:00
|
|
|
player_getInput();
|
2016-11-25 23:10:08 +01:00
|
|
|
|
|
|
|
if (engine.keyState[KEY_FIRE] || engine.keyState[KEY_ALTFIRE])
|
|
|
|
break;
|
|
|
|
|
|
|
|
renderer_update();
|
|
|
|
|
|
|
|
screen_unBuffer();
|
|
|
|
x = ((screen->w - gameover->w) / 2) - RANDRANGE(-2, 2);
|
|
|
|
y = ((screen->h - gameover->h) / 2) - RANDRANGE(-2, 2);
|
|
|
|
screen_blit(gameover, x, y);
|
|
|
|
|
|
|
|
game_delayFrame();
|
|
|
|
}
|
|
|
|
|
|
|
|
SDL_FreeSurface(gameover);
|
|
|
|
audio_haltMusic();
|
|
|
|
screen_flushBuffer();
|
|
|
|
}
|
|
|
|
|
2015-05-21 01:41:43 +02:00
|
|
|
int game_mainLoop()
|
2015-04-08 01:16:46 +02:00
|
|
|
{
|
2016-11-23 03:16:49 +01:00
|
|
|
engine_resetLists();
|
2015-04-08 01:16:46 +02:00
|
|
|
|
2016-11-25 18:29:15 +01:00
|
|
|
mission_set(game.area);
|
|
|
|
mission_showStartScreen();
|
2015-04-08 01:16:46 +02:00
|
|
|
|
2015-04-24 22:27:07 +02:00
|
|
|
cargo_init();
|
2016-11-26 00:01:36 +01:00
|
|
|
player_init();
|
2015-04-08 01:16:46 +02:00
|
|
|
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)
|
2016-11-19 17:43:50 +01:00
|
|
|
aliens[ALIEN_KLINE].active = 0;
|
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:
|
2016-11-19 17:43:50 +01:00
|
|
|
aliens[ALIEN_PHOEBE].active = 0;
|
|
|
|
aliens[ALIEN_URSULA].active = 0;
|
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;
|
2019-05-26 23:43:14 +02:00
|
|
|
aliens[0].collectTypeOriginal = 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
|
|
|
{
|
2016-01-05 12:44:26 +01:00
|
|
|
if ((game.system > SYSTEM_EYANANTH) && ((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;
|
2016-11-19 17:43:50 +01:00
|
|
|
aliens[ALIEN_KLINE].active = 1;
|
2015-03-09 01:59:33 +01:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2016-01-05 12:44:26 +01:00
|
|
|
if ((game.system == SYSTEM_MORDOR) && (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
|
|
|
{
|
2016-01-03 22:20:22 +01:00
|
|
|
aliens[ALIEN_BOSS] = alien_defs[CD_CLOAKFIGHTER];
|
|
|
|
aliens[ALIEN_BOSS].owner = &aliens[ALIEN_BOSS];
|
|
|
|
aliens[ALIEN_BOSS].target = &aliens[ALIEN_BOSS];
|
|
|
|
aliens[ALIEN_BOSS].shield = 1000;
|
2016-11-19 17:43:50 +01:00
|
|
|
aliens[ALIEN_BOSS].active = 1;
|
2016-01-03 22:20:22 +01:00
|
|
|
aliens[ALIEN_BOSS].x = player.x - 1000;
|
|
|
|
aliens[ALIEN_BOSS].y = player.y;
|
|
|
|
player_setTarget(ALIEN_BOSS);
|
|
|
|
aliens[ALIEN_BOSS].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_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:
|
2016-01-03 22:20:22 +01:00
|
|
|
player_setTarget(ALIEN_FRIEND1);
|
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;
|
2019-05-26 22:19:33 +02:00
|
|
|
case MISN_POSWIC:
|
|
|
|
if (game.difficulty == DIFFICULTY_ORIGINAL)
|
|
|
|
player_setTarget(ALIEN_BOSS);
|
|
|
|
else
|
|
|
|
player_setTarget(ALIEN_SID);
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2016-11-23 03:16:49 +01:00
|
|
|
info_clearLines();
|
2011-08-24 14:14:44 +02:00
|
|
|
|
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++)
|
|
|
|
{
|
2016-11-25 18:53:53 +01:00
|
|
|
if ((mission.primaryType[i] == M_DESTROY_TARGET_TYPE) &&
|
|
|
|
(mission.target1[i] == CD_ANY))
|
|
|
|
allowableAliens = mission.targetValue1[i];
|
2011-08-24 14:14:44 +02:00
|
|
|
|
2016-11-25 18:53:53 +01:00
|
|
|
if (mission.primaryType[i] == M_DESTROY_ALL_TARGETS)
|
2011-08-24 14:14:44 +02:00
|
|
|
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;
|
2016-11-26 00:01:36 +01:00
|
|
|
player_flushInput();
|
2011-08-24 14:14:44 +02:00
|
|
|
|
|
|
|
while (engine.done != 1)
|
|
|
|
{
|
2015-10-27 01:07:31 +01:00
|
|
|
renderer_update();
|
2011-08-24 14:14:44 +02:00
|
|
|
|
2016-11-25 18:29:15 +01:00
|
|
|
if ((mission_checkCompleted()) && (engine.missionCompleteTimer == 0))
|
2011-08-24 14:14:44 +02:00
|
|
|
{
|
|
|
|
engine.missionCompleteTimer = SDL_GetTicks() + 4000;
|
|
|
|
}
|
|
|
|
|
2016-11-25 18:29:15 +01:00
|
|
|
if ((mission_checkFailed()) && (engine.missionCompleteTimer == 0))
|
2011-08-24 14:14:44 +02:00
|
|
|
{
|
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)
|
|
|
|
{
|
2016-11-25 18:29:15 +01:00
|
|
|
if ((!mission_checkFailed()) && (game.area != MISN_VENUS))
|
2011-08-24 14:14:44 +02:00
|
|
|
{
|
2016-11-26 00:01:36 +01:00
|
|
|
player_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
|
|
|
|
{
|
2016-11-26 00:01:36 +01:00
|
|
|
player_getInput();
|
2011-08-24 14:14:44 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
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
|
|
|
|
{
|
2016-11-26 00:01:36 +01:00
|
|
|
player_getInput();
|
2011-08-24 14:14:44 +02:00
|
|
|
}
|
|
|
|
|
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
|
|
|
|
2019-05-11 08:15:36 +02:00
|
|
|
// Start delaying damage again gradually
|
2019-05-11 08:26:37 +02:00
|
|
|
if (player_damageDelay > 0)
|
2019-05-11 08:15:36 +02:00
|
|
|
{
|
2019-05-11 08:26:37 +02:00
|
|
|
if (player_resetDamageDelay)
|
|
|
|
{
|
|
|
|
player_damageDelay--;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
player_resetDamageDelay = 1;
|
|
|
|
}
|
2019-05-11 08:15:36 +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
|
|
|
{
|
2019-05-31 00:42:10 +02:00
|
|
|
gfx_createTextObject(TS_PAUSED, "PAUSED", 0, 0, FONT_WHITE);
|
2015-04-26 13:45:58 +02:00
|
|
|
audio_pauseMusic();
|
2011-09-05 11:40:35 +02:00
|
|
|
|
|
|
|
while (engine.paused)
|
|
|
|
{
|
2019-06-02 05:42:13 +02:00
|
|
|
screen_blitText(TS_PAUSED, -1, screen->h / 2);
|
|
|
|
renderer_update();
|
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
|
|
|
|
2017-01-27 04:41:59 +01:00
|
|
|
if (!engine.done)
|
|
|
|
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.
|
2017-02-05 23:37:22 +01:00
|
|
|
collectable_add(screen->w + RANDRANGE(0, 700),
|
2015-03-29 20:27:29 +02:00
|
|
|
RANDRANGE(-screen->h / 3, (4 * screen->h) / 3), P_MINE, 25,
|
2017-02-05 23:37:22 +01:00
|
|
|
180 * screen->w / 800 + RANDRANGE(0, 60));
|
2011-08-24 14:14:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (engine.addAliens > -1)
|
|
|
|
{
|
2016-11-25 18:53:53 +01:00
|
|
|
WRAP_ADD(engine.addAliens, -1, 0, mission.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
|
|
|
{
|
2016-01-11 05:56:26 +01:00
|
|
|
audio_playSound(SFX_DEATH, aliens[ALIEN_BOSS].x, aliens[ALIEN_BOSS].y);
|
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)
|
2016-01-11 05:56:26 +01:00
|
|
|
audio_playSound(SFX_EXPLOSION, aliens[ALIEN_BOSS].x, aliens[ALIEN_BOSS].y);
|
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
|
|
|
|
2016-11-25 18:29:15 +01:00
|
|
|
if ((player.shield > 0) && (!mission_checkFailed()))
|
2011-08-24 14:14:44 +02:00
|
|
|
{
|
2015-05-21 01:41:43 +02:00
|
|
|
if (game.area < MISN_VENUS)
|
2016-11-25 18:29:15 +01:00
|
|
|
mission_showFinishedScreen();
|
2011-08-24 14:14:44 +02:00
|
|
|
|
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:
|
2016-01-05 02:17:06 +01:00
|
|
|
cutscene_init(1);
|
|
|
|
cutscene_init(2);
|
2011-08-24 14:14:44 +02:00
|
|
|
break;
|
2015-03-29 19:11:12 +02:00
|
|
|
case MISN_NEROD:
|
2016-01-05 02:17:06 +01:00
|
|
|
cutscene_init(3);
|
2011-08-24 14:14:44 +02:00
|
|
|
break;
|
2015-03-29 19:11:12 +02:00
|
|
|
case MISN_ELAMALE:
|
2016-01-05 02:17:06 +01:00
|
|
|
cutscene_init(4);
|
2011-08-24 14:14:44 +02:00
|
|
|
break;
|
2015-03-29 19:11:12 +02:00
|
|
|
case MISN_ODEON:
|
2016-01-05 02:17:06 +01:00
|
|
|
cutscene_init(5);
|
2011-08-24 14:14:44 +02:00
|
|
|
break;
|
2015-03-29 19:11:12 +02:00
|
|
|
case MISN_ELLESH:
|
2016-01-05 02:17:06 +01:00
|
|
|
cutscene_init(6);
|
2011-08-24 14:14:44 +02:00
|
|
|
break;
|
2015-03-29 19:11:12 +02:00
|
|
|
case MISN_VENUS:
|
2016-11-25 23:10:08 +01:00
|
|
|
title_showCredits();
|
2011-08-24 14:14:44 +02:00
|
|
|
break;
|
|
|
|
}
|
2019-06-06 04:13:48 +02:00
|
|
|
|
2015-05-21 01:41:43 +02:00
|
|
|
if (game.area < MISN_VENUS)
|
2011-08-24 14:14:44 +02:00
|
|
|
{
|
2016-11-25 18:29:15 +01:00
|
|
|
intermission_updateSystemStatus();
|
2016-11-17 01:43:03 +01:00
|
|
|
save(0);
|
2011-08-24 14:14:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
rtn = 1;
|
2019-06-06 04:13:48 +02:00
|
|
|
|
2015-05-21 01:41:43 +02:00
|
|
|
if (game.area == MISN_VENUS)
|
2011-08-24 14:14:44 +02:00
|
|
|
rtn = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-11-25 23:10:08 +01:00
|
|
|
game_showGameOver();
|
2011-08-24 14:14:44 +02:00
|
|
|
rtn = 0;
|
|
|
|
}
|
|
|
|
|
2016-11-26 00:01:36 +01:00
|
|
|
player_exit();
|
2011-08-29 09:10:50 +02:00
|
|
|
|
2011-08-24 14:14:44 +02:00
|
|
|
return rtn;
|
|
|
|
}
|