Пример #1
0
        public void HandleReproduction()
        {
            if (CurrentTask.HasValue())
            {
                return;
            }
            if (!Creature.Stats.Species.CanReproduce)
            {
                return;
            }
            if (Creature.IsPregnant)
            {
                return;
            }
            if (!MathFunctions.RandEvent(0.0002f))
            {
                return;
            }

            CreatureAI closestMate = null;
            float      closestDist = float.MaxValue;

            foreach (var ai in Faction.Minions.Where(minion => minion != this && Mating.CanMate(minion.Creature, this.Creature)))
            {
                var dist = (ai.Position - Position).LengthSquared();
                if (!(dist < closestDist))
                {
                    continue;
                }
                closestDist = dist;
                closestMate = ai;
            }

            if (closestMate != null && closestDist < 30)
            {
                Tasks.Add(new MateTask(closestMate));
            }
        }
Пример #2
0
        public ResourceSet GenerateTradeItems(WorldManager world)
        {
            var toReturn = new ResourceSet();

            String[] blacklistTags = { "Money", "Corpse" };

            foreach (var tags in TradeGoods)
            {
                int num = MathFunctions.RandInt(tags.Value, tags.Value + 4);

                if (tags.Key == "Craft")
                {
                    for (int i = 0; i < num; i++)
                    {
                        MaybeNull <Resource> randResource = null;

                        if (tags.Key == "Craft")
                        {
                            var craftTag        = Datastructures.SelectRandom(Crafts);
                            var availableCrafts = Library.EnumerateResourceTypesWithTag(craftTag);
                            if (Library.CreateMetaResource("Trinket", null, new Resource("Trinket"), new List <Resource> {
                                new Resource(Datastructures.SelectRandom(availableCrafts))
                            }).HasValue(out var trinket))
                            {
                                if (MathFunctions.RandEvent(0.3f) && Encrustings.Count > 0)
                                {
                                    randResource = Library.CreateMetaResource("GemTrinket", null, new Resource("Gem-set Trinket"), new List <Resource>
                                    {
                                        trinket,
                                        new Resource(Datastructures.SelectRandom(Library.EnumerateResourceTypesWithTag(Datastructures.SelectRandom(Encrustings))))
                                    });
                                }
                                else
                                {
                                    randResource = trinket;
                                }
                            }
                        }

                        if (randResource.HasValue(out var res))
                        {
                            toReturn.Add(res);
                        }
                    }
                }
                else
                {
                    var resources = Library.EnumerateResourceTypesWithTag(tags.Key).Select(r => new Resource(r));
                    if (resources.Count() <= 0)
                    {
                        continue;
                    }

                    for (int i = 0; i < num; i++)
                    {
                        MaybeNull <Resource> randResource = Datastructures.SelectRandom(resources);

                        if (!randResource.HasValue(out var res) || !res.ResourceType.HasValue(out var resType) || resType.Tags.Any(blacklistTags.Contains))
                        {
                            continue;
                        }

                        if (randResource.HasValue(out res))
                        {
                            toReturn.Add(res);
                        }
                    }
                }
            }

            return(toReturn);
        }
Пример #3
0
        override public void Update(DwarfTime gameTime, ChunkManager chunks, Camera camera) 
        {
            base.Update(gameTime, chunks, camera);

            if (!Active)
                return;

            Creature.NoiseMaker.BasePitch = Stats.VoicePitch;

            // Non-dwarves are always at full energy.
            Stats.Energy.CurrentValue = 100.0f;

            AutoGatherTimer.Update(gameTime);

            if (AutoGatherTimer.HasTriggered)
            {
                if (!String.IsNullOrEmpty(Faction.Race.BecomeWhenEvil) && MathFunctions.RandEvent(0.01f))
                {
                    Faction.Minions.Remove(this);
                    Faction = World.Factions.Factions[Faction.Race.BecomeWhenEvil];
                    Faction.AddMinion(this);
                }
                else if (!String.IsNullOrEmpty(Faction.Race.BecomeWhenNotEvil) && MathFunctions.RandEvent(0.01f))
                {
                    Faction.Minions.Remove(this);
                    Faction = World.Factions.Factions[Faction.Race.BecomeWhenNotEvil];
                    Faction.AddMinion(this);
                }

                foreach (var body in World.EnumerateIntersectingObjects(Physics.BoundingBox.Expand(3.0f)).OfType<ResourceEntity>().Where(r => r.Active && r.AnimationQueue.Count == 0))
                {
                    var resource = Library.GetResourceType(body.Resource.Type);
                    if (resource.Tags.Contains(Resource.ResourceTags.Edible))
                    {
                        if ((Faction.Race.EatsMeat && resource.Tags.Contains(Resource.ResourceTags.AnimalProduct)) ||
                            (Faction.Race.EatsPlants && !resource.Tags.Contains(Resource.ResourceTags.AnimalProduct)))
                        {
                            Creature.GatherImmediately(body);
                            AssignTask(new ActWrapperTask(new EatFoodAct(this, false)));
                        }
                    }
                }

                OrderEnemyAttack();
            }

            DeleteBadTasks();
            PreEmptTasks();
            HandleReproduction();

            // Try to find food if we are hungry. Wait - doesn't this rob the player?
            if (Stats.Hunger.IsDissatisfied() && World.CountResourcesWithTag(Resource.ResourceTags.Edible) > 0)
            {
                Task toReturn = new SatisfyHungerTask();
                if (Stats.Hunger.IsCritical())
                    toReturn.Priority = TaskPriority.Urgent;
                if (!Tasks.Contains(toReturn) && CurrentTask != toReturn)
                    AssignTask(toReturn);
            }

            if (CurrentTask == null) // We need something to do.
            {
                    var goal = GetEasiestTask(Tasks);

                    if (goal != null)
                        ChangeTask(goal);
                    else
                    {
                        var newTask = ActOnIdle();
                        if (newTask != null)
                            ChangeTask(newTask);
                    }
            }
            else
            {
                if (!CurrentAct.HasValue()) // Should be impossible to have a current task and no current act.
                {
                    // Try and recover the correct act.
                    // <blecki> I always run with a breakpoint set here... just in case.
                    ChangeAct(CurrentTask.CreateScript(Creature));

                    // This is a bad situation!
                    if (!CurrentAct.HasValue())
                        ChangeTask(null);
                }

                if (CurrentAct.HasValue(out Act currentAct))
                {
                    var status = currentAct.Tick();
                    bool retried = false;

                    if (CurrentAct.HasValue(out Act newCurrentAct) && CurrentTask != null)
                    {
                        if (status == Act.Status.Fail)
                        {
                            LastFailedAct = newCurrentAct.Name;

                            if (!FailedTasks.Any(task => task.TaskFailure.Equals(CurrentTask)))
                                FailedTasks.Add(new FailedTask() { TaskFailure = CurrentTask, FailedTime = World.Time.CurrentDate });

                            if (CurrentTask.ShouldRetry(Creature))
                                if (!Tasks.Contains(CurrentTask))
                                {
                                    ReassignCurrentTask();
                                    retried = true;
                                }
                        }
                    }

                    if (CurrentTask != null && CurrentTask.IsComplete(World))
                        ChangeTask(null);
                    else if (status != Act.Status.Running && !retried)
                        ChangeTask(null);
                }
            }

            // With a small probability, the creature will drown if its under water.
            if (MathFunctions.RandEvent(GameSettings.Default.DrownChance))
            {
                var above = VoxelHelpers.GetVoxelAbove(Physics.CurrentVoxel);
                var below = VoxelHelpers.GetVoxelBelow(Physics.CurrentVoxel);
                bool shouldDrown = (above.IsValid && (!above.IsEmpty || above.LiquidLevel > 0));
                if ((Physics.IsInLiquid || (!Movement.CanSwim && (below.IsValid && (below.LiquidLevel > 5)))) 
                    && (!Movement.CanSwim || shouldDrown))
                    Creature.Damage(Movement.CanSwim ? 1.0f : 30.0f, Health.DamageType.Normal);
            }

            if (PositionConstraint.Contains(Physics.LocalPosition) == ContainmentType.Disjoint)
            {
                Physics.LocalPosition = MathFunctions.Clamp(Physics.Position, PositionConstraint);
                Physics.PropogateTransforms();
            }
        }