private bool FireWeapon( TargetTuple target, Vector3 displacement, float distance, bool isServer) { Ammo ammo = PickBestAmmo(target, displacement, distance); if (ammo == null) { return(false); } ammo.ShellCountRemaining--; // sound _audioSource.PlayOneShot(ammo.ShotSound, _shotVolume); if (ammo.MuzzleFlashEffect != null) { ammo.MuzzleFlashEffect.transform.LookAt(target.Position); ammo.MuzzleFlashEffect.Play(); } GameObject shell = GameObject.Instantiate( _shellPrefab, _barrelTip.position, _barrelTip.transform.rotation); GameObject.Instantiate(ammo.ShellArtPrefab, shell.transform); float roll = _random.NextFloat(0.0, 100.0); bool isHit = roll <= ammo.Accuracy; Vector3 shellDestination = target.Position; if (!isHit) { int deviationMode = (int)roll % 4; float missFactor = _random.NextFloat( Constants.MISS_FACTOR_MIN, Constants.MISS_FACTOR_MAX); float weightX = _random.NextFloat(0, 1); switch (deviationMode) { case 0: shellDestination.x += distance * missFactor * weightX; shellDestination.y += distance * missFactor * (1 - weightX); break; case 1: shellDestination.x -= distance * missFactor * weightX; shellDestination.y += distance * missFactor * (1 - weightX); break; case 2: shellDestination.x += distance * missFactor * weightX; shellDestination.y -= distance * missFactor * (1 - weightX); break; case 3: shellDestination.x -= distance * missFactor * weightX; shellDestination.y -= distance * missFactor * (1 - weightX); break; } } ShellBehaviour shellBehaviour = shell.GetComponent <ShellBehaviour>(); shellBehaviour.Initialize(shellDestination, ammo); if (isServer) { if (target.IsUnit) { if (isHit && !ammo.IsAoe) { target.Enemy.HandleHit( ammo.DamageType, ammo.DamageValue, displacement, distance); } } else { // HE damage is applied by the shellBehavior when it explodes } } return(true); }
public void HandleUpdate() { _weapon?.HandleUpdate(); if (_target == null || !_target.Exists) { TurnTurretBackToDefaultPosition(); return; } bool aimed = false; float targetHorizontalAngle = 0f; float targetVerticalAngle = 0f; if (_target.Position != Vector3.zero) { aimed = true; Vector3 directionToTarget = _target.Position - _turret.position; directionToTarget = new Vector3(directionToTarget.x, 0, directionToTarget.z); Quaternion rotationToTarget = Quaternion.LookRotation( _turret.parent.transform.InverseTransformDirection(directionToTarget)); // Add any necessary cannon elevation to the rotation rotationToTarget *= ShellBehaviour.CalculateBarrelAngle( _shellVelocity, _turret.transform.position, _target.Position, out _); targetHorizontalAngle = rotationToTarget.eulerAngles.y.unwrapDegree(); // If this turret has no flexibility (ArcHorizontal = 0) and is fully // rotated by a parent turret, it can get stuck 0.0000000001 degrees // away from the target due to float rounding errors (parent rounds // one way and decides he's done, child rounds the other way). // So round away the last degree to avoid this case: targetHorizontalAngle = Util.RoundTowardZero(targetHorizontalAngle); if (Mathf.Abs(targetHorizontalAngle) > _arcHorizontal) { targetHorizontalAngle = 0f; aimed = false; } targetVerticalAngle = rotationToTarget.eulerAngles.x.unwrapDegree(); targetVerticalAngle = (float)Math.Floor(targetVerticalAngle); if (targetVerticalAngle < -_arcUp || targetVerticalAngle > _arcDown) { targetVerticalAngle = 0f; aimed = false; } } float turn = Time.deltaTime * _rotationRate; float horizontalAngle = _turret.localEulerAngles.y; float verticalAngle = _turret.localEulerAngles.x; float deltaAngle; deltaAngle = (targetHorizontalAngle - horizontalAngle).unwrapDegree(); if (Mathf.Abs(deltaAngle) > turn) { horizontalAngle += (deltaAngle > 0 ? 1 : -1) * turn; aimed = false; } else { horizontalAngle = targetHorizontalAngle; } deltaAngle = (targetVerticalAngle - verticalAngle).unwrapDegree(); if (Mathf.Abs(deltaAngle) > turn) { verticalAngle += (deltaAngle > 0 ? 1 : -1) * turn; aimed = false; } else { verticalAngle = targetVerticalAngle; } _turret.localEulerAngles = new Vector3(verticalAngle, horizontalAngle, 0); IsFacingTarget = aimed; foreach (Turret turret in Children) { turret.HandleUpdate(); } }