protected virtual Activity InnerTick(Actor self, AttackBase attack) { if (IsCanceled) { return(NextActivity); } var type = Target.Type; if (!Target.IsValidFor(self) || type == TargetType.FrozenActor) { return(NextActivity); } if (attack.Info.AttackRequiresEnteringCell && !positionable.CanEnterCell(Target.Actor.Location, null, false)) { return(NextActivity); } // Drop the target if it moves under the shroud / fog. // HACK: This would otherwise break targeting frozen actors // The problem is that Shroud.IsTargetable returns false (as it should) for // frozen actors, but we do want to explicitly target the underlying actor here. if (!attack.Info.IgnoresVisibility && type == TargetType.Actor && !Target.Actor.Info.HasTraitInfo <FrozenUnderFogInfo>() && !self.Owner.CanTargetActor(Target.Actor)) { return(NextActivity); } // Drop the target once none of the weapons are effective against it var armaments = attack.ChooseArmamentsForTarget(Target, forceAttack); if (!armaments.Any()) { return(NextActivity); } // Update ranges minRange = armaments.Max(a => a.Weapon.MinRange); maxRange = armaments.Min(a => a.MaxRange()); // Try to move within range if (move != null && (!Target.IsInRange(self.CenterPosition, maxRange) || Target.IsInRange(self.CenterPosition, minRange))) { return(Util.SequenceActivities(move.MoveWithinRange(Target, minRange, maxRange), this)); } var desiredFacing = Util.GetFacing(Target.CenterPosition - self.CenterPosition, 0); if (facing.Facing != desiredFacing) { return(Util.SequenceActivities(new Turn(self, desiredFacing), this)); } attack.DoAttack(self, Target, armaments); return(this); }
protected virtual Activity InnerTick(Actor self, AttackBase attack) { if (IsCanceled) { return(NextActivity); } if (!Target.IsValid) { return(NextActivity); } if (!self.Owner.HasFogVisibility() && Target.Actor != null && Target.Actor.HasTrait <Mobile>() && !self.Owner.Shroud.IsTargetable(Target.Actor)) { return(NextActivity); } if (targetable != null && !targetable.TargetableBy(Target.Actor, self)) { return(NextActivity); } if (!Combat.IsInRange(self.CenterLocation, Range, Target)) { if (--nextPathTime > 0) { return(this); } nextPathTime = self.World.SharedRandom.Next(delayBetweenPathingAttempts - delaySpread, delayBetweenPathingAttempts + delaySpread); return((AllowMovement) ? Util.SequenceActivities(self.Trait <Mobile>().MoveWithinRange(Target, Range), this) : NextActivity); } var desiredFacing = Util.GetFacing(Target.CenterLocation - self.CenterLocation, 0); var facing = self.Trait <IFacing>(); if (facing.Facing != desiredFacing) { return(Util.SequenceActivities(new Turn(desiredFacing), this)); } attack.DoAttack(self, Target); return(this); }
protected virtual Activity InnerTick(Actor self, AttackBase attack) { if (IsCanceled) { return(NextActivity); } var type = Target.Type; if (!Target.IsValidFor(self) || type == TargetType.FrozenActor) { return(NextActivity); } // TODO: This is horrible, and probably wrong. Work out what it is trying to solve, then redo it properly. if (type == TargetType.Actor && !self.Owner.HasFogVisibility() && Target.Actor.HasTrait <Mobile>() && !self.Owner.Shroud.IsTargetable(Target.Actor)) { return(NextActivity); } if (!Target.IsInRange(self.CenterPosition, Range)) { if (--nextPathTime > 0) { return(this); } nextPathTime = self.World.SharedRandom.Next(delayBetweenPathingAttempts - delaySpread, delayBetweenPathingAttempts + delaySpread); return((AllowMovement) ? Util.SequenceActivities(self.Trait <Mobile>().MoveWithinRange(Target, Range), this) : NextActivity); } var desiredFacing = Util.GetFacing(Target.CenterPosition - self.CenterPosition, 0); var facing = self.Trait <IFacing>(); if (facing.Facing != desiredFacing) { return(Util.SequenceActivities(new Turn(desiredFacing), this)); } attack.DoAttack(self, Target); return(this); }
protected virtual Activity InnerTick(Actor self, AttackBase attack) { if (IsCanceled) { return(NextActivity); } var type = Target.Type; if (!Target.IsValidFor(self) || type == TargetType.FrozenActor) { return(NextActivity); } // Drop the target if it moves under the shroud / fog. // HACK: This would otherwise break targeting frozen actors // The problem is that Shroud.IsTargetable returns false (as it should) for // frozen actors, but we do want to explicitly target the underlying actor here. if (type == TargetType.Actor && !Target.Actor.HasTrait <FrozenUnderFog>() && !self.Owner.Shroud.IsTargetable(Target.Actor)) { return(NextActivity); } // Try to move within range if (move != null && (!Target.IsInRange(self.CenterPosition, maxRange) || Target.IsInRange(self.CenterPosition, minRange))) { return(Util.SequenceActivities(move.MoveWithinRange(Target, minRange, maxRange), this)); } var desiredFacing = Util.GetFacing(Target.CenterPosition - self.CenterPosition, 0); if (facing.Facing != desiredFacing) { return(Util.SequenceActivities(new Turn(desiredFacing), this)); } attack.DoAttack(self, Target); return(this); }
protected virtual AttackStatus TickAttack(Actor self, AttackBase attack) { if (IsCanceled) { return(AttackStatus.UnableToAttack); } var type = Target.Type; if (!Target.IsValidFor(self) || type == TargetT.FrozenActor) { return(AttackStatus.UnableToAttack); } if (attack.Info.AttackRequiresEnteringCell && !positionable.CanEnterCell(Target.Actor.Location, null, false)) { return(AttackStatus.UnableToAttack); } //Drop the target if it moves under the shroud / fog. if (!attack.Info.IgnoresVisibility && type == TargetT.Actor && !Target.Actor.Info.HasTraitInfo <FrozenUnderFogInfo>() && !Target.Actor.CanBeViewedByPlayer(self.Owner)) { return(AttackStatus.UnableToAttack); } //Drop the target once none of the weapons are effective against it var armaments = attack.ChooseArmamentsForTarget(Target, forceAttack).ToList(); if (armaments.Count == 0) { return(AttackStatus.UnableToAttack); } //Update ranges minRange = armaments.Max(a => a.Weapon.MinRange); maxRange = armaments.Min(a => a.MaxRange()); var pos = self.CenterPosition; var mobile = move as Mobile; if (!Target.IsInRange(pos, maxRange) || (minRange.Length != 0 && Target.IsInRange(pos, minRange)) || (mobile != null && !mobile.CanInteractWithGroundLayer(self))) { //Try to move within range,drop the target otherwise. if (move == null) { return(AttackStatus.UnableToAttack); } attackStatus |= AttackStatus.NeedsToMove; moveActivity = ActivityUtils.SequenceActivities(move.MoveWithinRange(Target, minRange, maxRange), this); return(AttackStatus.NeedsToMove); } var targetedPosition = attack.GetTargetPosition(pos, Target); var desiredFacing = (targetedPosition - pos).Yaw.Facing; if (!Util.FacingWithinTolerance(facing.Facing, desiredFacing, facingTolerance)) { attackStatus |= AttackStatus.NeedsToTurn; turnActivity = ActivityUtils.SequenceActivities(new Turn(self, desiredFacing), this); return(AttackStatus.NeedsToTurn); } attackStatus |= AttackStatus.Attacking; attack.DoAttack(self, Target, armaments); return(AttackStatus.Attacking); }
protected virtual Activity InnerTick(Actor self, AttackBase attack) { if (IsCanceled) { return(NextActivity); } var type = Target.Type; if (!Target.IsValidFor(self) || type == TargetType.FrozenActor) { return(NextActivity); } if (attack.Info.AttackRequiresEnteringCell && !positionable.CanEnterCell(Target.Actor.Location, null, false)) { return(NextActivity); } // Drop the target if it moves under the shroud / fog. // HACK: This would otherwise break targeting frozen actors // The problem is that Shroud.IsTargetable returns false (as it should) for // frozen actors, but we do want to explicitly target the underlying actor here. if (!attack.Info.IgnoresVisibility && type == TargetType.Actor && !Target.Actor.Info.HasTraitInfo <FrozenUnderFogInfo>() && !self.Owner.CanTargetActor(Target.Actor)) { return(NextActivity); } // Drop the target once none of the weapons are effective against it var armaments = attack.ChooseArmamentsForTarget(Target, forceAttack).ToList(); if (armaments.Count == 0) { return(NextActivity); } // Update ranges minRange = armaments.Max(a => a.Weapon.MinRange); maxRange = armaments.Min(a => a.MaxRange()); var pos = self.CenterPosition; var mobile = move as Mobile; if (!Target.IsInRange(pos, maxRange) || (minRange.Length != 0 && Target.IsInRange(pos, minRange)) || (mobile != null && !mobile.CanInteractWithGroundLayer(self))) { // Try to move within range, drop the target otherwise if (move == null) { return(NextActivity); } attackStatus |= AttackStatus.NeedsToMove; moveActivity = ActivityUtils.SequenceActivities(move.MoveWithinRange(Target, minRange, maxRange), this); return(NextActivity); } var targetedPosition = attack.GetTargetPosition(pos, Target); var desiredFacing = (targetedPosition - pos).Yaw.Facing; if (facing.Facing != desiredFacing) { attackStatus |= AttackStatus.NeedsToTurn; turnActivity = ActivityUtils.SequenceActivities(new Turn(self, desiredFacing), this); return(NextActivity); } attackStatus |= AttackStatus.Attacking; attack.DoAttack(self, Target, armaments); return(this); }