Пример #1
0
        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.HasTrait<FrozenUnderFog>() && !self.Owner.CanTargetActor(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(self, desiredFacing), this);

            attack.DoAttack(self, Target);

            return this;
        }
Пример #2
0
        protected virtual Activity InnerTick( Actor self, AttackBase attack )
        {
            if (IsCanceled) return NextActivity;
            var facing = self.Trait<IFacing>();
            if (!Target.IsValid)
                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);
            if (facing.Facing != desiredFacing)
                return Util.SequenceActivities( new Turn( desiredFacing ), this );

            attack.DoAttack(self, Target);
            return this;
        }
Пример #3
0
        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<IMove>().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;
        }
Пример #4
0
        public AreaBeam(AreaBeamInfo info, ProjectileArgs args, Color color)
        {
            this.info = info;
            this.args = args;
            this.color = color;
            actorAttackBase = args.SourceActor.Trait<AttackBase>();

            var world = args.SourceActor.World;
            if (info.Speed.Length > 1)
                speed = new WDist(world.SharedRandom.Next(info.Speed[0].Length, info.Speed[1].Length));
            else
                speed = info.Speed[0];

            // Both the head and tail start at the source actor, but initially only the head is travelling.
            headPos = args.Source;
            tailPos = headPos;

            target = args.PassiveTarget;
            if (info.Inaccuracy.Length > 0)
            {
                var inaccuracy = Util.ApplyPercentageModifiers(info.Inaccuracy.Length, args.InaccuracyModifiers);
                var maxOffset = inaccuracy * (target - headPos).Length / args.Weapon.Range.Length;
                target += WVec.FromPDF(world.SharedRandom, 2) * maxOffset / 1024;
            }

            towardsTargetFacing = (target - headPos).Yaw.Facing;

            // Update the target position with the range we shoot beyond the target by
            // I.e. we can deliberately overshoot, so aim for that position
            var dir = new WVec(0, -1024, 0).Rotate(WRot.FromFacing(towardsTargetFacing));
            target += dir * info.BeyondTargetRange.Length / 1024;

            length = Math.Max((target - headPos).Length / speed.Length, 1);
        }
Пример #5
0
        protected override IActivity InnerTick( Actor self, AttackBase attack )
        {
            if (Target.IsActor && Target.Actor.GetDamageState() == DamageState.Undamaged)
                return NextActivity;

            return base.InnerTick(self, attack);
        }
Пример #6
0
        IActivity InnerTick( Actor self, AttackBase attack )
        {
            if (IsCanceled) return NextActivity;
            var facing = self.Trait<IFacing>();
            if (!Target.IsValid)
                return NextActivity;

            var targetCell = Util.CellContaining(Target.CenterLocation);

            if ((targetCell - self.Location).LengthSquared >= Range * Range)
                return Util.SequenceActivities( new Move( Target, Range ), this );

            var desiredFacing = Util.GetFacing((targetCell - self.Location).ToFloat2(), 0);
            var renderUnit = self.TraitOrDefault<RenderUnit>();
            var numDirs = (renderUnit != null)
                ? renderUnit.anim.CurrentSequence.Facings : 8;

            if (Util.QuantizeFacing(facing.Facing, numDirs)
                != Util.QuantizeFacing(desiredFacing, numDirs))
            {
                return Util.SequenceActivities( new Turn( desiredFacing ), this );
            }

            attack.target = Target;
            attack.DoAttack(self);
            return this;
        }
Пример #7
0
        protected override Activity InnerTick(Actor self, AttackBase attack)
        {
            if (!Target.IsValidFor(self))
                return NextActivity;

            if (Target.Type == TargetType.Actor && Target.Actor.GetDamageState() == DamageState.Undamaged)
                return NextActivity;

            return base.InnerTick(self, attack);
        }
Пример #8
0
		public Attack(Actor self, Target target, WRange minRange, WRange maxRange, bool allowMovement)
		{
			Target = target;
			this.minRange = minRange;
			this.maxRange = maxRange;

			attack = self.Trait<AttackBase>();
			facing = self.Trait<IFacing>();

			move = allowMovement ? self.TraitOrDefault<IMove>() : null;
		}
Пример #9
0
		public Attack(Actor self, Target target, bool allowMovement, bool forceAttack)
		{
			Target = target;

			this.forceAttack = forceAttack;

			attack = self.Trait<AttackBase>();
			facing = self.Trait<IFacing>();
			positionable = self.Trait<IPositionable>();

			move = allowMovement ? self.TraitOrDefault<IMove>() : null;
		}
Пример #10
0
        IActivity InnerTick( Actor self, AttackBase attack )
        {
            if (IsCanceled) return NextActivity;
            var facing = self.Trait<IFacing>();
            if (!Target.IsValid)
                return NextActivity;

            if (!Combat.IsInRange(self.CenterLocation, Range, Target))
                return (AllowMovement) ? Util.SequenceActivities(self.Trait<Mobile>().MoveWithinRange(Target, Range), this) : NextActivity;

            var desiredFacing = Util.GetFacing(Target.CenterLocation - self.CenterLocation, 0);
            if (facing.Facing != desiredFacing)
                return Util.SequenceActivities( new Turn( desiredFacing ), this );

            attack.DoAttack(self, Target);
            return this;
        }
Пример #11
0
        void DrawArmaments(Actor self, AttackBase attack, WorldRenderer wr, RgbaColorRenderer wcr, float iz)
        {
            var c = Color.White;

            // Fire ports on garrisonable structures
            var garrison = attack as AttackGarrisoned;
            if (garrison != null)
            {
                var bodyOrientation = coords.Value.QuantizeOrientation(self, self.Orientation);
                foreach (var p in garrison.Info.Ports)
                {
                    var pos = self.CenterPosition + coords.Value.LocalToWorld(p.Offset.Rotate(bodyOrientation));
                    var da = coords.Value.LocalToWorld(new WVec(224, 0, 0).Rotate(WRot.FromYaw(p.Yaw + p.Cone)).Rotate(bodyOrientation));
                    var db = coords.Value.LocalToWorld(new WVec(224, 0, 0).Rotate(WRot.FromYaw(p.Yaw - p.Cone)).Rotate(bodyOrientation));

                    var o = wr.ScreenPosition(pos);
                    var a = wr.ScreenPosition(pos + da * 224 / da.Length);
                    var b = wr.ScreenPosition(pos + db * 224 / db.Length);
                    wcr.DrawLine(o, a, iz, c);
                    wcr.DrawLine(o, b, iz, c);
                }

                return;
            }

            foreach (var a in attack.Armaments)
            {
                foreach (var b in a.Barrels)
                {
                    var muzzle = self.CenterPosition + a.MuzzleOffset(self, b);
                    var dirOffset = new WVec(0, -224, 0).Rotate(a.MuzzleOrientation(self, b));

                    var sm = wr.ScreenPosition(muzzle);
                    var sd = wr.ScreenPosition(muzzle + dirOffset);
                    wcr.DrawLine(sm, sd, iz, c);
                    TargetLineRenderable.DrawTargetMarker(wr, c, sm);
                }
            }
        }
Пример #12
0
        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());

            if (!Target.IsInRange(self.CenterPosition, maxRange) || Target.IsInRange(self.CenterPosition, minRange))
            {
                // 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 desiredFacing = (Target.CenterPosition - self.CenterPosition).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;
        }