예제 #1
0
 void IRulesetLoaded <ActorInfo> .RulesetLoaded(Ruleset rules, ActorInfo info)
 {
     if (!info.HasTraitInfo <SelectableInfo>() && !info.HasTraitInfo <IAutoSelectionSizeInfo>())
     {
         throw new YamlException("Cannot create a frozen actor for actor type '{0}' with empty bounds (no selection size given).".F(info.Name));
     }
 }
예제 #2
0
 public override void RulesetLoaded(Ruleset rules, ActorInfo ai)
 {
     if (!ai.HasTraitInfo <MobileInfo>() && !ai.HasTraitInfo <HuskInfo>())
     {
         throw new YamlException("Chronoshiftable requires actors to have the Mobile or Husk traits.");
     }
 }
예제 #3
0
        IEnumerable <Order> InnerOrder(World world, CPos cell, MouseInput mi)
        {
            if (world.Paused)
            {
                yield break;
            }

            var owner = queue.Actor.Owner;

            if (mi.Button == MouseButton.Left)
            {
                var orderType = "PlaceBuilding";
                var topLeft   = viewport.ViewToWorld(Viewport.LastMousePos + topLeftScreenOffset);

                var plugInfo = actorInfo.TraitInfoOrDefault <PlugInfo>();
                if (plugInfo != null)
                {
                    orderType = "PlacePlug";
                    if (!AcceptsPlug(topLeft, plugInfo))
                    {
                        Game.Sound.PlayNotification(world.Map.Rules, owner, "Speech", "BuildingCannotPlaceAudio", owner.Faction.InternalName);
                        yield break;
                    }
                }
                else
                {
                    if (!world.CanPlaceBuilding(topLeft, actorInfo, buildingInfo, null) ||
                        !buildingInfo.IsCloseEnoughToBase(world, owner, actorInfo, topLeft))
                    {
                        foreach (var order in ClearBlockersOrders(world, topLeft))
                        {
                            yield return(order);
                        }

                        Game.Sound.PlayNotification(world.Map.Rules, owner, "Speech", "BuildingCannotPlaceAudio", owner.Faction.InternalName);
                        yield break;
                    }

                    if (actorInfo.HasTraitInfo <LineBuildInfo>() && !mi.Modifiers.HasModifier(Modifiers.Shift))
                    {
                        orderType = "LineBuild";
                    }
                }

                yield return(new Order(orderType, owner.PlayerActor, Target.FromCell(world, topLeft), false)
                {
                    // Building to place
                    TargetString = actorInfo.Name,

                    // Actor to associate the placement with
                    ExtraData = queue.Actor.ActorID,
                    SuppressVisualFeedback = true
                });
            }
        }
예제 #4
0
        public int SetActor(WorldRenderer wr, ActorInfo actor, PlayerReference owner)
        {
            var ios          = actor.TraitInfoOrDefault <IOccupySpaceInfo>();
            var buildingInfo = ios as BuildingInfo;

            actorCenterOffset = buildingInfo != null?buildingInfo.CenterOffset(world) : WVec.Zero;

            actorSharesCell = ios != null && ios.SharesCell;
            actorSubCell    = SubCell.Invalid;

            // Enforce first entry of ValidOwnerNames as owner if the actor has RequiresSpecificOwners
            var ownerName         = owner.Name;
            var specificOwnerInfo = actor.TraitInfoOrDefault <RequiresSpecificOwnersInfo>();

            if (specificOwnerInfo != null && !specificOwnerInfo.ValidOwnerNames.Contains(ownerName))
            {
                ownerName = specificOwnerInfo.ValidOwnerNames.First();
            }

            var reference = new ActorReference(actor.Name);

            reference.Add(new OwnerInit(ownerName));
            reference.Add(new FactionInit(owner.Faction));

            var worldPx = wr.Viewport.ViewToWorldPx(Viewport.LastMousePos) - wr.ScreenPxOffset(actorCenterOffset);
            var cell    = wr.Viewport.ViewToWorld(wr.Viewport.WorldToViewPx(worldPx));

            reference.Add(new LocationInit(cell));
            if (ios != null && ios.SharesCell)
            {
                actorSubCell = editorLayer.FreeSubCellAt(cell);
                if (actorSubCell != SubCell.Invalid)
                {
                    reference.Add(new SubCellInit(actorSubCell));
                }
            }

            if (actor.HasTraitInfo <IFacingInfo>())
            {
                reference.Add(new FacingInit(info.PreviewFacing));
            }

            if (actor.HasTraitInfo <TurretedInfo>())
            {
                reference.Add(new TurretFacingInit(info.PreviewFacing));
            }

            Type            = EditorCursorType.Actor;
            Actor           = new EditorActorPreview(wr, null, reference, owner);
            TerrainTemplate = null;
            Resource        = null;

            return(++CurrentToken);
        }
        public override void Tick()
        {
            if (actorActions.Actor == null)
            {
                return;
            }

            string actorString = null;

            if (actorActions.Actor.Info.HasTraitInfo <SpawnsAcolytesInfo>())
            {
                actorString = actorActions.Actor.Info.TraitInfo <SpawnsAcolytesInfo>().Actor;
            }

            actorInfo = actorActions.BamUi.World.Map.Rules.Actors[actorString];

            if (actorInfo != null && actorInfo.HasTraitInfo <RenderSpritesInfo>())
            {
                animation = new Animation(actorActions.BamUi.World, actorInfo.TraitInfo <RenderSpritesInfo>().GetImage
                                          (
                                              actorInfo,
                                              actorActions.BamUi.World.Map.Rules.Sequences,
                                              actorActions.Actor.Owner.Faction.Name
                                          ));
            }

            var x = pressed ? 11 : 10;
            var y = pressed ? 450 + 1 : 450;

            Bounds = new Rectangle(x, y, 75, 68);
        }
예제 #6
0
 void IRulesetLoaded <ActorInfo> .RulesetLoaded(Ruleset rules, ActorInfo info)
 {
     if (ShowTicks && !info.HasTraitInfo <IOccupySpaceInfo>())
     {
         throw new YamlException($"CashTrickler is defined with ShowTicks 'true' but actor '{info.Name}' occupies no space.");
     }
 }
예제 #7
0
        public override void Tick()
        {
            if (actorActions.Actor == null)
            {
                return;
            }

            string actorString = null;

            if (actorActions.Actor.Trait <CanHoldTrinket>().HoldsTrinket != null)
            {
                actorString = actorActions.Actor.Trait <CanHoldTrinket>().HoldsTrinket.Info.Name;
            }

            actorInfo = actorActions.BamUi.World.Map.Rules.Actors[actorString];

            if (actorInfo != null && actorInfo.HasTraitInfo <RenderSpritesInfo>())
            {
                animation = new Animation(actorActions.BamUi.World, actorInfo.TraitInfo <RenderSpritesInfo>().GetImage
                                          (
                                              actorInfo,
                                              actorActions.BamUi.World.Map.Rules.Sequences,
                                              actorActions.Actor.Owner.Faction.Name
                                          ));
            }

            var x = pressed ? 1 : 0;
            var y = pressed ? 352 + 1 : 352;

            Bounds = new Rectangle(x, y, 76, 51);
        }
예제 #8
0
        public override bool Produce(Actor self, ActorInfo producee, string productionType, TypeDictionary inits)
        {
            var newexit = self.Info.TraitInfos <ExitInfo>().FirstOrDefault();
            var person  = producee.TraitInfo <PersonValuedInfo>();
            var numb    = person.ActorCount;

            var devMode = self.Owner.PlayerActor.TraitOrDefault <DeveloperMode>();

            if (devMode != null && devMode.FastBuild)
            {
                self.World.AddFrameEndTask(ww => DoProduction(self, producee, newexit, productionType, inits));
                Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", info.ReadyAudio,
                                            self.Owner.Faction.InternalName);
                return(true);
            }

            if (!producee.HasTraitInfo <PersonValuedInfo>() || self.Owner.PlayerActor.Trait <PlayerCivilization>().FreePopulation < numb)
            {
                return(false);
            }

            self.World.AddFrameEndTask(w => DoProduction(self, producee, newexit, productionType, inits));
            Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", info.ReadyAudio,
                                        self.Owner.Faction.InternalName);

            return(true);
        }
예제 #9
0
 public void RulesetLoaded(Ruleset rules, ActorInfo ai)
 {
     if (!ai.HasTraitInfo <HitShapeInfo>())
     {
         throw new YamlException("Actors with Health need at least one HitShape trait!");
     }
 }
예제 #10
0
        public void Do()
        {
            var ownerName         = owner.Name;
            var specificOwnerInfo = actor.TraitInfoOrDefault <RequiresSpecificOwnersInfo>();

            if (specificOwnerInfo != null && !specificOwnerInfo.ValidOwnerNames.Contains(ownerName))
            {
                ownerName = specificOwnerInfo.ValidOwnerNames.First();
            }

            var newActorReference = new ActorReference(actor.Name);

            newActorReference.Add(new OwnerInit(ownerName));

            newActorReference.Add(new LocationInit(cell));

            var ios = actor.TraitInfoOrDefault <IOccupySpaceInfo>();

            if (ios != null && ios.SharesCell)
            {
                var subcell = editorLayer.FreeSubCellAt(cell);
                if (subcell != SubCell.Invalid)
                {
                    newActorReference.Add(new SubCellInit(subcell));
                }
            }

            var initDict = newActorReference.InitDict;

            if (actor.HasTraitInfo <IFacingInfo>())
            {
                initDict.Add(new FacingInit(facing));
            }

            if (actor.HasTraitInfo <TurretedInfo>())
            {
                initDict.Add(new TurretFacingInit(facing));
            }

            editorActorPreview = editorLayer.Add(newActorReference);

            Text = "Added {0} ({1})".F(editorActorPreview.Info.Name, editorActorPreview.ID);
        }
예제 #11
0
        public static int GetBuildTime(this ActorInfo a)
        {
            var csv = a.TraitInfoOrDefault <CustomBuildTimeValueInfo>();

            if (csv != null)
            {
                return(csv.Value);
            }

            var cost = a.HasTraitInfo <ValuedInfo>() ? a.TraitInfo <ValuedInfo>().Cost : 0;

            return(cost * FramesPerMin / 1000);
        }
        public List <Actor> FindPeasants(Actor self, ActorInfo producee)
        {
            if (producee.HasTraitInfo <PersonValuedInfo>() && producee.TraitInfo <PersonValuedInfo>().ActorCount > 0 && producee.TraitInfo <PersonValuedInfo>().ConvertingActors.Any())
            {
                var validList = self.World.ActorsHavingTrait <IPositionable>().Where(a =>
                {
                    return(a.Owner == self.Owner && a.Info.HasTraitInfo <IsPeasantInfo>() &&
                           producee.TraitInfo <PersonValuedInfo>().ConvertingActors.Contains(a.Info.Name) &&
                           a.Trait <IsPeasant>().IsWorker == false);
                }).ToList();
                return(validList);
            }

            return(new List <Actor>());
        }
예제 #13
0
        public static int GetBuildTime(this ActorInfo a)
        {
            var csv = a.TraitInfoOrDefault <CustomBuildTimeValueInfo>();

            if (csv != null)
            {
                return(csv.Value);
            }

            var cost = a.HasTraitInfo <ValuedInfo>() ? a.TraitInfo <ValuedInfo>().Cost : 0;
            var time = cost
                       * (25 * 60)                                  /* frames per min */
                       / 1000;

            return
                (time);
        }
예제 #14
0
        public virtual bool Produce(Actor self, ActorInfo producee, string productionType, TypeDictionary inits, int refundableValue)
        {
            if (IsTraitDisabled || IsTraitPaused || Reservable.IsReserved(self))
            {
                return(false);
            }

            // Pick a spawn/exit point pair
            var exit = SelectExit(self, producee, productionType);

            if (exit != null || self.OccupiesSpace == null || !producee.HasTraitInfo <IOccupySpaceInfo>())
            {
                DoProduction(self, producee, exit?.Info, productionType, inits);
                return(true);
            }

            return(false);
        }
        public override bool Produce(Actor self, ActorInfo producee, string productionType, TypeDictionary inits)
        {
            if (self.Owner.PlayerActor.TraitOrDefault <DeveloperMode>() != null && self.Owner.PlayerActor.TraitOrDefault <DeveloperMode>().FastBuild)
            {
                var newexit2 = self.Info.TraitInfos <ExitInfo>().FirstOrDefault();

                self.World.AddFrameEndTask(ww => DoProduction(self, producee, newexit2, productionType, inits));
                Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", info.ReadyAudio,
                                            self.Owner.Faction.InternalName);
                return(true);
            }

            var owner = self.Owner;

            if (!owner.PlayerActor.Info.HasTraitInfo <PlayerCivilizationInfo>())
            {
                throw new System.Exception("PlayerCivilization Trait not found! Player must have PlayerCivilization trait!");
            }

            var neededPop = 1;

            if (producee.HasTraitInfo <PersonValuedInfo>())
            {
                neededPop = producee.TraitInfo <PersonValuedInfo>().ActorCount;
            }

            if (owner.PlayerActor.Trait <PlayerCivilization>().FreePopulation < neededPop)
            {
                return(false);
            }

            var newexit = self.Info.TraitInfos <ExitInfo>().FirstOrDefault();

            owner.World.AddFrameEndTask(w =>
            {
                self.World.AddFrameEndTask(ww => DoProduction(self, producee, newexit, productionType, inits));
                Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", info.ReadyAudio,
                                            self.Owner.Faction.InternalName);
            });

            return(true);
        }
예제 #16
0
        public override void Tick()
        {
            if (actorActions.Actor == null)
            {
                tooltip.Visible = false;
                return;
            }

            var playertrait = actorActions.BamUi.World.RenderPlayer.PlayerActor.TraitOrDefault <Research>().Researchable;

            if (playertrait != null && !playertrait.Contains(actorString))
            {
                disabled = true;
            }
            else
            {
                disabled = false;
            }


            actorString = null;
            if (actorActions.Actor.Info.HasTraitInfo <ConvertAdjetantInfo>() && actorActions.Actor.TraitOrDefault <ConvertAdjetant>().TransformEnabler != null)
            {
                actorString = animationString;
            }

            actorInfo = actorActions.BamUi.World.Map.Rules.Actors[actorString];
            if (actorInfo != null && actorInfo.HasTraitInfo <RenderSpritesInfo>())
            {
                animation = new Animation(actorActions.BamUi.World, actorInfo.TraitInfo <RenderSpritesInfo>().GetImage
                                          (
                                              actorInfo,
                                              actorActions.BamUi.World.Map.Rules.Sequences,
                                              actorActions.Actor.Owner.Faction.Name
                                          ));
            }

            var x = pressed ? posx + 1 : posx;
            var y = pressed ? posy + 1 : posy;

            Bounds = new Rectangle(x, y, 75, 68);
        }
예제 #17
0
        public virtual void DoProduction(Actor self, ActorInfo producee, ExitInfo exitinfo, string productionType, TypeDictionary inits)
        {
            var exit          = CPos.Zero;
            var exitLocations = new List <CPos>();

            // Clone the initializer dictionary for the new actor
            var td = new TypeDictionary();

            foreach (var init in inits)
            {
                td.Add(init);
            }

            if (exitinfo != null && self.OccupiesSpace != null && producee.HasTraitInfo <IOccupySpaceInfo>())
            {
                exit = self.Location + exitinfo.ExitCell;
                var spawn = self.CenterPosition + exitinfo.SpawnOffset;
                var to    = self.World.Map.CenterOfCell(exit);

                WAngle initialFacing;
                if (!exitinfo.Facing.HasValue)
                {
                    var delta = to - spawn;
                    if (delta.HorizontalLengthSquared == 0)
                    {
                        var fi = producee.TraitInfoOrDefault <IFacingInfo>();
                        initialFacing = fi != null?fi.GetInitialFacing() : WAngle.Zero;
                    }
                    else
                    {
                        initialFacing = delta.Yaw;
                    }
                }
                else
                {
                    initialFacing = exitinfo.Facing.Value;
                }

                exitLocations = rp != null && rp.Path.Count > 0 ? rp.Path : new List <CPos> {
                    exit
                };

                td.Add(new LocationInit(exit));
                td.Add(new CenterPositionInit(spawn));
                td.Add(new FacingInit(initialFacing));
                if (exitinfo != null)
                {
                    td.Add(new CreationActivityDelayInit(exitinfo.ExitDelay));
                }
            }

            self.World.AddFrameEndTask(w =>
            {
                // Here we check if production should go into the cargo of a passenger and if so, if cargo trait exists and if there is space to do so
                if (info.ProduceIntoCargoOfCargo && self.TraitOrDefault <Cargo>() != null && self.TraitOrDefault <Cargo>().Passengers.Any(p => p.TraitOrDefault <Cargo>().HasSpace(producee.TraitInfo <PassengerInfo>().Weight)))
                {
                    var newUnit = self.World.CreateActor(false, producee.Name, td);

                    foreach (var p in self.TraitOrDefault <Cargo>().Passengers)
                    {
                        if (p.TraitOrDefault <Cargo>().HasSpace(producee.TraitInfo <PassengerInfo>().Weight))
                        {
                            p.TraitOrDefault <Cargo>().Load(p, newUnit);

                            if (!self.IsDead)
                            {
                                foreach (var t in self.TraitsImplementing <INotifyProduction>())
                                {
                                    t.UnitProduced(self, newUnit, exit);
                                }
                            }

                            var notifyOthers = self.World.ActorsWithTrait <INotifyOtherProduction>();
                            foreach (var notify in notifyOthers)
                            {
                                notify.Trait.UnitProducedByOther(notify.Actor, self, newUnit, productionType, td);
                            }

                            break;
                        }
                    }
                }
                // Here we check if production should go into the cargo of the producer and if so, if cargo trait exists and if there is space to do so
                else if (info.ProduceIntoCargo && self.TraitOrDefault <Cargo>() != null && self.TraitOrDefault <Cargo>().HasSpace(producee.TraitInfo <PassengerInfo>().Weight))
                {
                    var newUnit = self.World.CreateActor(false, producee.Name, td);

                    self.TraitOrDefault <Cargo>().Load(self, newUnit);

                    if (!self.IsDead)
                    {
                        foreach (var t in self.TraitsImplementing <INotifyProduction>())
                        {
                            t.UnitProduced(self, newUnit, exit);
                        }
                    }

                    var notifyOthers = self.World.ActorsWithTrait <INotifyOtherProduction>();
                    foreach (var notify in notifyOthers)
                    {
                        notify.Trait.UnitProducedByOther(notify.Actor, self, newUnit, productionType, td);
                    }
                }
                // this is actually the good old production
                else
                {
                    var newUnit = self.World.CreateActor(producee.Name, td);

                    var move = newUnit.TraitOrDefault <IMove>();
                    if (exitinfo != null && move != null)
                    {
                        foreach (var cell in exitLocations)
                        {
                            newUnit.QueueActivity(new AttackMoveActivity(newUnit,
                                                                         () => move.MoveTo(cell, 1, evaluateNearestMovableCell: true,
                                                                                           targetLineColor: Color.OrangeRed)));
                        }
                    }

                    if (!self.IsDead)
                    {
                        foreach (var t in self.TraitsImplementing <INotifyProduction>())
                        {
                            t.UnitProduced(self, newUnit, exit);
                        }
                    }

                    var notifyOthers = self.World.ActorsWithTrait <INotifyOtherProduction>();
                    foreach (var notify in notifyOthers)
                    {
                        notify.Trait.UnitProducedByOther(notify.Actor, self, newUnit, productionType, td);
                    }
                }
            });
        }
예제 #18
0
        public static bool IsCellBuildable(this World world, CPos cell, ActorInfo ai, BuildingInfo bi, Actor toIgnore = null)
        {
            if (!world.Map.Contains(cell))
            {
                return(false);
            }

            if (!bi.AllowInvalidPlacement)
            {
                // Replaceable actors are rare, so avoid initializing state unless we have to
                var checkReplacements = ai != null && ai.HasTraitInfo <ReplacementInfo>();
                HashSet <string> acceptedReplacements = null;

                var foundActors = false;
                foreach (var a in world.ActorMap.GetActorsAt(cell))
                {
                    if (a == toIgnore)
                    {
                        continue;
                    }

                    // If this is potentially a replacement actor we must check *all* cell occupants
                    // before we know the placement is invalid
                    // Otherwise, we can bail immediately
                    if (!checkReplacements)
                    {
                        return(false);
                    }

                    foundActors = true;
                    foreach (var r in a.TraitsImplementing <Replaceable>())
                    {
                        if (r.IsTraitDisabled)
                        {
                            continue;
                        }

                        if (acceptedReplacements == null)
                        {
                            acceptedReplacements = new HashSet <string>();
                        }

                        acceptedReplacements.UnionWith(r.Info.Types);
                    }
                }

                // Replacements are enabled and the cell contained at least one (not ignored) actor or building bib
                var foundBuilding = world.WorldActor.Trait <BuildingInfluence>().AnyBuildingAt(cell);
                if (foundActors || foundBuilding)
                {
                    // The cell contains at least one actor, and none were replaceable
                    if (acceptedReplacements == null)
                    {
                        return(false);
                    }

                    // The cell contains at least one replaceable actor, but not of the types we accept
                    var foundReplacement = ai.TraitInfos <ReplacementInfo>()
                                           .Any(r => r.ReplaceableTypes.Overlaps(acceptedReplacements));

                    if (!foundReplacement)
                    {
                        return(false);
                    }
                }
            }
            else
            {
                // HACK: To preserve legacy behaviour, AllowInvalidPlacement should display red placement indicators
                // if (and only if) there is a building or bib in the cell
                if (world.WorldActor.Trait <BuildingInfluence>().AnyBuildingAt(cell))
                {
                    return(false);
                }
            }

            // Buildings can never be placed on ramps
            return(world.Map.Ramp[cell] == 0 && bi.TerrainTypes.Contains(world.Map.GetTerrainInfo(cell).Type));
        }
예제 #19
0
        public virtual void DoProduction(Actor self, ActorInfo producee, ExitInfo exitinfo, string productionType, TypeDictionary inits)
        {
            var exit          = CPos.Zero;
            var exitLocations = new List <CPos>();

            // Clone the initializer dictionary for the new actor
            var td = new TypeDictionary();

            foreach (var init in inits)
            {
                td.Add(init);
            }

            if (exitinfo != null && self.OccupiesSpace != null && producee.HasTraitInfo <IOccupySpaceInfo>())
            {
                exit = self.Location + exitinfo.ExitCell;
                var spawn = self.CenterPosition + exitinfo.SpawnOffset;
                var to    = self.World.Map.CenterOfCell(exit);

                var initialFacing = exitinfo.Facing;
                if (exitinfo.Facing < 0)
                {
                    var delta = to - spawn;
                    if (delta.HorizontalLengthSquared == 0)
                    {
                        var fi = producee.TraitInfoOrDefault <IFacingInfo>();
                        initialFacing = fi != null?fi.GetInitialFacing() : 0;
                    }
                    else
                    {
                        initialFacing = delta.Yaw.Facing;
                    }
                }

                exitLocations = rp.Value != null && rp.Value.Path.Count > 0 ? rp.Value.Path : new List <CPos> {
                    exit
                };

                td.Add(new LocationInit(exit));
                td.Add(new CenterPositionInit(spawn));
                td.Add(new FacingInit(initialFacing));
                if (exitinfo != null)
                {
                    td.Add(new CreationActivityDelayInit(exitinfo.ExitDelay));
                }
            }

            self.World.AddFrameEndTask(w =>
            {
                var newUnit = self.World.CreateActor(producee.Name, td);

                var move = newUnit.TraitOrDefault <IMove>();
                if (exitinfo != null && move != null)
                {
                    foreach (var cell in exitLocations)
                    {
                        newUnit.QueueActivity(new AttackMoveActivity(newUnit, () => move.MoveTo(cell, 1, evaluateNearestMovableCell: true, targetLineColor: Color.OrangeRed)));
                    }
                }

                if (!self.IsDead)
                {
                    foreach (var t in self.TraitsImplementing <INotifyProduction>())
                    {
                        t.UnitProduced(self, newUnit, exit);
                    }
                }

                var notifyOthers = self.World.ActorsWithTrait <INotifyOtherProduction>();
                foreach (var notify in notifyOthers)
                {
                    notify.Trait.UnitProducedByOther(notify.Actor, self, newUnit, productionType, td);
                }
            });
        }
예제 #20
0
        public void SpawnDeliveryVehicle(Actor self, ActorInfo actorInfo, ExitInfo exitInfo, Actor returning)
        {
            var exit          = CPos.Zero;
            var exitLocations = new List <CPos>();

            var td = new TypeDictionary();

            if (exitInfo != null && self.OccupiesSpace != null && actorInfo.HasTraitInfo <IOccupySpaceInfo>())
            {
                exit = self.Location + exitInfo.ExitCell;
                var spawn = self.CenterPosition + exitInfo.SpawnOffset;
                var to    = self.World.Map.CenterOfCell(exit);

                WAngle initialFacing;
                if (!exitInfo.Facing.HasValue)
                {
                    var delta = to - spawn;
                    if (delta.HorizontalLengthSquared == 0)
                    {
                        var fi = actorInfo.TraitInfoOrDefault <IFacingInfo>();
                        initialFacing = fi != null?fi.GetInitialFacing() : WAngle.Zero;
                    }
                    else
                    {
                        initialFacing = delta.Yaw;
                    }
                }
                else
                {
                    initialFacing = exitInfo.Facing.Value;
                }

                exitLocations = rallyPoint.Value != null && rallyPoint.Value.Path.Count > 0 ? rallyPoint.Value.Path : new List <CPos> {
                    exit
                };

                td.Add(new LocationInit(exit));
                td.Add(new CenterPositionInit(spawn));
                td.Add(new FacingInit(initialFacing));
                td.Add(new OwnerInit(self.Owner));
                if (exitInfo != null)
                {
                    td.Add(new CreationActivityDelayInit(exitInfo.ExitDelay));
                }
            }

            self.World.AddFrameEndTask(w =>
            {
                var deliveryVehicle = self.World.CreateActor(actorInfo.Name, td);
                deliveryVehicle.Trait <ResourceTransporter>().LinkedCollector = returning;

                var move = deliveryVehicle.TraitOrDefault <IMove>();
                if (exitInfo != null && move != null)
                {
                    foreach (var cell in exitLocations)
                    {
                        deliveryVehicle.QueueActivity(new Move(deliveryVehicle, cell));
                    }
                }
            });
        }
예제 #21
0
        void Run(Action <string> emitError, Action <string> emitWarning, MapPlayers players, MapVisibility visibility, ActorInfo worldActorInfo, CPos[] spawnPoints)
        {
            if (players.Players.Count > 64)
            {
                emitError("Defining more than 64 players is not allowed.");
            }

            var worldOwnerFound = false;
            var playerNames     = players.Players.Values.Select(p => p.Name).ToHashSet();

            foreach (var player in players.Players.Values)
            {
                foreach (var ally in player.Allies)
                {
                    if (!playerNames.Contains(ally))
                    {
                        emitError("Allies contains player {0} that is not in list.".F(ally));
                    }
                }

                foreach (var enemy in player.Enemies)
                {
                    if (!playerNames.Contains(enemy))
                    {
                        emitError("Enemies contains player {0} that is not in list.".F(enemy));
                    }
                }

                if (player.OwnsWorld)
                {
                    worldOwnerFound = true;
                    if (player.Enemies.Any() || player.Allies.Any())
                    {
                        emitWarning("The player {0} owning the world should not have any allies or enemies.".F(player.Name));
                    }

                    if (player.Playable)
                    {
                        emitError("The player {0} owning the world can't be playable.".F(player.Name));
                    }
                }
                else if (visibility == MapVisibility.MissionSelector && player.Playable && !player.LockFaction)
                {
                    // Missions must lock the faction of the player to force the server to override the default Random faction
                    emitError("The player {0} must specify LockFaction: True.".F(player.Name));
                }
            }

            if (!worldOwnerFound)
            {
                emitError("Found no player owning the world.");
            }

            var factions = worldActorInfo.TraitInfos <FactionInfo>().Select(f => f.InternalName).ToHashSet();

            foreach (var player in players.Players.Values)
            {
                if (!string.IsNullOrWhiteSpace(player.Faction) && !factions.Contains(player.Faction))
                {
                    emitError("Invalid faction {0} chosen for player {1}.".F(player.Faction, player.Name));
                }
            }

            if (worldActorInfo.HasTraitInfo <MapStartingLocationsInfo>())
            {
                var playerCount = players.Players.Count(p => p.Value.Playable);
                if (playerCount > spawnPoints.Length)
                {
                    emitError("The map allows {0} possible players, but defines only {1} spawn points".F(playerCount, spawnPoints.Length));
                }

                if (spawnPoints.Distinct().Count() != spawnPoints.Length)
                {
                    emitError("Duplicate spawn point locations detected.");
                }
            }
        }
        public bool HandleMouseInput(MouseInput mi)
        {
            // Exclusively uses left and right mouse buttons, but nothing else
            if (mi.Button != MouseButton.Left && mi.Button != MouseButton.Right)
            {
                return(false);
            }

            if (mi.Button == MouseButton.Right)
            {
                if (mi.Event == MouseInputEvent.Up)
                {
                    editorWidget.ClearBrush();
                    return(true);
                }

                return(false);
            }

            var cell = worldRenderer.Viewport.ViewToWorld(mi.Location - worldRenderer.ScreenPxOffset(centerOffset));

            if (mi.Button == MouseButton.Left && mi.Event == MouseInputEvent.Down)
            {
                // Check the actor is inside the map
                if (!footprint.All(c => world.Map.Tiles.Contains(cell + c)))
                {
                    return(true);
                }

                var newActorReference = new ActorReference(Actor.Name);
                newActorReference.Add(new OwnerInit(owner.Name));

                newActorReference.Add(new LocationInit(cell));

                var ios = Actor.TraitInfoOrDefault <IOccupySpaceInfo>();
                if (ios != null && ios.SharesCell)
                {
                    var subcell = editorLayer.FreeSubCellAt(cell);
                    if (subcell != SubCell.Invalid)
                    {
                        newActorReference.Add(new SubCellInit(subcell));
                    }
                }

                var initDict = newActorReference.InitDict;

                if (Actor.HasTraitInfo <IFacingInfo>())
                {
                    initDict.Add(new FacingInit(facing));
                }

                if (Actor.HasTraitInfo <TurretedInfo>())
                {
                    initDict.Add(new TurretFacingInit(facing));
                }

                editorLayer.Add(newActorReference);
            }

            return(true);
        }
예제 #23
0
        public override void DoProduction(Actor self, ActorInfo producee, ExitInfo exitinfo, string factionVariant, TypeDictionary init)
        {
            var   exit         = CPos.Zero;
            var   exitLocation = CPos.Zero;
            var   target       = Target.Invalid;
            Actor respawner    = self;

            var bi = producee.TraitInfoOrDefault <BuildableInfo>();

            if (bi != null && bi.ForceFaction != null)
            {
                factionVariant = bi.ForceFaction;
            }

            var td = new TypeDictionary
            {
                new OwnerInit(self.Owner),
            };

            if (self.OccupiesSpace != null)
            {
                exit = self.Location + exitinfo.ExitCell;
                var spawn = self.CenterPosition + exitinfo.SpawnOffset;
                var to    = self.World.Map.CenterOfCell(exit);

                if (producee.HasTraitInfo <IPositionableInfo>())
                {
                    var cell = Util.RandomWalk(self.Location, self.World.SharedRandom)
                               .Take(2)
                               .SkipWhile(p => !producee.TraitInfo <IPositionableInfo>().CanEnterCell(self.World, self, p))
                               .Cast <CPos?>().FirstOrDefault();

                    if (cell != null)
                    {
                        spawn = self.World.Map.CenterOfCell(cell.Value);
                    }
                }
                else if (producee.HasTraitInfo <MobileInfo>())
                {
                    var cell = Util.RandomWalk(self.Location, self.World.SharedRandom)
                               .Take(2)
                               .SkipWhile(p => !producee.TraitInfo <MobileInfo>().CanEnterCell(self.World, self, p))
                               .Cast <CPos?>().FirstOrDefault();

                    if (cell != null)
                    {
                        spawn = self.World.Map.CenterOfCell(cell.Value);
                    }
                }

                var initialFacing = exitinfo.Facing;
                if (exitinfo.Facing < 0)
                {
                    var delta = to - spawn;
                    if (delta.HorizontalLengthSquared == 0)
                    {
                        var fi = producee.TraitInfoOrDefault <IFacingInfo>();
                        initialFacing = fi != null?fi.GetInitialFacing() : 0;
                    }
                    else
                    {
                        initialFacing = delta.Yaw.Facing;
                    }
                }

                exitLocation = rp.Value != null ? rp.Value.Location : exit;

                respawner = self;

                var validreplacespawner = self.World.ActorsHavingTrait <UndeadGiantSpawner>()
                                          .Where(a =>
                {
                    return(a.Owner == self.Owner && a.TraitOrDefault <UndeadGiantSpawner>().Canspawn);
                });
                if (validreplacespawner.Any())
                {
                    respawner = validreplacespawner.Random(self.World.SharedRandom);
                    exit      = respawner.Location + new CVec(respawner.Info.TraitInfo <UndeadGiantSpawnerInfo>().Exit.X, respawner.Info.TraitInfo <UndeadGiantSpawnerInfo>().Exit.Y);
                    spawn     = respawner.CenterPosition + new WVec(respawner.Info.TraitInfo <UndeadGiantSpawnerInfo>()
                                                                    .SpawnOffset.X, respawner.Info.TraitInfo <UndeadGiantSpawnerInfo>().SpawnOffset.Y, respawner.Info.TraitInfo <UndeadGiantSpawnerInfo>().SpawnOffset.Z);
                    exitLocation = respawner.TraitOrDefault <RallyPoint>().Location;
                }

                td.Add(new LocationInit(exit));
                td.Add(new CenterPositionInit(spawn));
                td.Add(new FacingInit(initialFacing));
                if (factionVariant != null)
                {
                    td.Add(new FactionInit(factionVariant));
                }
            }

            target = Target.FromCell(self.World, exitLocation);

            self.World.AddFrameEndTask(w =>
            {
                var newUnit = self.World.CreateActor(producee.Name, td);

                if (newUnit.Info.HasTraitInfo <WithMakeAnimationInfo>() && respawner == self)
                {
                    var move = newUnit.TraitOrDefault <IMove>();
                    if (move != null)
                    {
                        if (exitinfo.MoveIntoWorld)
                        {
                            if (exitinfo.ExitDelay > 0)
                            {
                                newUnit.QueueActivity(new Wait(exitinfo.ExitDelay, false));
                            }

                            newUnit.Trait <WithMakeAnimation>().Forward(newUnit, () =>
                            {
                                newUnit.QueueActivity(move.MoveIntoWorld(newUnit, exit));
                                newUnit.QueueActivity(new AttackMoveActivity(
                                                          newUnit, move.MoveTo(exitLocation, 1)));

                                newUnit.SetTargetLine(target, rp.Value != null ? Color.Red : Color.Green, false);

                                if (!self.IsDead)
                                {
                                    foreach (var t in self.TraitsImplementing <INotifyProduction>())
                                    {
                                        t.UnitProduced(self, newUnit, exit);
                                    }
                                }

                                var notifyOthers = self.World.ActorsWithTrait <INotifyOtherProduction>();
                                foreach (var notify in notifyOthers)
                                {
                                    notify.Trait.UnitProducedByOther(notify.Actor, self, newUnit, producee.Name);
                                }

                                foreach (var t in newUnit.TraitsImplementing <INotifyBuildComplete>())
                                {
                                    t.BuildingComplete(newUnit);
                                }
                            });
                        }
                    }
                }
                else if (respawner == self)
                {
                    var move = newUnit.TraitOrDefault <IMove>();
                    if (move != null)
                    {
                        if (exitinfo.MoveIntoWorld)
                        {
                            if (exitinfo.ExitDelay > 0)
                            {
                                newUnit.QueueActivity(new Wait(exitinfo.ExitDelay, false));
                            }

                            newUnit.Trait <WithMakeAnimation>().Forward(newUnit, () =>
                            {
                                newUnit.QueueActivity(move.MoveIntoWorld(newUnit, exit));
                                newUnit.QueueActivity(new AttackMoveActivity(
                                                          newUnit, move.MoveTo(exitLocation, 1)));
                            });
                        }
                    }

                    newUnit.SetTargetLine(target, rp.Value != null ? Color.Red : Color.Green, false);

                    if (!self.IsDead)
                    {
                        foreach (var t in self.TraitsImplementing <INotifyProduction>())
                        {
                            t.UnitProduced(self, newUnit, exit);
                        }
                    }

                    var notifyOthers = self.World.ActorsWithTrait <INotifyOtherProduction>();
                    foreach (var notify in notifyOthers)
                    {
                        notify.Trait.UnitProducedByOther(notify.Actor, self, newUnit, producee.Name);
                    }

                    foreach (var t in newUnit.TraitsImplementing <INotifyBuildComplete>())
                    {
                        t.BuildingComplete(newUnit);
                    }
                }
                else
                {
                    var move = newUnit.TraitOrDefault <IMove>();
                    newUnit.QueueActivity(move.MoveIntoWorld(newUnit, exit));
                    newUnit.QueueActivity(new AttackMoveActivity(
                                              newUnit, move.MoveTo(exitLocation, 1)));

                    newUnit.SetTargetLine(target, rp.Value != null ? Color.Red : Color.Green, false);

                    if (!self.IsDead)
                    {
                        foreach (var t in self.TraitsImplementing <INotifyProduction>())
                        {
                            t.UnitProduced(self, newUnit, exit);
                        }
                    }

                    var notifyOthers = self.World.ActorsWithTrait <INotifyOtherProduction>();
                    foreach (var notify in notifyOthers)
                    {
                        notify.Trait.UnitProducedByOther(notify.Actor, self, newUnit, producee.Name);
                    }

                    foreach (var t in newUnit.TraitsImplementing <INotifyBuildComplete>())
                    {
                        t.BuildingComplete(newUnit);
                    }

                    respawner.TraitOrDefault <UndeadGiantSpawner>().Reset();
                }
            });
        }
예제 #24
0
        public override bool Produce(Actor self, ActorInfo producee, string factionVariant)
        {
            var devMode = self.Owner.PlayerActor.TraitOrDefault <DeveloperMode>();

            if (devMode != null && devMode.FastBuild)
            {
                var newexit2 = self.Info.TraitInfos <ExitInfo>().FirstOrDefault();

                self.World.AddFrameEndTask(ww => DoProduction(self, producee, newexit2, factionVariant));
                Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", info.ReadyAudio,
                                            self.Owner.Faction.InternalName);
                return(true);
            }

            //basic setup of values
            var owner = self.Owner;
            var exit  = CPos.Zero;


            //find produced unit cost values
            var ValidActors = new HashSet <string>();;
            var Actorcount  = 1;

            var guysFound      = new HashSet <Actor>();
            var underWay       = 0;
            var alreadyReached = 0;

            //find enough actors
            if (producee.HasTraitInfo <PersonValuedInfo>())
            {
                var BuilderInfo = producee.TraitInfo <PersonValuedInfo>();
                ValidActors = BuilderInfo.ConvertingActors;
                Actorcount  = BuilderInfo.ActorCount;

                for (int i = 0; i < Actorcount; i++)
                {
                    var poss = PossibleActor(self, guysFound, ValidActors);
                    if (poss != null)
                    {
                        guysFound.Add(poss);
                    }
                }
            }
            else
            {
                var poss = PossibleActor(self, new  HashSet <Actor>(), new  HashSet <string>());
                if (poss != null)
                {
                    guysFound.Add(poss);
                }
            }



            //find exit cell and spawn locations
            var newexit = self.Info.TraitInfos <ExitInfo>().FirstOrDefault();

            exit = self.Location + newexit.ExitCell;
            var infiltrate = self.CenterPosition + newexit.SpawnOffset;

            if (guysFound.Count < Actorcount)
            {
                return(false);
            }

            if (Actorcount > 0)
            {
                foreach (var actor in guysFound)
                {
                    owner.World.AddFrameEndTask(w =>
                    {
                        //Actor is possible to move?
                        var move = actor.TraitOrDefault <IMove>();

                        if ((!actor.IsInWorld || !actor.IsDead))
                        {
                            //safe in array and set underway statement +1
                            InUse.Add(actor);

                            //beginn movement
                            actor.CancelActivity();
                            actor.QueueActivity(move.MoveTo(exit, 5));

                            //what happens when actor or barracks dies
                            actor.QueueActivity(new CallFunc(() =>
                            {
                                if (StillValid(actor, self))
                                {
                                    return;
                                }
                                //if not died continue and recalculate ow position

                                //visually enter the building
                                var selfposition = actor.CenterPosition;
                                //actor.QueueActivity(move.MoveIntoWorld(actor,exit));
                                actor.QueueActivity(move.VisualMove(actor, selfposition, infiltrate));
                                //if dead before finished
                                actor.QueueActivity(new CallFunc(() =>
                                {
                                    if (StillValid(actor, self))
                                    {
                                        return;
                                    }

                                    if (!self.IsInWorld || self.IsDead)
                                    {
                                        return;
                                    }
                                    //if not continue
                                    alreadyReached++;
                                    if (alreadyReached >= Actorcount)
                                    {
                                        self.World.AddFrameEndTask(ww => DoProduction(self, producee, newexit, factionVariant));
                                        Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", info.ReadyAudio,
                                                                    self.Owner.Faction.InternalName);
                                    }
                                }));
                                //set reached units state +1 and units in movement state -1
                                actor.QueueActivity(new RemoveSelf());                                 //of he goes
                            }));
                        }
                        //if not enough actors reached the barracks yet or died repeat
                    });
                }
            }
            else
            {
                self.World.AddFrameEndTask(ww => DoProduction(self, producee, newexit, factionVariant));
                Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", info.ReadyAudio,
                                            self.Owner.Faction.InternalName);
            }
            return(true);
        }
예제 #25
0
        public virtual void DoProduction(Actor self, ActorInfo producee, ExitInfo exitinfo, string productionType, TypeDictionary inits)
        {
            var exit         = CPos.Zero;
            var exitLocation = CPos.Zero;
            var target       = Target.Invalid;

            // Clone the initializer dictionary for the new actor
            var td = new TypeDictionary();

            foreach (var init in inits)
            {
                td.Add(init);
            }

            if (exitinfo != null && self.OccupiesSpace != null && producee.HasTraitInfo <IOccupySpaceInfo>())
            {
                exit = self.Location + exitinfo.ExitCell;
                var spawn = self.CenterPosition + exitinfo.SpawnOffset;
                var to    = self.World.Map.CenterOfCell(exit);

                var initialFacing = exitinfo.Facing;
                if (exitinfo.Facing < 0)
                {
                    var delta = to - spawn;
                    if (delta.HorizontalLengthSquared == 0)
                    {
                        var fi = producee.TraitInfoOrDefault <IFacingInfo>();
                        initialFacing = fi != null?fi.GetInitialFacing() : 0;
                    }
                    else
                    {
                        initialFacing = delta.Yaw.Facing;
                    }
                }

                exitLocation = rp.Value != null ? rp.Value.Location : exit;
                target       = Target.FromCell(self.World, exitLocation);

                td.Add(new LocationInit(exit));
                td.Add(new CenterPositionInit(spawn));
                td.Add(new FacingInit(initialFacing));
            }

            self.World.AddFrameEndTask(w =>
            {
                var newUnit = self.World.CreateActor(producee.Name, td);

                var move = newUnit.TraitOrDefault <IMove>();
                if (exitinfo != null && move != null)
                {
                    if (exitinfo.MoveIntoWorld)
                    {
                        if (exitinfo.ExitDelay > 0)
                        {
                            newUnit.QueueActivity(new Wait(exitinfo.ExitDelay, false));
                        }

                        newUnit.QueueActivity(move.MoveIntoWorld(newUnit, exit));
                        newUnit.QueueActivity(new AttackMoveActivity(newUnit, () => move.MoveTo(exitLocation, 1)));
                    }
                }

                newUnit.SetTargetLine(target, rp.Value != null ? Color.Red : Color.Green, false);

                if (!self.IsDead)
                {
                    foreach (var t in self.TraitsImplementing <INotifyProduction>())
                    {
                        t.UnitProduced(self, newUnit, exit);
                    }
                }

                var notifyOthers = self.World.ActorsWithTrait <INotifyOtherProduction>();
                foreach (var notify in notifyOthers)
                {
                    notify.Trait.UnitProducedByOther(notify.Actor, self, newUnit, productionType, td);
                }
            });
        }