示例#1
0
 public override void Launch(IElementAttackable target, AWeapon weapon, Topography topography) {
     base.Launch(target, weapon, topography);
     AdjustHeadingForInaccuracy();
     InitializeVelocity();
     enabled = true;
     _collider.enabled = true;
 }
示例#2
0
    /// <summary>
    /// Confirms the provided enemyTarget is in range prior to launching the weapon's ordnance.
    /// </summary>
    /// <param name="enemyTarget">The target.</param>
    /// <returns></returns>
    public override bool ConfirmInRangeForLaunch(IElementAttackable enemyTarget) {
        float distanceToPushover = TempGameValues.__ReqdMissileTravelDistanceBeforePushover;
        Vector3 launchDirection = MuzzleFacing;
        Vector3 vectorToPushover = launchDirection * distanceToPushover;
        Vector3 launchPosition = MuzzleLocation;
        Vector3 pushoverPosition = launchPosition + vectorToPushover;

        Vector3 vectorToTargetFromPushover = enemyTarget.Position - pushoverPosition;
        float targetDistanceFromPushover = vectorToTargetFromPushover.magnitude;
        return distanceToPushover + targetDistanceFromPushover < Weapon.RangeDistance;
    }
示例#3
0
    /// <summary>
    /// Tries to develop a firing solution from this WeaponMount to the provided target. If successful, returns <c>true</c> and provides the
    /// firing solution, otherwise <c>false</c>.
    /// </summary>
    /// <param name="enemyTarget">The enemy target.</param>
    /// <param name="firingSolution"></param>
    /// <returns></returns>
    public override bool TryGetFiringSolution(IElementAttackable enemyTarget, out WeaponFiringSolution firingSolution) {
        D.Assert(enemyTarget.IsOperational);
        D.Assert(enemyTarget.IsAttackByAllowed(Weapon.Owner));

        if (!ConfirmInRangeForLaunch(enemyTarget)) {
            //D.Log("{0}.CheckFiringSolution({1}) has determined target is out of range.", DebugName, enemyTarget.DebugName);
            firingSolution = null;
            return false;
        }
        firingSolution = new WeaponFiringSolution(Weapon, enemyTarget);
        return true;
    }
示例#4
0
        /// <summary>
        /// Called by the weapon's ordnance when this weapon's firing process against <c>targetFiredOn</c> has begun.
        /// </summary>
        /// <param name="targetFiredOn">The target fired on.</param>
        /// <param name="ordnanceFired">The ordnance fired.</param>
        public virtual void HandleFiringInitiated(IElementAttackable targetFiredOn, IOrdnance ordnanceFired) {
            if (!IsOperational) {
                D.Error("{0} fired at {1} while not operational.", Name, targetFiredOn.DebugName);
            }

            if (!_qualifiedEnemyTargets.Contains(targetFiredOn)) {
                D.Error("{0} fired at {1} but not in list of targets.", Name, targetFiredOn.DebugName);
            }

            //D.Log(ShowDebugLog, "{0}.HandleFiringInitiated(Target: {1}, Ordnance: {2}) called.", DebugName, targetFiredOn.DebugName, ordnanceFired.Name);
            RecordFiredOrdnance(ordnanceFired);
            ordnanceFired.deathOneShot += OrdnanceDeathEventHandler;

            RecordShotFired(targetFiredOn);

            _isLoaded = false;
            AssessReadiness();
        }
示例#5
0
    public override void Launch(IElementAttackable target, AWeapon weapon, Topography topography) {
        base.Launch(target, weapon, topography);
        _positionLastRangeCheck = Position;
        _rigidbody.velocity = ElementVelocityAtLaunch;
        _courseUpdatePeriod = new GameTimeDuration(1F / CourseUpdateFrequency);
        SteeringInaccuracy = CalcSteeringInaccuracy();
        target.deathOneShot += TargetDeathEventHandler;
        _driftCorrector = new DriftCorrector(FullName, transform, _rigidbody);

        enabled = true;
    }
示例#6
0
    /// <summary>
    /// Applies accumulated damage to the _impactedTarget, if any.
    /// </summary>
    private void AssessApplyDamage() {
        //D.Log(ShowDebugLog, "{0}.AssessApplyDamage() called.", DebugName);
        if (_impactedTarget == null) {
            // no target that can take damage has been hit, so _cumImpactTime should be zero
            D.AssertEqual(Constants.ZeroF, _cumHoursOfImpactOnImpactedTarget);
            return;
        }
        if (!_impactedTarget.IsOperational) {
            // target is dead so don't apply more damage
            _cumHoursOfImpactOnImpactedTarget = Constants.ZeroF;
            _impactedTarget = null;
            return;
        }

        DamageStrength cumDamageToApply = DamagePotential * (_cumHoursOfImpactOnImpactedTarget / Weapon.Duration);
        //D.Log(ShowDebugLog, "{0} is applying hit of strength {1} to {2}.", DebugName, cumDamageToApply, _impactedTarget.DisplayName);
        _impactedTarget.TakeHit(cumDamageToApply);

        if (_impactedTarget == Target) {
            D.Log(ShowDebugLog, "{0} has hit its intended target {1}.", DebugName, _impactedTarget.DebugName);
            _isIntendedTargetHit = true;
        }
        else {
            _isInterdicted = true;
        }
        _cumHoursOfImpactOnImpactedTarget = Constants.ZeroF;
        _impactedTarget = null;
    }
示例#7
0
    private void HandleImpact(RaycastHit impactInfo, float deltaTimeInHours) {
        //D.Log(ShowDebugLog, "{0} impacted on {1}.", DebugName, impactInfo.collider.name);
        RefreshImpactLocation(impactInfo);

        var impactedGo = impactInfo.collider.gameObject;
        if (impactedGo.layer == (int)Layers.Shields) {
            var shield = impactedGo.GetComponent<Shield>();
            D.AssertNotNull(shield);
            AssessApplyDamage();    // hit a shield so apply cumDamage to previous valid target, if any
            HandleShieldImpact(shield, deltaTimeInHours);
            // for now, no impact force will be applied to the shield's parentElement
            return;
        }

        Profiler.BeginSample("Editor-only GC allocation (GetComponent returns null)", gameObject);
        var impactedTarget = impactedGo.GetComponent<IElementAttackable>();
        Profiler.EndSample();

        if (impactedTarget != null) {
            // hit an attackableTarget
            //D.Log(ShowDebugLog, "{0} has hit {1} {2}.", DebugName, typeof(IElementAttackable).Name, impactedTarget.DebugName);
            if (impactedTarget != _impactedTarget) {
                // hit a new target that can take damage, so apply cumDamage to previous impactedTarget, if any
                AssessApplyDamage();
            }
            _impactedTarget = impactedTarget;

            float percentOfBeamDuration = deltaTimeInHours / Weapon.Duration;    // the percentage of the beam's duration that deltaTime represents

            Profiler.BeginSample("Editor-only GC allocation (GetComponent returns null)", gameObject);
            var impactedTargetRigidbody = impactedGo.GetComponent<Rigidbody>();
            Profiler.EndSample();

            if (impactedTargetRigidbody != null && !impactedTargetRigidbody.isKinematic) {
                // target has a normal rigidbody so apply impact force
                float forceMagnitude = DamagePotential.Total * percentOfBeamDuration;
                Vector3 force = transform.forward * forceMagnitude;
                //D.Log(ShowDebugLog, "{0} applying impact force of {1} to {2}.", DebugName, force, impactedTarget.DisplayName);
                impactedTargetRigidbody.AddForceAtPosition(force, impactInfo.point, ForceMode.Impulse);
            }
            // accumulate total impact time on _impactedTarget
            _cumHoursOfImpactOnImpactedTarget += deltaTimeInHours;
        }
        else {
            // hit something else that can't take damage so apply cumDamage to previous valid target, if any
            AssessApplyDamage();
        }
    }
示例#8
0
 void ExecuteAttackOrder_ExitState() {
     LogEvent();
     //bool isUnsubscribed = __AttemptFsmTgtSubscriptionChg(FsmTgtEventSubscriptionMode.TargetDeath, _fsmPrimaryAttackTgt, toSubscribe: false);
     //D.Assert(isUnsubscribed);
     //isUnsubscribed = __AttemptFsmTgtSubscriptionChg(FsmTgtEventSubscriptionMode.InfoAccessChg, _fsmPrimaryAttackTgt, toSubscribe: false);
     //D.Assert(isUnsubscribed);
     _fsmPrimaryAttackTgt = null;
 }
示例#9
0
    /// <summary>
    /// Tries to develop a firing solution from this WeaponMount to the provided target. If successful, returns <c>true</c> and provides the
    /// firing solution, otherwise <c>false</c>.
    /// </summary>
    /// <param name="enemyTarget">The enemy target.</param>
    /// <param name="firingSolution"></param>
    /// <returns></returns>
    public override bool TryGetFiringSolution(IElementAttackable enemyTarget, out WeaponFiringSolution firingSolution) {
        D.Assert(enemyTarget.IsOperational);
        D.Assert(enemyTarget.IsAttackByAllowed(Weapon.Owner));

        firingSolution = null;
        if (!ConfirmInRangeForLaunch(enemyTarget)) {
            //D.Log(ShowDebugLog, "{0}: Target {1} is out of range.", DebugName, enemyTarget.DebugName);
            return false;
        }

        Vector3 targetPosition = enemyTarget.Position;
        Quaternion reqdHubRotation, reqdBarrelElevation;
        bool canTraverseToTarget = TryCalcTraverse(targetPosition, out reqdHubRotation, out reqdBarrelElevation);
        if (!canTraverseToTarget) {
            //D.Log(ShowDebugLog, "{0}: Target {1} is out of traverse range.", DebugName, enemyTarget.DebugName);
            return false;
        }

        bool isLosClear = CheckLineOfSight(enemyTarget);
        if (!isLosClear) {
            return false;
        }
        firingSolution = new LosWeaponFiringSolution(Weapon, enemyTarget, reqdHubRotation, reqdBarrelElevation);
        return true;
    }
示例#10
0
 private void ReportCombatResults(IElementAttackable target) {
     if (DebugSettings.Instance.EnableCombatResultLogging) {
         CombatResult combatResult;
         if (_combatResults.TryGetValue(target, out combatResult)) {    // if the weapon never fired, there won't be a combat result
             D.Log(combatResult.ToString());
             //_combatResults.Remove(target);    // for now let these accumulate so logging of hits and misses after the target
         }                                       // is out of the monitor's range doesn't encounter a Dictionary key not found error
     }
 }
示例#11
0
 /// <summary>
 /// Called by fired ordnance when it is fatally interdicted by a Countermeasure
 /// (ActiveCM or Shield) or some other obstacle that was not its target.
 /// </summary>
 /// <param name="target">The target.</param>
 public void HandleOrdnanceInterdicted(IElementAttackable target) {
     var combatResult = _combatResults[target];
     combatResult.Interdictions++;
 }
示例#12
0
 /// <summary>
 /// Called by fired ordnance when it misses its intended target without being fatally interdicted.
 /// </summary>
 /// <param name="target">The target.</param>
 public void HandleTargetMissed(IElementAttackable target) {
     var combatResult = _combatResults[target];
     combatResult.Misses++;
 }
示例#13
0
 /// <summary>
 /// Called by fired ordnance when it hits its intended target.
 /// </summary>
 /// <param name="target">The target.</param>
 public void HandleTargetHit(IElementAttackable target) {
     var combatResult = _combatResults[target];
     combatResult.Hits++;
 }
示例#14
0
 /// <summary>
 /// Records a shot was fired for purposes of tracking CombatResults.
 /// </summary>
 /// <param name="target">The target.</param>
 private void RecordShotFired(IElementAttackable target) {
     string targetName = target.DebugName;
     CombatResult combatResult;
     if (!_combatResults.TryGetValue(target, out combatResult)) {
         combatResult = new CombatResult(DebugName, targetName);
         _combatResults.Add(target, combatResult);
     }
     combatResult.ShotsTaken++;
 }
示例#15
0
 private bool IsQualifiedEnemyTarget(IElementAttackable enemyTarget) {
     return true;    // UNDONE
 }
示例#16
0
 private void UponOrderOutcome(FacilityDirective directive, FacilityItem facility, bool isSuccess, IElementAttackable target, UnitItemOrderFailureCause failCause) {
     RelayToCurrentState(directive, facility, isSuccess, target, failCause);
 }
示例#17
0
    public void Launch(IElementAttackable target, AWeapon weapon) {
        PrepareForLaunch(target, weapon);
        D.Assert((Layers)gameObject.layer == Layers.TransparentFX, "{0} is not on Layer {1}.".Inject(Name, Layers.TransparentFX.GetValueName()));
        weapon.isOperationalChanged += WeaponIsOperationalChangedEventHandler;
        _operatingEffectRenderer.SetPosition(index: 0, position: Vector3.zero);  // start beam where ordnance located

        _beamEnd = TrackingWidgetFactory.Instance.MakeTrackableLocation(parent: gameObject);
        _beamEndListener = TrackingWidgetFactory.Instance.MakeInvisibleCameraLosChangedListener(_beamEnd, Layers.Cull_15);
        _beamEndListener.inCameraLosChanged += BeamEndInCameraLosChangedEventHandler;

        AssessShowMuzzleEffects();
        AssessShowOperatingEffects();
        enabled = true;
    }
示例#18
0
 /// <summary>
 /// Confirms the provided enemyTarget is in range prior to launching the weapon's ordnance.
 /// </summary>
 /// <param name="enemyTarget">The target.</param>
 /// <returns></returns>
 public override bool ConfirmInRangeForLaunch(IElementAttackable enemyTarget) {
     float weaponRange = Weapon.RangeDistance;
     return Vector3.SqrMagnitude(enemyTarget.Position - _hub.position) < weaponRange * weaponRange;
 }
示例#19
0
    public void Launch(IElementAttackable target, AWeapon weapon) {
        PrepareForLaunch(target, weapon);
        D.AssertEqual(Layers.TransparentFX, (Layers)gameObject.layer, ((Layers)gameObject.layer).GetValueName());

        _operatingEffectRenderer.SetPosition(index: 0, position: Vector3.zero);
        AdjustHeadingForInaccuracy();

        AssessShowMuzzleEffects();
        AssessShowOperatingEffects();
        enabled = true;
    }
示例#20
0
    /// <summary>
    /// Checks the line of sight from this LOSWeaponMount to the provided enemy target, returning <c>true</c>
    /// if there is a clear line of sight in the direction of the target, otherwise <c>false</c>.
    /// </summary>
    /// <param name="enemyTarget">The enemy target.</param>
    /// <returns></returns>
    private bool CheckLineOfSight(IElementAttackable enemyTarget) {
        Vector3 turretPosition = _hub.position;
        Vector3 vectorToTarget = enemyTarget.Position - turretPosition;
        Vector3 targetDirection = vectorToTarget.normalized;
        float targetDistance = vectorToTarget.magnitude;
        RaycastHit raycastHitInfo;
        if (Physics.Raycast(turretPosition, targetDirection, out raycastHitInfo, targetDistance, _defaultOnlyLayerMask)) {

            Profiler.BeginSample("Editor-only GC allocation (GetComponent returns null)", gameObject);
            var attackableTgtEncountered = raycastHitInfo.transform.GetComponent<IElementAttackable>();
            Profiler.EndSample();

            if (attackableTgtEncountered != null) {
                if (attackableTgtEncountered == enemyTarget) {
                    //D.Log(ShowDebugLog, "{0}: CheckLineOfSight({1}) found its target.", DebugName, enemyTarget.DebugName);
                    return true;
                }
                if (attackableTgtEncountered.IsAttackByAllowed(Weapon.Owner)) {
                    D.Log(ShowDebugLog, "{0}: CheckLineOfSight({1}) found interfering attackable target {2} on {3}.", DebugName, enemyTarget.DebugName, attackableTgtEncountered.DebugName, _gameTime.CurrentDate);
                    return false;
                }
                D.Log(ShowDebugLog, "{0}: CheckLineOfSight({1}) found interfering non-attackable target {2} on {3}.", DebugName, enemyTarget.DebugName, attackableTgtEncountered.DebugName, _gameTime.CurrentDate);
                return false;
            }
            D.Log(ShowDebugLog, "{0}: CheckLineOfSight({1}) didn't find target but found {2} on {3}.", DebugName, enemyTarget.DebugName, raycastHitInfo.transform.name, _gameTime.CurrentDate);
            return false;
        }
        //D.Log(ShowDebugLog, "{0}: CheckLineOfSight({1}) didn't find anything. Date: {2}.", DebugName, enemyTarget.DebugName, _gameTime.CurrentDate);
        return true;
    }
示例#21
0
 protected override void OnDespawned() {
     base.OnDespawned();
     _cumHoursOperating = Constants.ZeroF;
     _cumHoursOfImpactOnImpactedTarget = Constants.ZeroF;
     _impactedTarget = null;
     _isCurrentImpact = false;
     _isIntendedTargetHit = false;
     _isInterdicted = false;
     _animateOperatingEffectJob = null;
     _impactLocation = Vector3.zero;
     _operatingAudioSource = null;
 }
    public virtual void Launch(IElementAttackable target, AWeapon weapon, Topography topography) {
        PrepareForLaunch(target, weapon);
        D.Assert((Layers)gameObject.layer == Layers.Projectiles, "{0} is not on Layer {1}.".Inject(Name, Layers.Projectiles.GetValueName()));
        _launchPosition = transform.position;

        _rigidbody.drag = OpenSpaceDrag * topography.GetRelativeDensity();
        _rigidbody.mass = Mass;
        AssessShowMuzzleEffects();
        _hasWeaponFired = true;
        weapon.HandleFiringComplete(this);

        _displayMgr = InitializeDisplayMgr();
    }
示例#23
0
    protected void PrepareForLaunch(IElementAttackable target, AWeapon weapon) {
        //D.Log(ShowDebugLog, "{0} is assigning target {1}.", DebugName, target.DebugName);
        Target = target;
        Weapon = weapon;
        Subscribe();

        DeliveryVehicleStrength = weapon.DeliveryVehicleStrength;

        AssignName();
        weapon.HandleFiringInitiated(target, this);

        _range = weapon.RangeDistance;
        IsOperational = true;
    }
示例#24
0
 public override void HandleFiringInitiated(IElementAttackable targetFiredOn, IOrdnance ordnanceFired) {
     base.HandleFiringInitiated(targetFiredOn, ordnanceFired);
     // IMPROVE Track target with turret
 }
示例#25
0
    protected void PrepareForLaunch(IElementAttackable target, AWeapon weapon) {
        Target = target;
        Weapon = weapon;
        SubscribeToWeaponChanges();

        DeliveryVehicleStrength = weapon.DeliveryVehicleStrength;

        SyncName();
        weapon.HandleFiringInitiated(target, this);

        _range = weapon.RangeDistance;
        IsOperational = true;
    }
示例#26
0
 public override void Launch(IElementAttackable target, AWeapon weapon, Topography topography) {
     base.Launch(target, weapon, topography);
     InitializeVelocity();
     enabled = true;
 }
示例#27
0
 protected void ExecuteAttackOrder_UponOrderOutcome(FacilityDirective directive, FacilityItem facility, bool isSuccess, IElementAttackable target, UnitItemOrderFailureCause failCause) {
     LogEvent();
     if (directive != FacilityDirective.Attack) {
         D.Warn("{0} State {1} erroneously received OrderOutcome callback with {2} {3}.", DebugName, CurrentState.GetValueName(), typeof(FacilityDirective).Name, directive.GetValueName());
         return;
     }
     // TODO What? It will be common for an attack by a facility to fail for cause unreachable as its target moves out of range...
 }
示例#28
0
 /// <summary>
 /// Handles the results of the facility's attempt to execute the provided directive.
 /// </summary>
 /// <param name="directive">The directive.</param>
 /// <param name="facility">The facility.</param>
 /// <param name="isSuccess">if set to <c>true</c> the directive was successfully completed. May still be ongoing.</param>
 /// <param name="target">The target. Can be null.</param>
 /// <param name="failCause">The failure cause if not successful.</param>
 internal void HandleOrderOutcome(FacilityDirective directive, FacilityItem facility, bool isSuccess, IElementAttackable target = null, UnitItemOrderFailureCause failCause = UnitItemOrderFailureCause.None) {
     UponOrderOutcome(directive, facility, isSuccess, target, failCause);
 }
 public WeaponFiringSolution(AWeapon weapon, IElementAttackable enemyTgt) {
     Weapon = weapon;
     EnemyTarget = enemyTgt;
 }
示例#30
0
 /// <summary>
 /// Confirms the provided enemyTarget is in range PRIOR to launching the weapon's ordnance.
 /// <remarks>12.15.16 Got a HandleFiringInitiated error so added _qualifiedEnemyTgt criteria as 
 /// WeaponMount range confirmation is not exactly the same thing. I'm theorizing that the target was
 /// barely in range of the mount (measured from the mount's hub), but just outside of the Weapon's 
 /// Monitor range implying that the target had already been removed via OnTriggerExit().</remarks>
 /// </summary>
 /// <param name="enemyTarget">The target.</param>
 /// <returns></returns>
 public bool ConfirmInRangeForLaunch(IElementAttackable enemyTarget) {
     return _qualifiedEnemyTargets.Contains(enemyTarget) && WeaponMount.ConfirmInRangeForLaunch(enemyTarget);
 }