/******************************************************************************
This source file is part of AstroMenace game
(Hardcore 3D space shooter with spaceship upgrade possibilities.)
For the latest info, see http://www.viewizard.com/
File name: SpaceShip.cpp
Copyright (c) 2006-2007 Michael Kurinnoy, Viewizard
All Rights Reserved.
File Version: 1.2
******************************************************************************
AstroMenace game source code available under "dual licensing" model.
The licensing options available are:
* Commercial Licensing. This is the appropriate option if you are
creating proprietary applications and you are not prepared to
distribute and share the source code of your application.
Contact us for pricing at viewizard@viewizard.com
* Open Source Licensing. This is the appropriate option if you want
to share the source code of your application with everyone you
distribute it to, and you also want to give them the right to share
who uses it. You should have received a copy of the GNU General Public
License version 3 with this source codes.
If not, see .
******************************************************************************/
/// подключаем нужные файлы
#include "SpaceShip.h"
#include "../../Game.h"
extern bool PlayerFighterLeftEng;
extern bool PlayerFighterRightEng;
extern CProjectile *StartProjectile;
extern CProjectile *EndProjectile;
//-----------------------------------------------------------------------------
// Конструктор, инициализация всех переменных
//-----------------------------------------------------------------------------
CSpaceShip::CSpaceShip(void)
{
// никуда не двигаемся
Velocity = VECTOR3D(0.0f, 0.0f, 0.0f);
// болтание объекта, в случае кораблей болтаем всю модель
DeviationOn = false;
DeviationObjQuantity = 1;
Deviation = new VECTOR3D[DeviationObjQuantity];
NeedDeviation = new float[DeviationObjQuantity];
CurentDeviation = new float[DeviationObjQuantity];
CurentDeviationSum = new float[DeviationObjQuantity];
Deviation[0] = VECTOR3D(0.0f, 1.0f, 0.0f);
NeedDeviation[0] = vw_Randf0*0.1f;
CurentDeviation[0] = CurentDeviationSum[0] = 0.0f;
// и никуда не нужно поворачивать
NeedRotate = VECTOR3D(0.0f, 0.0f, 0.0f);
RotationSpeed = VECTOR3D(1.0f, 1.0f, 1.0f);
// скорость
MaxSpeed = Speed = NeedSpeed = 0.0f;
SpeedLR = NeedSpeedLR = SpeedUD = NeedSpeedUD = 0.0f;
SpeedByCamFB = NeedSpeedByCamFB = SpeedByCamLR = NeedSpeedByCamLR = SpeedByCamUD = NeedSpeedByCamUD = 0.0f;
// ускорение, пока нет двигателей - его нет...
MaxAcceler = MaxSpeedRotate = Acceler = AccelerLR = AccelerUD = AccelerByCamFB = AccelerByCamLR = AccelerByCamUD = 0.0f;
// даем максимальное ускорение
NeedAcceler = NeedAccelerLR = NeedAccelerUD = NeedAccelerByCamFB = NeedAccelerByCamLR = NeedAccelerByCamUD = 1.0f;
// двигатели не установлены
EngineDestroyType = false;
EngineQuantity = EngineLeftQuantity = EngineRightQuantity = 0;
Engine = EngineLeft = EngineRight = 0;
EngineLocation = EngineLeftLocation = EngineRightLocation = 0;
NeedStopRotation = false;
// никуда не двигаемся
MoveForward = MoveBackward = MoveLeft = MoveRight = MoveUp = MoveDown = 0.0f;
// оружие пока не установлено
WeaponQuantity = 0;
WeaponSetFire = 0;
WeaponLocation = 0;
WeaponType = 0;
Weapon = 0;
WeaponYAngle = 0;
WeaponFireType = 2;
WeaponGroupCurrentFireNum = -1;
WeaponGroupCurrentFireDelay = 0.0f;
BossWeaponQuantity = 0;
BossWeaponSetFire = 0;
BossWeaponLocation = 0;
BossWeaponType = 0;
BossWeapon = 0;
BossWeaponYAngle = 0;
BossWeaponFireType = 2;
BossWeaponGroupCurrentFireNum = -1;
BossWeaponGroupCurrentFireDelay = 0.0f;
WeaponFlare = 0;
// подключаем к своему списку
Next = Prev = 0;
AttachSpaceShip(this);
}
//-----------------------------------------------------------------------------
// Деструктор
//-----------------------------------------------------------------------------
CSpaceShip::~CSpaceShip(void)
{
if (WeaponSetFire != 0) {delete [] WeaponSetFire; WeaponSetFire = 0;}
if (WeaponLocation != 0) {delete [] WeaponLocation; WeaponLocation = 0;}
if (WeaponType != 0) {delete [] WeaponType; WeaponType = 0;}
if (WeaponYAngle != 0) {delete [] WeaponYAngle; WeaponYAngle = 0;}
if (Weapon != 0)
{
for (int i=0; iIsSuppressed = true;
Engine[i]->DestroyIfNoParticles = true;
}
else
{
delete Engine[i]; Engine[i] = 0;
}
}
delete [] Engine; Engine = 0;
}
if (EngineLeftLocation != 0) {delete [] EngineLeftLocation; EngineLeftLocation = 0;}
if (EngineLeft != 0)
{
for (int i=0; iIsSuppressed = true;
EngineLeft[i]->DestroyIfNoParticles = true;
}
else
{
delete EngineLeft[i]; EngineLeft[i] = 0;
}
}
delete [] EngineLeft; EngineLeft = 0;
}
if (EngineRightLocation != 0) {delete [] EngineRightLocation; EngineRightLocation = 0;}
if (EngineRight != 0)
{
for (int i=0; iIsSuppressed = true;
EngineRight[i]->DestroyIfNoParticles = true;
}
else
{
delete EngineRight[i]; EngineRight[i] = 0;
}
}
delete [] EngineRight; EngineRight = 0;
}
DetachSpaceShip(this);
}
//-----------------------------------------------------------------------------
// Установка положения объекта
//-----------------------------------------------------------------------------
void CSpaceShip::SetLocation(VECTOR3D NewLocation)
{
// вызываем родительскую функцию
::CObject3D::SetLocation(NewLocation);
// если оружие вообще есть
if (Weapon != 0)
for (int i=0; iSetLocation(NewLocation + WeaponLocation[i]);
}
if (BossWeapon != 0)
for (int i=0; iSetLocation(NewLocation + BossWeaponLocation[i]);
}
if (WeaponFlare != 0)
{
WeaponFlare->SetLocation(NewLocation + WeaponFlareLocation);
}
// положение двигателей
if (Engine != 0)
for (int i=0; iMoveSystem(NewLocation + EngineLocation[i]);
Engine[i]->SetStartLocation(EngineLocation[i] + NewLocation);
}
}
if (EngineLeft != 0)
for (int i=0; iMoveSystem(NewLocation + EngineLeftLocation[i]);
EngineLeft[i]->SetStartLocation(EngineLeftLocation[i] + NewLocation);
}
}
if (EngineRight != 0)
for (int i=0; iMoveSystem(NewLocation + EngineRightLocation[i]);
EngineRight[i]->SetStartLocation(EngineRightLocation[i] + NewLocation);
}
}
}
//-----------------------------------------------------------------------------
// Установка положения объекта, для аркадного режима
//-----------------------------------------------------------------------------
void CSpaceShip::SetLocationArcadePlayer(VECTOR3D NewLocation)
{
// вызываем родительскую функцию
::CObject3D::SetLocation(NewLocation);
// если оружие вообще есть
if (Weapon != 0)
for (int i=0; iSetLocation(NewLocation + WeaponLocation[i]);
}
if (BossWeapon != 0)
for (int i=0; iSetLocation(NewLocation + BossWeaponLocation[i]);
}
if (WeaponFlare != 0)
{
WeaponFlare->SetLocation(NewLocation + WeaponFlareLocation);
}
// положение двигателей
if (Engine != 0)
for (int i=0; iMoveSystem(NewLocation + EngineLocation[i]);
Engine[i]->SetStartLocation(NewLocation + EngineLocation[i]);
}
if (EngineLeft != 0)
for (int i=0; iMoveSystem(NewLocation + EngineLeftLocation[i]);
EngineLeft[i]->SetStartLocation(NewLocation + EngineLeftLocation[i]);
}
if (EngineRight != 0)
for (int i=0; iMoveSystem(NewLocation + EngineRightLocation[i]);
EngineRight[i]->SetStartLocation(NewLocation + EngineRightLocation[i]);
}
}
//-----------------------------------------------------------------------------
// Установка углов поворота объекта
//-----------------------------------------------------------------------------
void CSpaceShip::SetRotation(VECTOR3D NewRotation, bool NeedWeaponRotate)
{
// вызываем родительскую функцию
::CObject3D::SetRotation(NewRotation);
// оружие
if (Weapon != 0)
for (int i=0; iNeedRotateOnTargeting))
{
Weapon[i]->SetRotation(NewRotation);
Weapon[i]->SetLocation(Location + WeaponLocation[i]);
}
}
if (BossWeapon != 0)
for (int i=0; iNeedRotateOnTargeting))
{
BossWeapon[i]->SetRotation(NewRotation);
BossWeapon[i]->SetLocation(Location + BossWeaponLocation[i]);
}
}
if (WeaponFlare != 0)
{
Matrix33CalcPoint(&WeaponFlareLocation, OldInvRotationMat);
Matrix33CalcPoint(&WeaponFlareLocation, CurrentRotationMat);
WeaponFlare->SetRotation(NewRotation);
WeaponFlare->SetLocation(Location + WeaponFlareLocation);
}
// двигатели
if (Engine != 0)
for (int i=0; iSpeedOnCreation == -1.0f)
{
Engine[i]->MoveSystem(EngineLocation[i] + Location);
Engine[i]->SetStartLocation(EngineLocation[i] + Location);
Engine[i]->RotateSystemAndParticlesByAngle(Rotation);
}
else
{
Engine[i]->MoveSystemLocation(EngineLocation[i] + Location);
Engine[i]->RotateSystemByAngle(Rotation);
}
}
}
if (EngineLeft != 0)
for (int i=0; iMoveSystemLocation(EngineLeftLocation[i] + Location);
EngineLeft[i]->SetStartLocation(EngineLeftLocation[i] + Location);
EngineLeft[i]->RotateSystemByAngle(Rotation);
}
}
if (EngineRight != 0)
for (int i=0; iMoveSystemLocation(EngineRightLocation[i] + Location);
EngineRight[i]->SetStartLocation(EngineRightLocation[i] + Location);
EngineRight[i]->RotateSystemByAngle(Rotation);
}
}
}
//-----------------------------------------------------------------------------
// Обновление данных объектa Object3D
//-----------------------------------------------------------------------------
bool CSpaceShip::Update(float Time)
{
// вызываем родительскую функцию
// если там передали удалить - выходим
if (!::CObject3D::Update(Time)) return false;
// быстро вызвали еще раз... время не изменилось, или почти не изменилось
if (TimeDelta == 0.0f) return true;
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// обработка скрипта
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
if (StartTimeSheet != 0)
if (!StartTimeSheet->InUse)
{
StartTimeSheet->InUse = true;
NeedSpeed = StartTimeSheet->Speed;
NeedAcceler = StartTimeSheet->Acceler;
NeedSpeedLR = StartTimeSheet->SpeedLR;
NeedAccelerLR = StartTimeSheet->AccelerLR;
NeedSpeedUD = StartTimeSheet->SpeedUD;
NeedAccelerUD = StartTimeSheet->AccelerUD;
NeedSpeedByCamFB = StartTimeSheet->SpeedByCamFB;
NeedAccelerByCamFB = StartTimeSheet->AccelerByCamFB;
NeedSpeedByCamLR = StartTimeSheet->SpeedByCamLR;
NeedAccelerByCamLR = StartTimeSheet->AccelerByCamLR;
NeedSpeedByCamUD = StartTimeSheet->SpeedByCamUD;
NeedAccelerByCamUD = StartTimeSheet->AccelerByCamUD;
NeedRotate = StartTimeSheet->Rotation;
RotationSpeed = StartTimeSheet->RotationAcceler;
if (Weapon != 0)
for (int i=0; iFire;
}
if (BossWeapon != 0)
for (int i=0; iBossFire;
}
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// если у корабля есть спец средства против ракет...
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
if (WeaponFlare != 0)
{
// проверка, есть ли вражеские ракеты?
bool NeedFlare = false;
CProjectile *tmpProjectile = StartProjectile;
while (!NeedFlare && tmpProjectile!=0)
{
CProjectile *tmpProjectile2 = tmpProjectile->Next;
if ((ObjectStatus == 1 && tmpProjectile->ObjectStatus > 1) ||
// снаряды врагов - с союзниками или игроком
(ObjectStatus > 1 && tmpProjectile->ObjectStatus == 1) ||
// снаряды игрока со всеми, кроме игрока
(ObjectStatus != 3 && tmpProjectile->ObjectStatus == 3))
if (tmpProjectile->ProjectileType == 1)
{
NeedFlare = true;
}
tmpProjectile = tmpProjectile2;
}
tmpProjectile = StartProjectile;
if (NeedFlare)
while (tmpProjectile!=0)
{
CProjectile *tmpProjectile2 = tmpProjectile->Next;
// если навелись на этот объект ракетой
// т.к. только у ракеты тут не ноль
if (tmpProjectile->Target == this)
{
// начинаем отстреливать фларес
WeaponFlareSetFire = true;
}
tmpProjectile = tmpProjectile2;
}
else
WeaponFlareSetFire = false;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// обработка указателей действия, нужно для управления кораблем игрока
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
if (ObjectStatus == 3)
{
if (MoveForward > 0.0f || MoveBackward > 0.0f)
{
NeedSpeed = MaxSpeed*MoveForward-MaxSpeed*MoveBackward;
}
else NeedSpeed = 0.0f;
if (MoveLeft > 0.0f || MoveRight > 0.0f)
{
NeedRotate.y = MaxAcceler*MaxSpeed*MoveRight-MaxAcceler*MaxSpeed*MoveLeft;
}
else NeedRotate.y = 0.0f;
if (MoveUp > 0.0f || MoveDown > 0.0f)
{
NeedRotate.x = MaxAcceler*MaxSpeed*MoveUp-MaxAcceler*MaxSpeed*MoveDown;
}
else NeedRotate.x = 0.0f;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// повотор
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// выключаем двигатели, если нужно - включим
if (EngineLeft != 0)
for (int i=0; iIsSuppressed = true;
}
if (EngineRight != 0)
for (int i=0; iIsSuppressed = true;
}
// если нужно поворачивать
if ( !(ObjectStatus == 3) )
{
if (NeedRotate.x != 0.0f || NeedRotate.y != 0.0f || NeedRotate.z != 0.0f)
{
// Находим допустимый поворот по углу
VECTOR3D tmpRotate(0.0f, 0.0f, 0.0f);
// угол по x
if (NeedRotate.x != 0.0f)
{
float Sign = 1.0f;
if (NeedRotate.x < 0.0f) Sign = -1.0f;
// вычисляем скорость поворота по данным двигателя
tmpRotate.x = Sign*MaxSpeedRotate*RotationSpeed.x*TimeDelta;
// смотрим, если уже повернули - снимаем
if (Sign == 1.0f)
{if (tmpRotate.x >= NeedRotate.x) {tmpRotate.x = NeedRotate.x; NeedRotate.x = 0.0f;}}
else {if (tmpRotate.x <= NeedRotate.x) {tmpRotate.x = NeedRotate.x; NeedRotate.x = 0.0f;}}
// меняем значение
if (NeedRotate.x != 0.0f) NeedRotate.x -= tmpRotate.x;
}
// угол по y
if (NeedRotate.y != 0.0f)
{
float Sign = 1.0f;
if (NeedRotate.y < 0.0f) Sign = -1.0f;
// вычисляем скорость поворота по данным двигателя
tmpRotate.y = Sign*MaxSpeedRotate*RotationSpeed.y*TimeDelta;
// смотрим, если уже повернули - снимаем
if (Sign == 1.0f)
{
if (tmpRotate.y >= NeedRotate.y)
{
tmpRotate.y = NeedRotate.y;
NeedRotate.y = 0.0f;
}
}
else
{
if (tmpRotate.y <= NeedRotate.y)
{
tmpRotate.y = NeedRotate.y;
NeedRotate.y = 0.0f;
}
}
// меняем значение
if (NeedRotate.y != 0.0f) NeedRotate.y -= tmpRotate.y;
// включаем двигатель на поворот
if (NeedRotate.y > 0.0f)
{
if (EngineLeft != 0)
for (int i=0; iIsSuppressed = false;
}
}
else
{
if (EngineRight != 0)
for (int i=0; iIsSuppressed = false;
}
}
// создаем эффект торможения другим двигателем
NeedStopRotation = true;
}
// угол по z
if (NeedRotate.z != 0.0f)
{
float Sign = 1.0f;
if (NeedRotate.z < 0.0f) Sign = -1.0f;
// вычисляем скорость поворота по данным двигателя
tmpRotate.z = Sign*MaxSpeedRotate*RotationSpeed.z*TimeDelta;
// смотрим, если уже повернули - снимаем
if (Sign == 1.0f)
{if (tmpRotate.z >= NeedRotate.z) {tmpRotate.z = NeedRotate.z; NeedRotate.z = 0.0f;}}
else {if (tmpRotate.z <= NeedRotate.z) {tmpRotate.z = NeedRotate.z; NeedRotate.z = 0.0f;}}
// меняем значение
if (NeedRotate.z != 0.0f) NeedRotate.z -= tmpRotate.z;
// включаем двигатель на поворот
if (NeedRotate.z < 0.0f)
{
if (EngineLeft != 0)
for (int i=0; iIsSuppressed = false;
}
}
else
{
if (EngineRight != 0)
for (int i=0; iIsSuppressed = false;
}
}
// создаем эффект торможения другим двигателем
NeedStopRotation = true;
}
// установка поворота там же сохраняем, какой общий поворот модели
SetRotation(tmpRotate);
}
else
{
if (NeedStopRotation)
{
if (EngineLeft != 0)
for (int i=0; iIsSuppressed = false;
}
if (EngineRight != 0)
for (int i=0; iIsSuppressed = false;
}
NeedStopRotation = false;
}
else
{
if (EngineLeft != 0)
for (int i=0; iIsSuppressed = true;
}
if (EngineRight != 0)
for (int i=0; iIsSuppressed = true;
}
}
}
}
else
{
if (EngineLeft != 0)
for (int i=0; iIsSuppressed = !PlayerFighterLeftEng;
}
if (EngineRight != 0)
for (int i=0; iIsSuppressed = !PlayerFighterRightEng;
}
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ускорение-замедление
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// вперед-назад
// если нужно разогнаться, или управление на игроке - и нужно стремиться к нулю
if (NeedSpeed != 0.0f || (ObjectStatus == 3 && Speed != 0.0f))
{
float Sign = 1.0f;
// нужно двигать назад
if (NeedSpeed < 0.0f) Sign = -1.0f;
// "ровняем" скорость под модель
if (Sign == 1.0f)
{Clamp(NeedSpeed, 0.0f, MaxSpeed);}
else
{Clamp(NeedSpeed, -MaxSpeed, 0.0f);}
// случай, когда нужно затормозить а не менять направление
if (Sign == 1.0f)
{if (NeedSpeed < Speed) Sign = -1.0f;}
else
{if (NeedSpeed > Speed) Sign = 1.0f;}
// даем полный газ, учитывая сколько процентов можем выдать
Acceler = Sign*MaxAcceler*NeedAcceler;
// считаем текущую скорость
Speed = Speed + Acceler*TimeDelta;
// смотрим, если уже разогнались - снимаем
if (Sign == 1.0f)
{if (NeedSpeed <= Speed) {Speed = NeedSpeed; NeedSpeed = 0.0f;}}
else {if (NeedSpeed >= Speed) {Speed = NeedSpeed; NeedSpeed = 0.0f;}}
// если нужны двигатели торможения - включаем маневровые
if (Sign == -1.0f)
{
if (EngineLeft != 0)
for (int i=0; iIsSuppressed = false;
}
if (EngineRight != 0)
for (int i=0; iIsSuppressed = false;
}
}
}
// влево-вправо
if (NeedSpeedLR != 0.0f)
{
float Sign = 1.0f;
// нужно двигать назад
if (NeedSpeedLR < 0.0f) Sign = -1.0f;
// "ровняем" скорость под модель
if (Sign == 1.0f)
{Clamp(NeedSpeedLR, 0.0f, MaxSpeed);}
else
{Clamp(NeedSpeedLR, -MaxSpeed, 0.0f);}
// случай, когда нужно затормозить а не менять направление
if (Sign == 1.0f)
{if (NeedSpeedLR < SpeedLR) Sign = -1.0f;}
else
{if (NeedSpeedLR > SpeedLR) Sign = 1.0f;}
// даем полный газ, учитывая сколько процентов можем выдать
AccelerLR = Sign*MaxAcceler*NeedAccelerLR;
// считаем текущую скорость
SpeedLR = SpeedLR + AccelerLR*TimeDelta;
// смотрим, если уже разогнались - снимаем
if (Sign == 1.0f)
{if (NeedSpeedLR <= SpeedLR) {SpeedLR = NeedSpeedLR; NeedSpeedLR = 0.0f;}}
else {if (NeedSpeedLR >= SpeedLR) {SpeedLR = NeedSpeedLR; NeedSpeedLR = 0.0f;}}
}
// вверх-вниз
if (NeedSpeedUD != 0.0f)
{
float Sign = 1.0f;
// нужно двигать назад
if (NeedSpeedUD < 0.0f) Sign = -1.0f;
// "ровняем" скорость под модель
if (Sign == 1.0f)
{Clamp(NeedSpeedUD, 0.0f, MaxSpeed);}
else
{Clamp(NeedSpeedUD, -MaxSpeed, 0.0f);}
// случай, когда нужно затормозить а не менять направление
if (Sign == 1.0f)
{if (NeedSpeedUD < SpeedUD) Sign = -1.0f;}
else
{if (NeedSpeedUD > SpeedUD) Sign = 1.0f;}
// даем полный газ, учитывая сколько процентов можем выдать
AccelerUD = Sign*MaxAcceler*NeedAccelerUD;
// считаем текущую скорость
SpeedUD = SpeedUD + AccelerUD*TimeDelta;
// смотрим, если уже разогнались - снимаем
if (Sign == 1.0f)
{if (NeedSpeedUD <= SpeedUD) {SpeedUD = NeedSpeedUD; NeedSpeedUD = 0.0f;}}
else {if (NeedSpeedUD >= SpeedUD) {SpeedUD = NeedSpeedUD; NeedSpeedUD = 0.0f;}}
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ускорение-замедление по вектору камеры
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// вперед-назад
if (NeedSpeedByCamFB != 0.0f)
{
float Sign = 1.0f;
// нужно двигать назад
if (NeedSpeedByCamFB < 0.0f) Sign = -1.0f;
// "ровняем" скорость под модель
if (Sign == 1.0f)
{Clamp(NeedSpeedByCamFB, 0.0f, MaxSpeed);}
else
{Clamp(NeedSpeedByCamFB, -MaxSpeed, 0.0f);}
// случай, когда нужно затормозить а не менять направление
if (Sign == 1.0f)
{if (NeedSpeedByCamFB < SpeedByCamFB) Sign = -1.0f;}
else
{if (NeedSpeedByCamFB > SpeedByCamFB) Sign = 1.0f;}
// даем полный газ, учитывая сколько процентов можем выдать
AccelerByCamFB = Sign*MaxAcceler*NeedAccelerByCamFB;
// считаем текущую скорость
SpeedByCamFB = SpeedByCamFB + AccelerByCamFB*TimeDelta;
// смотрим, если уже разогнались - снимаем
if (Sign == 1.0f)
{if (NeedSpeedByCamFB <= SpeedByCamFB) {SpeedByCamFB = NeedSpeedByCamFB; NeedSpeedByCamFB = 0.0f;}}
else {if (NeedSpeedByCamFB >= SpeedByCamFB) {SpeedByCamFB = NeedSpeedByCamFB; NeedSpeedByCamFB = 0.0f;}}
}
// влево-вправо
if (NeedSpeedByCamLR != 0.0f)
{
float Sign = 1.0f;
// нужно двигать назад
if (NeedSpeedByCamLR < 0.0f) Sign = -1.0f;
// "ровняем" скорость под модель
if (Sign == 1.0f)
{Clamp(NeedSpeedByCamLR, 0.0f, MaxSpeed);}
else
{Clamp(NeedSpeedByCamLR, -MaxSpeed, 0.0f);}
// случай, когда нужно затормозить а не менять направление
if (Sign == 1.0f)
{if (NeedSpeedByCamLR < SpeedByCamLR) Sign = -1.0f;}
else
{if (NeedSpeedByCamLR > SpeedByCamLR) Sign = 1.0f;}
// даем полный газ, учитывая сколько процентов можем выдать
AccelerByCamLR = Sign*MaxAcceler*NeedAccelerByCamLR;
// считаем текущую скорость
SpeedByCamLR = SpeedByCamLR + AccelerByCamLR*TimeDelta;
// смотрим, если уже разогнались - снимаем
if (Sign == 1.0f)
{if (NeedSpeedByCamLR <= SpeedByCamLR) {SpeedByCamLR = NeedSpeedByCamLR; NeedSpeedByCamLR = 0.0f;}}
else {if (NeedSpeedByCamLR >= SpeedByCamLR) {SpeedByCamLR = NeedSpeedByCamLR; NeedSpeedByCamLR = 0.0f;}}
}
// вверх-вниз
if (NeedSpeedByCamUD != 0.0f)
{
float Sign = 1.0f;
// нужно двигать назад
if (NeedSpeedByCamUD < 0.0f) Sign = -1.0f;
// "ровняем" скорость под модель
if (Sign == 1.0f)
{Clamp(NeedSpeedByCamUD, 0.0f, MaxSpeed);}
else
{Clamp(NeedSpeedByCamUD, -MaxSpeed, 0.0f);}
// случай, когда нужно затормозить а не менять направление
if (Sign == 1.0f)
{if (NeedSpeedByCamUD < SpeedByCamUD) Sign = -1.0f;}
else
{if (NeedSpeedByCamUD > SpeedByCamUD) Sign = 1.0f;}
// даем полный газ, учитывая сколько процентов можем выдать
AccelerByCamUD = Sign*MaxAcceler*NeedAccelerByCamUD;
// считаем текущую скорость
SpeedByCamUD = SpeedByCamUD + AccelerByCamUD*TimeDelta;
// смотрим, если уже разогнались - снимаем
if (Sign == 1.0f)
{if (NeedSpeedByCamUD <= SpeedByCamUD) {SpeedByCamUD = NeedSpeedByCamUD; NeedSpeedByCamUD = 0.0f;}}
else {if (NeedSpeedByCamUD >= SpeedByCamUD) {SpeedByCamUD = NeedSpeedByCamUD; NeedSpeedByCamUD = 0.0f;}}
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// смотрим, есть ли команда открыть огонь
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
if (Weapon != 0)
{
// если залп или игрок (игроку регулируем сами)
if (WeaponFireType == 1 || ObjectStatus == 3)
{
for (int i=0; iWeaponFire(Time);
}
else// переменный огонь
{
int PrimCount = 0;
float PrimTime = 0.0f;
int FirstWeapon = 6;
int LastWeapon = 0;
WeaponGroupCurrentFireDelay -= TimeDelta;
// находим кол-во оружия
for (int i=0; iNextFireTime;
if (FirstWeapon > i) FirstWeapon = i;
if (LastWeapon < i) LastWeapon = i;
}
// если еще не было начальной установки
if (WeaponGroupCurrentFireNum == -1) WeaponGroupCurrentFireNum = FirstWeapon;
// стреляем
for (int i=0; iWeaponFire(Time);
WeaponGroupCurrentFireDelay = PrimTime/(PrimCount*PrimCount);
WeaponGroupCurrentFireNum ++;
if (WeaponGroupCurrentFireNum > LastWeapon) WeaponGroupCurrentFireNum = FirstWeapon;
// если такого оружия нет, берем что есть
if (Weapon[WeaponGroupCurrentFireNum] == 0)
{
bool exit = false;
while (!exit)
{
WeaponGroupCurrentFireNum ++;
if (WeaponGroupCurrentFireNum > LastWeapon) WeaponGroupCurrentFireNum = FirstWeapon;
if (Weapon[WeaponGroupCurrentFireNum] != 0) exit = true;
}
}
}
}
}
}
if (BossWeapon != 0)
{
// если залп
if (BossWeaponFireType == 1)
{
for (int i=0; iWeaponFire(Time);
}
else// переменный огонь
{
int PrimCount = 0;
float PrimTime = 0.0f;
int FirstWeapon = 6;
int LastWeapon = 0;
BossWeaponGroupCurrentFireDelay -= TimeDelta;
// находим кол-во оружия
for (int i=0; iNextFireTime;
if (FirstWeapon > i) FirstWeapon = i;
if (LastWeapon < i) LastWeapon = i;
}
// если еще не было начальной установки
if (BossWeaponGroupCurrentFireNum == -1) BossWeaponGroupCurrentFireNum = FirstWeapon;
// стреляем
for (int i=0; iWeaponFire(Time);
BossWeaponGroupCurrentFireDelay = PrimTime/(PrimCount*PrimCount);
BossWeaponGroupCurrentFireNum ++;
if (BossWeaponGroupCurrentFireNum > LastWeapon) BossWeaponGroupCurrentFireNum = FirstWeapon;
// если такого оружия нет, берем что есть
if (BossWeapon[BossWeaponGroupCurrentFireNum] == 0)
{
bool exit = false;
while (!exit)
{
BossWeaponGroupCurrentFireNum ++;
if (BossWeaponGroupCurrentFireNum > LastWeapon) BossWeaponGroupCurrentFireNum = FirstWeapon;
if (BossWeapon[BossWeaponGroupCurrentFireNum] != 0) exit = true;
}
}
}
}
}
}
if (WeaponFlare != 0)
{
if (WeaponFlareSetFire)
WeaponFlare->WeaponFire(Time);
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// небольшая девиация-болтание корпуса
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
if (DeviationOn)
for (int i=0; i CurentDeviationSum[i]) Sign = 1.0f;}
CurentDeviation[i] = Sign*0.035f*TimeDelta;
if (Sign == 1.0f)
{
if (NeedDeviation[i] <= CurentDeviationSum[i]+CurentDeviation[i])
{
CurentDeviation[i] -= CurentDeviationSum[i]+CurentDeviation[i]-NeedDeviation[i];
CurentDeviationSum[i] += CurentDeviation[i];
NeedDeviation[i] = vw_Randf0*0.1f;
}
else CurentDeviationSum[i] += CurentDeviation[i];
}
else
{
if (NeedDeviation[i] >= CurentDeviationSum[i]+CurentDeviation[i])
{
CurentDeviation[i] += CurentDeviationSum[i]+CurentDeviation[i]-NeedDeviation[i];
CurentDeviationSum[i] += CurentDeviation[i];
NeedDeviation[i] = vw_Randf0*0.1f;
}
else CurentDeviationSum[i] += CurentDeviation[i];
}
}
// только для корабля игрока - небольшое болтание во время полета
if (ObjectStatus == 3)
if (DeviationOn)
{
SetRotation((Deviation[0]^(CurentDeviation[0]*50.0f)), false);
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// считаем вектор движения
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Velocity = Orientation^(Speed*TimeDelta);
if (fabs(SpeedLR) > 0.01f)
{
VECTOR3D tmp(SpeedLR*TimeDelta,0.0f,0.0f);
Matrix33CalcPoint(&tmp, CurrentRotationMat);
Velocity += tmp;
}
if (fabs(SpeedUD) > 0.01f)
{
VECTOR3D tmp(0.0f,SpeedUD*TimeDelta,0.0f);
Matrix33CalcPoint(&tmp, CurrentRotationMat);
Velocity += tmp;
}
if (fabs(SpeedByCamFB) > 0.01f)
{
VECTOR3D tmp = GameCameraMovement^(SpeedByCamFB*TimeDelta);
Velocity += tmp;
}
if (fabs(SpeedByCamLR) > 0.01f)
{
VECTOR3D tmp = GameCameraMovement^(SpeedByCamLR*TimeDelta);
RotatePoint(&tmp, VECTOR3D(0.0,-90.0f,0.0f));
Velocity += tmp;
}
if (fabs(SpeedByCamUD) > 0.01f)
{
VECTOR3D tmp = GameCameraMovement^(SpeedByCamUD*TimeDelta);
RotatePoint(&tmp, VECTOR3D(90.0f,0.0f,0.0f));
Velocity += tmp;
}
// если это не корабль игрока и включена девиация
if (ObjectStatus != 3)
if (DeviationOn) Velocity += Deviation[0]^CurentDeviation[0];
// перемещение объекта, если нужно
if (Velocity.x != 0.0f || Velocity.y != 0.0f || Velocity.z != 0.0f )
{
// делаем сдвиг модели в указанную точку
SetLocation(Location+Velocity);
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Делаем установку работы двигателей, согласуем со скоростью корабля
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
if (Engine != 0)
{
float tmpSpeed = Speed;
if (tmpSpeed>6.0f) tmpSpeed=6.0f;
if (tmpSpeed<-6.0f) tmpSpeed=-6.0f;
tmpSpeed/=2.0f;
for (int i=0; iSpeedOnCreation != -1.0f)
Engine[i]->Speed = Engine[i]->SpeedOnCreation + tmpSpeed;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// работа с оружием - наведение его на ближайшую цель
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// а нужно ли стерять
bool NeedFire = false;
if (Weapon != 0)
for (int i=0; iNeedRotateOnTargeting)
{
WeaponAvLocation = WeaponAvLocation + WeaponLocation[i] + Weapon[i]->FireLocation + Location;
UsedWeaponQunt ++;
}
WeaponAvLocation.x = WeaponAvLocation.x / UsedWeaponQunt;
WeaponAvLocation.y = WeaponAvLocation.y / UsedWeaponQunt;
WeaponAvLocation.z = WeaponAvLocation.z / UsedWeaponQunt;
int WeapNum = -1;
VECTOR3D FirePos(0.0f,0.0f,0.0f);
if (Weapon != 0)
{
// находим номер
for (int i=0; iNeedRotateOnTargeting)
if (WeapNum == -1)
{
WeapNum = Weapon[0]->ObjectCreationType;
}
if (WeapNum == -1) WeapNum = 204; // номер самого простого из пиратского оружия
int Count = 0;
for (int i=0; iNeedRotateOnTargeting)
{
FirePos += WeaponLocation[i];
Count++;
}
FirePos = FirePos^(1.0f/Count);
}
GetEnemyShipOnTargetOrientateion(ObjectStatus, WeaponAvLocation, Rotation,
CurrentRotationMat, &NeedAngle, WeapNum, FirePos);
// всему оружию ставим нужную ориентацию
if (Weapon != 0)
for (int i=0; iNeedRotateOnTargeting)
{
NeedAngle.y = Weapon[i]->Rotation.y;
NeedAngle.z = Weapon[i]->Rotation.z;
Weapon[i]->SetRotation(Weapon[i]->Rotation^(-1));
Weapon[i]->SetRotation(NeedAngle);
}
}
ID = tmpID;
}
if (ObjectStatus == 1 && NeedBossFire)
{
VECTOR3D NeedAngle = Rotation;
// используем ID как маркер, чтобы не обрабатывать этот объект в процедуре
int tmpID = ID;
ID = 111111;
// ставим скорость наведения оружия
float TargetingSpeed = 4.0f/GameNPCTargetingSpeedPenalty;
// находим среднюю точку положение оружия
VECTOR3D WeaponAvLocation(0.0f,0.0f,0.0f);
int UsedWeaponQunt = 0;
if (BossWeapon != 0)
for (int i=0; iNeedRotateOnTargeting)
{
WeaponAvLocation = WeaponAvLocation + BossWeaponLocation[i] + BossWeapon[i]->FireLocation + Location;
UsedWeaponQunt ++;
}
WeaponAvLocation.x = WeaponAvLocation.x / UsedWeaponQunt;
WeaponAvLocation.y = WeaponAvLocation.y / UsedWeaponQunt;
WeaponAvLocation.z = WeaponAvLocation.z / UsedWeaponQunt;
int WeapNum = -1;
VECTOR3D FirePos(0.0f,0.0f,0.0f);
if (BossWeapon != 0)
{
// находим номер
for (int i=0; iNeedRotateOnTargeting)
if (WeapNum == -1)
{
WeapNum = BossWeapon[0]->ObjectCreationType;
}
if (WeapNum == -1) WeapNum = 204; // номер самого простого из пиратского оружия
int Count = 0;
for (int i=0; iNeedRotateOnTargeting)
{
FirePos += BossWeaponLocation[i];
Count++;
}
FirePos = FirePos^(1.0f/Count);
}
GetEnemyShipOnTargetOrientateion(ObjectStatus, WeaponAvLocation, Rotation,
CurrentRotationMat, &NeedAngle, WeapNum, FirePos);
// всему оружию ставим нужную ориентацию
if (BossWeapon != 0)
for (int i=0; iNeedRotateOnTargeting)
{
NeedAngle.y = BossWeapon[i]->Rotation.y;
NeedAngle.z = BossWeapon[i]->Rotation.z;
BossWeapon[i]->SetRotation(BossWeapon[i]->Rotation^(-1));
BossWeapon[i]->SetRotation(NeedAngle);
}
}
ID = tmpID;
}
// если в игре, а не в меню - иначе в оружейной дергается оружие
if (GameStatus == GAME)
// так стреляют только свои :)
if (ObjectStatus == 2)
{
// используем ID как маркер, чтобы не обрабатывать этот объект в процедуре
int tmpID = ID;
ID = 111111;
// ставим скорость наведения оружия
float TargetingSpeed = 1.0f;
// находим среднюю точку положение оружия
VECTOR3D WeaponAvLocation(0.0f,0.0f,0.0f);
int UsedWeaponQunt = 0;
if (Weapon != 0)
for (int i=0; iFireLocation + Location;
UsedWeaponQunt ++;
}
WeaponAvLocation.x = WeaponAvLocation.x / UsedWeaponQunt;
WeaponAvLocation.y = WeaponAvLocation.y / UsedWeaponQunt;
WeaponAvLocation.z = WeaponAvLocation.z / UsedWeaponQunt;
VECTOR3D NeedAngle = Rotation;
// всему оружию ставим нужную ориентацию
if (Weapon != 0)
for (int i=0; iNeedRotateOnTargeting)
{
NeedAngle = Rotation;
// добавляем базовый угол, чтобы по умолчанию устанавливало его
NeedAngle.y += WeaponYAngle[i];
GetShipOnTargetOrientateion(ObjectStatus, Location + WeaponLocation[i] + Weapon[i]->FireLocation, Rotation,
Length, CurrentRotationMat, &NeedAngle, Width, true, true, Location + WeaponLocation[i] + Weapon[i]->FireLocation, Weapon[i]->ObjectCreationType);
VECTOR3D NeedAngleTmp = NeedAngle;
// учитываем скорость поворота по вертикали
if (Weapon[i]->Rotation.x < NeedAngle.x)
{
float NeedAngle_x = Weapon[i]->Rotation.x+40.0f*TargetingSpeed*TimeDelta;
if (NeedAngle_x > NeedAngle.x) NeedAngle_x = NeedAngle.x;
NeedAngle.x = NeedAngle_x;
}
if (Weapon[i]->Rotation.x > NeedAngle.x)
{
float NeedAngle_x = Weapon[i]->Rotation.x-40.0f*TargetingSpeed*TimeDelta;
if (NeedAngle_x < NeedAngle.x) NeedAngle_x = NeedAngle.x;
NeedAngle.x = NeedAngle_x;
}
// учитываем скорость поворота по горизонтали
float Min = 0.0f;
float Max = 0.0f;
GetShipWeaponSlotAngle(Setup.Profile[CurrentProfile].Ship, i, &Min, &Max);
if (Weapon[i]->Rotation.y < NeedAngle.y)
{
float NeedAngle_y = Weapon[i]->Rotation.y+40.0f*TargetingSpeed*TimeDelta;
if (NeedAngle_y > NeedAngle.y) NeedAngle_y = NeedAngle.y;
NeedAngle.y = NeedAngle_y;
// проверка на достижение предела поворота
if (NeedAngle.y > Max+Rotation.y) NeedAngle.y = Max+Rotation.y;
}
if (Weapon[i]->Rotation.y > NeedAngle.y)
{
float NeedAngle_y = Weapon[i]->Rotation.y-40.0f*TargetingSpeed*TimeDelta;
if (NeedAngle_y < NeedAngle.y) NeedAngle_y = NeedAngle.y;
NeedAngle.y = NeedAngle_y;
// проверка на достижение предела поворота
if (NeedAngle.y < Min+Rotation.y) NeedAngle.y = Min+Rotation.y;
}
// если выключен прикол с поворотом - моментально поворачиваем ствол
if (GameWeaponTargetingMode == 1) NeedAngle = NeedAngleTmp;
// если это не ракетные системы, нужно повернуть
if (Weapon[i]->ObjectCreationType < 16)
{
Weapon[i]->SetRotation(Weapon[i]->Rotation^(-1));
Weapon[i]->SetRotation(NeedAngle);
}
}
}
ID = tmpID;
}
// если корабль игрока
if (ObjectStatus == 3)
{
// используем ID как маркер, чтобы не обрабатывать этот объект в процедуре
int tmpID = ID;
ID = 111111;
// ставим скорость наведения оружия
float TargetingSpeed = GameTargetingMechanicSystem*1.0f;
// находим среднюю точку положение оружия
VECTOR3D WeaponAvLocation(0.0f,0.0f,0.0f);
int UsedWeaponQunt = 0;
if (Weapon != 0)
for (int i=0; iFireLocation + Location;
UsedWeaponQunt ++;
}
WeaponAvLocation.x = WeaponAvLocation.x / UsedWeaponQunt;
WeaponAvLocation.y = WeaponAvLocation.y / UsedWeaponQunt;
WeaponAvLocation.z = WeaponAvLocation.z / UsedWeaponQunt;
VECTOR3D NeedAngle = Rotation;
// у оружия есть (для каждого слота в корабле свои)
// мин-макс и базовый (выставляет пользователь) углы поворота орудия
// передавать на проверку всегда базовый угол!!! не текущий!
/* типы наведения
1 - простое наведение всех орудий по кораблю
2 - простое наведение всех орудий по кораблю + доворот на центр
3 - наведение каждого орудия на свою цель
4 - наведение каждого орудия на свою цель + доворот
*/
// т.к. у нас включена девиация, нужно принять меры
float RotationMat2[9];
memcpy(RotationMat2, CurrentRotationMat, sizeof(float)*9);
VECTOR3D Rotation2 = Rotation;
if (DeviationOn)
{
Rotation2 = Rotation - (Deviation[0]^(CurentDeviation[0]*50.0f));
Matrix33CreateRotate(RotationMat2, Rotation2);
}
// всему оружию ставим нужную ориентацию
if (Weapon != 0)
for (int i=0; iNeedRotateOnTargeting)
{
NeedAngle = Rotation2;
// добавляем базовый угол, чтобы по умолчанию устанавливало его
NeedAngle.y += WeaponYAngle[i];
if (GameTargetingSystem == 1)
GetShipOnTargetOrientateion(ObjectStatus, WeaponAvLocation, Rotation2,
Length, RotationMat2, &NeedAngle, Width, false, true, Location + WeaponLocation[i] + Weapon[i]->FireLocation, Weapon[i]->ObjectCreationType);
if (GameTargetingSystem == 2)
GetShipOnTargetOrientateion(ObjectStatus, WeaponAvLocation, Rotation2,
Length, RotationMat2, &NeedAngle, Width, true, true, Location + WeaponLocation[i] + Weapon[i]->FireLocation, Weapon[i]->ObjectCreationType);
if (GameTargetingSystem == 3)
GetShipOnTargetOrientateion(ObjectStatus, Location + WeaponLocation[i] + Weapon[i]->FireLocation, Weapon[i]->Rotation,
Length, Weapon[i]->CurrentRotationMat, &NeedAngle, Weapon[i]->Width, false, true, Location + WeaponLocation[i] + Weapon[i]->FireLocation, Weapon[i]->ObjectCreationType);
if (GameTargetingSystem == 4)
GetShipOnTargetOrientateion(ObjectStatus, Location + WeaponLocation[i] + Weapon[i]->FireLocation, VECTOR3D(Weapon[i]->Rotation.x,0,Weapon[i]->Rotation.z)+VECTOR3D(0,WeaponYAngle[i],0),
Length, Weapon[i]->CurrentRotationMat, &NeedAngle, Width, true, true, Location + WeaponLocation[i] + Weapon[i]->FireLocation, Weapon[i]->ObjectCreationType);
VECTOR3D NeedAngleTmp = NeedAngle;
// учитываем скорость поворота по вертикали
if (Weapon[i]->Rotation.x < NeedAngle.x)
{
float NeedAngle_x = Weapon[i]->Rotation.x+40.0f*TargetingSpeed*TimeDelta;
if (NeedAngle_x > NeedAngle.x) NeedAngle_x = NeedAngle.x;
NeedAngle.x = NeedAngle_x;
}
if (Weapon[i]->Rotation.x > NeedAngle.x)
{
float NeedAngle_x = Weapon[i]->Rotation.x-40.0f*TargetingSpeed*TimeDelta;
if (NeedAngle_x < NeedAngle.x) NeedAngle_x = NeedAngle.x;
NeedAngle.x = NeedAngle_x;
}
// учитываем скорость поворота по горизонтали
float Min = 0.0f;
float Max = 0.0f;
GetShipWeaponSlotAngle(Setup.Profile[CurrentProfile].Ship, i, &Min, &Max);
if (Weapon[i]->Rotation.y < NeedAngle.y)
{
float NeedAngle_y = Weapon[i]->Rotation.y+40.0f*TargetingSpeed*TimeDelta;
if (NeedAngle_y > NeedAngle.y) NeedAngle_y = NeedAngle.y;
NeedAngle.y = NeedAngle_y;
// проверка на достижение предела поворота
if (NeedAngle.y > Max+Rotation2.y) NeedAngle.y = Max+Rotation2.y;
}
if (Weapon[i]->Rotation.y > NeedAngle.y)
{
float NeedAngle_y = Weapon[i]->Rotation.y-40.0f*TargetingSpeed*TimeDelta;
if (NeedAngle_y < NeedAngle.y) NeedAngle_y = NeedAngle.y;
NeedAngle.y = NeedAngle_y;
// проверка на достижение предела поворота
if (NeedAngle.y < Min+Rotation2.y) NeedAngle.y = Min+Rotation2.y;
}
// если выключен прикол с поворотом - моментально поворачиваем ствол
if (GameWeaponTargetingMode == 1) NeedAngle = NeedAngleTmp;
Weapon[i]->SetRotation(Weapon[i]->Rotation^(-1));
Weapon[i]->SetRotation(NeedAngle);
}
}
ID = tmpID;
}
// объект в порядке - удалять не нужно
return true;
}