2015-10-20 13:51:49 +02:00
|
|
|
/*
|
|
|
|
Copyright (C) 2015 Parallel Realities
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "player.h"
|
|
|
|
|
|
|
|
static void selectTarget(void);
|
2015-10-23 08:08:18 +02:00
|
|
|
static void switchGuns(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);
|
|
|
|
static void activateECM(void);
|
2015-10-23 08:08:18 +02:00
|
|
|
|
2015-10-31 11:00:46 +01:00
|
|
|
static int selectedPlayerIndex;
|
2015-10-23 08:08:18 +02:00
|
|
|
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;
|
|
|
|
|
|
|
|
memset(&availableGuns, 0, sizeof(int) * BT_MAX);
|
|
|
|
|
|
|
|
player->selectedGunType = -1;
|
|
|
|
|
|
|
|
for (i = 0 ; i < MAX_FIGHTER_GUNS ; i++)
|
|
|
|
{
|
|
|
|
n = player->guns[i].type;
|
|
|
|
|
|
|
|
if (n)
|
|
|
|
{
|
|
|
|
availableGuns[n] = 1;
|
|
|
|
|
|
|
|
if (player->selectedGunType == -1)
|
|
|
|
{
|
|
|
|
player->selectedGunType = n;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-10-29 11:14:21 +01:00
|
|
|
|
|
|
|
STRNCPY(player->name, "Player", MAX_NAME_LENGTH);
|
2015-11-01 00:09:43 +01:00
|
|
|
|
|
|
|
player->action = NULL;
|
2015-11-15 17:19:21 +01:00
|
|
|
|
|
|
|
battle.boostTimer = 0;
|
|
|
|
battle.ecmTimer = 0;
|
2015-10-23 08:08:18 +02:00
|
|
|
}
|
2015-10-20 13:51:49 +02:00
|
|
|
|
|
|
|
void doPlayer(void)
|
|
|
|
{
|
2015-11-15 17:18:17 +01:00
|
|
|
battle.boostTimer = MAX(battle.boostTimer - 1, 0);
|
|
|
|
battle.ecmTimer = MAX(battle.ecmTimer - 1, 0);
|
|
|
|
|
|
|
|
if (battle.boostTimer == BOOST_FINISHED_TIME)
|
|
|
|
{
|
|
|
|
applyFighterThrust();
|
|
|
|
}
|
|
|
|
|
2015-10-20 13:51:49 +02:00
|
|
|
if (player != NULL)
|
|
|
|
{
|
|
|
|
self = player;
|
|
|
|
|
|
|
|
if (player->alive == ALIVE_ALIVE)
|
|
|
|
{
|
|
|
|
if (app.keyboard[SDL_SCANCODE_LEFT])
|
|
|
|
{
|
|
|
|
player->angle -= 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (app.keyboard[SDL_SCANCODE_RIGHT])
|
|
|
|
{
|
|
|
|
player->angle += 4;
|
|
|
|
}
|
|
|
|
|
2015-11-15 17:18:17 +01:00
|
|
|
if (app.keyboard[SDL_SCANCODE_UP] && battle.boostTimer < BOOST_FINISHED_TIME)
|
2015-10-20 13:51:49 +02:00
|
|
|
{
|
|
|
|
applyFighterThrust();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (app.keyboard[SDL_SCANCODE_DOWN])
|
|
|
|
{
|
|
|
|
applyFighterBrakes();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (app.keyboard[SDL_SCANCODE_LCTRL] && !player->reload && player->guns[0].type)
|
|
|
|
{
|
|
|
|
fireGuns(player);
|
|
|
|
}
|
|
|
|
|
2015-10-23 08:08:18 +02:00
|
|
|
if (app.keyboard[SDL_SCANCODE_LSHIFT])
|
|
|
|
{
|
|
|
|
switchGuns();
|
|
|
|
|
|
|
|
app.keyboard[SDL_SCANCODE_LSHIFT] = 0;
|
|
|
|
}
|
|
|
|
|
2015-10-20 13:51:49 +02:00
|
|
|
if (app.keyboard[SDL_SCANCODE_RETURN] && player->missiles.ammo && player->target)
|
|
|
|
{
|
2015-10-31 00:31:20 +01:00
|
|
|
if (getDistance(player->x, player->y, player->target->x, player->target->y) <= 1000)
|
|
|
|
{
|
|
|
|
fireMissile(player);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
addHudMessage(colors.white, "Target not in range");
|
|
|
|
}
|
2015-10-20 13:51:49 +02:00
|
|
|
|
|
|
|
app.keyboard[SDL_SCANCODE_RETURN] = 0;
|
|
|
|
}
|
|
|
|
|
2015-11-15 17:18:17 +01:00
|
|
|
if (!player->target || player->target->health <= 0 || player->target->systemPower <= 0 || app.keyboard[SDL_SCANCODE_T])
|
2015-10-20 13:51:49 +02:00
|
|
|
{
|
|
|
|
selectTarget();
|
2015-10-31 00:31:20 +01:00
|
|
|
|
|
|
|
app.keyboard[SDLK_t] = 0;
|
2015-10-20 13:51:49 +02:00
|
|
|
}
|
2015-10-27 08:24:17 +01:00
|
|
|
|
2015-11-15 17:18:17 +01:00
|
|
|
if (app.keyboard[SDL_SCANCODE_SPACE] && !battle.boostTimer)
|
|
|
|
{
|
|
|
|
activateBoost();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (app.keyboard[SDL_SCANCODE_E] && !battle.ecmTimer)
|
|
|
|
{
|
|
|
|
activateECM();
|
|
|
|
}
|
|
|
|
|
2015-10-27 08:24:17 +01:00
|
|
|
if (!battle.missionTarget)
|
|
|
|
{
|
|
|
|
selectMissionTarget();
|
|
|
|
}
|
2015-10-20 13:51:49 +02:00
|
|
|
}
|
|
|
|
|
2015-10-26 20:16:12 +01:00
|
|
|
player->angle = ((int)player->angle) % 360;
|
2015-10-20 13:51:49 +02:00
|
|
|
|
|
|
|
if (player->health <= 0 && battle.status == MS_IN_PROGRESS)
|
|
|
|
{
|
2015-11-01 00:09:43 +01:00
|
|
|
if (!battle.epic)
|
2015-10-31 11:00:46 +01:00
|
|
|
{
|
2015-11-14 09:41:31 +01:00
|
|
|
failMission();
|
2015-10-31 11:00:46 +01:00
|
|
|
}
|
2015-11-01 00:09:43 +01:00
|
|
|
else if (player->health == -FPS)
|
|
|
|
{
|
|
|
|
initPlayerSelect();
|
|
|
|
}
|
2015-10-20 13:51:49 +02:00
|
|
|
}
|
|
|
|
}
|
2015-10-31 11:00:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void initPlayerSelect(void)
|
|
|
|
{
|
|
|
|
Entity *e;
|
|
|
|
|
|
|
|
memset(&availablePlayerUnits, 0, sizeof(Entity*) * MAX_SELECTABLE_PLAYERS);
|
|
|
|
|
|
|
|
selectedPlayerIndex = 0;
|
|
|
|
|
|
|
|
for (e = battle.entityHead.next ; e != NULL ; e = e->next)
|
|
|
|
{
|
|
|
|
if (e->type == ET_FIGHTER && e->health > 0 && e->side == SIDE_ALLIES && selectedPlayerIndex < MAX_SELECTABLE_PLAYERS)
|
|
|
|
{
|
|
|
|
availablePlayerUnits[selectedPlayerIndex++] = e;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-01 00:09:43 +01:00
|
|
|
if (selectedPlayerIndex > 0)
|
|
|
|
{
|
|
|
|
battle.playerSelect = 1;
|
|
|
|
selectedPlayerIndex = 0;
|
|
|
|
memset(&app.keyboard, 0, sizeof(int) * MAX_KEYBOARD_KEYS);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
battle.epic = 0;
|
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
if (app.keyboard[SDL_SCANCODE_LEFT])
|
|
|
|
{
|
|
|
|
selectNewPlayer(-1);
|
|
|
|
|
|
|
|
app.keyboard[SDL_SCANCODE_LEFT] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (app.keyboard[SDL_SCANCODE_RIGHT])
|
|
|
|
{
|
|
|
|
selectNewPlayer(1);
|
|
|
|
|
|
|
|
app.keyboard[SDL_SCANCODE_RIGHT] = 0;
|
|
|
|
}
|
|
|
|
|
2015-11-01 13:31:26 +01:00
|
|
|
if (app.keyboard[SDL_SCANCODE_RETURN] && player->health > 0)
|
2015-10-31 11:00:46 +01:00
|
|
|
{
|
2015-11-01 00:09:43 +01:00
|
|
|
battle.playerSelect = 0;
|
|
|
|
|
|
|
|
initPlayer();
|
2015-10-31 11:00:46 +01:00
|
|
|
|
2015-11-01 00:09:43 +01:00
|
|
|
app.keyboard[SDL_SCANCODE_RETURN] = 0;
|
2015-10-31 11:00:46 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void selectNewPlayer(int dir)
|
|
|
|
{
|
|
|
|
do
|
|
|
|
{
|
|
|
|
selectedPlayerIndex += dir;
|
|
|
|
|
|
|
|
selectedPlayerIndex = mod(selectedPlayerIndex, MAX_SELECTABLE_PLAYERS);
|
2015-11-01 00:09:43 +01:00
|
|
|
|
|
|
|
player = availablePlayerUnits[selectedPlayerIndex];
|
2015-10-31 11:00:46 +01:00
|
|
|
}
|
2015-11-01 00:09:43 +01:00
|
|
|
while (player == NULL);
|
|
|
|
|
|
|
|
battle.camera.x = player->x - (SCREEN_WIDTH / 2);
|
|
|
|
battle.camera.y = player->y - (SCREEN_HEIGHT / 2);
|
2015-10-20 13:51:49 +02:00
|
|
|
}
|
|
|
|
|
2015-11-15 17:18:17 +01:00
|
|
|
static void activateBoost(void)
|
|
|
|
{
|
|
|
|
self->dx += sin(TO_RAIDANS(self->angle)) * 10;
|
|
|
|
self->dy += -cos(TO_RAIDANS(self->angle)) * 10;
|
|
|
|
self->thrust = sqrt((self->dx * self->dx) + (self->dy * self->dy));
|
|
|
|
|
|
|
|
battle.boostTimer = BOOST_RECHARGE_TIME;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void activateECM(void)
|
|
|
|
{
|
|
|
|
battle.ecmTimer = ECM_RECHARGE_TIME;
|
|
|
|
}
|
|
|
|
|
2015-10-23 08:08:18 +02:00
|
|
|
static void switchGuns(void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
i = player->selectedGunType;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
i = (i + 1) % BT_MAX;
|
|
|
|
}
|
|
|
|
while (!availableGuns[i]);
|
|
|
|
|
|
|
|
player->selectedGunType = i;
|
|
|
|
}
|
|
|
|
|
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;
|
2015-10-27 08:24:17 +01:00
|
|
|
Entity *e;
|
2015-10-20 13:51:49 +02:00
|
|
|
|
|
|
|
player->target = NULL;
|
|
|
|
|
2015-10-27 08:24:17 +01:00
|
|
|
for (e = battle.entityHead.next ; e != NULL ; e = e->next)
|
2015-10-20 13:51:49 +02:00
|
|
|
{
|
2015-10-31 00:31:20 +01:00
|
|
|
if (e->active && e != player && e->type == ET_FIGHTER && e->side != player->side && e->alive == ALIVE_ALIVE)
|
2015-10-20 13:51:49 +02:00
|
|
|
{
|
2015-10-27 08:24:17 +01:00
|
|
|
dist = getDistance(self->x, self->y, e->x, e->y);
|
2015-10-20 13:51:49 +02:00
|
|
|
if (dist < closest)
|
|
|
|
{
|
2015-10-27 08:24:17 +01:00
|
|
|
player->target = e;
|
2015-10-20 13:51:49 +02:00
|
|
|
closest = dist;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
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;
|
2015-10-27 08:24:17 +01:00
|
|
|
Entity *e;
|
|
|
|
|
|
|
|
battle.missionTarget = NULL;
|
|
|
|
|
|
|
|
for (e = battle.entityHead.next ; e != NULL ; e = e->next)
|
|
|
|
{
|
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
|
|
|
{
|
|
|
|
if (battle.missionTarget == NULL)
|
|
|
|
{
|
|
|
|
battle.missionTarget = e;
|
|
|
|
}
|
|
|
|
else if (battle.missionTarget->type == ET_WAYPOINT && e->type != ET_WAYPOINT)
|
|
|
|
{
|
|
|
|
battle.missionTarget = e;
|
|
|
|
}
|
|
|
|
else if (battle.missionTarget->type != ET_WAYPOINT)
|
|
|
|
{
|
|
|
|
dist = getDistance(self->x, self->y, e->x, e->y);
|
|
|
|
if (dist < closest)
|
|
|
|
{
|
|
|
|
battle.missionTarget = e;
|
|
|
|
closest = dist;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (battle.missionTarget->type == ET_WAYPOINT && e->type == ET_WAYPOINT && e->id < battle.missionTarget->id)
|
|
|
|
{
|
|
|
|
battle.missionTarget = e;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|