/****************************************************************************** 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: Projectile.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 "Projectile.h" #include "../Explosion/BulletExplosion/BulletExplosion.h" CObject3D *GetMissileOnTargetOrientateion(int ObjectStatus, VECTOR3D Location, VECTOR3D CurrentObjectRotation, float RotationMatrix[9], VECTOR3D *NeedAngle); struct ProjectileData { float Radius; float DamageHull; float DamageSystems; // 0-обычный снаряд, 1-уничтожаемый, 2-лучевой, 3-мина (не уничтожаемая), 4-мина (уничтожаемая) int ProjectileType; float Speed; float Age; int GraphicFXQuantity; }; // снаряды для оружия землян 1-99 const int PresetEarthProjectileDataCount = 19; ProjectileData PresetEarthProjectileData[PresetEarthProjectileDataCount] = { // Kinetic {0.3f, 5, 0, 0, 50, 4, 1}, {0.6f, 20, 0, 0, 45, 4, 1}, {0.6f, 40, 0, 0, 45, 4, 1}, {0.4f, 10, 0, 0, 50, 4, 1}, // Ion {1.5f, 0, 10, 0, 40, 4, 1}, {1.5f, 0, 30, 0, 40, 4, 2}, {2.0f, 0, 50, 0, 40, 4, 2}, // Plasma {1.0f, 30, 5, 0, 40, 4, 1}, {1.3f, 40, 25, 0, 40, 4, 3}, {1.3f, 50, 50, 0, 45, 4, 3}, // Maser {0.6f, 50, 0, 2, 0, 2, 1}, {1.0f, 80, 0, 2, 0, 2, 2}, // Antimatter {1.0f, 80, 10, 0, 70, 3, 1}, // Laser {0.4f, 150, 0, 2, 0, 1, 1}, // Gauss {1.1f, 100, 0, 0, 80, 3, 1}, // Missiles {0.2f, 100, 0, 1, 40, 8, 1}, {0.2f, 20, 0, 1, 40, 6, 1}, {0.2f, 400, 0, 1, 35, 7, 1}, {0.2f, 800, 0, 1, 30, 6, 1}, }; // снаряды для оружия пришельцев 101-199 const int PresetAlienProjectileDataCount = 10; ProjectileData PresetAlienProjectileData[PresetAlienProjectileDataCount] = { // как Kinetic1 {0.3f, 5, 0, 0, 70, 4, 1}, // с наведением, как Kinetic2 {0.6f, 10, 0, 0, 50, 4, 1}, // как Kinetic3 {0.6f, 20, 0, 0, 60, 4, 1}, // с наведением, как Kinetic3 {0.6f, 20, 0, 0, 60, 4, 1}, // как Kinetic2 {0.6f, 10, 0, 0, 50, 4, 1}, // энергетическая мина (1-й тип), только позиционируется по высоте (на ближайшего врага) {2.0f, 60, 0, 3, 0, 16, 1}, // энергетическая мина (2-й тип), позиционируется по высоте (на ближайшего врага) + немного приближается {2.0f, 120, 0, 3, 7, 16, 1}, // как Plasma3 {1.3f, 50, 50, 0, 55, 4, 3}, // как Plasma2 {1.3f, 40, 25, 0, 55, 4, 3}, // как Laser (для больших кораблей) {1.0f, 250, 0, 2, 0, 1, 1}, }; // снаряды для оружия пиратов 201-299 const int PresetPirateProjectileDataCount = 17; ProjectileData PresetPirateProjectileData[PresetPirateProjectileDataCount] = { // стрельба турели 1 {0.3f, 5, 0, 0, 60, 4, 1}, // стрельба турели 2 {0.6f, 20, 0, 0, 45, 4, 1}, // фларес {3.0f, 5, 0, 3, 5, 5, 1}, // как Kinetic1 {0.3f, 5, 0, 0, 60, 4, 1}, // как Missile1 {0.2f, 40, 0, 1, 60, 6, 1}, // как Missile2 {0.2f, 20, 0, 1, 60, 6, 1}, // как Ion2 {1.5f, 0, 30, 0, 40, 4, 2}, // как Antimatter {1.0f, 80, 10, 0, 70, 3, 1}, // как Missile3 (торпеда) {0.2f, 400, 0, 1, 55, 7, 1}, // как Missile4 (бомба) {0.2f, 1000, 0, 1, 50, 6, 1}, // как Kinetic2 {0.6f, 20, 0, 0, 45, 4, 1}, // как Kinetic3 {0.6f, 40, 0, 0, 45, 4, 1}, // как Plasma2 {1.3f, 40, 25, 0, 40, 4, 3}, // мина1 (простое наведение по высоте) {1.2f, 50, 0, 4, 0, -1, 1}, // мина2 (наведение по высоте + приближение) {1.2f, 100, 0, 4, 7, -1, 1}, // мина3 (наведение по высоте + стрельба снарядами) {1.2f, 150, 0, 4, 0, -1, 1}, // мина4 (наведение по высоте + стрельба ракетами) {1.2f, 200, 0, 4, 0, -1, 1}, }; // получаем время жизни снаряда float GetProjectileRange(int Num) { if (Num >= 1 && Num <= 99) { float Return = PresetEarthProjectileData[Num-1].Age * PresetEarthProjectileData[Num-1].Speed; if (Num == 11) Return = 100.0f; if (Num == 12) Return = 110.0f; if (Num == 14) Return = 120.0f; return Return; } else if (Num >= 101 && Num <= 199) { if (Num == 110) return 200.0f; return PresetAlienProjectileData[Num-101].Age * PresetAlienProjectileData[Num-101].Speed; } else if (Num >= 201 && Num <= 299) { return PresetPirateProjectileData[Num-201].Age * PresetPirateProjectileData[Num-201].Speed; } return 0.0f; } int GetWeaponHullDamage(int Num) { if (Num >= 1 && Num <= 99) { // если система залпового огня if (Num == 17) return 10 * (int)PresetEarthProjectileData[Num-1].DamageHull; return (int)PresetEarthProjectileData[Num-1].DamageHull; } else if (Num >= 101 && Num <= 199) { return (int)PresetAlienProjectileData[Num-101].DamageHull; } else if (Num >= 201 && Num <= 299) { return (int)PresetPirateProjectileData[Num-201].DamageHull; } } int GetWeaponSystemsDamage(int Num) { if (Num >= 1 && Num <= 99) { // если система залпового огня if (Num == 17) return 10 * (int)PresetEarthProjectileData[Num-1].DamageSystems; return (int)PresetEarthProjectileData[Num-1].DamageSystems; } else if (Num >= 101 && Num <= 199) { return (int)PresetAlienProjectileData[Num-101].DamageSystems; } else if (Num >= 201 && Num <= 299) { return (int)PresetPirateProjectileData[Num-201].DamageSystems; } } float GetProjectileSpeed(int Num) { if (Num >= 1 && Num <= 99) { return PresetEarthProjectileData[Num-1].Speed; } else if (Num >= 101 && Num <= 199) { return PresetAlienProjectileData[Num-101].Speed; } else if (Num >= 201 && Num <= 299) { return PresetPirateProjectileData[Num-201].Speed; } } //----------------------------------------------------------------------------- // Конструктор, инициализация всех переменных //----------------------------------------------------------------------------- CProjectile::CProjectile(void) { // друг ObjectStatus = 2; ObjectType = 10; // проверяем на столкновения только по радиусу Radius = 0.0f; // нет цели Target = 0; // пока не повреждает вообще DamageHull = 0.0f; DamageSystems = 0.0f; // нет графических эффектов GraphicFXQuantity = 0; GraphicFXLocation = 0; GraphicFX = 0; GraphicFXDestroyType = false; NeedStopPartic = false; // не можем сбивать снаряд ProjectileType = 0; ProjectileCenter = VECTOR3D(0.0f, 0.0f, 0.0f); Age = 0.0f; NeedDeadSound = true; SpeedStart = SpeedEnd = Speed = 0.0f; MineReloadTime = MineNextFireTime = 1.0f; Ambient[0] = Ambient[1] = Ambient[2] = Ambient[3] = 0.35f; Next = Prev = 0; AttachProjectile(this); } //----------------------------------------------------------------------------- // выполнение действий //----------------------------------------------------------------------------- void CProjectile::Create(int ProjectileNum) { Num = ProjectileNum; // внутренний номер, номер в таблицах int IntNum = ProjectileNum; if (Num >= 1 && Num <= 99) { Radius = PresetEarthProjectileData[IntNum-1].Radius; DamageHull = PresetEarthProjectileData[IntNum-1].DamageHull; DamageSystems = PresetEarthProjectileData[IntNum-1].DamageSystems; ProjectileType = PresetEarthProjectileData[IntNum-1].ProjectileType; SpeedStart = SpeedEnd = Speed = PresetEarthProjectileData[IntNum-1].Speed; Age = Lifetime = PresetEarthProjectileData[IntNum-1].Age; GraphicFXQuantity = PresetEarthProjectileData[IntNum-1].GraphicFXQuantity; } else if (Num >= 101 && Num <= 199) { IntNum = ProjectileNum - 100; Radius = PresetAlienProjectileData[IntNum-1].Radius; DamageHull = PresetAlienProjectileData[IntNum-1].DamageHull; DamageSystems = PresetAlienProjectileData[IntNum-1].DamageSystems; ProjectileType = PresetAlienProjectileData[IntNum-1].ProjectileType; SpeedStart = SpeedEnd = Speed = PresetAlienProjectileData[IntNum-1].Speed; Age = Lifetime = PresetAlienProjectileData[IntNum-1].Age; GraphicFXQuantity = PresetAlienProjectileData[IntNum-1].GraphicFXQuantity; } else if (Num >= 201 && Num <= 299) { IntNum = ProjectileNum - 200; // радиус для мин потом изменим при инициализации геометрии Radius = PresetPirateProjectileData[IntNum-1].Radius; DamageHull = PresetPirateProjectileData[IntNum-1].DamageHull; DamageSystems = PresetPirateProjectileData[IntNum-1].DamageSystems; ProjectileType = PresetPirateProjectileData[IntNum-1].ProjectileType; SpeedStart = SpeedEnd = Speed = PresetPirateProjectileData[IntNum-1].Speed; Age = Lifetime = PresetPirateProjectileData[IntNum-1].Age; GraphicFXQuantity = PresetPirateProjectileData[IntNum-1].GraphicFXQuantity; } // начальные установки GraphicFXLocation = new VECTOR3D[GraphicFXQuantity]; GraphicFX = new eParticleSystem*[GraphicFXQuantity]; for (int i=0; iCreationSize = VECTOR3D(2.5f,2.5f,0.5f); GraphicFX[1]->DeadZone = 1.9f; break; case 7: GraphicFX[0] = new eParticleSystem; SetProjectileGFX(GraphicFX[0], 12); GraphicFX[1] = new eParticleSystem; SetProjectileGFX(GraphicFX[1], 5); break; // Plasma case 8: GraphicFX[0] = new eParticleSystem; SetProjectileGFX(GraphicFX[0], 7); break; case 9: GraphicFX[0] = new eParticleSystem; SetProjectileGFX(GraphicFX[0], 10); GraphicFX[1] = new eParticleSystem; SetProjectileGFX(GraphicFX[1], 8); GraphicFX[2] = new eParticleSystem; SetProjectileGFX(GraphicFX[2], 9); break; case 10: GraphicFX[0] = new eParticleSystem; SetProjectileGFX(GraphicFX[0], 8); GraphicFX[1] = new eParticleSystem; SetProjectileGFX(GraphicFX[1], 9); GraphicFX[2] = new eParticleSystem; SetProjectileGFX(GraphicFX[2], 11); break; // Maser case 11: GraphicFX[0] = new eParticleSystem; SetProjectileGFX(GraphicFX[0], 17); GraphicFX[0]->CreationSize = VECTOR3D(0.8f,0.8f,100.0f); ProjectileCenter = VECTOR3D(0.0f,0.0f,50.0f); NeedStopPartic = true; { float MinX = -GraphicFX[0]->CreationSize.x/2; float MaxX = GraphicFX[0]->CreationSize.x/2; float MinY = -GraphicFX[0]->CreationSize.y/2; float MaxY = GraphicFX[0]->CreationSize.y/2; float MinZ = -GraphicFX[0]->CreationSize.z/2; float MaxZ = GraphicFX[0]->CreationSize.z/2; // запоминаем только то, что нужно - float x, float y, float z, float sizeX, float sizeY, float sizeZ OBB[0] = AABB[0] = VECTOR3D(MaxX, MaxY, MaxZ); OBB[1] = AABB[1] = VECTOR3D(MinX, MaxY, MaxZ); OBB[2] = AABB[2] = VECTOR3D(MinX, MaxY, MinZ); OBB[3] = AABB[3] = VECTOR3D(MaxX, MaxY, MinZ); OBB[4] = AABB[4] = VECTOR3D(MaxX, MinY, MaxZ); OBB[5] = AABB[5] = VECTOR3D(MinX, MinY, MaxZ); OBB[6] = AABB[6] = VECTOR3D(MinX, MinY, MinZ); OBB[7] = AABB[7] = VECTOR3D(MaxX, MinY, MinZ); OBBLocation = VECTOR3D(0,0,0); Width = fabsf(MaxX-MinX); Height = fabsf(MaxY-MinY); Length = fabsf(MaxZ-MinZ); } break; case 12: GraphicFX[0] = new eParticleSystem; SetProjectileGFX(GraphicFX[0], 17); GraphicFX[0]->CreationSize = VECTOR3D(0.8f,0.8f,110.0f); GraphicFX[1] = new eParticleSystem; SetProjectileGFX(GraphicFX[1], 18); GraphicFX[1]->CreationSize = VECTOR3D(1.6f,1.6f,110.0f); ProjectileCenter = VECTOR3D(0.0f,0.0f,55.0f); NeedStopPartic = true; { float MinX = -GraphicFX[0]->CreationSize.x/2; float MaxX = GraphicFX[0]->CreationSize.x/2; float MinY = -GraphicFX[0]->CreationSize.y/2; float MaxY = GraphicFX[0]->CreationSize.y/2; float MinZ = -GraphicFX[0]->CreationSize.z/2; float MaxZ = GraphicFX[0]->CreationSize.z/2; // запоминаем только то, что нужно - float x, float y, float z, float sizeX, float sizeY, float sizeZ OBB[0] = AABB[0] = VECTOR3D(MaxX, MaxY, MaxZ); OBB[1] = AABB[1] = VECTOR3D(MinX, MaxY, MaxZ); OBB[2] = AABB[2] = VECTOR3D(MinX, MaxY, MinZ); OBB[3] = AABB[3] = VECTOR3D(MaxX, MaxY, MinZ); OBB[4] = AABB[4] = VECTOR3D(MaxX, MinY, MaxZ); OBB[5] = AABB[5] = VECTOR3D(MinX, MinY, MaxZ); OBB[6] = AABB[6] = VECTOR3D(MinX, MinY, MinZ); OBB[7] = AABB[7] = VECTOR3D(MaxX, MinY, MinZ); OBBLocation = VECTOR3D(0,0,0); Width = fabsf(MaxX-MinX); Height = fabsf(MaxY-MinY); Length = fabsf(MaxZ-MinZ); } break; // Antimatter case 13: GraphicFX[0] = new eParticleSystem; SetProjectileGFX(GraphicFX[0], 19); break; // Laser case 14: GraphicFX[0] = new eParticleSystem; SetProjectileGFX(GraphicFX[0], 20); GraphicFX[0]->CreationSize = VECTOR3D(0.4f,0.4f,120.0f); ProjectileCenter = VECTOR3D(0.0f,0.0f,60.0f); NeedStopPartic = true; { float MinX = -GraphicFX[0]->CreationSize.x/2; float MaxX = GraphicFX[0]->CreationSize.x/2; float MinY = -GraphicFX[0]->CreationSize.y/2; float MaxY = GraphicFX[0]->CreationSize.y/2; float MinZ = -GraphicFX[0]->CreationSize.z/2; float MaxZ = GraphicFX[0]->CreationSize.z/2; // запоминаем только то, что нужно - float x, float y, float z, float sizeX, float sizeY, float sizeZ OBB[0] = AABB[0] = VECTOR3D(MaxX, MaxY, MaxZ); OBB[1] = AABB[1] = VECTOR3D(MinX, MaxY, MaxZ); OBB[2] = AABB[2] = VECTOR3D(MinX, MaxY, MinZ); OBB[3] = AABB[3] = VECTOR3D(MaxX, MaxY, MinZ); OBB[4] = AABB[4] = VECTOR3D(MaxX, MinY, MaxZ); OBB[5] = AABB[5] = VECTOR3D(MinX, MinY, MaxZ); OBB[6] = AABB[6] = VECTOR3D(MinX, MinY, MinZ); OBB[7] = AABB[7] = VECTOR3D(MaxX, MinY, MinZ); OBBLocation = VECTOR3D(0,0,0); Width = fabsf(MaxX-MinX); Height = fabsf(MaxY-MinY); Length = fabsf(MaxZ-MinZ); } break; // Gauss case 15: GraphicFX[0] = new eParticleSystem; SetProjectileGFX(GraphicFX[0], 21); break; // ракета case 16: LoadObjectData("DATA/MODELS/EARTHFIGHTER/missile.VW3D", this, 0); Texture[0] = vw_FindTextureByName("DATA/MODELS/EARTHFIGHTER/rockets.jpg"); ::CObject3D::InitByDrawObjectList(); GraphicFX[0] = new eParticleSystem; SetProjectileGFX(GraphicFX[0], 13); GraphicFXLocation[0] = VECTOR3D(0.0f, 0.0f, -Length/2.0f); NeedStopPartic = true; break; // рой case 17: LoadObjectData("DATA/MODELS/EARTHFIGHTER/swarm.VW3D", this, 0); Texture[0] = vw_FindTextureByName("DATA/MODELS/EARTHFIGHTER/rockets.jpg"); ::CObject3D::InitByDrawObjectList(); GraphicFX[0] = new eParticleSystem; SetProjectileGFX(GraphicFX[0], 16); GraphicFXLocation[0] = VECTOR3D(0.0f, 0.0f, -Length/2.0f); NeedStopPartic = true; break; // торпеда case 18: LoadObjectData("DATA/MODELS/EARTHFIGHTER/torpedo.VW3D", this, 0); Texture[0] = vw_FindTextureByName("DATA/MODELS/EARTHFIGHTER/rockets.jpg"); ::CObject3D::InitByDrawObjectList(); GraphicFX[0] = new eParticleSystem; SetProjectileGFX(GraphicFX[0], 14); GraphicFXLocation[0] = VECTOR3D(0.0f, 0.0f, -Length/2.0f); NeedStopPartic = true; break; // бомба case 19: LoadObjectData("DATA/MODELS/EARTHFIGHTER/nuke.VW3D", this, 0); Texture[0] = vw_FindTextureByName("DATA/MODELS/EARTHFIGHTER/rockets.jpg"); ::CObject3D::InitByDrawObjectList(); GraphicFX[0] = new eParticleSystem; SetProjectileGFX(GraphicFX[0], 15); GraphicFXLocation[0] = VECTOR3D(0.0f, 0.0f, -Length/2.0f); NeedStopPartic = true; break; // снаряды пришельцев // как Kinetic1 case 101: GraphicFX[0] = new eParticleSystem; SetProjectileGFX(GraphicFX[0], 22); break; // с наведением, как Kinetic2 case 102: GraphicFX[0] = new eParticleSystem; SetProjectileGFX(GraphicFX[0], 23); break; // как Kinetic3 case 103: GraphicFX[0] = new eParticleSystem; SetProjectileGFX(GraphicFX[0], 24); break; // с наведением, как Kinetic3 case 104: GraphicFX[0] = new eParticleSystem; SetProjectileGFX(GraphicFX[0], 24); break; // как Kinetic2 case 105: GraphicFX[0] = new eParticleSystem; SetProjectileGFX(GraphicFX[0], 23); break; // энергетическая мина (1-й тип) case 106: GraphicFX[0] = new eParticleSystem; SetProjectileGFX(GraphicFX[0], 36); break; // энергетическая мина (2-й тип) case 107: GraphicFX[0] = new eParticleSystem; SetProjectileGFX(GraphicFX[0], 37); break; // как Plasma3 case 108: GraphicFX[0] = new eParticleSystem; SetProjectileGFX(GraphicFX[0], 8); GraphicFX[1] = new eParticleSystem; SetProjectileGFX(GraphicFX[1], 9); GraphicFX[2] = new eParticleSystem; SetProjectileGFX(GraphicFX[2], 11); break; // как Plasma2 case 109: GraphicFX[0] = new eParticleSystem; SetProjectileGFX(GraphicFX[0], 10); GraphicFX[1] = new eParticleSystem; SetProjectileGFX(GraphicFX[1], 8); GraphicFX[2] = new eParticleSystem; SetProjectileGFX(GraphicFX[2], 9); break; // как Laser case 110: GraphicFX[0] = new eParticleSystem; SetProjectileGFX(GraphicFX[0], 38); GraphicFX[0]->CreationSize = VECTOR3D(2.0f,2.0f,110.0f); ProjectileCenter = VECTOR3D(0.0f,0.0f,55.0f); NeedStopPartic = true; { float MinX = -GraphicFX[0]->CreationSize.x/2; float MaxX = GraphicFX[0]->CreationSize.x/2; float MinY = -GraphicFX[0]->CreationSize.y/2; float MaxY = GraphicFX[0]->CreationSize.y/2; float MinZ = -GraphicFX[0]->CreationSize.z/2; float MaxZ = GraphicFX[0]->CreationSize.z/2; // запоминаем только то, что нужно - float x, float y, float z, float sizeX, float sizeY, float sizeZ OBB[0] = AABB[0] = VECTOR3D(MaxX, MaxY, MaxZ); OBB[1] = AABB[1] = VECTOR3D(MinX, MaxY, MaxZ); OBB[2] = AABB[2] = VECTOR3D(MinX, MaxY, MinZ); OBB[3] = AABB[3] = VECTOR3D(MaxX, MaxY, MinZ); OBB[4] = AABB[4] = VECTOR3D(MaxX, MinY, MaxZ); OBB[5] = AABB[5] = VECTOR3D(MinX, MinY, MaxZ); OBB[6] = AABB[6] = VECTOR3D(MinX, MinY, MinZ); OBB[7] = AABB[7] = VECTOR3D(MaxX, MinY, MinZ); OBBLocation = VECTOR3D(0,0,0); Width = fabsf(MaxX-MinX); Height = fabsf(MaxY-MinY); Length = fabsf(MaxZ-MinZ); } break; // снаряды пиратов // стрельба турели 1 case 201: GraphicFX[0] = new eParticleSystem; SetProjectileGFX(GraphicFX[0], 26); break; // стрельба турели 2 case 202: GraphicFX[0] = new eParticleSystem; SetProjectileGFX(GraphicFX[0], 34); break; // фларес case 203: // смотрит вверх Orientation = VECTOR3D(0.0f, 0.5f, 0.5f); GraphicFX[0] = new eParticleSystem; SetProjectileGFX(GraphicFX[0], 25); break; // как Kinetic1 case 204: GraphicFX[0] = new eParticleSystem; SetProjectileGFX(GraphicFX[0], 26); break; // как Missile1 case 205: LoadObjectData("DATA/MODELS/EARTHFIGHTER/missile.VW3D", this, 0); Texture[0] = vw_FindTextureByName("DATA/MODELS/EARTHFIGHTER/rockets.jpg"); ::CObject3D::InitByDrawObjectList(); GraphicFX[0] = new eParticleSystem; SetProjectileGFX(GraphicFX[0], 27); GraphicFXLocation[0] = VECTOR3D(0.0f, 0.0f, -Length/2.0f); NeedStopPartic = true; break; // как Missile2 case 206: LoadObjectData("DATA/MODELS/EARTHFIGHTER/swarm.VW3D", this, 0); Texture[0] = vw_FindTextureByName("DATA/MODELS/EARTHFIGHTER/rockets.jpg"); ::CObject3D::InitByDrawObjectList(); GraphicFX[0] = new eParticleSystem; SetProjectileGFX(GraphicFX[0], 31); GraphicFXLocation[0] = VECTOR3D(0.0f, 0.0f, -Length/2.0f); NeedStopPartic = true; break; // как Ion2 case 207: GraphicFX[0] = new eParticleSystem; SetProjectileGFX(GraphicFX[0], 6); GraphicFX[1] = new eParticleSystem; SetProjectileGFX(GraphicFX[1], 5); GraphicFX[1]->CreationSize = VECTOR3D(2.5f,2.5f,0.5f); GraphicFX[1]->DeadZone = 1.9f; break; // как Antimatter case 208: GraphicFX[0] = new eParticleSystem; SetProjectileGFX(GraphicFX[0], 19); break; // как торпеда case 209: LoadObjectData("DATA/MODELS/EARTHFIGHTER/torpedo.VW3D", this, 0); Texture[0] = vw_FindTextureByName("DATA/MODELS/EARTHFIGHTER/rockets.jpg"); ::CObject3D::InitByDrawObjectList(); GraphicFX[0] = new eParticleSystem; SetProjectileGFX(GraphicFX[0], 32); GraphicFXLocation[0] = VECTOR3D(0.0f, 0.0f, -Length/2.0f); NeedStopPartic = true; break; // как бомба case 210: LoadObjectData("DATA/MODELS/EARTHFIGHTER/nuke.VW3D", this, 0); Texture[0] = vw_FindTextureByName("DATA/MODELS/EARTHFIGHTER/rockets.jpg"); ::CObject3D::InitByDrawObjectList(); GraphicFX[0] = new eParticleSystem; SetProjectileGFX(GraphicFX[0], 33); GraphicFXLocation[0] = VECTOR3D(0.0f, 0.0f, -Length/2.0f); NeedStopPartic = true; break; // как Kinetic2 case 211: GraphicFX[0] = new eParticleSystem; SetProjectileGFX(GraphicFX[0], 34); break; // как Kinetic3 case 212: GraphicFX[0] = new eParticleSystem; SetProjectileGFX(GraphicFX[0], 35); break; // как Plasma2 case 213: GraphicFX[0] = new eParticleSystem; SetProjectileGFX(GraphicFX[0], 10); GraphicFX[1] = new eParticleSystem; SetProjectileGFX(GraphicFX[1], 8); GraphicFX[2] = new eParticleSystem; SetProjectileGFX(GraphicFX[2], 9); break; // мина1 (простое наведение по высоте) case 214: MineIData = 0.0f; Strength = StrengthStart = 10.0f; LoadObjectData("DATA/MODELS/MINE/mine-01.VW3D", this, 0); Texture[0] = vw_FindTextureByName("DATA/MODELS/MINE/mine1.jpg"); TextureIllum[0] = vw_FindTextureByName("DATA/MODELS/MINE/mine1i.jpg"); ::CObject3D::InitByDrawObjectList(); break; // мина2 (наведение по высоте + приближение) case 215: MineIData = 0.0f; Strength = StrengthStart = 15.0f; LoadObjectData("DATA/MODELS/MINE/mine-02.VW3D", this, 0); Texture[0] = vw_FindTextureByName("DATA/MODELS/MINE/mine2.jpg"); TextureIllum[0] = vw_FindTextureByName("DATA/MODELS/MINE/mine2i.jpg"); ::CObject3D::InitByDrawObjectList(); GraphicFX[0] = new eParticleSystem; SetProjectileGFX(GraphicFX[0], 28); GraphicFXLocation[0] = VECTOR3D(0.0f, -0.8f, 0.0f); NeedStopPartic = true; break; // мина3 (наведение по высоте + стрельба снарядами) case 216: MineIData = 0.0f; Strength = StrengthStart = 20.0f; MineReloadTime = MineNextFireTime = 1.0f; LoadObjectData("DATA/MODELS/MINE/mine-03.VW3D", this, 0); Texture[0] = vw_FindTextureByName("DATA/MODELS/MINE/mine3.jpg"); TextureIllum[0] = vw_FindTextureByName("DATA/MODELS/MINE/mine3i.jpg"); ::CObject3D::InitByDrawObjectList(); GraphicFX[0] = new eParticleSystem; SetProjectileGFX(GraphicFX[0], 29); GraphicFXLocation[0] = VECTOR3D(0.0f, -2.5f, 0.0f); NeedStopPartic = true; break; // мина4 (наведение по высоте + стрельба ракетами) case 217: MineIData = 0.0f; Strength = StrengthStart = 40.0f; MineReloadTime = MineNextFireTime = 3.0f; LoadObjectData("DATA/MODELS/MINE/mine-04.VW3D", this, 0); Texture[0] = vw_FindTextureByName("DATA/MODELS/MINE/mine4.jpg"); TextureIllum[0] = vw_FindTextureByName("DATA/MODELS/MINE/mine4i.jpg"); ::CObject3D::InitByDrawObjectList(); GraphicFX[0] = new eParticleSystem; SetProjectileGFX(GraphicFX[0], 30); GraphicFXLocation[0] = VECTOR3D(0.0f, -0.7f, 0.0f); NeedStopPartic = true; break; default: fprintf(stderr, "Wrong ProjectileNum!"); } } //----------------------------------------------------------------------------- // Деструктор //----------------------------------------------------------------------------- CProjectile::~CProjectile(void) { if (GraphicFX != 0) { for (int i=0; iChangeSpeed(Orientation^Speed); else GraphicFX[i]->StopAllParticles(); GraphicFX[i]->IsSuppressed = true; GraphicFX[i]->DestroyIfNoParticles = true; } } delete [] GraphicFX; GraphicFX = 0; } if (GraphicFXLocation != 0){delete [] GraphicFXLocation; GraphicFXLocation = 0;} DetachProjectile(this); } //----------------------------------------------------------------------------- // Установка положения //----------------------------------------------------------------------------- void CProjectile::SetRotation(VECTOR3D NewRotation) { // вызываем родительскую функцию ::CObject3D::SetRotation(NewRotation); if (GraphicFX != 0) for (int i=0; iRotateSystemAndParticlesByAngle(Rotation); else GraphicFX[i]->RotateSystemByAngle(Rotation); } } } //----------------------------------------------------------------------------- // Установка положения //----------------------------------------------------------------------------- void CProjectile::SetLocation(VECTOR3D NewLocation) { // вызываем родительскую функцию ::CObject3D::SetLocation(NewLocation); if (GraphicFX != 0) for (int i=0; iMoveSystemLocation(GraphicFXLocation[0] + Location); break; // Ion case 5: if (GraphicFX[0] != 0) GraphicFX[0]->MoveSystem(GraphicFXLocation[0] + Location); break; case 6: if (GraphicFX[0] != 0) GraphicFX[0]->MoveSystem(GraphicFXLocation[0] + Location); if (GraphicFX[1] != 0) GraphicFX[1]->MoveSystem(GraphicFXLocation[1] + Location); break; case 7: if (GraphicFX[0] != 0) GraphicFX[0]->MoveSystemLocation(GraphicFXLocation[0] + Location); if (GraphicFX[1] != 0) GraphicFX[1]->MoveSystem(GraphicFXLocation[1] + Location); break; // Plasma case 8: if (GraphicFX[0] != 0) GraphicFX[0]->MoveSystem(GraphicFXLocation[0] + Location); break; case 9: if (GraphicFX[0] != 0) GraphicFX[0]->MoveSystem(GraphicFXLocation[0] + Location); if (GraphicFX[1] != 0) GraphicFX[1]->MoveSystem(GraphicFXLocation[1] + Location); if (GraphicFX[2] != 0) GraphicFX[2]->MoveSystem(GraphicFXLocation[2] + Location); break; case 10: if (GraphicFX[0] != 0) GraphicFX[0]->MoveSystem(GraphicFXLocation[0] + Location); if (GraphicFX[1] != 0) GraphicFX[1]->MoveSystem(GraphicFXLocation[1] + Location); if (GraphicFX[2] != 0) GraphicFX[2]->MoveSystemLocation(GraphicFXLocation[2] + Location); break; // Maser case 11: if (GraphicFX[0] != 0) { GraphicFX[0]->MoveSystem(GraphicFXLocation[0] + Location); GraphicFX[0]->SetStartLocation(GraphicFXLocation[0] + Location); } break; case 12: if (GraphicFX[0] != 0) { GraphicFX[0]->MoveSystem(GraphicFXLocation[0] + Location); GraphicFX[0]->SetStartLocation(GraphicFXLocation[0] + Location); } if (GraphicFX[1] != 0) { GraphicFX[1]->MoveSystem(GraphicFXLocation[1] + Location); GraphicFX[1]->SetStartLocation(GraphicFXLocation[1] + Location); } break; // Antimatter case 13: if (GraphicFX[0] != 0) GraphicFX[0]->MoveSystem(GraphicFXLocation[0] + Location); break; // Laser case 14: if (GraphicFX[0] != 0) { GraphicFX[0]->MoveSystem(GraphicFXLocation[0] + Location); GraphicFX[0]->SetStartLocation(GraphicFXLocation[0] + Location); } break; // Gauss case 15: if (GraphicFX[0] != 0) GraphicFX[0]->MoveSystem(GraphicFXLocation[0] + Location); break; // Missiles case 16: case 17: case 18: case 19: if (GraphicFX[0] != 0) GraphicFX[0]->MoveSystemLocation(GraphicFXLocation[0] + Location); break; // снаряды пришельцев // как Kinetic1 case 101: if (GraphicFX[0] != 0) GraphicFX[0]->MoveSystemLocation(GraphicFXLocation[0] + Location); break; // с наведением, как Kinetic2 case 102: if (GraphicFX[0] != 0) GraphicFX[0]->MoveSystemLocation(GraphicFXLocation[0] + Location); break; case 103: // как Kinetic3 if (GraphicFX[0] != 0) GraphicFX[0]->MoveSystemLocation(GraphicFXLocation[0] + Location); break; // с наведением, как Kinetic3 case 104: if (GraphicFX[0] != 0) GraphicFX[0]->MoveSystemLocation(GraphicFXLocation[0] + Location); break; // как Kinetic2 case 105: if (GraphicFX[0] != 0) GraphicFX[0]->MoveSystemLocation(GraphicFXLocation[0] + Location); break; // энергетическая мина (1-й тип) case 106: if (GraphicFX[0] != 0) GraphicFX[0]->MoveSystemLocation(GraphicFXLocation[0] + Location); break; break; // энергетическая мина (2-й тип) case 107: if (GraphicFX[0] != 0) GraphicFX[0]->MoveSystemLocation(GraphicFXLocation[0] + Location); break; // как Plasma3 case 108: if (GraphicFX[0] != 0) GraphicFX[0]->MoveSystem(GraphicFXLocation[0] + Location); if (GraphicFX[1] != 0) GraphicFX[1]->MoveSystem(GraphicFXLocation[1] + Location); if (GraphicFX[2] != 0) GraphicFX[2]->MoveSystemLocation(GraphicFXLocation[2] + Location); break; // как Plasma2 case 109: if (GraphicFX[0] != 0) GraphicFX[0]->MoveSystem(GraphicFXLocation[0] + Location); if (GraphicFX[1] != 0) GraphicFX[1]->MoveSystem(GraphicFXLocation[1] + Location); if (GraphicFX[2] != 0) GraphicFX[2]->MoveSystem(GraphicFXLocation[2] + Location); break; // как Laser case 110: if (GraphicFX[0] != 0) { GraphicFX[0]->MoveSystem(GraphicFXLocation[0] + Location); GraphicFX[0]->SetStartLocation(GraphicFXLocation[0] + Location); } break; // снаряды пиратов // стрельба турели 1 case 201: if (GraphicFX[0] != 0) GraphicFX[0]->MoveSystemLocation(GraphicFXLocation[0] + Location); break; // стрельба турели 2 case 202: if (GraphicFX[0] != 0) GraphicFX[0]->MoveSystemLocation(GraphicFXLocation[0] + Location); break; // фларес case 203: if (GraphicFX[0] != 0) GraphicFX[0]->MoveSystemLocation(GraphicFXLocation[0] + Location); break; // как Kinetic1 case 204: if (GraphicFX[0] != 0) GraphicFX[0]->MoveSystemLocation(GraphicFXLocation[0] + Location); break; // как Missile1 case 205: // как Missile2 case 206: if (GraphicFX[0] != 0) GraphicFX[0]->MoveSystemLocation(GraphicFXLocation[0] + Location); break; // как Ion2 case 207: if (GraphicFX[0] != 0) GraphicFX[0]->MoveSystem(GraphicFXLocation[0] + Location); if (GraphicFX[1] != 0) GraphicFX[1]->MoveSystem(GraphicFXLocation[1] + Location); break; // Antimatter case 208: if (GraphicFX[0] != 0) GraphicFX[0]->MoveSystem(GraphicFXLocation[0] + Location); break; // как Missile3 case 209: // как Missile4 case 210: if (GraphicFX[0] != 0) GraphicFX[0]->MoveSystemLocation(GraphicFXLocation[0] + Location); break; // как Kinetic2 case 211: // как Kinetic3 case 212: if (GraphicFX[0] != 0) GraphicFX[0]->MoveSystemLocation(GraphicFXLocation[0] + Location); break; // как Plasma2 case 213: if (GraphicFX[0] != 0) GraphicFX[0]->MoveSystem(GraphicFXLocation[0] + Location); if (GraphicFX[1] != 0) GraphicFX[1]->MoveSystem(GraphicFXLocation[1] + Location); if (GraphicFX[2] != 0) GraphicFX[2]->MoveSystem(GraphicFXLocation[2] + Location); break; // снаряды без оружия // мины case 214: break; case 215: if (GraphicFX[0] != 0) { GraphicFX[0]->MoveSystem(GraphicFXLocation[0] + Location); GraphicFX[0]->SetStartLocation(GraphicFXLocation[0] + Location); } break; case 216: if (GraphicFX[0] != 0) { GraphicFX[0]->MoveSystem(GraphicFXLocation[0] + Location); GraphicFX[0]->SetStartLocation(GraphicFXLocation[0] + Location); } break; case 217: if (GraphicFX[0] != 0) { GraphicFX[0]->MoveSystem(GraphicFXLocation[0] + Location); GraphicFX[0]->SetStartLocation(GraphicFXLocation[0] + Location); } break; } } } //----------------------------------------------------------------------------- // выполнение действий //----------------------------------------------------------------------------- bool CProjectile::Update(float Time) { // вызываем родительскую функцию // если там передали удалить - выходим if (!::CObject3D::Update(Time)) { // если лучевое оружие, никогда не уничтожаем его!!! // это сделаем в пушке... if (ProjectileType == 2) return true; // передаем на самоуничтожение... там все сделаем правильно CBulletExplosion *TMPBulletExplosion; TMPBulletExplosion = new CBulletExplosion; TMPBulletExplosion->Create(0, this, -Num, Location, Speed); return false; } // быстро вызвали еще раз... время не изменилось, или почти не изменилось if (TimeDelta == 0.0f) return true; Speed = SpeedStart*(Lifetime/Age) + SpeedEnd*((Age-Lifetime)/Age); //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Общее перемещение снаряда... //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ VECTOR3D Velocity = Orientation^(Speed*TimeDelta); SetLocation(Location+Velocity); //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // общий - пенальти, если не игрок //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ float CurrentPenalty = GameNPCWeaponPenalty*1.0f; // если игрок или свои - ничего не надо... if (ObjectStatus >= 2) CurrentPenalty = 1.0f; float RotationSpeed; //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Если что-то надо делать со снарядом (наводить к примеру) //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ switch (Num) { // Plasma case 9: case 109: GraphicFX[1]->RotateSystemAndParticlesByAngle(VECTOR3D(GraphicFX[1]->Angle.x-360.0f*TimeDelta,GraphicFX[1]->Angle.y,GraphicFX[1]->Angle.z)); GraphicFX[2]->RotateSystemAndParticlesByAngle(VECTOR3D(GraphicFX[2]->Angle.x-360.0f*TimeDelta,GraphicFX[2]->Angle.y,GraphicFX[2]->Angle.z)); break; case 10: case 108: case 213: GraphicFX[0]->RotateSystemAndParticlesByAngle(VECTOR3D(GraphicFX[0]->Angle.x-360.0f*TimeDelta,GraphicFX[0]->Angle.y,GraphicFX[0]->Angle.z)); GraphicFX[1]->RotateSystemAndParticlesByAngle(VECTOR3D(GraphicFX[1]->Angle.x-360.0f*TimeDelta,GraphicFX[1]->Angle.y,GraphicFX[1]->Angle.z)); break; // Maser case 11: GraphicFX[0]->RotateParticlesByAngle(VECTOR3D(0.0f, 0.0f, 360.0f*TimeDelta*3.0f)); if (Lifetime <= GraphicFX[0]->Life/1.5f) GraphicFX[0]->IsSuppressed = true; break; case 12: GraphicFX[0]->RotateParticlesByAngle(VECTOR3D(0.0f,0.0f,360.0f*TimeDelta*4.0f)); if (Lifetime <= GraphicFX[0]->Life/1.5f) GraphicFX[0]->IsSuppressed = true; GraphicFX[1]->RotateParticlesByAngle(VECTOR3D(0.0f,0.0f,-360.0f*TimeDelta*2.0f)); if (Lifetime <= GraphicFX[1]->Life/1.5f) GraphicFX[1]->IsSuppressed = true; break; // Antimatter case 13: case 208: GraphicFX[0]->RotateSystemAndParticlesByAngle(VECTOR3D(GraphicFX[0]->Angle.x,GraphicFX[0]->Angle.y-360.0f*TimeDelta*2.0f,GraphicFX[0]->Angle.z)); break; // Laser case 14: case 110: if (Lifetime <= GraphicFX[0]->Life/1.5f) GraphicFX[0]->IsSuppressed = true; break; // Gauss case 15: GraphicFX[0]->RotateParticlesByAngle(VECTOR3D(0.0f,0.0f,360.0f*TimeDelta*6.0f)); break; // ракеты // ракеты землян case 16: RotationSpeed = 50.0f; goto missile; case 17: RotationSpeed = 60.0f; goto missile; case 18: RotationSpeed = 30.0f; goto missile; case 19: RotationSpeed = 10.0f; goto missile; // ракеты пришельцев case 102: RotationSpeed = 20.0f; goto missile; case 104: RotationSpeed = 40.0f; goto missile; // ракеты пиратов case 205: RotationSpeed = 35.0f; goto missile; case 206: RotationSpeed = 40.0f; goto missile; case 209: RotationSpeed = 30.0f; goto missile; case 210: RotationSpeed = 10.0f; { missile: VECTOR3D NeedAngle = Rotation; // устанавливаем в Target на что наведен этот снаряд Target = GetMissileOnTargetOrientateion(ObjectStatus, Location, Rotation, CurrentRotationMat, &NeedAngle); // учитываем скорость поворота по вертикали if (Rotation.y < NeedAngle.y) { float NeedAngle_y = Rotation.y+RotationSpeed*TimeDelta; if (NeedAngle_y > NeedAngle.y) NeedAngle_y = NeedAngle.y; NeedAngle.y = NeedAngle_y; } if (Rotation.y > NeedAngle.y) { float NeedAngle_y = Rotation.y-RotationSpeed*TimeDelta; if (NeedAngle_y < NeedAngle.y) NeedAngle_y = NeedAngle.y; NeedAngle.y = NeedAngle_y; } if (Rotation.x < NeedAngle.x) { float NeedAngle_x = Rotation.x+RotationSpeed*TimeDelta; if (NeedAngle_x > NeedAngle.x) NeedAngle_x = NeedAngle.x; NeedAngle.x = NeedAngle_x; } if (Rotation.x > NeedAngle.x) { float NeedAngle_x = Rotation.x-RotationSpeed*TimeDelta; if (NeedAngle_x < NeedAngle.x) NeedAngle_x = NeedAngle.x; NeedAngle.x = NeedAngle_x; } VECTOR3D TTT = NeedAngle-Rotation; SetRotation(TTT); } break; // мины // мина пиратов (1-й тип) case 214: MineIData += TimeDelta; if (MineIData >= 0.1f) { if (TextureIllum[0] == 0) TextureIllum[0] = vw_FindTextureByName("DATA/MODELS/MINE/mine1i.jpg"); else TextureIllum[0] = 0; MineIData = 0.0f; } DrawObjectList[0].Rotation.y += 90.0f*TimeDelta; while (DrawObjectList[0].Rotation.y > 360.0f) DrawObjectList[0].Rotation.y -= 360.0f; // мина пришельцев, энергетическая (1-й тип) case 106: { float MineSpeed = 5.0f; // получаем положение ближайшего врага CObject3D *tmpTarget = GetCloserTargetPosition(ObjectStatus, Location); // !!! упращенно, не учитываем положение плоскости if (tmpTarget != 0) { float SpeedTmp = MineSpeed*TimeDelta; if (SpeedTmp > fabs(Location.y-tmpTarget->Location.y)) SpeedTmp = fabs(Location.y-tmpTarget->Location.y); if (SpeedTmp != 0.0f) { // находим направление (если нужно вниз, меняем знак) if (Location.y > tmpTarget->Location.y) SpeedTmp *= -1.0f; VECTOR3D VelocityUp = VECTOR3D(0.0f,SpeedTmp,0.0f); SetLocation(Location+VelocityUp); } } else { // если некуда целиться, ставим правильные данные для гфх if (GraphicFXQuantity >= 1) if (GraphicFX[0] != 0) GraphicFX[0]->SetStartLocation(GraphicFXLocation[0] + Location); } } break; // мина пиратов (2-й тип) case 215: MineIData += TimeDelta; if (MineIData >= 0.1f) { if (TextureIllum[0] == 0) TextureIllum[0] = vw_FindTextureByName("DATA/MODELS/MINE/mine2i.jpg"); else TextureIllum[0] = 0; MineIData = 0.0f; } DrawObjectList[0].Rotation.y += 90.0f*TimeDelta; while (DrawObjectList[0].Rotation.y > 360.0f) DrawObjectList[0].Rotation.y -= 360.0f; // мина пришельцев, энергетическая (2-й тип) case 107: RotationSpeed = 180.0f; { VECTOR3D NeedAngle = Rotation; // устанавливаем в Target на что наведен этот снаряд Target = GetMissileOnTargetOrientateion(ObjectStatus, Location, Rotation, CurrentRotationMat, &NeedAngle); // учитываем скорость поворота по вертикали if (Rotation.y < NeedAngle.y) { float NeedAngle_y = Rotation.y+RotationSpeed*TimeDelta; if (NeedAngle_y > NeedAngle.y) NeedAngle_y = NeedAngle.y; NeedAngle.y = NeedAngle_y; } if (Rotation.y > NeedAngle.y) { float NeedAngle_y = Rotation.y-RotationSpeed*TimeDelta; if (NeedAngle_y < NeedAngle.y) NeedAngle_y = NeedAngle.y; NeedAngle.y = NeedAngle_y; } NeedAngle.z = Rotation.z; NeedAngle.x = Rotation.x; VECTOR3D TTT = NeedAngle-Rotation; SetRotation(TTT); // если есть цель, поднимаемся на ее уровень if (Target != 0) { float MineSpeed = 5.0f; // получаем положение ближайшего врага VECTOR3D NeedPoint = Target->Location; // !!! упращенно, не учитываем положение плоскости float SpeedTmp = MineSpeed*TimeDelta; if (SpeedTmp > fabs(Location.y-NeedPoint.y)) SpeedTmp = fabs(Location.y-NeedPoint.y); if (SpeedTmp != 0.0f) { // находим направление (если нужно вниз, меняем знак) if (Location.y > NeedPoint.y) SpeedTmp *= -1.0f; VECTOR3D VelocityUp = VECTOR3D(0.0f,SpeedTmp,0.0f); SetLocation(Location+VelocityUp); } } else { // если некуда целиться, ставим правильные данные для гфх if (GraphicFXQuantity >= 1) if (GraphicFX[0] != 0) GraphicFX[0]->SetStartLocation(GraphicFXLocation[0] + Location); } // сбрасываем установку, чтобы не было голосового предупреждения Target = 0; } break; case 216: MineIData += TimeDelta; if (MineIData >= 0.1f) { if (TextureIllum[0] == 0) TextureIllum[0] = vw_FindTextureByName("DATA/MODELS/MINE/mine3i.jpg"); else TextureIllum[0] = 0; MineIData = 0.0f; } DrawObjectList[0].Rotation.y += 120.0f*TimeDelta; while (DrawObjectList[0].Rotation.y > 360.0f) DrawObjectList[0].Rotation.y -= 360.0f; RotationSpeed = 180.0f; { VECTOR3D NeedAngle = Rotation; // устанавливаем в Target на что наведен этот снаряд Target = GetMissileOnTargetOrientateion(ObjectStatus, Location, Rotation, CurrentRotationMat, &NeedAngle); // учитываем скорость поворота по вертикали if (Rotation.y < NeedAngle.y) { float NeedAngle_y = Rotation.y+RotationSpeed*TimeDelta; if (NeedAngle_y > NeedAngle.y) NeedAngle_y = NeedAngle.y; NeedAngle.y = NeedAngle_y; } if (Rotation.y > NeedAngle.y) { float NeedAngle_y = Rotation.y-RotationSpeed*TimeDelta; if (NeedAngle_y < NeedAngle.y) NeedAngle_y = NeedAngle.y; NeedAngle.y = NeedAngle_y; } NeedAngle.z = Rotation.z; NeedAngle.x = Rotation.x; VECTOR3D TTT = NeedAngle-Rotation; SetRotation(TTT); // если есть цель, поднимаемся на ее уровень if (Target != 0) { float MineSpeed = 5.0f; // получаем положение ближайшего врага VECTOR3D NeedPoint = Target->Location; // !!! упращенно, не учитываем положение плоскости float SpeedTmp = MineSpeed*TimeDelta; if (SpeedTmp > fabs(Location.y-2.0f-NeedPoint.y)) SpeedTmp = fabs(Location.y-2.0f-NeedPoint.y); if (SpeedTmp != 0.0f) { // находим направление (если нужно вниз, меняем знак) if (Location.y-2.0f > NeedPoint.y) SpeedTmp *= -1.0f; VECTOR3D VelocityUp = VECTOR3D(0.0f,SpeedTmp,0.0f); SetLocation(Location+VelocityUp); } // стрельба MineNextFireTime -= TimeDelta; if (MineNextFireTime <= 0.0f) { // создаем снаряд CProjectile *Projectile = 0; Projectile = new CProjectile; Projectile->Create(204); Projectile->SetLocation(Location+VECTOR3D(0.0f, -2.0f, 0.0f)); // общий - пенальти, если не игрок float CurrentPenalty = GameNPCWeaponPenalty*1.0f; // если игрок или свои - ничего не надо... if (ObjectStatus >= 2) CurrentPenalty = 1.0f; Projectile->SetRotation(Rotation); for (int i=0; iGraphicFXQuantity; i++) { Projectile->GraphicFX[i]->Direction = Orientation; // учитываем пенальти для визуальных эффектов Projectile->GraphicFX[i]->ParticlesPerSec = (int)(Projectile->GraphicFX[i]->ParticlesPerSec/CurrentPenalty); Projectile->GraphicFX[i]->Speed = Projectile->GraphicFX[i]->Speed/CurrentPenalty; Projectile->GraphicFX[i]->Life = Projectile->GraphicFX[i]->Life*CurrentPenalty; Projectile->GraphicFX[i]->AttractiveValue = Projectile->GraphicFX[i]->AttractiveValue/(CurrentPenalty*CurrentPenalty); } Projectile->ObjectStatus = ObjectStatus; // учитываем пенальти для снаряда Projectile->SpeedStart = Projectile->SpeedEnd = Projectile->SpeedStart/CurrentPenalty; Projectile->Age = Projectile->Lifetime = Projectile->Age*CurrentPenalty; Projectile->DamageHull = Projectile->DamageHull/CurrentPenalty; Projectile->DamageSystems = Projectile->DamageSystems/CurrentPenalty; MineNextFireTime = MineReloadTime; } } // сбрасываем установку, чтобы не было голосового предупреждения Target = 0; } break; case 217: MineIData += TimeDelta; if (MineIData >= 0.1f) { if (TextureIllum[0] == 0) TextureIllum[0] = vw_FindTextureByName("DATA/MODELS/MINE/mine4i.jpg"); else TextureIllum[0] = 0; MineIData = 0.0f; } DrawObjectList[0].Rotation.y += 90.0f*TimeDelta; while (DrawObjectList[0].Rotation.y > 360.0f) DrawObjectList[0].Rotation.y -= 360.0f; RotationSpeed = 180.0f; { VECTOR3D NeedAngle = Rotation; // устанавливаем в Target на что наведен этот снаряд Target = GetMissileOnTargetOrientateion(ObjectStatus, Location, Rotation, CurrentRotationMat, &NeedAngle); // учитываем скорость поворота по вертикали if (Rotation.y < NeedAngle.y) { float NeedAngle_y = Rotation.y+RotationSpeed*TimeDelta; if (NeedAngle_y > NeedAngle.y) NeedAngle_y = NeedAngle.y; NeedAngle.y = NeedAngle_y; } if (Rotation.y > NeedAngle.y) { float NeedAngle_y = Rotation.y-RotationSpeed*TimeDelta; if (NeedAngle_y < NeedAngle.y) NeedAngle_y = NeedAngle.y; NeedAngle.y = NeedAngle_y; } NeedAngle.z = Rotation.z; NeedAngle.x = Rotation.x; VECTOR3D TTT = NeedAngle-Rotation; SetRotation(TTT); // если есть цель, поднимаемся на ее уровень if (Target != 0) { float MineSpeed = 5.0f; // получаем положение ближайшего врага VECTOR3D NeedPoint = Target->Location; // !!! упращенно, не учитываем положение плоскости float SpeedTmp = MineSpeed*TimeDelta; if (SpeedTmp > fabs(Location.y+2.0f-NeedPoint.y)) SpeedTmp = fabs(Location.y+2.0f-NeedPoint.y); if (SpeedTmp != 0.0f) { // находим направление (если нужно вниз, меняем знак) if (Location.y+2.0f > NeedPoint.y) SpeedTmp *= -1.0f; VECTOR3D VelocityUp = VECTOR3D(0.0f,SpeedTmp,0.0f); SetLocation(Location+VelocityUp); } // стрельба MineNextFireTime -= TimeDelta; if (MineNextFireTime <= 0.0f) { // создаем снаряд CProjectile *Projectile = 0; Projectile = new CProjectile; Projectile->Create(206); Projectile->SetLocation(Location+VECTOR3D(0.0f, 0.0f, 0.0f)); // общий - пенальти, если не игрок float CurrentPenalty = GameNPCWeaponPenalty*1.0f; // если игрок или свои - ничего не надо... if (ObjectStatus >= 2) CurrentPenalty = 1.0f; Projectile->SetRotation(Rotation); for (int i=0; iGraphicFXQuantity; i++) { Projectile->GraphicFX[i]->Direction = Orientation; // учитываем пенальти для визуальных эффектов Projectile->GraphicFX[i]->ParticlesPerSec = (int)(Projectile->GraphicFX[i]->ParticlesPerSec/CurrentPenalty); Projectile->GraphicFX[i]->Speed = Projectile->GraphicFX[i]->Speed/CurrentPenalty; Projectile->GraphicFX[i]->Life = Projectile->GraphicFX[i]->Life*CurrentPenalty; Projectile->GraphicFX[i]->AttractiveValue = Projectile->GraphicFX[i]->AttractiveValue/(CurrentPenalty*CurrentPenalty); } Projectile->ObjectStatus = ObjectStatus; // учитываем пенальти для снаряда Projectile->SpeedStart = Projectile->SpeedEnd = Projectile->SpeedStart/CurrentPenalty; Projectile->Age = Projectile->Lifetime = Projectile->Age*CurrentPenalty; Projectile->DamageHull = Projectile->DamageHull/CurrentPenalty; Projectile->DamageSystems = Projectile->DamageSystems/CurrentPenalty; MineNextFireTime = MineReloadTime; } } // сбрасываем установку, чтобы не было голосового предупреждения Target = 0; } break; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // понемногу сводим снаряд на нет... так красивее //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ /* for (int i=0; iTheta = 1.0f + 20.0f*((Age-Lifetime)/Age); if (Lifetime <= GraphicFX[i]->Life-0.1f) GraphicFX[i]->IsSuppressed = true; } */ // объект в порядке - удалять не нужно return true; }