2015-10-20 13:51:49 +02:00
|
|
|
/*
|
2022-07-30 17:10:02 +02:00
|
|
|
Copyright (C) 2015-2019,2022 Parallel Realities
|
2015-10-20 13:51:49 +02:00
|
|
|
|
|
|
|
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 2
|
|
|
|
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, write to the Free Software
|
|
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
2022-07-30 17:10:02 +02:00
|
|
|
#include "../common.h"
|
2022-07-31 11:43:20 +02:00
|
|
|
|
|
|
|
#include "../battle/bullets.h"
|
|
|
|
#include "../battle/effects.h"
|
2022-07-30 17:10:02 +02:00
|
|
|
#include "../battle/fighters.h"
|
|
|
|
#include "../battle/hud.h"
|
|
|
|
#include "../battle/objectives.h"
|
2022-07-31 11:43:20 +02:00
|
|
|
#include "../galaxy/mission.h"
|
|
|
|
#include "../game/trophies.h"
|
|
|
|
#include "../json/cJSON.h"
|
|
|
|
#include "../system/controls.h"
|
|
|
|
#include "../system/lookup.h"
|
|
|
|
#include "../system/sound.h"
|
|
|
|
#include "../system/util.h"
|
|
|
|
#include "player.h"
|
2022-07-30 17:10:02 +02:00
|
|
|
|
2022-07-31 11:43:20 +02:00
|
|
|
#define MAX_SELECTABLE_PLAYERS 8
|
|
|
|
#define MAX_SELECTABLE_TARGETS 8
|
2022-07-30 17:10:02 +02:00
|
|
|
|
2022-07-31 11:43:20 +02:00
|
|
|
extern App app;
|
|
|
|
extern Battle battle;
|
|
|
|
extern Colors colors;
|
|
|
|
extern Dev dev;
|
2022-07-30 17:10:02 +02:00
|
|
|
extern Entity *player;
|
|
|
|
extern Entity *self;
|
2022-07-31 11:43:20 +02:00
|
|
|
extern Game game;
|
2015-10-20 13:51:49 +02:00
|
|
|
|
|
|
|
static void selectTarget(void);
|
2015-10-23 08:08:18 +02:00
|
|
|
static void switchGuns(void);
|
2015-11-24 08:16:48 +01:00
|
|
|
static void cycleRadarZoom(void);
|
2015-10-27 08:24:17 +01:00
|
|
|
static void selectMissionTarget(void);
|
2015-10-31 11:00:46 +01:00
|
|
|
static void selectNewPlayer(int dir);
|
|
|
|
static void initPlayerSelect(void);
|
2015-11-15 17:18:17 +01:00
|
|
|
static void activateBoost(void);
|
2015-11-16 00:23:03 +01:00
|
|
|
static void deactivateBoost(void);
|
2015-11-15 17:18:17 +01:00
|
|
|
static void activateECM(void);
|
2015-11-23 15:52:11 +01:00
|
|
|
static void handleKeyboard(void);
|
|
|
|
static void faceMouse(void);
|
|
|
|
static void handleMouse(void);
|
2015-12-14 12:41:43 +01:00
|
|
|
static void preFireMissile(void);
|
2016-03-02 23:19:26 +01:00
|
|
|
static void applyRestrictions(void);
|
2022-07-31 11:43:20 +02:00
|
|
|
static int isPriorityMissionTarget(Entity *e, int dist, int closest);
|
|
|
|
static int targetOutOfRange(void);
|
2016-06-05 12:22:19 +02:00
|
|
|
static void rechargeBoostECM(void);
|
2016-05-16 12:40:39 +02:00
|
|
|
static void setPilotName(void);
|
2016-07-27 17:17:56 +02:00
|
|
|
static void updateDeathStats(void);
|
2017-06-22 08:56:40 +02:00
|
|
|
static void handleSuspicionLevel(void);
|
2015-10-23 08:08:18 +02:00
|
|
|
|
2022-07-31 11:43:20 +02:00
|
|
|
static int selectedPlayerIndex;
|
|
|
|
static int availableGuns[BT_MAX];
|
2015-10-31 11:00:46 +01:00
|
|
|
static Entity *availablePlayerUnits[MAX_SELECTABLE_PLAYERS];
|
2015-10-23 08:08:18 +02:00
|
|
|
|
|
|
|
void initPlayer(void)
|
|
|
|
{
|
|
|
|
int i, n;
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2015-10-23 08:08:18 +02:00
|
|
|
memset(&availableGuns, 0, sizeof(int) * BT_MAX);
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2015-12-28 14:44:57 +01:00
|
|
|
battle.numPlayerGuns = 0;
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2015-10-23 08:08:18 +02:00
|
|
|
player->selectedGunType = -1;
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2015-12-14 15:05:02 +01:00
|
|
|
if (!player->combinedGuns)
|
2015-10-23 08:08:18 +02:00
|
|
|
{
|
2022-07-31 11:43:20 +02:00
|
|
|
for (i = 0; i < MAX_FIGHTER_GUNS; i++)
|
2015-10-23 08:08:18 +02:00
|
|
|
{
|
2015-12-14 15:05:02 +01:00
|
|
|
n = player->guns[i].type;
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2015-12-14 15:05:02 +01:00
|
|
|
if (n)
|
2015-10-23 08:08:18 +02:00
|
|
|
{
|
2015-12-28 14:44:57 +01:00
|
|
|
if (!availableGuns[n])
|
|
|
|
{
|
|
|
|
battle.numPlayerGuns++;
|
|
|
|
}
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2015-12-14 15:05:02 +01:00
|
|
|
availableGuns[n] = 1;
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2015-12-14 15:05:02 +01:00
|
|
|
if (player->selectedGunType == -1)
|
|
|
|
{
|
|
|
|
player->selectedGunType = n;
|
|
|
|
}
|
2015-10-23 08:08:18 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-12-14 15:05:02 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
player->selectedGunType = 0;
|
|
|
|
}
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2016-05-16 12:40:39 +02:00
|
|
|
setPilotName();
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2015-11-01 00:09:43 +01:00
|
|
|
player->action = NULL;
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2015-11-15 18:12:04 +01:00
|
|
|
battle.boostTimer = BOOST_RECHARGE_TIME;
|
|
|
|
battle.ecmTimer = ECM_RECHARGE_TIME;
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2016-05-15 09:19:26 +02:00
|
|
|
player->flags |= EF_NO_HEALTH_BAR;
|
2016-07-27 09:44:02 +02:00
|
|
|
player->flags &= ~EF_IMMORTAL;
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2017-06-04 10:31:36 +02:00
|
|
|
player->target = NULL;
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2016-05-24 17:49:14 +02:00
|
|
|
game.stats[STAT_EPIC_KILL_STREAK] = MAX(game.stats[STAT_EPIC_KILL_STREAK], battle.stats[STAT_EPIC_KILL_STREAK]);
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2016-05-24 17:49:14 +02:00
|
|
|
battle.stats[STAT_EPIC_KILL_STREAK] = 0;
|
2015-10-23 08:08:18 +02:00
|
|
|
}
|
2015-10-20 13:51:49 +02:00
|
|
|
|
2016-05-16 12:40:39 +02:00
|
|
|
static void setPilotName(void)
|
|
|
|
{
|
|
|
|
int i, pos;
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2016-05-16 12:40:39 +02:00
|
|
|
pos = -1;
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2022-07-31 11:43:20 +02:00
|
|
|
for (i = 0; i < strlen(game.currentMission->pilot); i++)
|
2016-05-16 12:40:39 +02:00
|
|
|
{
|
|
|
|
if (game.currentMission->pilot[i] == ' ')
|
|
|
|
{
|
|
|
|
pos = i;
|
|
|
|
}
|
|
|
|
}
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2016-05-16 12:40:39 +02:00
|
|
|
memset(player->name, '\0', MAX_NAME_LENGTH);
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2016-05-16 12:40:39 +02:00
|
|
|
if (pos != -1)
|
|
|
|
{
|
|
|
|
memcpy(player->name, game.currentMission->pilot + pos + 1, strlen(game.currentMission->pilot) - pos - 1);
|
|
|
|
}
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2016-05-16 12:40:39 +02:00
|
|
|
SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "Pilot name = '%s'", player->name);
|
|
|
|
}
|
|
|
|
|
2015-10-20 13:51:49 +02:00
|
|
|
void doPlayer(void)
|
|
|
|
{
|
2016-05-15 09:19:26 +02:00
|
|
|
self = player;
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2016-07-20 08:13:40 +02:00
|
|
|
rechargeBoostECM();
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2016-05-15 09:19:26 +02:00
|
|
|
if (game.currentMission->challengeData.isChallenge)
|
2015-10-20 13:51:49 +02:00
|
|
|
{
|
2016-05-15 09:19:26 +02:00
|
|
|
applyRestrictions();
|
|
|
|
}
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2016-05-15 09:19:26 +02:00
|
|
|
if (player->alive == ALIVE_ALIVE && player->systemPower > 0)
|
|
|
|
{
|
|
|
|
handleKeyboard();
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2016-05-15 09:19:26 +02:00
|
|
|
handleMouse();
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2017-06-22 08:56:40 +02:00
|
|
|
handleSuspicionLevel();
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2016-05-15 09:19:26 +02:00
|
|
|
if (!player->target || player->target->health <= 0 || player->target->systemPower <= 0 || targetOutOfRange())
|
|
|
|
{
|
|
|
|
selectTarget();
|
2015-11-23 15:52:11 +01:00
|
|
|
}
|
2016-05-15 09:19:26 +02:00
|
|
|
}
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2016-05-15 09:19:26 +02:00
|
|
|
player->angle = ((int)player->angle) % 360;
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2016-05-15 09:19:26 +02:00
|
|
|
if (player->health <= 0 && battle.status == MS_IN_PROGRESS)
|
|
|
|
{
|
|
|
|
if (game.currentMission->challengeData.isChallenge)
|
|
|
|
{
|
|
|
|
if (!game.currentMission->challengeData.allowPlayerDeath)
|
2015-10-20 13:51:49 +02:00
|
|
|
{
|
2016-07-27 17:17:56 +02:00
|
|
|
updateDeathStats();
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2015-11-23 15:52:11 +01:00
|
|
|
failMission();
|
2015-10-20 13:51:49 +02:00
|
|
|
}
|
2015-11-23 15:52:11 +01:00
|
|
|
}
|
2016-05-15 09:19:26 +02:00
|
|
|
else if (!battle.isEpic)
|
|
|
|
{
|
2016-07-27 17:17:56 +02:00
|
|
|
updateDeathStats();
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2016-05-15 09:19:26 +02:00
|
|
|
failMission();
|
|
|
|
}
|
|
|
|
else if (player->health == -FPS)
|
2015-11-23 15:52:11 +01:00
|
|
|
{
|
2016-07-27 17:17:56 +02:00
|
|
|
updateDeathStats();
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2016-08-20 12:42:10 +02:00
|
|
|
updateCondition("PLAYER", TT_DESTROY);
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2016-08-20 12:42:10 +02:00
|
|
|
if (battle.status == MS_IN_PROGRESS)
|
|
|
|
{
|
|
|
|
initPlayerSelect();
|
|
|
|
}
|
2015-11-23 15:52:11 +01:00
|
|
|
}
|
2016-05-15 09:19:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (battle.status == MS_IN_PROGRESS)
|
|
|
|
{
|
|
|
|
selectMissionTarget();
|
|
|
|
}
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2016-05-15 09:19:26 +02:00
|
|
|
if (dev.playerUnlimitedMissiles)
|
|
|
|
{
|
|
|
|
player->missiles = 999;
|
|
|
|
}
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2016-05-15 09:19:26 +02:00
|
|
|
/* really only used in challenge mode */
|
|
|
|
if (player->systemPower <= 0 && battle.status == MS_IN_PROGRESS)
|
|
|
|
{
|
|
|
|
if (game.currentMission->challengeData.isChallenge)
|
2015-12-18 11:12:37 +01:00
|
|
|
{
|
2016-05-15 09:19:26 +02:00
|
|
|
addHudMessage(colors.red, _("Challenge Failed!"));
|
|
|
|
failMission();
|
2015-12-18 11:12:37 +01:00
|
|
|
}
|
2015-11-23 15:52:11 +01:00
|
|
|
}
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2015-11-23 15:52:11 +01:00
|
|
|
if (battle.boostTimer == (int)BOOST_FINISHED_TIME)
|
|
|
|
{
|
|
|
|
deactivateBoost();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-27 17:17:56 +02:00
|
|
|
static void updateDeathStats(void)
|
|
|
|
{
|
|
|
|
battle.stats[STAT_PLAYER_KILLED]++;
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2016-07-27 17:17:56 +02:00
|
|
|
/* the player is known as "Player", so we need to check the craft they were assigned to */
|
|
|
|
if (strcmp(game.currentMission->craft, "ATAF") == 0)
|
|
|
|
{
|
|
|
|
awardTrophy("ATAF_DESTROYED");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-05 12:22:19 +02:00
|
|
|
static void rechargeBoostECM(void)
|
|
|
|
{
|
|
|
|
int boostTimer, ecmTimer;
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2016-06-05 12:22:19 +02:00
|
|
|
boostTimer = battle.boostTimer;
|
|
|
|
battle.boostTimer = MIN(battle.boostTimer + 1, BOOST_RECHARGE_TIME);
|
|
|
|
if (boostTimer < BOOST_RECHARGE_TIME && battle.boostTimer == BOOST_RECHARGE_TIME)
|
|
|
|
{
|
|
|
|
playSound(SND_RECHARGED);
|
|
|
|
}
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2016-06-05 12:22:19 +02:00
|
|
|
ecmTimer = battle.ecmTimer;
|
|
|
|
battle.ecmTimer = MIN(battle.ecmTimer + 1, ECM_RECHARGE_TIME);
|
|
|
|
if (ecmTimer < ECM_RECHARGE_TIME && battle.ecmTimer == ECM_RECHARGE_TIME)
|
|
|
|
{
|
|
|
|
playSound(SND_RECHARGED);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-15 09:19:26 +02:00
|
|
|
static int targetOutOfRange(void)
|
|
|
|
{
|
|
|
|
return (app.gameplay.autoSwitchPlayerTarget && getDistance(player->x, player->y, player->target->x, player->target->y) > SCREEN_WIDTH * 2);
|
|
|
|
}
|
|
|
|
|
2016-03-02 23:19:26 +01:00
|
|
|
static void applyRestrictions(void)
|
|
|
|
{
|
|
|
|
if (game.currentMission->challengeData.noMissiles)
|
|
|
|
{
|
|
|
|
player->missiles = 0;
|
|
|
|
}
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2016-03-02 23:19:26 +01:00
|
|
|
if (game.currentMission->challengeData.noBoost)
|
|
|
|
{
|
|
|
|
battle.boostTimer = 0;
|
|
|
|
}
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2016-03-02 23:19:26 +01:00
|
|
|
if (game.currentMission->challengeData.noECM)
|
|
|
|
{
|
|
|
|
battle.ecmTimer = 0;
|
|
|
|
}
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2016-03-02 23:19:26 +01:00
|
|
|
if (game.currentMission->challengeData.noGuns)
|
|
|
|
{
|
|
|
|
player->reload = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-23 15:52:11 +01:00
|
|
|
static void handleKeyboard(void)
|
|
|
|
{
|
|
|
|
if (battle.status == MS_IN_PROGRESS)
|
|
|
|
{
|
2016-04-16 17:48:30 +02:00
|
|
|
if (isControl(CONTROL_BOOST) && player->speed > 0)
|
2015-11-23 15:52:11 +01:00
|
|
|
{
|
2016-02-15 16:24:19 +01:00
|
|
|
if (battle.boostTimer == BOOST_RECHARGE_TIME)
|
|
|
|
{
|
|
|
|
playSound(SND_BOOST);
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2016-02-15 16:24:19 +01:00
|
|
|
activateBoost();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
playSound(SND_GUI_DENIED);
|
|
|
|
}
|
2016-03-03 19:03:07 +01:00
|
|
|
|
|
|
|
clearControl(CONTROL_BOOST);
|
2015-11-23 15:52:11 +01:00
|
|
|
}
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2016-03-05 14:21:17 +01:00
|
|
|
if (isControl(CONTROL_TARGET))
|
2015-11-23 15:52:11 +01:00
|
|
|
{
|
2015-11-26 10:53:49 +01:00
|
|
|
selectTarget();
|
2016-03-03 19:03:07 +01:00
|
|
|
|
|
|
|
clearControl(CONTROL_TARGET);
|
2015-11-26 10:53:49 +01:00
|
|
|
}
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2016-03-05 14:21:17 +01:00
|
|
|
if (isControl(CONTROL_ECM))
|
2015-11-26 10:53:49 +01:00
|
|
|
{
|
2016-02-15 16:24:19 +01:00
|
|
|
if (battle.ecmTimer == ECM_RECHARGE_TIME)
|
|
|
|
{
|
2016-02-20 15:19:59 +01:00
|
|
|
playSound(SND_ECM);
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2016-02-15 16:24:19 +01:00
|
|
|
activateECM();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
playSound(SND_GUI_DENIED);
|
|
|
|
}
|
2016-03-03 19:03:07 +01:00
|
|
|
|
|
|
|
clearControl(CONTROL_ECM);
|
2015-11-23 15:52:11 +01:00
|
|
|
}
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2016-03-05 14:21:17 +01:00
|
|
|
if (isControl(CONTROL_BRAKE))
|
2015-11-23 15:52:11 +01:00
|
|
|
{
|
2015-11-26 10:53:49 +01:00
|
|
|
applyFighterBrakes();
|
2015-11-23 15:52:11 +01:00
|
|
|
}
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2016-03-05 14:21:17 +01:00
|
|
|
if (isControl(CONTROL_GUNS))
|
2015-12-14 12:41:43 +01:00
|
|
|
{
|
|
|
|
switchGuns();
|
2016-03-03 19:03:07 +01:00
|
|
|
|
|
|
|
clearControl(CONTROL_GUNS);
|
2015-12-14 12:41:43 +01:00
|
|
|
}
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2016-03-05 14:21:17 +01:00
|
|
|
if (isControl(CONTROL_RADAR))
|
2015-12-14 12:41:43 +01:00
|
|
|
{
|
|
|
|
cycleRadarZoom();
|
2016-03-03 19:03:07 +01:00
|
|
|
|
|
|
|
clearControl(CONTROL_RADAR);
|
2015-12-14 12:41:43 +01:00
|
|
|
}
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2016-03-05 14:21:17 +01:00
|
|
|
if (isControl(CONTROL_MISSILE))
|
2015-12-14 12:41:43 +01:00
|
|
|
{
|
|
|
|
preFireMissile();
|
2016-03-03 19:03:07 +01:00
|
|
|
|
|
|
|
clearControl(CONTROL_MISSILE);
|
2015-12-14 12:41:43 +01:00
|
|
|
}
|
2015-11-23 15:52:11 +01:00
|
|
|
}
|
2016-02-27 17:15:41 +01:00
|
|
|
else
|
|
|
|
{
|
2016-05-15 09:19:26 +02:00
|
|
|
applyFighterBrakes();
|
2016-02-27 17:15:41 +01:00
|
|
|
}
|
2015-11-23 15:52:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void handleMouse(void)
|
|
|
|
{
|
|
|
|
faceMouse();
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2015-11-23 15:52:11 +01:00
|
|
|
if (battle.status == MS_IN_PROGRESS)
|
|
|
|
{
|
2016-03-05 14:21:17 +01:00
|
|
|
if (isControl(CONTROL_FIRE) && !player->reload && player->guns[0].type)
|
2015-11-23 15:52:11 +01:00
|
|
|
{
|
2015-12-23 17:25:25 +01:00
|
|
|
if (player->selectedGunType != BT_ROCKET)
|
|
|
|
{
|
|
|
|
fireGuns(player);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fireRocket(player);
|
|
|
|
}
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2017-06-22 08:56:40 +02:00
|
|
|
if (battle.hasSuspicionLevel && !battle.numEnemies && !battle.suspicionCoolOff)
|
2016-05-16 18:03:46 +02:00
|
|
|
{
|
2017-06-22 08:56:40 +02:00
|
|
|
battle.suspicionLevel += (MAX_SUSPICION_LEVEL * 0.05);
|
2016-05-16 18:03:46 +02:00
|
|
|
}
|
2015-11-23 15:52:11 +01:00
|
|
|
}
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2016-03-05 14:21:17 +01:00
|
|
|
if (isControl(CONTROL_ACCELERATE))
|
2015-11-23 15:52:11 +01:00
|
|
|
{
|
2016-03-02 23:19:26 +01:00
|
|
|
if (battle.boostTimer > BOOST_FINISHED_TIME || game.currentMission->challengeData.noBoost)
|
2015-10-20 13:51:49 +02:00
|
|
|
{
|
2015-11-23 15:52:11 +01:00
|
|
|
applyFighterThrust();
|
2015-10-27 08:24:17 +01:00
|
|
|
}
|
2015-10-20 13:51:49 +02:00
|
|
|
}
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2016-03-05 14:21:17 +01:00
|
|
|
if (isControl(CONTROL_MISSILE))
|
2015-10-20 13:51:49 +02:00
|
|
|
{
|
2015-12-14 12:41:43 +01:00
|
|
|
preFireMissile();
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2015-11-23 15:52:11 +01:00
|
|
|
app.mouse.button[SDL_BUTTON_MIDDLE] = 0;
|
2015-10-20 13:51:49 +02:00
|
|
|
}
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2016-03-05 14:21:17 +01:00
|
|
|
if (isControl(CONTROL_GUNS))
|
2015-11-24 08:16:48 +01:00
|
|
|
{
|
2016-02-21 08:48:22 +01:00
|
|
|
switchGuns();
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2015-11-24 08:16:48 +01:00
|
|
|
app.mouse.button[SDL_BUTTON_X1] = 0;
|
|
|
|
}
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2016-03-05 14:21:17 +01:00
|
|
|
if (isControl(CONTROL_RADAR))
|
2015-11-24 08:16:48 +01:00
|
|
|
{
|
2016-02-21 08:48:22 +01:00
|
|
|
cycleRadarZoom();
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2015-11-24 08:16:48 +01:00
|
|
|
app.mouse.button[SDL_BUTTON_X2] = 0;
|
|
|
|
}
|
2015-10-20 13:51:49 +02:00
|
|
|
}
|
2015-11-23 15:52:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void faceMouse(void)
|
|
|
|
{
|
|
|
|
int dir;
|
|
|
|
int x, y, wantedAngle;
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2015-11-23 15:52:11 +01:00
|
|
|
x = player->x - battle.camera.x;
|
|
|
|
y = player->y - battle.camera.y;
|
|
|
|
wantedAngle = getAngle(x, y, app.mouse.x, app.mouse.y);
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2015-11-23 15:52:11 +01:00
|
|
|
wantedAngle %= 360;
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2015-11-23 15:52:11 +01:00
|
|
|
if (fabs(wantedAngle - player->angle) > 2)
|
2015-11-16 00:23:03 +01:00
|
|
|
{
|
2015-11-23 15:52:11 +01:00
|
|
|
dir = ((int)(wantedAngle - player->angle + 360)) % 360 > 180 ? -1 : 1;
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2015-11-23 15:52:11 +01:00
|
|
|
player->angle += dir * 4;
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2015-11-23 15:52:11 +01:00
|
|
|
player->angle = mod(player->angle, 360);
|
2015-11-16 00:23:03 +01:00
|
|
|
}
|
2015-10-31 11:00:46 +01:00
|
|
|
}
|
|
|
|
|
2015-12-14 12:41:43 +01:00
|
|
|
static void preFireMissile(void)
|
|
|
|
{
|
|
|
|
if (player->missiles && player->target)
|
|
|
|
{
|
|
|
|
if (getDistance(player->x, player->y, player->target->x, player->target->y) <= SCREEN_WIDTH)
|
|
|
|
{
|
|
|
|
fireMissile(player);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-06-05 12:22:19 +02:00
|
|
|
playSound(SND_GUI_DENIED);
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2016-02-28 14:45:17 +01:00
|
|
|
addHudMessage(colors.white, _("Target not in range"));
|
2015-12-14 12:41:43 +01:00
|
|
|
}
|
|
|
|
}
|
2016-06-05 12:22:19 +02:00
|
|
|
else if (!player->missiles)
|
|
|
|
{
|
|
|
|
addHudMessage(colors.white, _("Out of missiles"));
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2016-06-05 12:22:19 +02:00
|
|
|
playSound(SND_NO_MISSILES);
|
|
|
|
}
|
2015-12-14 12:41:43 +01:00
|
|
|
}
|
|
|
|
|
2016-08-28 19:48:55 +02:00
|
|
|
static void initPlayerSelect(void)
|
2015-10-31 11:00:46 +01:00
|
|
|
{
|
|
|
|
Entity *e;
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2022-07-31 11:43:20 +02:00
|
|
|
memset(&availablePlayerUnits, 0, sizeof(Entity *) * MAX_SELECTABLE_PLAYERS);
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2015-10-31 11:00:46 +01:00
|
|
|
selectedPlayerIndex = 0;
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2016-08-28 19:48:55 +02:00
|
|
|
if (battle.epicLives == 0 || (battle.epicLives > 0 && --battle.epicLives > 0))
|
2015-10-31 11:00:46 +01:00
|
|
|
{
|
2022-07-31 11:43:20 +02:00
|
|
|
for (e = battle.entityHead.next; e != NULL; e = e->next)
|
2015-10-31 11:00:46 +01:00
|
|
|
{
|
2016-08-20 12:42:10 +02:00
|
|
|
if (e->active && e->type == ET_FIGHTER && e->health > 0 && e->side == SIDE_ALLIES && selectedPlayerIndex < MAX_SELECTABLE_PLAYERS)
|
|
|
|
{
|
|
|
|
availablePlayerUnits[selectedPlayerIndex++] = e;
|
|
|
|
}
|
2015-10-31 11:00:46 +01:00
|
|
|
}
|
|
|
|
}
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2015-11-01 00:09:43 +01:00
|
|
|
if (selectedPlayerIndex > 0)
|
|
|
|
{
|
|
|
|
battle.playerSelect = 1;
|
2016-03-03 19:03:07 +01:00
|
|
|
selectedPlayerIndex = 0;
|
2015-11-01 00:09:43 +01:00
|
|
|
memset(&app.keyboard, 0, sizeof(int) * MAX_KEYBOARD_KEYS);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-02-28 14:02:57 +01:00
|
|
|
battle.isEpic = 0;
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2016-08-28 19:48:55 +02:00
|
|
|
if (battle.epicKills > 0 && battle.stats[STAT_ENEMIES_KILLED_PLAYER] < battle.epicKills)
|
|
|
|
{
|
|
|
|
battle.unwinnable = 0;
|
|
|
|
}
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2015-11-14 09:41:31 +01:00
|
|
|
failMission();
|
2015-11-01 00:09:43 +01:00
|
|
|
}
|
2015-10-31 11:00:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void doPlayerSelect(void)
|
|
|
|
{
|
2016-03-27 09:55:58 +02:00
|
|
|
if (isControl(CONTROL_PREV_FIGHTER))
|
2015-10-31 11:00:46 +01:00
|
|
|
{
|
|
|
|
selectNewPlayer(-1);
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2016-03-27 09:55:58 +02:00
|
|
|
clearControl(CONTROL_PREV_FIGHTER);
|
2015-10-31 11:00:46 +01:00
|
|
|
}
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2016-03-27 09:55:58 +02:00
|
|
|
if (isControl(CONTROL_NEXT_FIGHTER))
|
2015-10-31 11:00:46 +01:00
|
|
|
{
|
|
|
|
selectNewPlayer(1);
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2016-03-27 09:55:58 +02:00
|
|
|
clearControl(CONTROL_NEXT_FIGHTER);
|
2015-10-31 11:00:46 +01:00
|
|
|
}
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2016-03-27 09:55:58 +02:00
|
|
|
if (player->health > 0 && isAcceptControl())
|
2015-10-31 11:00:46 +01:00
|
|
|
{
|
2015-11-01 00:09:43 +01:00
|
|
|
battle.playerSelect = 0;
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2015-11-01 00:09:43 +01:00
|
|
|
initPlayer();
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2016-03-27 09:55:58 +02:00
|
|
|
resetAcceptControls();
|
2015-10-31 11:00:46 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void selectNewPlayer(int dir)
|
|
|
|
{
|
2016-05-15 09:19:26 +02:00
|
|
|
player = NULL;
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2015-10-31 11:00:46 +01:00
|
|
|
do
|
|
|
|
{
|
|
|
|
selectedPlayerIndex += dir;
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2015-10-31 11:00:46 +01:00
|
|
|
selectedPlayerIndex = mod(selectedPlayerIndex, MAX_SELECTABLE_PLAYERS);
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2015-11-01 00:09:43 +01:00
|
|
|
player = availablePlayerUnits[selectedPlayerIndex];
|
2022-07-31 11:43:20 +02:00
|
|
|
} while (player == NULL);
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2018-12-14 09:00:16 +01:00
|
|
|
battle.camera.x = player->x - (app.winWidth / 2);
|
|
|
|
battle.camera.y = player->y - (app.winHeight / 2);
|
2015-10-20 13:51:49 +02:00
|
|
|
}
|
|
|
|
|
2015-11-15 17:18:17 +01:00
|
|
|
static void activateBoost(void)
|
|
|
|
{
|
2016-07-20 08:13:40 +02:00
|
|
|
player->dx += sin(TO_RAIDANS(player->angle)) * 10;
|
|
|
|
player->dy += -cos(TO_RAIDANS(player->angle)) * 10;
|
|
|
|
player->thrust = sqrt((player->dx * player->dx) + (player->dy * player->dy));
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2015-11-15 18:12:04 +01:00
|
|
|
battle.boostTimer = 0;
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2015-11-17 08:23:50 +01:00
|
|
|
battle.stats[STAT_BOOST]++;
|
2015-11-15 17:18:17 +01:00
|
|
|
}
|
|
|
|
|
2015-11-16 00:23:03 +01:00
|
|
|
static void deactivateBoost(void)
|
|
|
|
{
|
|
|
|
float v, thrust;
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2015-11-16 00:23:03 +01:00
|
|
|
thrust = -1;
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2016-07-20 08:13:40 +02:00
|
|
|
while (thrust != player->thrust)
|
2015-11-16 00:23:03 +01:00
|
|
|
{
|
2016-07-20 08:13:40 +02:00
|
|
|
thrust = player->thrust;
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2016-07-20 08:13:40 +02:00
|
|
|
v = (player->speed / sqrt(player->thrust));
|
|
|
|
player->dx = v * player->dx;
|
|
|
|
player->dy = v * player->dy;
|
|
|
|
player->thrust = sqrt((player->dx * player->dx) + (player->dy * player->dy));
|
2015-11-16 00:23:03 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-15 17:18:17 +01:00
|
|
|
static void activateECM(void)
|
|
|
|
{
|
2015-11-15 18:12:04 +01:00
|
|
|
battle.ecmTimer = 0;
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2015-11-29 09:34:25 +01:00
|
|
|
addECMEffect(player);
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2015-11-17 08:23:50 +01:00
|
|
|
battle.stats[STAT_ECM]++;
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2017-06-22 08:56:40 +02:00
|
|
|
if (battle.hasSuspicionLevel && !battle.numEnemies && !battle.suspicionCoolOff)
|
2016-05-16 18:03:46 +02:00
|
|
|
{
|
|
|
|
battle.suspicionLevel += (MAX_SUSPICION_LEVEL * 0.25);
|
|
|
|
}
|
2015-11-15 17:18:17 +01:00
|
|
|
}
|
|
|
|
|
2015-10-23 08:08:18 +02:00
|
|
|
static void switchGuns(void)
|
|
|
|
{
|
|
|
|
int i;
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2015-10-23 08:08:18 +02:00
|
|
|
i = player->selectedGunType;
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2016-08-10 00:13:25 +02:00
|
|
|
if (!player->combinedGuns && battle.numPlayerGuns)
|
2015-10-23 08:08:18 +02:00
|
|
|
{
|
2015-12-14 15:05:02 +01:00
|
|
|
do
|
|
|
|
{
|
|
|
|
i = (i + 1) % BT_MAX;
|
2022-07-31 11:43:20 +02:00
|
|
|
} while (!availableGuns[i]);
|
2015-10-23 08:08:18 +02:00
|
|
|
}
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2016-02-20 16:04:15 +01:00
|
|
|
if (player->selectedGunType != i)
|
|
|
|
{
|
|
|
|
playSound(SND_SELECT_WEAPON);
|
|
|
|
player->selectedGunType = i;
|
|
|
|
}
|
2015-10-23 08:08:18 +02:00
|
|
|
}
|
|
|
|
|
2015-10-20 13:51:49 +02:00
|
|
|
static void selectTarget(void)
|
|
|
|
{
|
2015-11-01 11:46:24 +01:00
|
|
|
unsigned int closest = MAX_TARGET_RANGE;
|
|
|
|
unsigned int dist = MAX_TARGET_RANGE;
|
2022-07-31 11:43:20 +02:00
|
|
|
int i, total;
|
|
|
|
Entity *e, *near;
|
|
|
|
Entity *targets[MAX_SELECTABLE_TARGETS];
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2015-11-23 11:14:28 +01:00
|
|
|
i = 0;
|
2015-11-23 15:52:11 +01:00
|
|
|
near = NULL;
|
2022-07-31 11:43:20 +02:00
|
|
|
memset(targets, 0, sizeof(Entity *) * MAX_SELECTABLE_TARGETS);
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2016-03-03 12:31:18 +01:00
|
|
|
if (player->target && (!player->target->health || !player->target->systemPower))
|
|
|
|
{
|
|
|
|
player->target = NULL;
|
|
|
|
}
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2022-07-31 11:43:20 +02:00
|
|
|
for (e = battle.entityHead.next; e != NULL; e = e->next)
|
2015-10-20 13:51:49 +02:00
|
|
|
{
|
2016-04-09 14:22:45 +02:00
|
|
|
if (e->active && e != player && (e->flags & EF_TAKES_DAMAGE) && (!(e->flags & EF_NO_PLAYER_TARGET)) && e->side != player->side && e->alive == ALIVE_ALIVE && e->systemPower > 0 && i < MAX_SELECTABLE_TARGETS)
|
2015-10-20 13:51:49 +02:00
|
|
|
{
|
2016-07-20 08:13:40 +02:00
|
|
|
dist = getDistance(player->x, player->y, e->x, e->y);
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2015-10-20 13:51:49 +02:00
|
|
|
if (dist < closest)
|
|
|
|
{
|
2015-11-23 11:14:28 +01:00
|
|
|
near = e;
|
2015-10-20 13:51:49 +02:00
|
|
|
closest = dist;
|
|
|
|
}
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2015-11-23 11:14:28 +01:00
|
|
|
if (collision(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, e->x - battle.camera.x - (e->w / 2), e->y - battle.camera.y - (e->h / 2), e->w, e->h))
|
|
|
|
{
|
|
|
|
targets[i++] = e;
|
|
|
|
}
|
|
|
|
else if (e == player->target)
|
|
|
|
{
|
|
|
|
player->target = NULL;
|
|
|
|
}
|
2015-10-20 13:51:49 +02:00
|
|
|
}
|
|
|
|
}
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2015-11-23 11:14:28 +01:00
|
|
|
total = i;
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2022-07-31 11:43:20 +02:00
|
|
|
for (i = 0; i < total; i++)
|
2015-11-23 11:14:28 +01:00
|
|
|
{
|
|
|
|
if (targets[i] == player->target)
|
|
|
|
{
|
|
|
|
if (i + 1 < MAX_SELECTABLE_TARGETS && targets[i + 1])
|
|
|
|
{
|
|
|
|
player->target = targets[i + 1];
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
player->target = targets[0];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2015-12-10 11:16:44 +01:00
|
|
|
if (!player->target || !targets[0])
|
2015-11-23 11:14:28 +01:00
|
|
|
{
|
|
|
|
player->target = near;
|
|
|
|
}
|
2015-10-20 13:51:49 +02:00
|
|
|
}
|
2015-10-27 08:24:17 +01:00
|
|
|
|
|
|
|
static void selectMissionTarget(void)
|
|
|
|
{
|
2015-11-01 11:46:24 +01:00
|
|
|
unsigned int closest = MAX_TARGET_RANGE;
|
|
|
|
unsigned int dist = MAX_TARGET_RANGE;
|
2022-07-31 11:43:20 +02:00
|
|
|
Entity *e;
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2015-10-27 08:24:17 +01:00
|
|
|
battle.missionTarget = NULL;
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2022-07-31 11:43:20 +02:00
|
|
|
for (e = battle.entityHead.next; e != NULL; e = e->next)
|
2015-10-27 08:24:17 +01:00
|
|
|
{
|
2015-10-31 00:31:20 +01:00
|
|
|
if (e->active && e->flags & EF_MISSION_TARGET && e->alive == ALIVE_ALIVE)
|
2015-10-27 08:24:17 +01:00
|
|
|
{
|
2016-07-20 08:13:40 +02:00
|
|
|
dist = getDistance(player->x, player->y, e->x, e->y);
|
2016-03-03 19:03:07 +01:00
|
|
|
|
2015-10-27 08:24:17 +01:00
|
|
|
if (battle.missionTarget == NULL)
|
|
|
|
{
|
|
|
|
battle.missionTarget = e;
|
2015-11-22 12:42:04 +01:00
|
|
|
closest = dist;
|
2015-10-27 08:24:17 +01:00
|
|
|
}
|
|
|
|
else if (battle.missionTarget->type == ET_WAYPOINT && e->type != ET_WAYPOINT)
|
|
|
|
{
|
|
|
|
battle.missionTarget = e;
|
|
|
|
}
|
|
|
|
else if (battle.missionTarget->type != ET_WAYPOINT)
|
|
|
|
{
|
2016-03-03 12:31:18 +01:00
|
|
|
if (isPriorityMissionTarget(e, dist, closest))
|
2015-10-27 08:24:17 +01:00
|
|
|
{
|
|
|
|
battle.missionTarget = e;
|
|
|
|
closest = dist;
|
|
|
|
}
|
|
|
|
}
|
2016-04-04 12:23:32 +02:00
|
|
|
else if (battle.missionTarget->type == ET_WAYPOINT && e->type == ET_WAYPOINT && e->id == battle.missionTarget->id)
|
2015-10-27 08:24:17 +01:00
|
|
|
{
|
|
|
|
battle.missionTarget = e;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-11-24 08:16:48 +01:00
|
|
|
|
2016-03-03 12:31:18 +01:00
|
|
|
static int isPriorityMissionTarget(Entity *e, int dist, int closest)
|
|
|
|
{
|
|
|
|
/* battle.missionTarget is secondary, e is not */
|
|
|
|
if ((battle.missionTarget->flags & EF_SECONDARY_TARGET) > (e->flags & EF_SECONDARY_TARGET))
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2016-03-03 12:31:18 +01:00
|
|
|
/* battle.missionTarget is not secondary, e is */
|
|
|
|
if ((battle.missionTarget->flags & EF_SECONDARY_TARGET) < (e->flags & EF_SECONDARY_TARGET))
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2016-03-03 12:31:18 +01:00
|
|
|
/* normal distance check */
|
|
|
|
return dist < closest;
|
|
|
|
}
|
|
|
|
|
2016-07-20 08:13:40 +02:00
|
|
|
void setInitialPlayerAngle(void)
|
|
|
|
{
|
|
|
|
Entity *e;
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2016-07-20 08:13:40 +02:00
|
|
|
selectMissionTarget();
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2016-07-20 08:13:40 +02:00
|
|
|
if (battle.missionTarget)
|
|
|
|
{
|
|
|
|
player->angle = getAngle(player->x, player->y, battle.missionTarget->x, battle.missionTarget->y);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
selectTarget();
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2016-07-20 08:13:40 +02:00
|
|
|
if (player->target)
|
|
|
|
{
|
|
|
|
player->angle = getAngle(player->x, player->y, player->target->x, player->target->y);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (battle.jumpgate)
|
|
|
|
{
|
|
|
|
player->angle = getAngle(player->x, player->y, battle.jumpgate->x, battle.jumpgate->y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2022-07-31 11:43:20 +02:00
|
|
|
for (e = battle.entityHead.next; e != NULL; e = e->next)
|
2016-07-20 08:13:40 +02:00
|
|
|
{
|
|
|
|
if (e->side == player->side)
|
|
|
|
{
|
|
|
|
e->angle = player->angle;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-24 08:16:48 +01:00
|
|
|
static void cycleRadarZoom(void)
|
|
|
|
{
|
2016-05-25 08:57:13 +02:00
|
|
|
battle.radarRange = (battle.radarRange + 1) % 3;
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2016-06-05 12:22:19 +02:00
|
|
|
playSound(SND_ZOOM);
|
2015-11-24 08:16:48 +01:00
|
|
|
}
|
2016-02-20 16:04:15 +01:00
|
|
|
|
|
|
|
int playerHasGun(int type)
|
|
|
|
{
|
|
|
|
return availableGuns[type];
|
|
|
|
}
|
2016-03-17 09:11:52 +01:00
|
|
|
|
2017-06-22 08:56:40 +02:00
|
|
|
static void handleSuspicionLevel(void)
|
|
|
|
{
|
|
|
|
if (battle.hasSuspicionLevel)
|
|
|
|
{
|
|
|
|
/* don't allow the suspicion level to drop too far */
|
|
|
|
battle.suspicionLevel = MAX(battle.suspicionLevel, -(MAX_SUSPICION_LEVEL * 0.25));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-17 09:11:52 +01:00
|
|
|
void loadPlayer(cJSON *node)
|
|
|
|
{
|
|
|
|
char *type;
|
2022-07-31 11:43:20 +02:00
|
|
|
int side, addFlags;
|
|
|
|
long flags;
|
2016-03-17 09:11:52 +01:00
|
|
|
|
|
|
|
type = cJSON_GetObjectItem(node, "type")->valuestring;
|
|
|
|
side = lookup(cJSON_GetObjectItem(node, "side")->valuestring);
|
2016-05-15 09:19:26 +02:00
|
|
|
flags = -1;
|
2016-03-17 09:11:52 +01:00
|
|
|
|
|
|
|
player = spawnFighter(type, 0, 0, side);
|
|
|
|
player->x = BATTLE_AREA_WIDTH / 2;
|
|
|
|
player->y = BATTLE_AREA_HEIGHT / 2;
|
|
|
|
|
|
|
|
if (cJSON_GetObjectItem(node, "x"))
|
|
|
|
{
|
|
|
|
player->x = (cJSON_GetObjectItem(node, "x")->valuedouble / BATTLE_AREA_CELLS) * BATTLE_AREA_WIDTH;
|
|
|
|
player->y = (cJSON_GetObjectItem(node, "y")->valuedouble / BATTLE_AREA_CELLS) * BATTLE_AREA_HEIGHT;
|
|
|
|
}
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2016-05-15 09:19:26 +02:00
|
|
|
if (cJSON_GetObjectItem(node, "flags"))
|
|
|
|
{
|
|
|
|
flags = flagsToLong(cJSON_GetObjectItem(node, "flags")->valuestring, &addFlags);
|
|
|
|
}
|
2019-11-07 09:13:57 +01:00
|
|
|
|
2016-05-15 09:19:26 +02:00
|
|
|
if (flags != -1)
|
|
|
|
{
|
|
|
|
if (addFlags)
|
|
|
|
{
|
|
|
|
player->flags |= flags;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
player->flags = flags;
|
|
|
|
|
|
|
|
SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN, "Flags for Player replaced");
|
|
|
|
}
|
|
|
|
}
|
2016-03-17 09:11:52 +01:00
|
|
|
|
|
|
|
if (strcmp(type, "Tug") == 0)
|
|
|
|
{
|
|
|
|
battle.stats[STAT_TUG]++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strcmp(type, "Shuttle") == 0)
|
|
|
|
{
|
|
|
|
battle.stats[STAT_SHUTTLE]++;
|
|
|
|
}
|
|
|
|
}
|