1390 lines
45 KiB
C
1390 lines
45 KiB
C
/*
|
|
Copyright (C) 2003 Parallel Realities
|
|
Copyright (C) 2011, 2012, 2013 Guus Sliepen
|
|
Copyright (C) 2012, 2015-2020 The Diligent Circle <diligentcircle@riseup.net>
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 3
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <libintl.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "SDL.h"
|
|
|
|
#include "colors.h"
|
|
#include "defs.h"
|
|
#include "structs.h"
|
|
|
|
#include "alien.h"
|
|
#include "audio.h"
|
|
#include "engine.h"
|
|
#include "event.h"
|
|
#include "game.h"
|
|
#include "gfx.h"
|
|
#include "info.h"
|
|
#include "intermission.h"
|
|
#include "mission.h"
|
|
#include "player.h"
|
|
#include "radio.h"
|
|
#include "renderer.h"
|
|
#include "screen.h"
|
|
|
|
Mission mission;
|
|
|
|
static Mission missions[MISN_MAX];
|
|
|
|
/*
|
|
Timer Variable:
|
|
1+ : Time in minutes
|
|
-1 : Time up
|
|
-2 : No timer
|
|
*/
|
|
static void mission_clearAll()
|
|
{
|
|
for (int m = 0 ; m < MISN_MAX ; m++)
|
|
{
|
|
for (int i = 0 ; i < 3 ; i++)
|
|
{
|
|
strcpy(missions[m].primaryObjective[i], "");
|
|
missions[m].primaryType[i] = M_NONE;
|
|
missions[m].target1[i] = -1;
|
|
missions[m].targetValue1[i] = -1;
|
|
missions[m].timeLimit1[i] = MT_NONE;
|
|
missions[m].completed1[i] = OB_COMPLETED;
|
|
}
|
|
|
|
for (int i = 0 ; i < 3 ; i++)
|
|
{
|
|
strcpy(missions[m].secondaryObjective[i], "");
|
|
missions[m].secondaryType[i] = M_NONE;
|
|
missions[m].target2[i] = -1;
|
|
missions[m].targetValue2[i] = -1;
|
|
missions[m].timeLimit2[i] = MT_NONE;
|
|
missions[m].completed2[i] = OB_COMPLETED;
|
|
}
|
|
|
|
missions[m].addAliens = -1;
|
|
}
|
|
}
|
|
|
|
/*
|
|
This is where all the missions are defined.
|
|
*/
|
|
void mission_init()
|
|
{
|
|
// Seconds to wait between attempting to add an enemy
|
|
static const int SOMETIMES = 40 * 60;
|
|
static const int NORMAL = 15 * 60;
|
|
static const int FREQUENT = 5 * 60;
|
|
static const int ALWAYS = 1 * 60;
|
|
static const int NEVER = -1;
|
|
|
|
/// Mission objective
|
|
const char *ob_destroyAll = _("Destroy all remaining WEAPCO fighters");
|
|
|
|
mission_clearAll();
|
|
|
|
/// Mission objective (start)
|
|
strcpy(missions[MISN_START].primaryObjective[0], _("Escape from WEAPCO Pursuit"));
|
|
missions[MISN_START].primaryType[0] = M_DESTROY_ALL_TARGETS;
|
|
missions[MISN_START].completed1[0] = OB_INCOMPLETE;
|
|
|
|
|
|
/// Mission objective (Hail)
|
|
strcpy(missions[MISN_HAIL].primaryObjective[0], _("Collect $500 to pay Mercenary for FIREFLY"));
|
|
missions[MISN_HAIL].primaryType[0] = M_COLLECT;
|
|
missions[MISN_HAIL].target1[0] = P_CASH;
|
|
missions[MISN_HAIL].targetValue1[0] = 500;
|
|
missions[MISN_HAIL].completed1[0] = OB_INCOMPLETE;
|
|
|
|
strcpy(missions[MISN_HAIL].primaryObjective[1], ob_destroyAll);
|
|
missions[MISN_HAIL].primaryType[1] = M_DESTROY_ALL_TARGETS;
|
|
missions[MISN_HAIL].completed1[1] = OB_INCOMPLETE;
|
|
|
|
missions[MISN_HAIL].addAliens = FREQUENT;
|
|
|
|
|
|
/// Mission objective (Ceradse)
|
|
strcpy(missions[MISN_CERADSE].primaryObjective[0], _("Collect 6 Cargo Pods"));
|
|
missions[MISN_CERADSE].primaryType[0] = M_COLLECT;
|
|
missions[MISN_CERADSE].target1[0] = P_CARGO;
|
|
missions[MISN_CERADSE].targetValue1[0] = 6;
|
|
missions[MISN_CERADSE].completed1[0] = OB_INCOMPLETE;
|
|
|
|
/// Mission objective (Ceradse)
|
|
strcpy(missions[MISN_CERADSE].primaryObjective[1], _("Do not destroy *ANY* Cargo Pods"));
|
|
missions[MISN_CERADSE].primaryType[1] = M_PROTECT_PICKUP;
|
|
missions[MISN_CERADSE].target1[1] = P_CARGO;
|
|
missions[MISN_CERADSE].targetValue1[1] = 0;
|
|
missions[MISN_CERADSE].completed1[1] = OB_CONDITION;
|
|
|
|
strcpy(missions[MISN_CERADSE].secondaryObjective[0], ob_destroyAll);
|
|
missions[MISN_CERADSE].secondaryType[0] = M_DESTROY_ALL_TARGETS;
|
|
missions[MISN_CERADSE].completed2[0] = OB_INCOMPLETE;
|
|
|
|
missions[MISN_CERADSE].addAliens = FREQUENT;
|
|
|
|
|
|
/// Mission objective (Hinstag)
|
|
strcpy(missions[MISN_HINSTAG].primaryObjective[0], _("Destroy 5 WEAPCO Missile Boats"));
|
|
missions[MISN_HINSTAG].primaryType[0] = M_DESTROY_TARGET_TYPE;
|
|
missions[MISN_HINSTAG].target1[0] = CD_MISSILEBOAT;
|
|
missions[MISN_HINSTAG].targetValue1[0] = 5;
|
|
missions[MISN_HINSTAG].completed1[0] = OB_INCOMPLETE;
|
|
|
|
strcpy(missions[MISN_HINSTAG].secondaryObjective[0], ob_destroyAll);
|
|
missions[MISN_HINSTAG].secondaryType[0] = M_DESTROY_ALL_TARGETS;
|
|
missions[MISN_HINSTAG].completed2[0] = OB_INCOMPLETE;
|
|
|
|
missions[MISN_HINSTAG].addAliens = NORMAL;
|
|
|
|
|
|
/// Mission objective (Joldar)
|
|
strcpy(missions[MISN_JOLDAR].primaryObjective[0], _("Destroy 9 WEAPCO Mine-droppers"));
|
|
missions[MISN_JOLDAR].primaryType[0] = M_DESTROY_TARGET_TYPE;
|
|
missions[MISN_JOLDAR].target1[0] = CD_MINER;
|
|
missions[MISN_JOLDAR].targetValue1[0] = 9;
|
|
missions[MISN_JOLDAR].completed1[0] = OB_INCOMPLETE;
|
|
|
|
strcpy(missions[MISN_JOLDAR].secondaryObjective[0], ob_destroyAll);
|
|
missions[MISN_JOLDAR].secondaryType[0] = M_DESTROY_ALL_TARGETS;
|
|
missions[MISN_JOLDAR].completed2[0] = OB_INCOMPLETE;
|
|
|
|
missions[MISN_JOLDAR].addAliens = NORMAL;
|
|
|
|
|
|
/// Mission objective (Moebo)
|
|
strcpy(missions[MISN_MOEBO].primaryObjective[0], _("Destroy WEAPCO Frigate"));
|
|
missions[MISN_MOEBO].primaryType[0] = M_DESTROY_TARGET_TYPE;
|
|
missions[MISN_MOEBO].target1[0] = CD_BOSS;
|
|
missions[MISN_MOEBO].targetValue1[0] = 1;
|
|
missions[MISN_MOEBO].completed1[0] = OB_INCOMPLETE;
|
|
|
|
missions[MISN_MOEBO].timeLimit1[0] = 3;
|
|
|
|
missions[MISN_MOEBO].addAliens = SOMETIMES;
|
|
|
|
|
|
/// Mission objective (Nerod)
|
|
strcpy(missions[MISN_NEROD].primaryObjective[0], _("Rescue Phoebe Lexx"));
|
|
missions[MISN_NEROD].primaryType[0] = M_DESTROY_TARGET_TYPE;
|
|
missions[MISN_NEROD].target1[0] = CD_CARGOSHIP;
|
|
missions[MISN_NEROD].targetValue1[0] = 1;
|
|
missions[MISN_NEROD].completed1[0] = OB_INCOMPLETE;
|
|
|
|
/// Mission objective (Nerod)
|
|
strcpy(missions[MISN_NEROD].primaryObjective[1], _("Do not allow Phoebe to be killed"));
|
|
missions[MISN_NEROD].primaryType[1] = M_PROTECT_TARGET;
|
|
missions[MISN_NEROD].target1[1] = CD_PHOEBE;
|
|
missions[MISN_NEROD].targetValue1[1] = 0;
|
|
missions[MISN_NEROD].completed1[1] = OB_CONDITION;
|
|
|
|
strcpy(missions[MISN_NEROD].primaryObjective[2], ob_destroyAll);
|
|
missions[MISN_NEROD].primaryType[2] = M_DESTROY_TARGET_TYPE;
|
|
missions[MISN_NEROD].target1[2] = CD_ANY;
|
|
missions[MISN_NEROD].targetValue1[2] = 35;
|
|
missions[MISN_NEROD].completed1[2] = OB_INCOMPLETE;
|
|
|
|
missions[MISN_NEROD].addAliens = ALWAYS;
|
|
|
|
|
|
/// Mission objective (Allez)
|
|
strcpy(missions[MISN_ALLEZ].primaryObjective[0], _("Assist medical supply craft"));
|
|
missions[MISN_ALLEZ].primaryType[0] = M_ESCAPE_TARGET;
|
|
missions[MISN_ALLEZ].target1[0] = CD_GOODTRANSPORT;
|
|
missions[MISN_ALLEZ].targetValue1[0] = 0;
|
|
missions[MISN_ALLEZ].completed1[0] = OB_INCOMPLETE;
|
|
|
|
/// Mission objective (Allez)
|
|
strcpy(missions[MISN_ALLEZ].primaryObjective[1], _("Do not allow supply craft to be destroyed"));
|
|
missions[MISN_ALLEZ].primaryType[1] = M_PROTECT_TARGET;
|
|
missions[MISN_ALLEZ].target1[1] = CD_GOODTRANSPORT;
|
|
missions[MISN_ALLEZ].targetValue1[1] = 0;
|
|
missions[MISN_ALLEZ].completed1[1] = OB_CONDITION;
|
|
|
|
strcpy(missions[MISN_ALLEZ].secondaryObjective[0], ob_destroyAll);
|
|
missions[MISN_ALLEZ].secondaryType[0] = M_DESTROY_ALL_TARGETS;
|
|
missions[MISN_ALLEZ].completed2[0] = OB_INCOMPLETE;
|
|
|
|
missions[MISN_ALLEZ].addAliens = FREQUENT;
|
|
|
|
|
|
/// Mission objective (Urusor)
|
|
strcpy(missions[MISN_URUSOR].primaryObjective[0], _("Disable five WEAPCO supply craft"));
|
|
missions[MISN_URUSOR].primaryType[0] = M_DISABLE_TARGET;
|
|
missions[MISN_URUSOR].target1[0] = CD_CARGOSHIP;
|
|
missions[MISN_URUSOR].targetValue1[0] = 5;
|
|
missions[MISN_URUSOR].completed1[0] = OB_INCOMPLETE;
|
|
|
|
strcpy(missions[MISN_URUSOR].primaryObjective[1], ob_destroyAll);
|
|
missions[MISN_URUSOR].primaryType[1] = M_DESTROY_ALL_TARGETS;
|
|
missions[MISN_URUSOR].completed1[1] = OB_INCOMPLETE;
|
|
|
|
/// Mission objective (Urusor)
|
|
strcpy(missions[MISN_URUSOR].primaryObjective[2], _("Protect supply craft AND Sid Wilson"));
|
|
missions[MISN_URUSOR].primaryType[2] = M_PROTECT_TARGET;
|
|
missions[MISN_URUSOR].target1[2] = CD_CARGOSHIP;
|
|
missions[MISN_URUSOR].targetValue1[2] = 0;
|
|
missions[MISN_URUSOR].completed1[2] = OB_CONDITION;
|
|
|
|
missions[MISN_URUSOR].addAliens = FREQUENT;
|
|
|
|
|
|
/// Mission objective (Dorim)
|
|
strcpy(missions[MISN_DORIM].primaryObjective[0], _("Locate doctor's escape pod"));
|
|
missions[MISN_DORIM].primaryType[0] = M_COLLECT;
|
|
missions[MISN_DORIM].target1[0] = P_ESCAPEPOD;
|
|
missions[MISN_DORIM].targetValue1[0] = 1;
|
|
missions[MISN_DORIM].completed1[0] = OB_INCOMPLETE;
|
|
|
|
/// Mission objective (Dorim)
|
|
strcpy(missions[MISN_DORIM].primaryObjective[1], _("Do not destroy doctor's escape pod"));
|
|
missions[MISN_DORIM].primaryType[1] = M_PROTECT_PICKUP;
|
|
missions[MISN_DORIM].target1[1] = P_ESCAPEPOD;
|
|
missions[MISN_DORIM].targetValue1[1] = 1; // DONE ON PURPOSE!! DO NOT CHANGE THIS!!!!
|
|
missions[MISN_DORIM].completed1[1] = OB_CONDITION;
|
|
|
|
/// Mission objective (Dorim)
|
|
strcpy(missions[MISN_DORIM].secondaryObjective[0], _("Collect 10 pieces of Ore"));
|
|
missions[MISN_DORIM].secondaryType[0] = M_COLLECT;
|
|
missions[MISN_DORIM].target2[0] = P_ORE;
|
|
missions[MISN_DORIM].targetValue2[0] = 10;
|
|
missions[MISN_DORIM].completed2[0] = OB_INCOMPLETE;
|
|
|
|
missions[MISN_DORIM].addAliens = ALWAYS;
|
|
|
|
missions[MISN_DORIM].timeLimit1[0] = 3;
|
|
missions[MISN_DORIM].timeLimit2[0] = 3;
|
|
|
|
|
|
/// Mission objective (Elamale)
|
|
strcpy(missions[MISN_ELAMALE].primaryObjective[0], _("Destroy WEAPCO ore mining craft"));
|
|
missions[MISN_ELAMALE].primaryType[0] = M_DESTROY_TARGET_TYPE;
|
|
missions[MISN_ELAMALE].target1[0] = CD_BOSS;
|
|
missions[MISN_ELAMALE].targetValue1[0] = 1;
|
|
missions[MISN_ELAMALE].completed1[0] = OB_INCOMPLETE;
|
|
|
|
/// Mission objective (Elamale)
|
|
strcpy(missions[MISN_ELAMALE].secondaryObjective[0], _("Save present slaves"));
|
|
missions[MISN_ELAMALE].secondaryType[0] = M_PROTECT_PICKUP;
|
|
missions[MISN_ELAMALE].target2[0] = P_SLAVES;
|
|
missions[MISN_ELAMALE].completed2[0] = OB_CONDITION;
|
|
|
|
/// Mission objective (Elamale)
|
|
strcpy(missions[MISN_ELAMALE].primaryObjective[1], _("Battle Kline"));
|
|
missions[MISN_ELAMALE].primaryType[1] = M_ESCAPE_TARGET;
|
|
missions[MISN_ELAMALE].target1[1] = CD_KLINE;
|
|
missions[MISN_ELAMALE].targetValue1[1] = 1;
|
|
missions[MISN_ELAMALE].completed1[1] = OB_HIDDEN;
|
|
|
|
missions[MISN_ELAMALE].addAliens = NEVER;
|
|
|
|
|
|
/// Mission objective (Odeon)
|
|
strcpy(missions[MISN_ODEON].primaryObjective[0], _("Destroy Ursula's ship"));
|
|
missions[MISN_ODEON].primaryType[0] = M_DESTROY_TARGET_TYPE;
|
|
missions[MISN_ODEON].target1[0] = CD_EVILURSULA;
|
|
missions[MISN_ODEON].targetValue1[0] = 0;
|
|
missions[MISN_ODEON].completed1[0] = OB_INCOMPLETE;
|
|
|
|
/// Mission objective (Odeon)
|
|
strcpy(missions[MISN_ODEON].primaryObjective[1], _("Capture Ursula's escape pod"));
|
|
missions[MISN_ODEON].primaryType[1] = M_COLLECT;
|
|
missions[MISN_ODEON].target1[1] = P_ESCAPEPOD;
|
|
missions[MISN_ODEON].targetValue1[1] = 1;
|
|
missions[MISN_ODEON].completed1[1] = OB_INCOMPLETE;
|
|
|
|
/// Mission objective (Odeon)
|
|
strcpy(missions[MISN_ODEON].primaryObjective[2], _("Do not kill Ursula"));
|
|
missions[MISN_ODEON].primaryType[2] = M_PROTECT_PICKUP;
|
|
missions[MISN_ODEON].target1[2] = P_ESCAPEPOD;
|
|
missions[MISN_ODEON].targetValue1[2] = 0;
|
|
missions[MISN_ODEON].completed1[2] = OB_CONDITION;
|
|
|
|
strcpy(missions[MISN_ODEON].secondaryObjective[0], ob_destroyAll);
|
|
missions[MISN_ODEON].secondaryType[0] = M_DESTROY_ALL_TARGETS;
|
|
missions[MISN_ODEON].completed2[0] = OB_INCOMPLETE;
|
|
|
|
missions[MISN_ODEON].addAliens = FREQUENT;
|
|
|
|
|
|
/// Mission objective (Fellon)
|
|
strcpy(missions[MISN_FELLON].primaryObjective[0], _("Assist attack on WEAPCO ore mining craft"));
|
|
missions[MISN_FELLON].primaryType[0] = M_DESTROY_TARGET_TYPE;
|
|
missions[MISN_FELLON].target1[0] = CD_BOSS;
|
|
missions[MISN_FELLON].targetValue1[0] = 1;
|
|
missions[MISN_FELLON].completed1[0] = OB_INCOMPLETE;
|
|
|
|
/// Mission objective (Fellon)
|
|
strcpy(missions[MISN_FELLON].primaryObjective[1], _("At least 1 rebel craft must survive"));
|
|
missions[MISN_FELLON].primaryType[1] = M_PROTECT_TARGET;
|
|
missions[MISN_FELLON].target1[1] = CD_REBELCARRIER;
|
|
missions[MISN_FELLON].targetValue1[1] = 2;
|
|
missions[MISN_FELLON].completed1[1] = OB_CONDITION;
|
|
|
|
strcpy(missions[MISN_FELLON].primaryObjective[2], ob_destroyAll);
|
|
missions[MISN_FELLON].primaryType[2] = M_DESTROY_ALL_TARGETS;
|
|
missions[MISN_FELLON].completed1[2] = OB_INCOMPLETE;
|
|
|
|
missions[MISN_FELLON].addAliens = ALWAYS;
|
|
|
|
|
|
/// Mission objective (Sivedi)
|
|
strcpy(missions[MISN_SIVEDI].primaryObjective[0], _("Collect 25 pieces of Ore"));
|
|
missions[MISN_SIVEDI].primaryType[0] = M_COLLECT;
|
|
missions[MISN_SIVEDI].target1[0] = P_ORE;
|
|
missions[MISN_SIVEDI].targetValue1[0] = 25;
|
|
missions[MISN_SIVEDI].completed1[0] = OB_INCOMPLETE;
|
|
|
|
/// Mission objective (Sivedi)
|
|
strcpy(missions[MISN_SIVEDI].secondaryObjective[0], _("Collect 50 pieces of Ore"));
|
|
missions[MISN_SIVEDI].secondaryType[0] = M_COLLECT;
|
|
missions[MISN_SIVEDI].target2[0] = P_ORE;
|
|
missions[MISN_SIVEDI].targetValue2[0] = 25; // 25 + 25 = 50 (the overall total)
|
|
missions[MISN_SIVEDI].completed2[0] = OB_INCOMPLETE;
|
|
|
|
missions[MISN_SIVEDI].addAliens = ALWAYS;
|
|
|
|
|
|
/// Mission objective (Almartha)
|
|
strcpy(missions[MISN_ALMARTHA].primaryObjective[0], _("Collect $2000 to pay mercenary"));
|
|
missions[MISN_ALMARTHA].primaryType[0] = M_COLLECT;
|
|
missions[MISN_ALMARTHA].target1[0] = P_CASH;
|
|
missions[MISN_ALMARTHA].targetValue1[0] = 2000;
|
|
missions[MISN_ALMARTHA].completed1[0] = OB_INCOMPLETE;
|
|
|
|
strcpy(missions[MISN_ALMARTHA].primaryObjective[1], ob_destroyAll);
|
|
missions[MISN_ALMARTHA].primaryType[1] = M_DESTROY_ALL_TARGETS;
|
|
missions[MISN_ALMARTHA].completed1[1] = OB_INCOMPLETE;
|
|
|
|
missions[MISN_ALMARTHA].addAliens = ALWAYS;
|
|
|
|
|
|
/// Mission objective (Poswic)
|
|
strcpy(missions[MISN_POSWIC].primaryObjective[0], _("Destroy escorts"));
|
|
missions[MISN_POSWIC].primaryType[0] = M_DESTROY_TARGET_TYPE;
|
|
missions[MISN_POSWIC].target1[0] = CD_ESCORT;
|
|
missions[MISN_POSWIC].targetValue1[0] = 5;
|
|
missions[MISN_POSWIC].completed1[0] = OB_INCOMPLETE;
|
|
|
|
/// Mission objective (Poswic)
|
|
strcpy(missions[MISN_POSWIC].primaryObjective[1], _("Disable executive transport"));
|
|
missions[MISN_POSWIC].primaryType[1] = M_ESCAPE_TARGET;
|
|
missions[MISN_POSWIC].target1[1] = CD_BOSS;
|
|
missions[MISN_POSWIC].targetValue1[1] = 1;
|
|
missions[MISN_POSWIC].completed1[1] = OB_INCOMPLETE;
|
|
|
|
strcpy(missions[MISN_POSWIC].primaryObjective[2], ob_destroyAll);
|
|
missions[MISN_POSWIC].primaryType[2] = M_DESTROY_ALL_TARGETS;
|
|
missions[MISN_POSWIC].completed1[2] = OB_INCOMPLETE;
|
|
|
|
missions[MISN_POSWIC].addAliens = NORMAL;
|
|
|
|
|
|
/// Mission objective (Ellesh)
|
|
strcpy(missions[MISN_ELLESH].primaryObjective[0], _("Destroy executive transport"));
|
|
missions[MISN_ELLESH].primaryType[0] = M_DESTROY_TARGET_TYPE;
|
|
missions[MISN_ELLESH].target1[0] = CD_BOSS;
|
|
missions[MISN_ELLESH].targetValue1[0] = 1;
|
|
missions[MISN_ELLESH].completed1[0] = OB_INCOMPLETE;
|
|
|
|
missions[MISN_ELLESH].addAliens = ALWAYS;
|
|
|
|
|
|
/// Mission objective (Pluto, Neptune, Uranus)
|
|
strcpy(missions[MISN_PLUTO].primaryObjective[0], _("Destroy planetary guardian"));
|
|
missions[MISN_PLUTO].primaryType[0] = M_DESTROY_TARGET_TYPE;
|
|
missions[MISN_PLUTO].target1[0] = CD_PLUTOBOSS;
|
|
missions[MISN_PLUTO].targetValue1[0] = 1;
|
|
missions[MISN_PLUTO].completed1[0] = OB_INCOMPLETE;
|
|
|
|
strcpy(missions[MISN_PLUTO].primaryObjective[1], ob_destroyAll);
|
|
missions[MISN_PLUTO].primaryType[1] = M_DESTROY_ALL_TARGETS;
|
|
missions[MISN_PLUTO].completed1[1] = OB_INCOMPLETE;
|
|
|
|
missions[MISN_PLUTO].timeLimit1[0] = 5;
|
|
missions[MISN_PLUTO].timeLimit1[1] = 5;
|
|
|
|
missions[MISN_PLUTO].addAliens = ALWAYS;
|
|
|
|
|
|
strcpy(missions[MISN_NEPTUNE].primaryObjective[0], missions[MISN_PLUTO].primaryObjective[0]);
|
|
missions[MISN_NEPTUNE].primaryType[0] = M_DESTROY_TARGET_TYPE;
|
|
missions[MISN_NEPTUNE].target1[0] = CD_NEPTUNEBOSS;
|
|
missions[MISN_NEPTUNE].targetValue1[0] = 1;
|
|
missions[MISN_NEPTUNE].completed1[0] = OB_INCOMPLETE;
|
|
|
|
strcpy(missions[MISN_NEPTUNE].primaryObjective[1], ob_destroyAll);
|
|
missions[MISN_NEPTUNE].primaryType[1] = M_DESTROY_ALL_TARGETS;
|
|
missions[MISN_NEPTUNE].completed1[1] = OB_INCOMPLETE;
|
|
|
|
missions[MISN_NEPTUNE].timeLimit1[0] = 5;
|
|
missions[MISN_NEPTUNE].timeLimit1[1] = 5;
|
|
|
|
missions[MISN_NEPTUNE].addAliens = ALWAYS;
|
|
|
|
|
|
strcpy(missions[MISN_URANUS].primaryObjective[0], missions[MISN_PLUTO].primaryObjective[0]);
|
|
missions[MISN_URANUS].primaryType[0] = M_DESTROY_TARGET_TYPE;
|
|
missions[MISN_URANUS].target1[0] = CD_URANUSBOSS;
|
|
missions[MISN_URANUS].targetValue1[0] = 1;
|
|
missions[MISN_URANUS].completed1[0] = OB_INCOMPLETE;
|
|
|
|
strcpy(missions[MISN_URANUS].primaryObjective[1], ob_destroyAll);
|
|
missions[MISN_URANUS].primaryType[1] = M_DESTROY_ALL_TARGETS;
|
|
missions[MISN_URANUS].completed1[1] = OB_INCOMPLETE;
|
|
|
|
missions[MISN_URANUS].timeLimit1[0] = 5;
|
|
missions[MISN_URANUS].timeLimit1[1] = 5;
|
|
|
|
missions[MISN_URANUS].addAliens = ALWAYS;
|
|
|
|
|
|
/// Mission objective (Saturn)
|
|
strcpy(missions[MISN_SATURN].primaryObjective[0], _("Destroy outer defence systems"));
|
|
missions[MISN_SATURN].primaryType[0] = M_DESTROY_TARGET_TYPE;
|
|
missions[MISN_SATURN].target1[0] = CD_MOBILE_RAY;
|
|
missions[MISN_SATURN].targetValue1[0] = 6;
|
|
missions[MISN_SATURN].completed1[0] = OB_INCOMPLETE;
|
|
|
|
strcpy(missions[MISN_SATURN].primaryObjective[1], ob_destroyAll);
|
|
missions[MISN_SATURN].primaryType[1] = M_DESTROY_ALL_TARGETS;
|
|
missions[MISN_SATURN].completed1[1] = OB_INCOMPLETE;
|
|
|
|
missions[MISN_SATURN].addAliens = NORMAL;
|
|
|
|
|
|
/// Mission objective (Jupiter)
|
|
strcpy(missions[MISN_JUPITER].primaryObjective[0], _("Investigate distress call"));
|
|
missions[MISN_JUPITER].primaryType[0] = M_DESTROY_ALL_TARGETS;
|
|
missions[MISN_JUPITER].completed1[0] = OB_CONDITION;
|
|
|
|
/// Mission objective (Jupiter)
|
|
strcpy(missions[MISN_JUPITER].primaryObjective[1], _("Defeat Krass Tyler"));
|
|
missions[MISN_JUPITER].primaryType[1] = M_DESTROY_TARGET_TYPE;
|
|
missions[MISN_JUPITER].target1[1] = CD_KRASS;
|
|
missions[MISN_JUPITER].targetValue1[1] = 1;
|
|
missions[MISN_JUPITER].completed1[1] = OB_HIDDEN;
|
|
|
|
/// Mission objective (Jupiter)
|
|
strcpy(missions[MISN_JUPITER].primaryObjective[2], _("Destroy Krass' support group"));
|
|
missions[MISN_JUPITER].primaryType[2] = M_DESTROY_ALL_TARGETS;
|
|
missions[MISN_JUPITER].target1[1] = CD_FIREFLY;
|
|
missions[MISN_JUPITER].targetValue1[1] = 4;
|
|
missions[MISN_JUPITER].completed1[2] = OB_HIDDEN;
|
|
|
|
missions[MISN_JUPITER].addAliens = ALWAYS;
|
|
|
|
|
|
/// Mission objective (Mars)
|
|
strcpy(missions[MISN_MARS].primaryObjective[0], _("Navigate asteroid belt"));
|
|
missions[MISN_MARS].primaryType[0] = M_DESTROY_TARGET_TYPE;
|
|
missions[MISN_MARS].target1[0] = CD_BOSS;
|
|
missions[MISN_MARS].targetValue1[0] = 1;
|
|
missions[MISN_MARS].completed1[0] = OB_INCOMPLETE;
|
|
|
|
missions[MISN_MARS].timeLimit1[0] = 2;
|
|
|
|
missions[MISN_MARS].addAliens = ALWAYS;
|
|
|
|
|
|
/// Mission objective (Earth)
|
|
strcpy(missions[MISN_EARTH].primaryObjective[0], _("Destroy WEAPCO frontline forces"));
|
|
missions[MISN_EARTH].primaryType[0] = M_DESTROY_TARGET_TYPE;
|
|
missions[MISN_EARTH].target1[0] = CD_ANY;
|
|
missions[MISN_EARTH].targetValue1[0] = 100;
|
|
missions[MISN_EARTH].completed1[0] = OB_INCOMPLETE;
|
|
|
|
missions[MISN_EARTH].addAliens = ALWAYS;
|
|
|
|
|
|
/// Mission objective (Venus)
|
|
strcpy(missions[MISN_VENUS].primaryObjective[0], _("Defeat Kline"));
|
|
missions[MISN_VENUS].primaryType[0] = M_DESTROY_ALL_TARGETS;
|
|
missions[MISN_VENUS].completed1[0] = OB_INCOMPLETE;
|
|
|
|
|
|
strcpy(missions[MISN_INTERCEPTION].primaryObjective[0], "");
|
|
missions[MISN_INTERCEPTION].primaryType[0] = M_DESTROY_ALL_TARGETS;
|
|
missions[MISN_INTERCEPTION].completed1[0] = OB_INCOMPLETE;
|
|
}
|
|
|
|
/*
|
|
Sets the mission Object to the mission number the player
|
|
is currently on. Timing is assigned if it is required. The rate
|
|
at which to add enemies in this mission is also set.
|
|
*/
|
|
void mission_set(int misn)
|
|
{
|
|
mission = missions[misn];
|
|
engine.minutes = mission.timeLimit1[0];
|
|
|
|
for (int i = 0 ; i < 3 ; i++)
|
|
{
|
|
if (mission.timeLimit1[i] > engine.minutes)
|
|
engine.minutes = mission.timeLimit1[i];
|
|
if (mission.timeLimit2[i] > engine.minutes)
|
|
engine.minutes = mission.timeLimit2[i];
|
|
|
|
if (mission.completed1[i] == OB_INCOMPLETE)
|
|
mission.remainingObjectives1++;
|
|
if (mission.completed2[i] == OB_INCOMPLETE)
|
|
mission.remainingObjectives1++;
|
|
}
|
|
|
|
engine.addAliens = mission.addAliens;
|
|
|
|
if (engine.minutes > -1)
|
|
{
|
|
engine.timeMission = 1;
|
|
engine.seconds = 0;
|
|
}
|
|
|
|
engine.counter2 = 0;
|
|
engine.timeTaken = 0;
|
|
}
|
|
|
|
/*
|
|
Call this whenever a mission requires all the remaining aliens to
|
|
automatically die
|
|
*/
|
|
static void mission_killAllEnemies()
|
|
{
|
|
for (int i = 0 ; i < ALIEN_MAX ; i++)
|
|
{
|
|
if ((aliens[i].flags & FL_WEAPCO) && (aliens[i].active)
|
|
&& (aliens[i].shield > 0))
|
|
aliens[i].shield = 0;
|
|
}
|
|
}
|
|
|
|
void mission_checkTimer()
|
|
{
|
|
for (int i = 0 ; i < 3 ; i++)
|
|
{
|
|
if ((mission.timeLimit1[i] == -1) && (mission.completed1[i] == OB_INCOMPLETE))
|
|
mission.completed1[i] = OB_JUST_FAILED;
|
|
}
|
|
|
|
for (int i = 0 ; i < 3 ; i++)
|
|
{
|
|
if ((mission.timeLimit2[i] == -1) && (mission.completed2[i] == OB_INCOMPLETE))
|
|
mission.completed2[i] = OB_JUST_FAILED;
|
|
}
|
|
|
|
// Find out if there are any uncompleted missions that require the timer
|
|
engine.timeMission = 0;
|
|
for (int i = 0 ; i < 3 ; i++)
|
|
{
|
|
if ((mission.timeLimit1[i] > -1) && (mission.completed1[i] == OB_INCOMPLETE))
|
|
engine.timeMission = 1;
|
|
if ((mission.timeLimit2[i] > -1) && (mission.completed2[i] == OB_INCOMPLETE))
|
|
engine.timeMission = 1;
|
|
}
|
|
|
|
// specific to Spirit Boss
|
|
if ((game.area == MISN_MOEBO)
|
|
&& (mission.completed1[0] < OB_INCOMPLETE))
|
|
engine.timeMission = 1;
|
|
|
|
// specific to the Asteroid belt
|
|
if ((game.area == MISN_MARS)
|
|
&& (mission.completed1[0] < OB_INCOMPLETE))
|
|
{
|
|
mission.completed1[0] = OB_COMPLETED;
|
|
mission_killAllEnemies();
|
|
engine.addAliens = -1;
|
|
info_setLine(_("*** All Primary Objectives Completed ***"), FONT_GREEN);
|
|
}
|
|
}
|
|
|
|
static void mission_evaluate(int type, int id, int *completed, int *targetValue, int fontColor)
|
|
{
|
|
char message[STRMAX_SHORT];
|
|
char fmt[STRMAX_SHORT];
|
|
|
|
if ((*targetValue <= 0) && (type != M_PROTECT_TARGET)
|
|
&& (type != M_PROTECT_PICKUP))
|
|
{
|
|
*completed = OB_JUST_COMPLETED;
|
|
mission_checkTimer();
|
|
if ((game.area == MISN_URUSOR) && (type == M_DISABLE_TARGET))
|
|
{
|
|
/// Dialog (Sid Wilson)
|
|
/// Used when Sid disables the last target in the Urusor mission.
|
|
radio_setMessage(FS_SID, _("All vessels disabled!"), 1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
strcpy(message, "");
|
|
switch(type)
|
|
{
|
|
case M_COLLECT:
|
|
switch(id)
|
|
{
|
|
case P_CASH:
|
|
radio_getRandomMessage(fmt, ngettext(
|
|
/// Info line messages for remaining cash to collect
|
|
/// This is a "\n"-separated list of possible choices to make. Please feel free
|
|
/// to add as many as you like. Each entry must have one instance of "%d", which
|
|
/// is replaced with the number remaining.
|
|
"Collect $%d more...\n"
|
|
"$%d more to collect...\n"
|
|
"Just $%d more needed...\n"
|
|
"Collect just $%d more...",
|
|
// Plural
|
|
"Collect $%d more...\n"
|
|
"$%d more to collect...\n"
|
|
"$%d more needed...",
|
|
*targetValue));
|
|
snprintf(message, STRMAX_SHORT, fmt, *targetValue);
|
|
break;
|
|
case P_CARGO:
|
|
radio_getRandomMessage(fmt, ngettext(
|
|
/// Info line messages for remaining cargo pods to collect
|
|
/// This is a "\n"-separated list of possible choices to make. Please feel free
|
|
/// to add as many as you like. Each entry must have one instance of "%d", which
|
|
/// is replaced with the number remaining.
|
|
"Collect %d more cargo pod...\n"
|
|
"%d more cargo pod to collect...\n"
|
|
"%d more cargo pod needed...\n"
|
|
"Collect just %d more cargo pod...\n"
|
|
"Only %d cargo pod left to collect...",
|
|
// Plural
|
|
"Collect %d more cargo pods...\n"
|
|
"%d more cargo pods to collect...\n"
|
|
"%d more cargo pods needed...\n"
|
|
"Collect %d remaining cargo pods...",
|
|
*targetValue));
|
|
snprintf(message, STRMAX_SHORT, fmt, *targetValue);
|
|
break;
|
|
case P_ORE:
|
|
radio_getRandomMessage(fmt, ngettext(
|
|
/// Info line messages for remaining ore to collect
|
|
/// This is a "\n"-separated list of possible choices to make. Please feel free
|
|
/// to add as many as you like. Each entry must have one instance of "%d", which
|
|
/// is replaced with the number remaining.
|
|
"Collect %d more piece of ore...\n"
|
|
"%d more piece of ore to collect...\n"
|
|
"%d more piece of ore needed...\n"
|
|
"Collect just %d more piece...",
|
|
// Plural
|
|
"Collect %d more pieces of ore...\n"
|
|
"%d more pieces of ore to collect...\n"
|
|
"%d more pieces of ore needed...",
|
|
*targetValue));
|
|
snprintf(message, STRMAX_SHORT, fmt, *targetValue);
|
|
break;
|
|
}
|
|
break;
|
|
case M_PROTECT_PICKUP:
|
|
*completed = OB_JUST_FAILED;
|
|
switch(id)
|
|
{
|
|
case P_CARGO:
|
|
strcpy(message, _("Cargo pod destroyed!"));
|
|
if (game.area == MISN_CERADSE) // Get lectured by Sid
|
|
/// Dialog (Sid Wilson)
|
|
/// Used when a cargo pod is destroyed in the Ceradse mission.
|
|
radio_setMessage(FS_SID, _("Chris, we needed that pod! I told you that we couldn't afford to lose a single one!"), 1);
|
|
break;
|
|
case P_ESCAPEPOD:
|
|
strcpy(message, _("Escape Pod lost!"));
|
|
if (game.area == MISN_ODEON) // Get lectured by Phoebe
|
|
{
|
|
/// Dialog (Phoebe Lexx)
|
|
/// Used when Ursula is lost in the Odeon mission.
|
|
radio_setMessage(FS_PHOEBE, _("No... Ursula..."), 1);
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
case M_PROTECT_TARGET:
|
|
if (*targetValue <= 0)
|
|
{
|
|
*completed = OB_JUST_FAILED;
|
|
switch (game.area)
|
|
{
|
|
case MISN_NEROD:
|
|
/// Dialog (Sid Wilson)
|
|
/// Used when Phoebe is killed in the Nerod mission.
|
|
radio_setMessage(FS_SID, _("Dammit, Chris! We just lost her!"), 1);
|
|
break;
|
|
case MISN_ALLEZ:
|
|
/// Dialog (friendly transport from Eyananth, Allez mission)
|
|
/// Used when the friendly transport in the Allez mission is destroyed.
|
|
radio_setMessage(FS_CREW, _("No no no no no! Hull bre-..."), 1);
|
|
break;
|
|
case MISN_URUSOR:
|
|
/// Dialog (Sid Wilson)
|
|
/// Used when a target transport is destroyed in the Urusor mission.
|
|
radio_setMessage(FS_SID, _("Chris, we've got to disable them, not destroy them!!"), 1);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case M_DESTROY_TARGET_TYPE:
|
|
if ((*targetValue <= 10) || (*targetValue % 10 == 0))
|
|
{
|
|
radio_getRandomMessage(fmt, ngettext(
|
|
/// Info line messages for remaining enemies to destroy
|
|
/// This is a "\n"-separated list of possible choices to make. Please feel free
|
|
/// to add as many as you like. Each entry must have one instance of "%d", which
|
|
/// is replaced with the number remaining.
|
|
"Destroy %d more target...\n"
|
|
"%d more target to destroy...\n"
|
|
"%d target remains...\n"
|
|
"Destroy just %d more...\n"
|
|
"Only %d target left...\n"
|
|
"Destroy %d last target...",
|
|
// Plural
|
|
"Destroy %d more targets...\n"
|
|
"%d more targets to destroy...\n"
|
|
"%d targets remain...\n"
|
|
"Destroy %d remaining targets...",
|
|
*targetValue));
|
|
snprintf(message, STRMAX_SHORT, fmt, *targetValue);
|
|
}
|
|
break;
|
|
case M_DISABLE_TARGET:
|
|
radio_getRandomMessage(fmt, ngettext(
|
|
/// Info line messages for remaining enemies to disable
|
|
/// This is a "\n"-separated list of possible choices to make. Please feel free
|
|
/// to add as many as you like. Each entry must have one instance of "%d", which
|
|
/// is replaced with the number remaining.
|
|
"Disable %d more target...\n"
|
|
"%d more target to disable...\n"
|
|
"Disable just %d more...\n"
|
|
"Disable %d last target...",
|
|
// Plural
|
|
"Disable %d more targets...\n"
|
|
"%d more targets to disable...\n"
|
|
"Disable %d remaining targets...",
|
|
*targetValue));
|
|
snprintf(message, STRMAX_SHORT, fmt, *targetValue);
|
|
break;
|
|
}
|
|
|
|
if (strcmp(message, "") != 0)
|
|
info_setLine(message, fontColor);
|
|
}
|
|
}
|
|
|
|
void mission_updateRequirements(int type, int id, int value)
|
|
{
|
|
char message[STRMAX_SHORT];
|
|
char fmt[STRMAX_SHORT];
|
|
int matched = 0;
|
|
int slavesNeeded;
|
|
|
|
// Can't complete missions if you're dead!
|
|
if (player.shield <= 0)
|
|
return;
|
|
|
|
// We don't need to worry here since if Sid dies,
|
|
// you will automatically fail the mission(!)
|
|
if ((type == M_DESTROY_TARGET_TYPE) && (id == CD_SID))
|
|
{
|
|
info_setLine(_("Sid has been killed!"), FONT_RED);
|
|
mission.completed1[0] = OB_JUST_FAILED;
|
|
/// Dialog (Sid Wilson)
|
|
/// Used when Sid is killed.
|
|
/// Translation note: the end is Sid trying to say "FUCK" and getting cut
|
|
/// out because of the failure of his communication system, so please
|
|
/// translate that to the start of a similar curse word in the target
|
|
/// language being similarly cut out.
|
|
radio_setMessage(FS_SID, _("HULL BREACHED! SYSTEMS FAILING! F-..."), 1);
|
|
}
|
|
|
|
for (int i = 0 ; i < 3 ; i++)
|
|
{
|
|
if ((mission.completed1[i] == OB_INCOMPLETE) || (mission.completed1[i] == OB_CONDITION))
|
|
{
|
|
if ((mission.primaryType[i] == type)
|
|
&& ((mission.target1[i] == id)
|
|
|| (mission.target1[i] == CD_ANY)))
|
|
{
|
|
matched = 1;
|
|
mission.targetValue1[i] -= value;
|
|
mission_evaluate(type, id, &mission.completed1[i], &mission.targetValue1[i], FONT_CYAN);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Don't evaluate secondary Objectives at the same time!
|
|
if (matched)
|
|
return;
|
|
|
|
for (int i = 0 ; i < 3 ; i++)
|
|
{
|
|
if ((mission.completed2[i] == OB_INCOMPLETE) || (mission.completed2[i] == OB_CONDITION))
|
|
{
|
|
if ((mission.secondaryType[i] == type)
|
|
&& ((mission.target2[i] == id)
|
|
|| (mission.target2[i] == CD_ANY)))
|
|
{
|
|
mission.targetValue2[i] -= value;
|
|
mission_evaluate(type, id, &mission.completed2[i], &mission.targetValue2[i], FONT_YELLOW);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Special Case - Interceptions
|
|
if (game.area == MISN_INTERCEPTION)
|
|
{
|
|
if ((type == M_COLLECT) && (id == P_SLAVES))
|
|
{
|
|
if (intermission_planets[PLANET_RESCUESLAVES].missionCompleted == 0)
|
|
{
|
|
if (game.slavesRescued >= SLAVE_RESCUE_TARGET)
|
|
{
|
|
info_setLine(_("*** Slaves Rescued - Mission Completed ***"), FONT_GREEN);
|
|
intermission_planets[PLANET_RESCUESLAVES].missionCompleted = 1;
|
|
/// Dialog (Chris Bainfield)
|
|
/// Used when you rescue enough slaves for the Eyananth slave rescue mission.
|
|
radio_setMessage(FS_CHRIS, _("Alright, I think I've rescued enough slaves to stir up some trouble for WEAPCO!"), 1);
|
|
}
|
|
else
|
|
{
|
|
slavesNeeded = SLAVE_RESCUE_TARGET - game.slavesRescued;
|
|
radio_getRandomMessage(fmt, ngettext(
|
|
/// Info line messages for remaining slaves to rescue
|
|
/// This is a "\n"-separated list of possible choices to make. Please feel free
|
|
/// to add as many as you like. Each entry must have one instance of "%d", which
|
|
/// is replaced with the number remaining.
|
|
"Rescue %d more slave...\n"
|
|
"Rescue at least %d more slave...\n"
|
|
"At least %d more slave to rescue...\n"
|
|
"At least %d more rescued slave needed...",
|
|
// Plural
|
|
"Rescue %d more slaves...\n"
|
|
"Rescue at least %d more slaves...\n"
|
|
"At least %d more slaves to rescue...\n"
|
|
"At least %d more rescued slaves needed...",
|
|
slavesNeeded));
|
|
snprintf(message, STRMAX_SHORT, fmt, slavesNeeded);
|
|
info_setLine(message, FONT_CYAN);
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((type == M_DESTROY_TARGET_TYPE) && (id == CD_CLOAKFIGHTER))
|
|
{
|
|
info_setLine(_("*** Experimental Fighter Destroyed - Mission Completed ***"), FONT_GREEN);
|
|
intermission_planets[PLANET_CLOAKFIGHTER].missionCompleted = 1;
|
|
/// Dialog (Chris Bainfield)
|
|
/// Used when the Mordor cloak ship is destroyed.
|
|
radio_setMessage(FS_CHRIS, _("That's one less surprise that WEAPCO can spring on us!"), 1);
|
|
game.experimentalShield = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
This is only used a few times in the game.
|
|
Missions 11 and 23 to be exact!
|
|
*/
|
|
static int mission_revealObjectives()
|
|
{
|
|
int allDone = 1;
|
|
|
|
for (int i = 0 ; i < 3 ; i++)
|
|
{
|
|
if (mission.completed1[i] == OB_HIDDEN)
|
|
{
|
|
mission.completed1[i] = OB_INCOMPLETE;
|
|
allDone = 0;
|
|
}
|
|
}
|
|
|
|
if (!allDone)
|
|
{
|
|
// Activate Kline!! :)
|
|
if (game.area == MISN_ELAMALE)
|
|
{
|
|
mission_killAllEnemies();
|
|
events_sync();
|
|
aliens[ALIEN_KLINE].active = 1;
|
|
aliens[ALIEN_KLINE].x = player.x + 1000;
|
|
aliens[ALIEN_KLINE].y = player.y;
|
|
aliens[ALIEN_KLINE].flags |= FL_IMMORTAL | FL_NOFIRE;
|
|
player_setTarget(ALIEN_KLINE);
|
|
#ifdef OLD_MUSIC
|
|
audio_playMusic("music/TranceGeneration.mod", -1);
|
|
#else
|
|
audio_playMusic("music/last_cyber_dance.ogg", -1);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
return allDone;
|
|
}
|
|
|
|
int mission_checkCompleted()
|
|
{
|
|
for (int i = 0 ; i < 3 ; i++)
|
|
{
|
|
if (mission.completed1[i] == OB_INCOMPLETE)
|
|
{
|
|
if ((mission.primaryType[i] == M_DESTROY_ALL_TARGETS)
|
|
&& (engine.allAliensDead)
|
|
&& (mission.remainingObjectives1 + mission.remainingObjectives2 == 1))
|
|
{
|
|
mission.completed1[i] = OB_JUST_COMPLETED;
|
|
mission_checkTimer();
|
|
}
|
|
}
|
|
}
|
|
|
|
for (int i = 0 ; i < 3 ; i++)
|
|
{
|
|
if (mission.completed2[i] == OB_INCOMPLETE)
|
|
{
|
|
if ((mission.secondaryType[i] == M_DESTROY_ALL_TARGETS)
|
|
&& (engine.allAliensDead)
|
|
&& (mission.remainingObjectives1 + mission.remainingObjectives2 == 1))
|
|
{
|
|
mission.completed2[i] = OB_JUST_COMPLETED;
|
|
mission_checkTimer();
|
|
}
|
|
}
|
|
}
|
|
|
|
for (int i = 0 ; i < 3 ; i++)
|
|
{
|
|
if (mission.completed1[i] == OB_JUST_COMPLETED)
|
|
{
|
|
if (mission.remainingObjectives1 > 1)
|
|
{
|
|
if ((game.area != MISN_POSWIC) || (i != 1))
|
|
info_setLine(_("*** Primary Objective Completed ***"), FONT_GREEN);
|
|
else
|
|
info_setLine(_(">>> Primary Objective Failed <<<"), FONT_RED);
|
|
mission.completed1[i] = OB_COMPLETED;
|
|
}
|
|
else
|
|
{
|
|
if (mission.remainingObjectives2 > 0)
|
|
{
|
|
info_setLine(_("Emergency warp drive activated. Press button to engage."), FONT_CYAN);
|
|
}
|
|
|
|
if (game.area != MISN_INTERCEPTION)
|
|
info_setLine(_("*** All Primary Objectives Completed ***"), FONT_GREEN);
|
|
else
|
|
info_setLine(_("*** Interception Destroyed ***"), FONT_GREEN);
|
|
mission.completed1[i] = OB_COMPLETED;
|
|
|
|
// do some area specific things
|
|
if ((game.area == MISN_MOEBO)
|
|
|| (game.area == MISN_DORIM)
|
|
|| (game.area == MISN_ELLESH)
|
|
|| (game.area == MISN_MARS))
|
|
{
|
|
if (mission.remainingObjectives2 == 0)
|
|
{
|
|
mission_killAllEnemies();
|
|
engine.addAliens = -1;
|
|
}
|
|
}
|
|
|
|
if (game.area == MISN_EARTH)
|
|
{
|
|
/// Dialog (Chris Bainfield)
|
|
/// Used when the Earth mission is completed.
|
|
radio_setMessage(FS_CHRIS, _("You guys stay here and keep things under control. I'm going after Kethlan!"), 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (mission.completed2[i] == OB_JUST_COMPLETED)
|
|
{
|
|
if (mission.remainingObjectives2 > 1)
|
|
{
|
|
info_setLine(_("*** Secondary Objective Completed ***"), FONT_GREEN);
|
|
mission.completed2[i] = OB_COMPLETED;
|
|
}
|
|
else
|
|
{
|
|
info_setLine(_("*** All Secondary Objectives Completed ***"), FONT_GREEN);
|
|
mission.completed2[i] = OB_COMPLETED;
|
|
|
|
// do some area specific things
|
|
if ((game.area == MISN_DORIM)
|
|
&& (mission.remainingObjectives1 == 0))
|
|
{
|
|
mission_killAllEnemies();
|
|
engine.addAliens = -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (mission.completed1[i] == OB_JUST_FAILED)
|
|
{
|
|
info_setLine(_(">>> MISSION FAILED <<<"), FONT_RED);
|
|
mission.completed1[i] = OB_FAILED;
|
|
}
|
|
|
|
if (mission.completed2[i] == OB_JUST_FAILED)
|
|
{
|
|
info_setLine(_(">>> Secondary Objective Failed <<<"), FONT_RED);
|
|
mission.completed2[i] = OB_FAILED;
|
|
}
|
|
}
|
|
|
|
int remaining;
|
|
int add = 0;
|
|
int allDone = 1;
|
|
|
|
// Zero Objective list for a recount
|
|
mission.remainingObjectives1 = mission.remainingObjectives2 = 0;
|
|
|
|
for (int i = 0 ; i < 3 ; i++)
|
|
{
|
|
if (mission.primaryType[i] != M_NONE)
|
|
{
|
|
if (mission.completed1[i] == OB_INCOMPLETE)
|
|
{
|
|
mission.remainingObjectives1++;
|
|
if (mission.primaryType[i] == M_DESTROY_ALL_TARGETS)
|
|
add = 1;
|
|
allDone = 0;
|
|
}
|
|
|
|
if (mission.completed1[i] < OB_INCOMPLETE)
|
|
return 0;
|
|
}
|
|
if (mission.secondaryType[i] != M_NONE)
|
|
{
|
|
if (mission.completed2[i] == OB_INCOMPLETE)
|
|
{
|
|
mission.remainingObjectives2++;
|
|
if (mission.secondaryType[i] == M_DESTROY_ALL_TARGETS)
|
|
add = 1;
|
|
allDone = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (allDone)
|
|
allDone = mission_revealObjectives();
|
|
|
|
remaining = mission.remainingObjectives1 + mission.remainingObjectives2;
|
|
|
|
// We've only got one Objective left and it's destroy all targets,
|
|
// so stop adding aliens (otherwise it might be impossible to finish!)
|
|
if ((add) && (remaining == 1))
|
|
engine.addAliens = -1;
|
|
|
|
return allDone;
|
|
}
|
|
|
|
int mission_checkFailed()
|
|
{
|
|
for (int i = 0 ; i < 3 ; i++)
|
|
{
|
|
if (mission.completed1[i] < OB_INCOMPLETE)
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void mission_drawScreen()
|
|
{
|
|
SDL_Rect r = {0, 0, (int)screen->w, 2};
|
|
|
|
for (int i = 0 ; i < (int)(screen->h / 4) - 30 ; i++)
|
|
{
|
|
r.y = (i * 2) + 62; // Not a typo; a black gap is left in the middle if it's 60.
|
|
SDL_FillRect(screen, &r, SDL_MapRGB(screen->format, 0, i, 0));
|
|
r.y = (screen->h - (i * 2) - 60);
|
|
SDL_FillRect(screen, &r, SDL_MapRGB(screen->format, 0, i, 0));
|
|
}
|
|
|
|
screen_drawRect(screen->w / 2 - BRIEFING_WIDTH / 2, screen->h / 2 - 235, BRIEFING_WIDTH, 20, 0x00, 0x77, 0x00);
|
|
screen_drawRect(screen->w / 2 - BRIEFING_WIDTH / 2, screen->h / 2 - 215, BRIEFING_WIDTH, 130, 0x00, 0x33, 0x00);
|
|
screen_renderUnicode(_("Primary Objectives"), screen->w / 2 - BRIEFING_WIDTH / 2 + 10, screen->h / 2 - 232, FONT_WHITE);
|
|
|
|
for (int i = 0 ; i < 3 ; i++)
|
|
{
|
|
if ((mission.primaryType[i] != M_NONE) && (mission.completed1[i] != OB_HIDDEN))
|
|
{
|
|
screen_renderUnicode(mission.primaryObjective[i], screen->w / 2 - BRIEFING_WIDTH / 2 + 20, screen->h / 2 + (i * 30) - 191, FONT_WHITE);
|
|
}
|
|
}
|
|
|
|
if (mission.secondaryType[0] != M_NONE)
|
|
{
|
|
screen_drawRect(screen->w / 2 - BRIEFING_WIDTH / 2, screen->h / 2 - 75, BRIEFING_WIDTH, 20, 0x00, 0x77, 0x77);
|
|
screen_drawRect(screen->w / 2 - BRIEFING_WIDTH / 2, screen->h / 2 - 55, BRIEFING_WIDTH, 130, 0x00, 0x33, 0x33);
|
|
screen_renderUnicode(_("Secondary Objectives"), screen->w / 2 - BRIEFING_WIDTH / 2 + 10, screen->h / 2 - 72, FONT_WHITE);
|
|
|
|
for (int i = 0 ; i < 3 ; i++)
|
|
{
|
|
if (mission.secondaryType[i] != M_NONE)
|
|
{
|
|
screen_renderUnicode(mission.secondaryObjective[i], screen->w / 2 - BRIEFING_WIDTH / 2 + 20, screen->h / 2 + (i * 30) - 31, FONT_WHITE);
|
|
game.secondaryMissions++;
|
|
}
|
|
}
|
|
}
|
|
|
|
screen_drawRect(screen->w / 2 - BRIEFING_WIDTH / 2, screen->h / 2 + 85, BRIEFING_WIDTH, 20, 0x77, 0x77, 0x00);
|
|
screen_drawRect(screen->w / 2 - BRIEFING_WIDTH / 2, screen->h / 2 + 105, BRIEFING_WIDTH, 130, 0x33, 0x33, 0x00);
|
|
screen_renderUnicode(_("Additional Information"), screen->w / 2 - BRIEFING_WIDTH / 2 + 10, screen->h / 2 + 88, FONT_WHITE);
|
|
}
|
|
|
|
/*
|
|
Simply displays a screen with all the mission information on it, pulled
|
|
back from the data stored in the mission Object. The music for the
|
|
mission begins playing here.
|
|
*/
|
|
void mission_showStartScreen()
|
|
{
|
|
char temp[STRMAX_SHORT];
|
|
|
|
screen_clear(black);
|
|
renderer_update();
|
|
|
|
gfx_loadSprites();
|
|
/// Used to indicate the player's shield meter in the HUD.
|
|
gfx_createTextObject(TS_SHIELD, _("Shield"), 0, 0, FONT_WHITE);
|
|
|
|
gfx_createTextObject(TS_TARGET, _("Target"), 0, 0, FONT_WHITE);
|
|
gfx_createTextObject(TS_TARGET_SID, _("Sid"), 0, 0, FONT_WHITE);
|
|
gfx_createTextObject(TS_TARGET_PHOEBE, _("Phoebe"), 0, 0, FONT_WHITE);
|
|
gfx_createTextObject(TS_TARGET_KLINE, _("Kline"), 0, 0, FONT_WHITE);
|
|
gfx_createTextObject(TS_POWER, "Power", 0, 0, FONT_WHITE);
|
|
gfx_createTextObject(TS_OUTPUT, "Output", 0, 0, FONT_WHITE);
|
|
gfx_createTextObject(TS_COOLER, "Cooler", 0, 0, FONT_WHITE);
|
|
audio_playRandomTrack();
|
|
|
|
if (game.area != MISN_INTERCEPTION)
|
|
{
|
|
renderer_update();
|
|
|
|
player_flushInput();
|
|
engine.done = ENGINE_RUNNING;
|
|
engine.keyState[KEY_FIRE] = 0;
|
|
engine.keyState[KEY_ALTFIRE] = 0;
|
|
engine.keyState[KEY_ESCAPE] = 0;
|
|
|
|
while (1)
|
|
{
|
|
screen_clear(black);
|
|
mission_drawScreen();
|
|
|
|
if (mission.timeLimit1[0] > 0)
|
|
{
|
|
if (game.area == MISN_MARS)
|
|
{
|
|
snprintf(temp, STRMAX_SHORT, ngettext(
|
|
/// "%d" must be retained. It is replaced with the mission required
|
|
/// survival time in minutes.
|
|
"SURVIVAL FOR %d minute",
|
|
"SURVIVAL FOR %d minutes",
|
|
mission.timeLimit1[0]), mission.timeLimit1[0]);
|
|
}
|
|
else
|
|
{
|
|
snprintf(temp, STRMAX_SHORT, ngettext(
|
|
/// "%d" must be retained. It is replaced with the mission time
|
|
/// limit in minutes.
|
|
"TIME LIMIT: %d minute",
|
|
"TIME LIMIT: %d minutes",
|
|
mission.timeLimit1[0]), mission.timeLimit1[0]);
|
|
}
|
|
screen_renderUnicode(temp, -1, screen->h / 2 + 195, FONT_RED);
|
|
}
|
|
|
|
switch (game.area)
|
|
{
|
|
case MISN_URUSOR:
|
|
case MISN_DORIM:
|
|
case MISN_SIVEDI:
|
|
case MISN_ALMARTHA:
|
|
case MISN_ELLESH:
|
|
case MISN_MARS:
|
|
case MISN_VENUS:
|
|
screen_renderUnicode(_("Phoebe Lexx will not be present"), screen->w / 2 - BRIEFING_WIDTH / 2 + 20, screen->h / 2 + 115, FONT_WHITE);
|
|
if (game.hasWingMate2)
|
|
screen_renderUnicode(_("Ursula Lexx will not be present"), screen->w / 2 - BRIEFING_WIDTH / 2 + 20, screen->h / 2 + 145, FONT_WHITE);
|
|
break;
|
|
}
|
|
|
|
if ((game.area == MISN_URUSOR)
|
|
|| (game.area == MISN_POSWIC)
|
|
|| (game.area == MISN_EARTH))
|
|
screen_renderUnicode(_("Sid Wilson will join you on this mission"), screen->w / 2 - BRIEFING_WIDTH / 2 + 20, screen->h / 2 + 175, FONT_WHITE);
|
|
|
|
renderer_update();
|
|
|
|
game_delayFrame();
|
|
player_getInput();
|
|
if ((engine.keyState[KEY_FIRE]) || (engine.keyState[KEY_ALTFIRE])
|
|
|| (engine.keyState[KEY_ESCAPE]))
|
|
break;
|
|
}
|
|
|
|
screen_clear(black);
|
|
renderer_update();
|
|
screen_clear(black);
|
|
}
|
|
|
|
engine.gameSection = SECTION_GAME;
|
|
}
|
|
|
|
/*
|
|
Display a screen showing all the information from the mission
|
|
the player has just done. This includes Objectives that have been
|
|
completed and failed. A mission timer is also displayed at the bottom
|
|
of the screen.
|
|
*/
|
|
void mission_showFinishedScreen()
|
|
{
|
|
int shield_bonus;
|
|
char temp[STRMAX_SHORT];
|
|
|
|
if (game.area != MISN_INTERCEPTION)
|
|
{
|
|
screen_clear(black);
|
|
renderer_update();
|
|
|
|
if (game.shots > 0)
|
|
game.accuracy = (game.hits * 100) / game.shots;
|
|
|
|
if (mission.secondaryType[0] != M_NONE)
|
|
{
|
|
for (int i = 0 ; i < 3 ; i++)
|
|
{
|
|
if ((mission.secondaryType[i] != M_NONE) && (mission.completed2[i] >= OB_COMPLETED))
|
|
game.secondaryMissionsCompleted++;
|
|
}
|
|
}
|
|
|
|
shield_bonus = 0;
|
|
if (mission.remainingObjectives1 + mission.remainingObjectives2 == 0)
|
|
{
|
|
if (game.difficulty == DIFFICULTY_NIGHTMARE)
|
|
shield_bonus = 100;
|
|
else
|
|
shield_bonus = player.shield * 10;
|
|
|
|
game.cash += shield_bonus;
|
|
game.cashEarned += shield_bonus;
|
|
}
|
|
|
|
game.timeTaken += engine.timeTaken;
|
|
|
|
// Do some mission specific stuff here...
|
|
if (game.area == MISN_HAIL)
|
|
game.cash -= 500;
|
|
else if (game.area == MISN_ODEON)
|
|
game.hasWingMate2 = 1;
|
|
else if (game.area == MISN_ALMARTHA)
|
|
game.cash -= 2000;
|
|
|
|
intermission_unlockPlanets();
|
|
|
|
renderer_update();
|
|
|
|
player_flushInput();
|
|
engine.done = ENGINE_RUNNING;
|
|
engine.keyState[KEY_FIRE] = 0;
|
|
|
|
while (1)
|
|
{
|
|
screen_clear(black);
|
|
mission_drawScreen();
|
|
|
|
for (int i = 0 ; i < 3 ; i++)
|
|
{
|
|
if (mission.primaryType[i] != M_NONE)
|
|
{
|
|
if ((game.area != MISN_POSWIC) || (i != 1))
|
|
{
|
|
strcpy(temp, _("COMPLETED"));
|
|
screen_renderUnicode(temp, screen->w / 2 + BRIEFING_WIDTH / 2 - gfx_unicodeWidth(temp) - 20, screen->h / 2 + (i * 30) - 191, FONT_GREEN);
|
|
}
|
|
else
|
|
{
|
|
strcpy(temp, _("FAILED"));
|
|
screen_renderUnicode(temp, screen->w / 2 + BRIEFING_WIDTH / 2 - gfx_unicodeWidth(temp) - 20, screen->h / 2 + (i * 30) - 191, FONT_RED);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (mission.secondaryType[0] != M_NONE)
|
|
{
|
|
for (int i = 0 ; i < 3 ; i++)
|
|
{
|
|
if (mission.secondaryType[i] != M_NONE)
|
|
{
|
|
strcpy(temp, mission.secondaryObjective[i]);
|
|
if (mission.completed2[i] >= OB_COMPLETED)
|
|
{
|
|
strcpy(temp, _("COMPLETED"));
|
|
screen_renderUnicode(temp, screen->w / 2 + BRIEFING_WIDTH / 2 - gfx_unicodeWidth(temp) - 20, screen->h / 2 + (i * 30) - 31, FONT_GREEN);
|
|
}
|
|
else
|
|
{
|
|
strcpy(temp, _("FAILED"));
|
|
screen_renderUnicode(temp, screen->w / 2 + BRIEFING_WIDTH / 2 - gfx_unicodeWidth(temp) - 20, screen->h / 2 + (i * 30) - 31, FONT_RED);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (shield_bonus)
|
|
{
|
|
/// "%d" must be retained. It is replaced with the money earned
|
|
/// from the shield bonus.
|
|
snprintf(temp, STRMAX_SHORT, _("Shield Bonus: $%d"), shield_bonus);
|
|
screen_renderUnicode(temp, -1, screen->h / 2 + 130, FONT_WHITE);
|
|
}
|
|
|
|
/// "%02ld" sequences (which represent minutes and seconds,
|
|
/// respectively) must remain and stay in the same order relative
|
|
/// to each other. The ":"s between them can be changed to other
|
|
/// characters if desired, e.g. this would be acceptable:
|
|
///
|
|
/// "Mission time: %02ldm %02lds"
|
|
///
|
|
/// If you are familiar with printf formatting, you may also change
|
|
/// the formatting as long as the "ld" type remains. For example,
|
|
/// the "%02ld" sequences may be changed to "%ld" if you wish to
|
|
/// not force two digits to be filled in (e.g. to render the number
|
|
/// 3 as "3" instead of "03").
|
|
snprintf(temp, STRMAX_SHORT, _("Mission Time: %02ld:%02ld"), engine.timeTaken / 60, engine.timeTaken % 60);
|
|
|
|
screen_renderUnicode(temp, -1, screen->h / 2 + 200, FONT_WHITE);
|
|
|
|
renderer_update();
|
|
game_delayFrame();
|
|
player_getInput();
|
|
if ((engine.keyState[KEY_FIRE]))
|
|
break;
|
|
}
|
|
}
|
|
|
|
audio_haltMusic();
|
|
}
|