/// <summary> /// Constructor /// </summary> /// <param name="_model">Projectile model</param> /// <param name="_position">Position of the missile</param> /// <param name="_angle">Angle at which the missile will be fired</param> /// <param name="_velocity">Velocity of the missile</param> /// <param name="_alive">Alive</param> /// <param name="_firedBy">Who fired the missile</param> public Projectile(Vector3 _position, VTankObject.Point target, double _angle, double _velocity, float _alive, PlayerTank _firedBy, ProjectileData projectileData) { this.data = projectileData; this.position = _position; position = _position + Vector3.UnitZ; ; base.ZRotation = (float)_angle; velocity = (float)_velocity; timeAlive = _alive; elapsed = 0; this.boundingSphere.Radius = projectileData.CollisionRadius; SetBoundingSpherePosition(); owner = _firedBy; RenderID = -1; ID = projectileData.ID; origin = position; if (_firedBy.Weapon.HasFiringArc) { this.usingLaunchAngle = true; float swivelAngle = ZRotation; float tiltAngle = _firedBy.Weapon.LaunchAngle; float projection = DEFAULT_CANNON_LENGTH * (float)Math.Cos(tiltAngle); float tipX = -projection * (float)Math.Cos(swivelAngle); float tipY = -projection * (float)Math.Sin(swivelAngle); float tipZ = Math.Abs(DEFAULT_CANNON_LENGTH * (float)Math.Sin(swivelAngle)); tip = new float[] { tipX, tipY, tipZ }; Vector3 newPosition = position + new Vector3(tipX, tipY, tipZ); // Calculate initial velocity based on the distance we travel. float distance = (float)Math.Sqrt( Math.Pow(target.x - newPosition.X, 2) + Math.Pow(target.y - newPosition.Y, 2)); float maxDistance = (int)projectileData.Range; if (distance > maxDistance) distance = maxDistance; // TODO: This is a temporary work-around until we figure out what velocity component // is missing from the formula. float offset = 1.1f; if (tiltAngle > MathHelper.ToRadians(45.0f)) offset = 1.6f; float V = (float)Math.Sqrt(-gravity * distance * offset); float Vx = -V * (float)(Math.Cos(tiltAngle) * Math.Cos(swivelAngle)); float Vy = -V * (float)(Math.Cos(tiltAngle) * Math.Sin(swivelAngle)); float Vz = V * (float)Math.Sin(tiltAngle); componentVelocity = new float[] { Vx, Vy, Vz }; elapsedDelta = 0f; /*this.verticalVelocity = this.FindVerticalVelocity(_firedBy.Weapon.LaunchAngle, velocity); float flightTime = this.FindFlightTime(verticalVelocity, gravity); float horizontalVelocity = this.FindHorizontalVelocity( distance, flightTime); velocity = horizontalVelocity;*/ } Object3 turret = owner.Turret; ModelBoneCollection.Enumerator collection = turret.Model.Bones.GetEnumerator(); List<ModelBone> emitters = new List<ModelBone>(); while (collection.MoveNext()) { if (collection.Current.Name.StartsWith("Emitter")) { emitters.Add(collection.Current); } } if (emitters.Count == 0) { ServiceManager.Game.Console.DebugPrint( "Warning: Can't attach to owner tank, no emitter exists."); } else { int emitter = _firedBy.Weapon.GetNextEmitterIndex(); this.Attach(turret, emitters[emitter].Name); this.MimicRotation(turret); this.Unattach(); Vector3 forward = emitters[emitter].Transform.Forward; forward.Z = Math.Abs(forward.Z); //position *= forward; } if (!String.IsNullOrEmpty(projectileData.Model)) { model = new Object3(ServiceManager.Resources.GetModel("projectiles\\" + projectileData.Model), position); model.MimicPosition(this, Vector3.Zero); model.MimicRotation(this); modelRenderID = ServiceManager.Scene.Add(model, 3); } else { model = null; } if (!String.IsNullOrEmpty(projectileData.ParticleEffect) && projectileData.Model == null) { ParticleEmitter.MimicPosition(this, Vector3.Zero); ParticleEmitter.MimicRotation(this); particleEmitterRenderID = ServiceManager.Scene.Add(ParticleEmitter, 3); } else if (!String.IsNullOrEmpty(projectileData.ParticleEffect)) { ParticleEmitter = new ParticleEmitter(projectileData.ParticleEffect, this.Position); this.particleEmitterRenderID = ServiceManager.Scene.Add(ParticleEmitter, 3); ParticleEmitter.Follow(this); } }