Ejemplo n.º 1
0
        public IEnumerable <Status> FarmATile()
        {
            if (FarmToWork == null)
            {
                yield return(Status.Fail);

                yield break;
            }
            else if (FarmToWork.Finished)
            {
                yield return(Status.Success);
            }
            else
            {
                Creature.CurrentCharacterMode = Creature.Stats.CurrentClass.AttackMode;
                Creature.Sprite.ResetAnimations(Creature.Stats.CurrentClass.AttackMode);
                Creature.Sprite.PlayAnimations(Creature.Stats.CurrentClass.AttackMode);
                while (FarmToWork.Progress < FarmToWork.TargetProgress && !FarmToWork.Finished)
                {
                    Creature.Physics.Velocity *= 0.1f;
                    FarmToWork.Progress       += 3 * Creature.Stats.BaseFarmSpeed * DwarfTime.Dt;

                    Drawer2D.DrawLoadBar(Agent.Manager.World.Renderer.Camera, Agent.Position + Vector3.Up, Color.LightGreen, Color.Black, 64, 4,
                                         FarmToWork.Progress / FarmToWork.TargetProgress);

                    if (FarmToWork.Progress >= (FarmToWork.TargetProgress * 0.5f) && FarmToWork.Voxel.Type.Name != "TilledSoil")
                    {
                        FarmToWork.Voxel.Type = Library.GetVoxelType("TilledSoil");
                    }

                    if (FarmToWork.Progress >= FarmToWork.TargetProgress && !FarmToWork.Finished)
                    {
                        var plant = EntityFactory.CreateEntity <Plant>(
                            Library.GetResourceType(FarmToWork.SeedString).PlantToGenerate,
                            FarmToWork.Voxel.WorldPosition + new Vector3(0.5f, 1.0f, 0.5f));

                        plant.Farm = FarmToWork;

                        Matrix original = plant.LocalTransform;
                        original.Translation += Vector3.Down;
                        plant.AnimationQueue.Add(new EaseMotion(0.5f, original, plant.LocalTransform.Translation));

                        Creature.Manager.World.ParticleManager.Trigger("puff", original.Translation, Color.White, 20);

                        SoundManager.PlaySound(ContentPaths.Audio.Oscar.sfx_env_plant_grow, FarmToWork.Voxel.WorldPosition, true);

                        FarmToWork.Finished = true;

                        DestroyResources();
                    }

                    if (MathFunctions.RandEvent(0.01f))
                    {
                        Creature.Manager.World.ParticleManager.Trigger("dirt_particle", Creature.AI.Position, Color.White, 1);
                    }
                    yield return(Status.Running);

                    Creature.Sprite.ReloopAnimations(Creature.Stats.CurrentClass.AttackMode);
                }

                Creature.CurrentCharacterMode = CharacterMode.Idle;
                Creature.AddThought("I farmed something!", new TimeSpan(0, 4, 0, 0), 1.0f);
                Creature.AI.AddXP(1);
                Creature.Sprite.PauseAnimations(Creature.Stats.CurrentClass.AttackMode);
                yield return(Status.Success);
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Called every frame
        /// </summary>
        /// <param name="gameTime">The current time</param>
        public void Update(DwarfTime gameTime)
        {
            #region Fast Forward To Day
            if (FastForwardToDay)
            {
                if (Time.IsDay())
                {
                    FastForwardToDay = false;
                    foreach (CreatureAI minion in PlayerFaction.Minions)
                    {
                        minion.Stats.Energy.CurrentValue = minion.Stats.Energy.MaxValue;
                    }
                    Time.Speed = 100;
                }
                else
                {
                    Time.Speed = 1000;
                }
            }
            #endregion

            IndicatorManager.Update(gameTime);
            HandleAmbientSound();
            UpdateOrphanedTasks();

            TaskManager.Update(PlayerFaction.Minions);

            //if (Paused)
            //    Renderer.Camera.LastWheel = Mouse.GetState().ScrollWheelValue;

            // Should we display the out of food message?
            checkFoodTimer.Update(gameTime);
            if (checkFoodTimer.HasTriggered)
            {
                var food = CountResourcesWithTag(Resource.ResourceTags.Edible);
                if (food == 0)
                {
                    MakeAnnouncement("We're out of food!", null, () => { return(CountResourcesWithTag(Resource.ResourceTags.Edible) == 0); });
                }
            }

            GamblingState.Update(gameTime);
            EventScheduler.Update(this, Time.CurrentDate);

            Time.Update(gameTime);

            if (Paused)
            {
                ComponentManager.UpdatePaused(gameTime, ChunkManager, Renderer.Camera);
                TutorialManager.Update(UserInterface.Gui);
            }
            // If not paused, we want to just update the rest of the game.
            else
            {
                ParticleManager.Update(gameTime, this);
                TutorialManager.Update(UserInterface.Gui);

                foreach (var updateSystem in UpdateSystems)
                {
                    try
                    {
                        updateSystem.Update(gameTime);
                    }
                    catch (Exception) { }
                }

                UpdateZones(gameTime);

                #region Mourn dead minions
                if (PlayerFaction.Minions.Any(m => m.IsDead))
                {
                    foreach (var minion in PlayerFaction.Minions)
                    {
                        minion.Creature.AddThought("A friend died recently.", new TimeSpan(2, 0, 0, 0), -25.0f);

                        if (!minion.IsDead)
                        {
                            continue;
                        }

                        MakeAnnouncement(String.Format("{0} ({1}) died!", minion.Stats.FullName, minion.Stats.CurrentClass.Name));
                        SoundManager.PlaySound(ContentPaths.Audio.Oscar.sfx_gui_negative_generic);
                        Tutorial("death");
                    }
                }
                #endregion

                #region Free stuck minions
                foreach (var minion in PlayerFaction.Minions)
                {
                    if (minion == null)
                    {
                        throw new InvalidProgramException("Null minion?");
                    }
                    if (minion.Stats == null)
                    {
                        throw new InvalidProgramException("Minion has null status?");
                    }

                    if (minion.Stats.IsAsleep)
                    {
                        continue;
                    }

                    if (minion.CurrentTask == null)
                    {
                        continue;
                    }

                    if (minion.Stats.IsTaskAllowed(TaskCategory.Dig))
                    {
                        minion.Movement.SetCan(MoveType.Dig, GameSettings.Default.AllowAutoDigging);
                    }

                    minion.ResetPositionConstraint();
                }
                #endregion

                foreach (var body in PlayerFaction.OwnedObjects)
                {
                    if (body.ReservedFor != null && body.ReservedFor.IsDead)
                    {
                        body.ReservedFor = null;
                    }
                }

                #region Manage selection circles
                PersistentData.SelectedMinions.RemoveAll(m => m.IsDead);

                foreach (var m in PlayerFaction.Minions)
                {
                    if (m.GetRoot().GetComponent <SelectionCircle>().HasValue(out var selectionCircle))
                    {
                        selectionCircle.SetFlagRecursive(GameComponent.Flag.Visible, false);
                    }

                    m.Creature.Sprite.DrawSilhouette = false;
                }
                ;

                foreach (var creature in PersistentData.SelectedMinions)
                {
                    if (creature.GetRoot().GetComponent <SelectionCircle>().HasValue(out var selectionCircle))
                    {
                        selectionCircle.SetFlag(GameComponent.Flag.ShouldSerialize, false);
                        selectionCircle.SetFlagRecursive(GameComponent.Flag.Visible, true);
                    }
                    else
                    {
                        selectionCircle = creature.GetRoot().AddChild(new SelectionCircle(creature.Manager)) as SelectionCircle;
                        selectionCircle.SetFlag(GameComponent.Flag.ShouldSerialize, false);
                        selectionCircle.SetFlagRecursive(GameComponent.Flag.Visible, true);
                    }

                    creature.Creature.Sprite.DrawSilhouette = true;
                }
                #endregion

                PersistentData.Designations.CleanupDesignations();

                Factions.Update(gameTime);

                foreach (var applicant in PersistentData.NewArrivals)
                {
                    if (Time.CurrentDate >= applicant.ArrivalTime)
                    {
                        HireImmediately(applicant.Applicant);
                    }
                }

                PersistentData.NewArrivals.RemoveAll(a => Time.CurrentDate >= a.ArrivalTime);



                ComponentManager.Update(gameTime, ChunkManager, Renderer.Camera);
                MonsterSpawner.Update(gameTime);
                bool allAsleep = AreAllEmployeesAsleep();

#if !UPTIME_TEST
                if (SleepPrompt == null && allAsleep && !FastForwardToDay && Time.IsNight()) // Todo: Kill?
                {
                    SleepPrompt = new QueuedAnnouncement()
                    {
                        Text        = "All your employees are asleep. Click here to skip to day.",
                        ClickAction = (sender, args) =>
                        {
                            FastForwardToDay = true;
                            SleepPrompt      = null;
                        },
                        ShouldKeep = () =>
                        {
                            return(FastForwardToDay == false && Time.IsNight() && AreAllEmployeesAsleep());
                        }
                    };
                    MakeAnnouncement(SleepPrompt);
                }
                else if (!allAsleep)
                {
                    Time.Speed       = 100;
                    FastForwardToDay = false;
                    SleepPrompt      = null;
                }
#endif
            }

            // These things are updated even when the game is paused

            Splasher.Splash(gameTime, ChunkManager.Water.GetSplashQueue());

            ChunkManager.Update(gameTime, Renderer.Camera, GraphicsDevice);
            SoundManager.Update(gameTime, Renderer.Camera, Time);
            Weather.Update(this.Time.CurrentDate, this);

#if DEBUG
            KeyboardState k = Keyboard.GetState();
            if (k.IsKeyDown(Keys.Home))
            {
                try
                {
                    GameState.Game.GraphicsDevice.Reset();
                }
                catch (Exception exception)
                {
                }
            }
#endif

            if (Time.CurrentDate.Hour != _prevHour)
            {
                TrackStats();
            }
            _prevHour = Time.CurrentDate.Hour;
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Hook called after PreUpdate but does not chain down to the trackers.
        /// Used to handle keyboard input and other global state changes.
        /// </summary>
        public void Update()
        {
            KeyboardState keyboard = Keyboard.GetState();

            if (keyboard.IsKeyDown(ControlSettings.Mappings.DebugVisualizationToggle))
            {
                DebugVisualizationKeyPressed = true;
            }
            else if (DebugVisualizationKeyPressed)
            {
                SoundManager.PlaySound(ContentPaths.Audio.pick, .15f);
                DebugVisualizationEnabled    = !DebugVisualizationEnabled;
                DebugVisualizationKeyPressed = false;
            }

            if (keyboard.IsKeyDown(ControlSettings.Mappings.TogglePerformanceOverlay))
            {
                if (!overlayKeyPressed)
                {
                    overlayKeyPressed = true;
                }
            }
            else
            {
                if (overlayKeyPressed)
                {
                    SoundManager.PlaySound(ContentPaths.Audio.pick, .15f);
                    GameSettings.Default.DrawDebugData = !GameSettings.Default.DrawDebugData;
                    FirstFrameAfterShown = GameSettings.Default.DrawDebugData;
                    overlayKeyPressed    = false;
                }
            }

            if (keyboard.IsKeyDown(ControlSettings.Mappings.DebugToggle1))
            {
                if (!debug1ToggleKeyPressed)
                {
                    debug1ToggleKeyPressed = true;
                }
            }
            else
            {
                if (debug1ToggleKeyPressed)
                {
                    SoundManager.PlaySound(ContentPaths.Audio.pick, .15f);
                    DebugToggle1           = !DebugToggle1;
                    debug1ToggleKeyPressed = false;
                }
            }

            if (keyboard.IsKeyDown(ControlSettings.Mappings.DebugToggle2))
            {
                if (!debug2ToggleKeyPressed)
                {
                    debug2ToggleKeyPressed = true;
                }
            }
            else
            {
                if (debug2ToggleKeyPressed)
                {
                    SoundManager.PlaySound(ContentPaths.Audio.pick, .15f);
                    DebugToggle2           = !DebugToggle2;
                    debug2ToggleKeyPressed = false;
                }
            }
        }
Ejemplo n.º 4
0
        public override IEnumerable <Act.Status> Run()
        {
            if (Spell.IsResearched)
            {
                Creature.CurrentCharacterMode  = CharacterMode.Idle;
                Creature.OverrideCharacterMode = false;
                yield return(Status.Success);

                yield break;
            }
            Timer   starParitcle  = new Timer(0.5f, false);
            float   totalResearch = 0.0f;
            Sound3D sound         = null;

            while (!Spell.IsResearched)
            {
                Creature.CurrentCharacterMode  = Creature.AttackMode;
                Creature.OverrideCharacterMode = true;
                Creature.Sprite.ReloopAnimations(Creature.AttackMode);
                float research = Creature.Stats.BuffedInt * 0.25f * DwarfTime.Dt;
                Spell.ResearchProgress    += research;
                totalResearch             += research;
                Creature.Physics.Velocity *= 0;
                Drawer2D.DrawLoadBar(Creature.World.Camera, Creature.Physics.Position, Color.Cyan, Color.Black, 64, 4, Spell.ResearchProgress / Spell.ResearchTime);
                if ((int)totalResearch > 0)
                {
                    if (sound == null || sound.EffectInstance.IsDisposed || sound.EffectInstance.State == SoundState.Stopped)
                    {
                        sound = SoundManager.PlaySound(ContentPaths.Audio.Oscar.sfx_ic_dwarf_magic_research,
                                                       Creature.AI.Position,
                                                       true);
                    }
                    //SoundManager.PlaySound(ContentPaths.Audio.tinkle, Creature.AI.Position, true);
                    Creature.AI.AddXP((int)(totalResearch));
                    totalResearch = 0.0f;
                }

                if (Spell.ResearchProgress >= Spell.ResearchTime)
                {
                    Creature.Manager.World.MakeAnnouncement(
                        new Gui.Widgets.QueuedAnnouncement
                    {
                        Text = String.Format("{0} ({1}) discovered the {2} spell!",
                                             Creature.Stats.FullName,
                                             Creature.Stats.CurrentLevel.Name, Spell.Spell.Name),
                        ClickAction = (gui, sender) => Agent.ZoomToMe()
                    });

                    SoundManager.PlaySound(ContentPaths.Audio.Oscar.sfx_gui_positive_generic, 0.15f);
                }

                starParitcle.Update(DwarfTime.LastTime);
                if (starParitcle.HasTriggered)
                {
                    Creature.Manager.World.ParticleManager.Trigger("star_particle", Creature.AI.Position, Color.White, 3);
                }
                yield return(Status.Running);
            }

            if (sound != null)
            {
                sound.Stop();
            }
            Creature.AddThought(Thought.ThoughtType.Researched);
            Creature.OverrideCharacterMode = false;
            Creature.CurrentCharacterMode  = CharacterMode.Idle;
            yield return(Status.Success);

            yield break;
        }
Ejemplo n.º 5
0
        override public void Update(DwarfTime gameTime, ChunkManager chunks, Camera camera)
        {
            //base.Update(gameTime, chunks, camera);

            if (!Active)
            {
                return;
            }
            Creature.NoiseMaker.BasePitch = Stats.VoicePitch;

            AutoGatherTimer.Update(gameTime);
            IdleTimer.Update(gameTime);
            SpeakTimer.Update(gameTime);

            if (AutoGatherTimer.HasTriggered)
            {
                foreach (var body in World.EnumerateIntersectingObjects(Physics.BoundingBox.Expand(3.0f)).OfType <ResourceEntity>().Where(r => r.Active && r.AnimationQueue.Count == 0))
                {
                    Creature.GatherImmediately(body, Inventory.RestockType.RestockResource);
                }

                OrderEnemyAttack();
            }

            DeleteBadTasks();
            PreEmptTasks();

            if (CurrentTask != null)
            {
                Stats.Boredom.CurrentValue -= (float)(CurrentTask.BoredomIncrease * gameTime.ElapsedGameTime.TotalSeconds);
                if (Stats.Boredom.IsCritical())
                {
                    Creature.AddThought("I have been overworked recently.", new TimeSpan(0, 4, 0, 0), -2.0f);
                }

                Stats.Energy.CurrentValue += (float)(CurrentTask.EnergyDecrease * gameTime.ElapsedGameTime.TotalSeconds);
            }

            // Heal thyself
            if (Stats.Health.IsDissatisfied())
            {
                Task toReturn = new GetHealedTask();
                if (!Tasks.Contains(toReturn) && CurrentTask != toReturn)
                {
                    AssignTask(toReturn);
                }
            }

            // Try to go to sleep if we are low on energy and it is night time.
            if (Stats.Energy.IsCritical())
            {
                Task toReturn = new SatisfyTirednessTask();
                if (!Tasks.Contains(toReturn) && CurrentTask != toReturn)
                {
                    AssignTask(toReturn);
                }
            }

            // Try to find food if we are hungry.
            if (Stats.Hunger.IsDissatisfied() && World.CountResourcesWithTag(Resource.ResourceTags.Edible) > 0)
            {
                Task toReturn = new SatisfyHungerTask()
                {
                    MustPay = true
                };
                if (Stats.Hunger.IsCritical())
                {
                    toReturn.Priority = TaskPriority.Urgent;
                }
                if (!Tasks.Contains(toReturn) && CurrentTask != toReturn)
                {
                    AssignTask(toReturn);
                }
            }

            if (Stats.Boredom.IsDissatisfied())
            {
                if (!Tasks.Any(task => task.BoredomIncrease < 0))
                {
                    Task toReturn = SatisfyBoredom();
                    if (toReturn != null && !Tasks.Contains(toReturn) && CurrentTask != toReturn)
                    {
                        AssignTask(toReturn);
                    }
                }
            }

            restockTimer.Update(DwarfTime.LastTime);
            if (restockTimer.HasTriggered && Creature.Inventory.Resources.Count > 10)
            {
                Creature.RestockAllImmediately();
            }

            if (CurrentTask == null)               // We need something to do.
            {
                if (Stats.Happiness.IsSatisfied()) // We're happy, so make sure we aren't on strike.
                {
                    Stats.IsOnStrike = false;
                    UnhappinessTime  = 0.0f;
                }

                if (Stats.IsOnStrike) // We're on strike, so track how long this job has sucked.
                {
                    UnhappinessTime += gameTime.ElapsedGameTime.TotalMinutes;
                    if (UnhappinessTime > GameSettings.Default.HoursUnhappyBeforeQuitting) // If we've been unhappy long enough, quit.
                    {
                        var thoughts = GetRoot().GetComponent <DwarfThoughts>();
                        Manager.World.MakeAnnouncement( // Can't use a popup because the dwarf will soon not exist. Also - this is a serious event!
                            Message: String.Format("{0} has quit!{1}",
                                                   Stats.FullName,
                                                   (thoughts == null ? "" : (" The last straw: " + thoughts.Thoughts.Last(t => t.HappinessModifier < 0.0f).Description))),
                            ClickAction: null,
                            logEvent: true,
                            eventDetails: (thoughts == null ? "So sick of this place!" : String.Join("\n", thoughts.Thoughts.Where(t => t.HappinessModifier < 0.0f).Select(t => t.Description)))
                            );

                        LeaveWorld();

                        GetRoot().GetComponent <Inventory>().Die();
                        GetRoot().GetComponent <SelectionCircle>().Die();

                        if (thoughts != null)
                        {
                            thoughts.Thoughts.Clear();
                        }

                        Faction.Minions.Remove(this);
                        World.PersistentData.SelectedMinions.Remove(this);

                        return;
                    }
                }
                else if (Stats.Happiness.IsDissatisfied()) // We aren't on strike, but we hate this place.
                {
                    if (MathFunctions.Rand(0, 1) < 0.25f)  // We hate it so much that we might just go on strike! This can probably be tweaked. As it stands,
                                                           // dorfs go on strike almost immediately every time.
                    {
                        Manager.World.UserInterface.MakeWorldPopup(String.Format("{0} ({1}) refuses to work!",
                                                                                 Stats.FullName, Stats.CurrentClass.Name), Creature.Physics, -10, 10);
                        Manager.World.Tutorial("happiness");
                        SoundManager.PlaySound(ContentPaths.Audio.Oscar.sfx_gui_negative_generic, 0.25f);
                        Stats.IsOnStrike = true;
                    }
                }

                if (!Stats.IsOnStrike) // We aren't on strike, so find a new task.
                {
                    var goal = GetEasiestTask(Tasks);
                    if (goal == null)
                    {
                        goal = World.TaskManager.GetBestTask(this);
                    }

                    if (goal != null)
                    {
                        IdleTimer.Reset(IdleTimer.TargetTimeSeconds);
                        ChangeTask(goal);
                    }
                    else
                    {
                        var newTask = ActOnIdle();
                        if (newTask != null)
                        {
                            ChangeTask(newTask);
                        }
                    }
                }
                else
                {
                    ChangeTask(ActOnIdle());
                }
            }
            else
            {
                if (CurrentAct == null) // 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 == null)
                    {
                        ChangeTask(null);
                    }
                }

                if (CurrentAct != null)
                {
                    var  status  = CurrentAct.Tick();
                    bool retried = false;
                    if (CurrentAct != null && CurrentTask != null)
                    {
                        if (status == Act.Status.Fail)
                        {
                            LastFailedAct = CurrentAct.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(0.01f))
            {
                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();
            }
        }
Ejemplo n.º 6
0
        override public void Update(DwarfTime gameTime, ChunkManager chunks, Camera camera)
        {
            base.Update(gameTime, chunks, camera);

            if (Active)
            {
                DeathTimer.Update(gameTime);

                switch (_state)
                {
                case State.Initializing:
                    if (PrepThread != null)
                    {
                        PrepThread.Abort();
                    }
                    PrepThread = new Thread(PrepareForExplosion)
                    {
                        IsBackground = true
                    };
                    _state = State.Prep;
                    PrepThread.Start();

                    foreach (GameComponent body in Manager.World.EnumerateIntersectingObjects(
                                 new BoundingBox(LocalPosition - new Vector3(VoxelRadius * 2.0f, VoxelRadius * 2.0f, VoxelRadius * 2.0f), LocalPosition + new Vector3(VoxelRadius * 2.0f, VoxelRadius * 2.0f, VoxelRadius * 2.0f)), CollisionType.Both))
                    {
                        var distance = (body.Position - LocalPosition).Length();
                        if (distance < (VoxelRadius * 2.0f))
                        {
                            var creature = body.EnumerateAll().OfType <CreatureAI>().FirstOrDefault();
                            if (creature != null)
                            {
                                creature.ChangeTask(new FleeEntityTask(this, VoxelRadius * 2));
                            }
                        }
                    }

                    break;

                case State.Prep:
                    if (PrepThread == null)     // Must have been saved mid-prep.
                    {
                        _state = State.Initializing;
                    }
                    break;

                case State.Ready:
                    if (OrderedExplosionList == null)     // Just a failsafe.
                    {
                        throw new InvalidOperationException();
                    }

                    float timeLeft  = (float)(DeathTimer.TargetTimeSeconds - DeathTimer.CurrentTimeSeconds);
                    float pulseRate = 15 - 2 * timeLeft;
                    float pulse     = (float)Math.Sin(timeLeft * pulseRate);
                    this.SetVertexColorRecursive(new Color(1.0f, 1.0f - pulse * pulse, 1.0f - pulse * pulse, 1.0f));
                    if (DeathTimer.HasTriggered)
                    {
                        _state = State.Exploding;
                        Manager.World.ParticleManager.Effects["explode"].Trigger(10, Position, Color.White);
                        SoundManager.PlaySound(ContentPaths.Audio.Oscar.sfx_trap_destroyed, 0.5f);

                        foreach (GameComponent body in Manager.World.EnumerateIntersectingObjects(
                                     new BoundingBox(LocalPosition - new Vector3(VoxelRadius * 2.0f, VoxelRadius * 2.0f, VoxelRadius * 2.0f), LocalPosition + new Vector3(VoxelRadius * 2.0f, VoxelRadius * 2.0f, VoxelRadius * 2.0f)), CollisionType.Both))
                        {
                            var distance = (body.Position - LocalPosition).Length();
                            if (distance <= (VoxelRadius * 2.0f))
                            {
                                var health = body.EnumerateAll().OfType <Health>().FirstOrDefault();
                                if (health != null)
                                {
                                    health.Damage(DamageAmount * (1.0f - (distance / (VoxelRadius * 2.0f))));     // Linear fall off on damage.
                                }
                            }
                        }
                    }

                    break;

                case State.Exploding:
                    SetFlagRecursive(Flag.Visible, false);
                    if (OrderedExplosionList == null)
                    {
                        throw new InvalidOperationException();
                    }

                    var voxelsExploded = 0;
                    while (true)
                    {
                        if (voxelsExploded >= VoxelsPerTick)
                        {
                            break;
                        }

                        if (ExplosionProgress >= OrderedExplosionList.Count)
                        {
                            GetRoot().Delete();
                            _state = State.Done;
                            foreach (var vox in OrderedExplosionList)
                            {
                                if (!vox.IsValid)
                                {
                                    continue;
                                }
                                var under = VoxelHelpers.GetVoxelBelow(vox);
                                if (under.IsValid && !under.IsEmpty && MathFunctions.RandEvent(0.5f))
                                {
                                    EntityFactory.CreateEntity <Fire>("Fire", vox.GetBoundingBox().Center());
                                }
                            }
                            break;
                        }

                        var nextVoxel = OrderedExplosionList[ExplosionProgress];
                        ExplosionProgress += 1;

                        if (nextVoxel.IsValid)
                        {
                            if (!nextVoxel.Type.IsInvincible && !nextVoxel.IsEmpty)
                            {
                                voxelsExploded += 1;
                                nextVoxel.Type  = Library.EmptyVoxelType;
                                Manager.World.ParticleManager.Effects["explode"].Trigger(1, nextVoxel.Coordinate.ToVector3() + new Vector3(0.5f, 0.5f, 0.5f), Color.White);
                                Manager.World.ParticleManager.Effects["dirt_particle"].Trigger(3, nextVoxel.Coordinate.ToVector3() + new Vector3(0.5f, 0.5f, 0.5f), Color.White);

                                Manager.World.OnVoxelDestroyed(nextVoxel);
                            }
                        }
                    }

                    break;

                case State.Done:
                default:
                    if (PrepThread != null)
                    {
                        PrepThread.Abort();
                    }
                    break;
                }
            }
        }
Ejemplo n.º 7
0
        public void UpdateTradeEnvoys(Faction faction)
        {
            foreach (TradeEnvoy envoy in faction.TradeEnvoys)
            {
                if (envoy.ExpiditionState == Expedition.State.Trading)
                {
                    if (envoy.UpdateWaitTimer(World.Time.CurrentDate))
                    {
                        World.MakeAnnouncement(String.Format("The envoy from {0} is leaving.", envoy.OwnerFaction.Name));
                        RecallEnvoy(envoy);
                    }
                }

                envoy.Creatures.RemoveAll(creature => creature.IsDead);
                if (envoy.DeathTimer.Update(faction.World.Time.CurrentDate))
                {
                    envoy.Creatures.ForEach((creature) => creature.GetRoot().Die());
                }

                Diplomacy.Politics politics = faction.World.Diplomacy.GetPolitics(faction, envoy.OtherFaction);
                if (politics.GetCurrentRelationship() == Relationship.Hateful)
                {
                    World.MakeAnnouncement(String.Format("The envoy from {0} is leaving.", envoy.OwnerFaction.Name));
                    RecallEnvoy(envoy);
                }
                else
                {
                    if (envoy.Creatures.Any(
                            // TODO (mklingen) why do I need this null check?
                            creature => creature.Creature != null &&
                            envoy.OtherFaction.Designations.IsDesignation(creature.Physics, DesignationType.Attack)))
                    {
                        if (!politics.HasEvent("You attacked our trade delegates"))
                        {
                            politics.RecentEvents.Add(new Diplomacy.PoliticalEvent()
                            {
                                Change      = -1.0f,
                                Description = "You attacked our trade delegates",
                                Duration    = new TimeSpan(1, 0, 0, 0),
                                Time        = faction.World.Time.CurrentDate
                            });
                        }
                        else
                        {
                            politics.RecentEvents.Add(new Diplomacy.PoliticalEvent()
                            {
                                Change      = -2.0f,
                                Description = "You attacked our trade delegates more than once",
                                Duration    = new TimeSpan(1, 0, 0, 0),
                                Time        = faction.World.Time.CurrentDate
                            });
                        }
                    }
                }

                if (!envoy.ShouldRemove && envoy.ExpiditionState == Expedition.State.Arriving)
                {
                    foreach (CreatureAI creature in envoy.Creatures)
                    {
                        Room tradePort = envoy.OtherFaction.GetNearestRoomOfType("Balloon Port", creature.Position);

                        if (tradePort == null)
                        {
                            World.MakeAnnouncement("We need a balloon trade port to trade.", null, () =>
                            {
                                return(envoy.OtherFaction.GetNearestRoomOfType("Balloon Port", creature.Position) == null);
                            });
                            World.Tutorial("trade");
                            SoundManager.PlaySound(ContentPaths.Audio.Oscar.sfx_gui_negative_generic, 0.5f);
                            RecallEnvoy(envoy);
                            break;
                        }

                        if (creature.Tasks.Count == 0)
                        {
                            TradeEnvoy envoy1 = envoy;
                            creature.Tasks.Add(new TradeTask(tradePort, envoy1));
                        }

                        if (!tradePort.IsRestingOnZone(creature.Position))
                        {
                            continue;
                        }

                        if (envoy.ExpiditionState != Expedition.State.Trading ||
                            !envoy.IsTradeWidgetValid())
                        {
                            envoy.MakeTradeWidget(World);
                        }
                        envoy.StartTrading(World.Time.CurrentDate);
                        envoy.ExpiditionState = Expedition.State.Trading;
                        break;
                    }
                }
                else if (envoy.ExpiditionState == Expedition.State.Leaving)
                {
                    BoundingBox worldBBox = faction.World.ChunkManager.Bounds;

                    foreach (CreatureAI creature in envoy.Creatures)
                    {
                        if (creature.Tasks.Count == 0)
                        {
                            creature.LeaveWorld();
                        }
                    }

                    foreach (CreatureAI creature in envoy.Creatures)
                    {
                        if (MathFunctions.Dist2D(worldBBox, creature.Position) < 2.0f)
                        {
                            creature.GetRoot().Delete();
                        }
                    }
                }
                else
                {
                    if (!envoy.IsTradeWidgetValid())
                    {
                        envoy.MakeTradeWidget(World);
                    }
                }
                if (envoy.Creatures.All(creature => creature.IsDead))
                {
                    envoy.ShouldRemove = true;

                    World.GoalManager.OnGameEvent(new Goals.Triggers.TradeEnvoyKilled
                    {
                        PlayerFaction = envoy.OtherFaction,
                        OtherFaction  = envoy.OwnerFaction
                    });
                }
            }

            bool hadFactions = faction.TradeEnvoys.Count > 0;

            faction.TradeEnvoys.RemoveAll(t => t == null || t.ShouldRemove);

            if (hadFactions && faction.TradeEnvoys.Count == 0)
            {
                var music = World.Time.IsDay() ? "main_theme_day" : "main_theme_night";
                SoundManager.PlayMusic(music);
            }
        }
Ejemplo n.º 8
0
        public void UpdateWarParties(Faction faction)
        {
            foreach (var party in faction.WarParties)
            {
                bool doneWaiting = party.UpdateTimer(World.Time.CurrentDate);
                party.Creatures.RemoveAll(creature => creature.IsDead);
                if (party.DeathTimer.Update(World.Time.CurrentDate))
                {
                    party.Creatures.ForEach((creature) => creature.Die());
                }

                Diplomacy.Politics politics = faction.World.Diplomacy.GetPolitics(faction, party.OtherFaction);

                if (politics.GetCurrentRelationship() != Relationship.Hateful)
                {
                    RecallWarParty(party);
                }

                if (party.Creatures.All(creature => creature.IsDead))
                {
                    party.ShouldRemove = true;

                    // Killed entire war party. Wonderful!
                    World.GoalManager.OnGameEvent(new Goals.Triggers.WarPartyDefeated
                    {
                        PlayerFaction = party.OtherFaction,
                        OtherFaction  = party.OwnerFaction
                    });
                }

                if (!doneWaiting)
                {
                    continue;
                }
                else
                {
                    foreach (var creature in party.OwnerFaction.Minions)
                    {
                        if (creature.Tasks.Count == 0)
                        {
                            CreatureAI enemyMinion = party.OtherFaction.GetNearestMinion(creature.Position);
                            if (enemyMinion != null)
                            {
                                creature.AssignTask(new KillEntityTask(enemyMinion.Physics, KillEntityTask.KillType.Auto));
                            }
                        }
                    }

                    if (party.ExpiditionState == Expedition.State.Arriving)
                    {
                        World.MakeAnnouncement(String.Format("The war party from {0} is attacking!", party.OwnerFaction.Name));
                        SoundManager.PlaySound(ContentPaths.Audio.Oscar.sfx_gui_negative_generic, 0.15f);
                        party.ExpiditionState = Expedition.State.Fighting;
                    }
                }

                foreach (var creature in party.Creatures)
                {
                    if (MathFunctions.RandEvent(0.001f))
                    {
                        creature.AssignTask(new ActWrapperTask(new GetMoneyAct(creature, (decimal)MathFunctions.Rand(0, 64.0f), party.OtherFaction))
                        {
                            Priority = Task.PriorityType.Medium
                        });
                    }
                }
            }

            faction.WarParties.RemoveAll(w => w.ShouldRemove);
        }
Ejemplo n.º 9
0
        override public void Update(DwarfTime gameTime, ChunkManager chunks, Camera camera)
        {
            base.Update(gameTime, chunks, camera);

            Storm.InitializeStatics();
            BoundingBox box = chunks.Bounds;

            box.Expand(10.0f);

            if (GlobalTransform.Translation.X < box.Min.X ||
                GlobalTransform.Translation.X > box.Max.X ||
                GlobalTransform.Translation.Z < box.Min.Z ||
                GlobalTransform.Translation.Z > box.Max.Z)
            {
                Die();
            }


            bool generateRainDrop = MathFunctions.RandEvent(Raininess * 0.75f);

            if (generateRainDrop)
            {
                for (int i = 0; i < MaxRainDrops; i++)
                {
                    if (!RainDrops[i].IsAlive)
                    {
                        RainDrops[i].IsAlive = true;
                        if (RainDrops[i].Particle != null)
                        {
                            RainDrops[i].Particle.LifeRemaining = 60.0f;
                            RainDrops[i].Particle.TimeAlive     = 0.0f;
                        }
                        RainDrops[i].Pos = MathFunctions.RandVector3Box(BoundingBox.Expand(5));
                        RainDrops[i].Pos = new Vector3(RainDrops[i].Pos.X, BoundingBox.Min.Y - 1, RainDrops[i].Pos.Z);
                        RainDrops[i].Vel = Vector3.Down * Storm.Properties[TypeofStorm].RainSpeed + Velocity;
                        break;
                    }
                }
            }

            bool generateLightning = LightningChance > 0.0f && MathFunctions.RandEvent((float)(LightningChance * 0.001f));

            if (generateLightning)
            {
                var below = VoxelHelpers.FindFirstVoxelBelowIncludingWater(new VoxelHandle(World.ChunkManager, GlobalVoxelCoordinate.FromVector3(new Vector3(Position.X, Math.Min(World.WorldSizeInVoxels.Y - 1, Position.Y), Position.Z))));
                if (below.IsValid && !below.IsEmpty)
                {
                    var above = VoxelHelpers.GetVoxelAbove(below);
                    if (above.IsValid)
                    {
                        EntityFactory.CreateEntity <Fire>("Fire", above.GetBoundingBox().Center());
                        List <Vector3> lightningStrikes = new List <Vector3>();
                        List <Color>   colors           = new List <Color>();
                        var            c = above.GetBoundingBox().Center();
                        for (float t = 0; t < 1.0f; t += 0.25f)
                        {
                            var p = c * t + Position * (1.0f - t);
                            lightningStrikes.Add(p + MathFunctions.RandVector3Box(-5, 5, 0, 0.1f, -5, 5));
                            colors.Add(Color.White);
                        }
                        lightningStrikes.Add(c);
                        colors.Add(Color.White);
                        Drawer3D.DrawLineList(lightningStrikes, colors, 0.3f);
                        SoundManager.PlaySound(ContentPaths.Audio.Oscar.sfx_gui_rain_storm_alert, MathFunctions.Rand(0.001f, 0.05f), MathFunctions.Rand(0.5f, 1.0f));
                        SoundManager.PlaySound(ContentPaths.Audio.Oscar.sfx_trap_destroyed, c, false, 1.0f, MathFunctions.Rand(-0.5f, 0.5f));
                        World.ParticleManager.Trigger("explode", c, Color.White, 10);
                    }
                }
            }

            Storm.StormProperties stormProperties = Storm.Properties[TypeofStorm];
            var rainEmitter = World.ParticleManager.Effects[stormProperties.RainEffect];
            var hitEmitter  = World.ParticleManager.Effects[stormProperties.HitEffect];

            for (int i = 0; i < MaxRainDrops; i++)
            {
                if (!RainDrops[i].IsAlive)
                {
                    continue;
                }

                RainDrops[i].Pos += RainDrops[i].Vel * DwarfTime.Dt;

                if (stormProperties.RainRandom > 0)
                {
                    RainDrops[i].Vel.X += MathFunctions.Rand(-1, 1) * stormProperties.RainRandom * DwarfTime.Dt;
                    RainDrops[i].Vel.Z += MathFunctions.Rand(-1, 1) * stormProperties.RainRandom * DwarfTime.Dt;
                }

                if (RainDrops[i].Pos.Y < 0)
                {
                    RainDrops[i].IsAlive = false;
                }

                if (!RainDrops[i].IsAlive && RainDrops[i].Particle != null)
                {
                    RainDrops[i].Particle.LifeRemaining = -1;
                }
                else if (RainDrops[i].IsAlive && RainDrops[i].Particle == null)
                {
                    RainDrops[i].Particle = rainEmitter.Emitters[0].CreateParticle(RainDrops[i].Pos,
                                                                                   RainDrops[i].Vel, Color.White);
                }
                else if (RainDrops[i].IsAlive && RainDrops[i].Particle != null)
                {
                    RainDrops[i].Particle.Position = RainDrops[i].Pos;
                    RainDrops[i].Particle.Velocity = RainDrops[i].Vel;
                }

                var test = new VoxelHandle(chunks, GlobalVoxelCoordinate.FromVector3(RainDrops[i].Pos));
                if (!test.IsValid || (test.IsEmpty && test.LiquidLevel == 0))
                {
                    continue;
                }

                RainDrops[i].IsAlive = false;

                var hitBodies = World.EnumerateIntersectingObjects(new BoundingBox(RainDrops[i].Pos - Vector3.One, RainDrops[i].Pos + Vector3.One));

                foreach (var body in hitBodies)
                {
                    if (body.Parent != Manager.RootComponent)
                    {
                        continue;
                    }

                    var flames = body.GetRoot().GetComponent <Flammable>();
                    if (flames != null)
                    {
                        flames.Heat *= 0.25f;
                    }

                    var seeds = body.GetRoot().GetComponent <Seedling>();
                    if (seeds != null)
                    {
                        if (TypeofStorm == StormType.RainStorm)
                        {
                            seeds.GrowthTime += MathFunctions.Rand(1.0f, 12.0f);
                        }
                        else if (MathFunctions.RandEvent(0.01f))
                        {
                            seeds.GetRoot().Die();
                        }
                    }
                }
                hitEmitter.Trigger(1, RainDrops[i].Pos + Vector3.UnitY * 0.5f, Color.White);

                //if (!MathFunctions.RandEvent(0.1f)) continue;

                var above = test.IsEmpty ? test : VoxelHelpers.GetVoxelAbove(test);

                if (!above.IsValid || !above.IsEmpty)
                {
                    continue;
                }
                if (TypeofStorm == StormType.RainStorm &&
                    (above.LiquidLevel < WaterManager.maxWaterLevel && (above.LiquidType == LiquidType.Water)))
                {
                    above.LiquidLevel = (byte)Math.Min(WaterManager.maxWaterLevel, above.LiquidLevel + WaterManager.rainFallAmount);
                    above.LiquidType  = stormProperties.LiquidToCreate;
                }
                else if (TypeofStorm == StormType.SnowStorm && above.IsEmpty && above.LiquidLevel == 0)
                {
                    if (test.GrassType == 0)
                    {
                        test.GrassType  = Library.GetGrassType("snow").ID;
                        test.GrassDecay = Library.GetGrassType("snow").InitialDecayValue;
                    }
                    else
                    {
                        var existingGrass = Library.GetGrassType((byte)test.GrassType);
                        if (!String.IsNullOrEmpty(existingGrass.BecomeWhenSnowedOn))
                        {
                            var newGrass = Library.GetGrassType(existingGrass.BecomeWhenSnowedOn);
                            test.GrassType  = newGrass.ID;
                            test.GrassDecay = newGrass.InitialDecayValue;
                        }
                    }
                }
            }

            Matrix tf = LocalTransform;

            tf.Translation += Velocity * DwarfTime.Dt;
            LocalTransform  = tf;
        }
Ejemplo n.º 10
0
        public TradeEnvoy SendTradeEnvoy(Faction natives, WorldManager world)
        {
            if (!world.PlayerFaction.GetRooms().Any(room => room is BalloonPort && room.IsBuilt))
            {
                world.MakeAnnouncement(String.Format("Trade envoy from {0} left. No balloon port!", natives.Name));
                SoundManager.PlaySound(ContentPaths.Audio.Oscar.sfx_gui_negative_generic, 0.15f);
                return(null);
            }
            TradeEnvoy envoy = null;

            List <CreatureAI> creatures =
                world.MonsterSpawner.Spawn(world.MonsterSpawner.GenerateSpawnEvent(natives,
                                                                                   world.PlayerFaction, MathFunctions.Random.Next(4) + 1, false));

            if (natives.TradeMoney < 100m)
            {
                natives.TradeMoney += MathFunctions.Rand(250.0f, 5000.0f);
            }

            envoy = new TradeEnvoy(world.Time.CurrentDate)
            {
                Creatures    = creatures,
                OtherFaction = world.PlayerFaction,
                ShouldRemove = false,
                OwnerFaction = natives,
                TradeGoods   = natives.Race.GenerateResources(world),
                TradeMoney   = natives.TradeMoney
            };

            if (natives.Race.IsNative)
            {
                if (natives.Economy == null)
                {
                    natives.Economy = new Economy(natives, 1000.0m, World, new CompanyInformation()
                    {
                        Name = natives.Name
                    });
                }

                foreach (CreatureAI creature in envoy.Creatures)
                {
                    creature.Physics.AddChild(new ResourcePack(World.ComponentManager));
                    creature.Physics.AddChild(new Flag(World.ComponentManager, Vector3.Up * 0.5f + Vector3.Backward * 0.25f, natives.Economy.Company.Information));
                }
            }
            else
            {
                Body balloon = world.PlayerFaction.DispatchBalloon();

                if (balloon != null)
                {
                    foreach (CreatureAI creature in creatures)
                    {
                        Matrix tf = creature.Physics.LocalTransform;
                        tf.Translation = balloon.LocalTransform.Translation;
                        creature.Physics.LocalTransform = tf;
                    }
                }
                else
                {
                    if (natives.Economy == null)
                    {
                        natives.Economy = new Economy(natives, 1000.0m, World, new CompanyInformation()
                        {
                            Name = natives.Name
                        });
                    }

                    foreach (CreatureAI creature in envoy.Creatures)
                    {
                        creature.Physics.AddChild(new ResourcePack(World.ComponentManager));
                        creature.Physics.AddChild(new Flag(World.ComponentManager, Vector3.Up * 0.5f + Vector3.Backward * 0.25f, natives.Economy.Company.Information));
                    }
                }
            }

            foreach (CreatureAI creature in envoy.Creatures)
            {
                creature.Physics.AddChild(new ResourcePack(World.ComponentManager));
            }

            envoy.DistributeGoods();
            natives.TradeEnvoys.Add(envoy);
            world.MakeAnnouncement(new DwarfCorp.Gui.Widgets.QueuedAnnouncement
            {
                Text        = String.Format("Trade envoy from {0} has arrived!", natives.Name),
                ClickAction = (gui, sender) =>
                {
                    if (envoy.Creatures.Count > 0)
                    {
                        envoy.Creatures.First().ZoomToMe();
                        World.MakeWorldPopup(String.Format("Traders from {0} ({1}) have entered our territory.\nThey will try to get to our balloon port to trade with us.", natives.Name, natives.Race.Name),
                                             envoy.Creatures.First().Physics, -10);
                    }
                },
                ShouldKeep = () =>
                {
                    return(envoy.ExpiditionState == Expedition.State.Arriving);
                }
            });

            SoundManager.PlaySound(ContentPaths.Audio.Oscar.sfx_gui_positive_generic, 0.15f);


            world.Tutorial("trade");
            if (!String.IsNullOrEmpty(natives.Race.TradeMusic))
            {
                SoundManager.PlayMusic(natives.Race.TradeMusic);
            }

            return(envoy);
        }
Ejemplo n.º 11
0
 public void Play(Vector3 position, float pitch = 0.0f)
 {
     SoundManager.PlaySound(Datastructures.SelectRandom(Sounds), position, RandomPitch, Volume, pitch);
 }
Ejemplo n.º 12
0
        public void Update(WorldManager World)
        {
            if (ExpiditionState == Expedition.State.Trading)
            {
                if (UpdateWaitTimer(World.Time.CurrentDate))
                {
                    World.MakeAnnouncement(String.Format("The envoy from {0} is leaving.", OwnerFaction.ParentFaction.Name));
                    RecallEnvoy();
                }
            }

            Creatures.RemoveAll(creature => creature.IsDead);
            if (DeathTimer.Update(World.Time.CurrentDate))
            {
                Creatures.ForEach((creature) => creature.GetRoot().Die());
            }

            var politics = World.Overworld.GetPolitics(OwnerFaction.ParentFaction, OtherFaction.ParentFaction);

            if (politics.GetCurrentRelationship() == Relationship.Hateful)
            {
                World.MakeAnnouncement(String.Format("The envoy from {0} left: we are at war with them.", OwnerFaction.ParentFaction.Name));
                RecallEnvoy();
            }
            else
            {
                if (Creatures.Any(
                        // TODO (mklingen) why do I need this null check?
                        creature => creature.Creature != null &&
                        World.PersistentData.Designations.IsDesignation(creature.Physics, DesignationType.Attack)))
                {
                    if (!politics.HasEvent("You attacked our trade delegates"))
                    {
                        politics.AddEvent(new PoliticalEvent()
                        {
                            Change      = -1.0f,
                            Description = "You attacked our trade delegates",
                        });
                    }
                    else
                    {
                        politics.AddEvent(new PoliticalEvent()
                        {
                            Change      = -2.0f,
                            Description = "You attacked our trade delegates more than once",
                        });
                    }
                }
            }

            if (!ShouldRemove && ExpiditionState == Expedition.State.Arriving)
            {
                foreach (var creature in Creatures)
                {
                    var tradePort = World.GetNearestRoomOfType("Balloon Port", creature.Position);

                    if (tradePort == null)
                    {
                        World.MakeAnnouncement("We need a balloon trade port to trade.", null, () =>
                        {
                            return(World.GetNearestRoomOfType("Balloon Port", creature.Position) == null);
                        });
                        World.Tutorial("trade");
                        SoundManager.PlaySound(ContentPaths.Audio.Oscar.sfx_gui_negative_generic, 0.5f);
                        RecallEnvoy();
                        break;
                    }

                    if (creature.Tasks.Count == 0)
                    {
                        creature.Tasks.Add(new TradeTask(tradePort, this));
                    }

                    if (!tradePort.IsRestingOnZone(creature.Position))
                    {
                        continue;
                    }

                    if (ExpiditionState != Expedition.State.Trading || !IsTradeWidgetValid())
                    {
                        MakeTradeWidget(World);
                    }

                    StartTrading(World.Time.CurrentDate);
                    ExpiditionState = Expedition.State.Trading;
                    break;
                }
            }
            else if (ExpiditionState == Expedition.State.Leaving)
            {
                BoundingBox worldBBox = World.ChunkManager.Bounds;

                foreach (CreatureAI creature in Creatures)
                {
                    if (creature.Tasks.Count == 0)
                    {
                        creature.LeaveWorld();
                    }
                }

                foreach (var creature in Creatures)
                {
                    if (MathFunctions.Dist2D(worldBBox, creature.Position) < 2.0f)
                    {
                        creature.GetRoot().Delete();
                    }
                }
            }
            else if (!IsTradeWidgetValid())
            {
                MakeTradeWidget(World);
            }

            if (!OwnerFaction.ParentFaction.IsCorporate && Creatures.All(creature => creature.IsDead))
            {
                ShouldRemove = true;
            }
        }
Ejemplo n.º 13
0
        public IEnumerable <Status> PerformStep(MoveAction Step)
        {
            var actionSpeed = GetAgentSpeed(Step.MoveType);

            switch (Step.MoveType)
            {
                #region Ride Elevator
            case MoveType.RideElevator:

                CleanupMinecart();
                var shafts = Step.DestinationState.Tag as Elevators.ElevatorMoveState;
                if (shafts == null || shafts.Entrance == null || shafts.Entrance.IsDead || shafts.Exit == null || shafts.Exit.IsDead)
                {
                    yield return(Status.Fail);
                }

                var shaft = shafts.Entrance.Shaft;
                if (shaft == null || shaft.Invalid)
                {
                    yield return(Status.Fail);
                }

                if (!shaft.EnqueuDwarf(Agent, shafts))
                {
                    yield return(Status.Fail);
                }

                while (!shaft.ReadyToBoard(Agent))
                {
                    if (DeltaTime > 30.0f)
                    {
                        yield return(Status.Fail);    // We waited too long.
                    }
                    if (shaft.Invalid)
                    {
                        yield return(Status.Fail);
                    }

                    SetCharacterMode(CharacterMode.Idle);

                    if (Debugger.Switches.DebugElevators)
                    {
                        Drawer3D.DrawBox(shafts.Entrance.GetBoundingBox(), Color.Red, 0.1f, false);
                        Drawer3D.DrawBox(shafts.Exit.GetBoundingBox(), Color.Red, 0.1f, false);
                        Drawer3D.DrawBox(Step.DestinationVoxel.GetBoundingBox(), Color.Red, 0.1f, false);
                    }

                    yield return(Status.Running);
                }

                DeltaTime = 0;
                foreach (var bit in Translate(Agent.Position, GetPathPoint(shafts.Entrance.GetContainingVoxel()), actionSpeed))
                {
                    if (shaft.Invalid)
                    {
                        yield return(Status.Fail);
                    }

                    shaft.WaitForMe(Agent);

                    SetCharacterMode(CharacterMode.Walking);

                    if (Debugger.Switches.DebugElevators)
                    {
                        Drawer3D.DrawBox(shafts.Entrance.GetBoundingBox(), Color.Green, 0.1f, false);
                        Drawer3D.DrawBox(shafts.Exit.GetBoundingBox(), Color.Green, 0.1f, false);
                        Drawer3D.DrawBox(Step.DestinationVoxel.GetBoundingBox(), Color.Green, 0.1f, false);
                    }
                    yield return(Status.Running);
                }

                shaft.StartMotion(Agent);

                var grav = Creature.Physics.Gravity;
                //Creature.Physics.Gravity = Vector3.Zero;
                while (!shaft.AtDestination(Agent))
                {
                    if (shaft.Invalid)
                    {
                        yield return(Status.Fail);
                    }

                    SetCharacterMode(CharacterMode.Idle);

                    if (Debugger.Switches.DebugElevators)
                    {
                        Drawer3D.DrawBox(shafts.Entrance.GetBoundingBox(), Color.Red, 0.1f, false);
                        Drawer3D.DrawBox(shafts.Exit.GetBoundingBox(), Color.Red, 0.1f, false);
                        Drawer3D.DrawBox(Step.DestinationVoxel.GetBoundingBox(), Color.Red, 0.1f, false);
                    }

                    yield return(Status.Running);
                }

                DeltaTime = 0;
                foreach (var bit in Translate(Agent.Physics.LocalPosition, GetPathPoint(Step.DestinationVoxel), actionSpeed))
                {
                    if (shaft.Invalid)
                    {
                        yield return(Status.Fail);
                    }

                    shaft.WaitForMe(Agent);

                    SetCharacterMode(CharacterMode.Walking);

                    if (Debugger.Switches.DebugElevators)
                    {
                        Drawer3D.DrawBox(shafts.Entrance.GetBoundingBox(), Color.Green, 0.1f, false);
                        Drawer3D.DrawBox(shafts.Exit.GetBoundingBox(), Color.Green, 0.1f, false);
                        Drawer3D.DrawBox(Step.DestinationVoxel.GetBoundingBox(), Color.Green, 0.1f, false);
                    }

                    yield return(Status.Running);
                }
                Creature.Physics.Gravity = grav;

                shaft.Done(Agent);

                break;

                #endregion
            case MoveType.EnterVehicle:

                if (!Step.DestinationVoxel.IsEmpty)
                {
                    yield return(Status.Fail);
                }

                Creature.NoiseMaker.MakeNoise("Jump", Agent.Position, false);

                foreach (var bit in Jump(GetPathPoint(Step.SourceVoxel), GetPathPoint(Step.DestinationVoxel), Step.DestinationVoxel.Center - Step.SourceVoxel.Center, actionSpeed, 1.5f))
                {
                    SetCharacterMode(Creature.Physics.Velocity.Y > 0 ? CharacterMode.Jumping : CharacterMode.Falling);
                    yield return(Status.Running);
                }

                DeltaTime = 0.0f;
                SetupMinecart();

                break;

            case MoveType.ExitVehicle:

                CleanupMinecart();

                if (!Step.DestinationVoxel.IsEmpty)
                {
                    yield return(Status.Fail);
                }

                SetAgentTranslation(GetPathPoint(Step.DestinationVoxel));
                break;

            case MoveType.RideVehicle:

                if (!Step.DestinationVoxel.IsEmpty)
                {
                    yield return(Status.Fail);
                }

                SetupMinecart();
                var rail = Step.SourceState.Rail;
                if (rail == null)
                {
                    yield return(Status.Fail);
                }

                var rideTime = 1.0f / actionSpeed;
                while (DeltaTime < rideTime)
                {
                    var pos = rail.InterpolateSpline(DeltaTime / rideTime, Step.SourceVoxel.WorldPosition, Step.DestinationVoxel.WorldPosition);

                    var transform = Agent.Physics.LocalTransform;
                    transform.Translation        = pos + Vector3.Up * 0.5f;
                    Agent.Physics.LocalTransform = transform;
                    Agent.Physics.Velocity       = GetPathPoint(Step.DestinationVoxel) - GetPathPoint(Step.SourceVoxel);

                    SetCharacterMode(CharacterMode.Minecart);

                    transform.Translation = pos + Vector3.Up * -0.1f;

                    if (Minecart != null)
                    {
                        Minecart.LocalTransform = transform;
                    }

                    yield return(Status.Running);
                }

                DeltaTime -= rideTime;

                break;

            case MoveType.Walk:

                CleanupMinecart();
                // Todo: Fail if distance is too great.

                if (!Step.DestinationVoxel.IsEmpty)
                {
                    yield return(Status.Fail);
                }

                foreach (var bit in Translate(Agent.Position, GetPathPoint(Step.DestinationVoxel), actionSpeed))
                {
                    SetCharacterMode(CharacterMode.Walking);
                    yield return(Status.Running);
                }
                break;

            case MoveType.Swim:

                CleanupMinecart();

                if (!Step.DestinationVoxel.IsEmpty)
                {
                    yield return(Status.Fail);
                }

                foreach (var bit in Translate(Agent.Position, GetPathPoint(Step.DestinationVoxel), actionSpeed))
                {
                    Creature.NoiseMaker.MakeNoise("Swim", Agent.Position, true);
                    SetCharacterMode(CharacterMode.Swimming);
                    yield return(Status.Running);
                }

                break;

            case MoveType.Jump:
            {
                CleanupMinecart();

                if (!Step.DestinationVoxel.IsEmpty)
                {
                    yield return(Status.Fail);
                }

                Creature.NoiseMaker.MakeNoise("Jump", Agent.Position, false);

                var dest  = GetPathPoint(Step.DestinationVoxel);
                var above = VoxelHelpers.GetVoxelAbove(Step.SourceVoxel);
                if (above.IsValid && !above.IsEmpty)
                {
                    yield return(Status.Fail);
                }

                foreach (var bit in Jump(Agent.Position, dest, dest - Agent.Position, actionSpeed / 2.0f, 0.0f))
                {
                    Creature.Physics.CollisionType = CollisionType.None;
                    Creature.OverrideCharacterMode = false;
                    SetCharacterMode(Creature.Physics.Velocity.Y > 0 ? CharacterMode.Jumping : CharacterMode.Falling);
                    yield return(Status.Running);
                }

                SetAgentTranslation(dest);

                break;
            }

            case MoveType.HighJump:
            {
                CleanupMinecart();

                if (!Step.DestinationVoxel.IsEmpty)
                {
                    yield return(Status.Fail);
                }

                Creature.NoiseMaker.MakeNoise("Jump", Agent.Position, false);

                var dest  = GetPathPoint(Step.DestinationVoxel);
                var above = VoxelHelpers.GetVoxelAbove(Step.SourceVoxel);
                if (above.IsValid && !above.IsEmpty)
                {
                    yield return(Status.Fail);
                }

                foreach (var bit in Jump(Agent.Position, dest, dest - Agent.Position, actionSpeed / 2.0f, 1.5f))
                {
                    Creature.Physics.CollisionType = CollisionType.None;
                    Creature.OverrideCharacterMode = false;
                    SetCharacterMode(Creature.Physics.Velocity.Y > 0 ? CharacterMode.Jumping : CharacterMode.Falling);
                    yield return(Status.Running);
                }

                SetAgentTranslation(dest);

                break;
            }

            case MoveType.Fall:

                CleanupMinecart();

                if (!Step.DestinationVoxel.IsEmpty)
                {
                    yield return(Status.Fail);
                }

                foreach (var bit in Translate(Agent.Position, GetPathPoint(Step.DestinationVoxel), actionSpeed))
                {
                    SetCharacterMode(CharacterMode.Falling);
                    yield return(Status.Running);
                }

                break;

            case MoveType.Climb:

                CleanupMinecart();

                if (!Step.DestinationVoxel.IsEmpty)
                {
                    yield return(Status.Fail);
                }

                DeltaTime = 0.0f;
                foreach (var bit in Translate(GetPathPoint(Step.SourceVoxel), GetPathPoint(Step.DestinationVoxel), actionSpeed))
                {
                    if (Step.InteractObject == null || Step.InteractObject.IsDead)
                    {
                        yield return(Status.Fail);
                    }

                    if (DeltaTime - LastNoiseTime > 1.0f)
                    {
                        Creature.NoiseMaker.MakeNoise("Climb", Agent.Position, false);
                        LastNoiseTime = DeltaTime;
                    }

                    SetCharacterMode(CharacterMode.Climbing);
                    yield return(Status.Running);
                }

                break;

            case MoveType.ClimbWalls:

                CleanupMinecart();

                if (!Step.DestinationVoxel.IsEmpty)
                {
                    yield return(Status.Fail);
                }

                DeltaTime = 0.0f;
                foreach (var bit in Translate(GetPathPoint(Step.SourceVoxel), GetPathPoint(Step.DestinationVoxel), actionSpeed))
                {
                    if (DeltaTime - LastNoiseTime > 1.0f)
                    {
                        Creature.NoiseMaker.MakeNoise("Climb", Agent.Position, false);
                        LastNoiseTime = DeltaTime;
                    }

                    SetCharacterMode(CharacterMode.Climbing);

                    if (Step.ActionVoxel.IsValid)
                    {
                        var voxelVector = new Vector3(Step.ActionVoxel.Coordinate.X + 0.5f, Agent.Physics.Position.Y, Step.ActionVoxel.Coordinate.Z + 0.5f);
                        Agent.Physics.Velocity = Vector3.Normalize(voxelVector - Agent.Physics.Position) * actionSpeed;
                    }

                    yield return(Status.Running);
                }

                break;

            case MoveType.Fly:

                CleanupMinecart();

                if (!Step.DestinationVoxel.IsEmpty)
                {
                    yield return(Status.Fail);
                }

                DeltaTime = 0.0f;
                foreach (var bit in Translate(GetPathPoint(Step.SourceVoxel), GetPathPoint(Step.DestinationVoxel), actionSpeed))
                {
                    if ((int)(DeltaTime * 100) % 2 == 0)
                    {
                        Creature.NoiseMaker.MakeNoise("Flap", Agent.Position, false);
                    }
                    SetCharacterMode(CharacterMode.Flying);

                    yield return(Status.Running);
                }

                break;

            case MoveType.Dig:

                CleanupMinecart();

                if (Step.DestinationVoxel.IsEmpty)     // Reverse of other states!
                {
                    yield return(Status.Fail);
                }

                var destroy = new DigAct(Creature.AI, new KillVoxelTask(Step.DestinationVoxel))
                {
                    CheckOwnership = false
                };
                destroy.Initialize();
                foreach (var status in destroy.Run())
                {
                    if (status == Act.Status.Fail)
                    {
                        yield return(Act.Status.Fail);
                    }
                    yield return(Act.Status.Running);
                }
                yield return(Act.Status.Fail);    // Abort the path so that they stop digging if a path has opened.

                break;

            case MoveType.DestroyObject:

                CleanupMinecart();

                if (!Step.DestinationVoxel.IsEmpty)
                {
                    yield return(Status.Fail);
                }

                var melee = new AttackAct(Creature.AI, (GameComponent)Step.InteractObject);
                melee.Initialize();
                foreach (var status in melee.Run())
                {
                    if (status == Act.Status.Fail)
                    {
                        yield return(Act.Status.Fail);
                    }
                    yield return(Act.Status.Running);
                }
                yield return(Act.Status.Fail);    // Abort the path so that they stop destroying things if a path has opened.

                break;

            case MoveType.Teleport:

                CleanupMinecart();

                if (!Step.DestinationVoxel.IsEmpty)
                {
                    yield return(Status.Fail);
                }

                if (Step.InteractObject == null || Step.InteractObject.IsDead)
                {
                    yield return(Status.Fail);
                }

                if (Step.InteractObject.GetComponent <MagicalObject>().HasValue(out var teleporter))
                {
                    teleporter.CurrentCharges--;
                }

                SoundManager.PlaySound(ContentPaths.Audio.Oscar.sfx_ic_dwarf_magic_research, Agent.Position, true, 1.0f);
                Agent.World.ParticleManager.Trigger("green_flame", (Step.InteractObject as GameComponent).Position, Color.White, 1);
                //Agent.GetRoot().SetFlagRecursive(GameComponent.Flag.Visible, false);

                {
                    var source = GetPathPoint(Step.SourceVoxel);
                    var dest   = GetPathPoint(Step.DestinationVoxel);
                    var delta  = dest - source;
                    var steps  = delta.Length() * 2.0f;
                    delta.Normalize();
                    delta *= 0.5f;

                    for (var i = 0; i <= steps; ++i)
                    {
                        Agent.World.ParticleManager.Trigger("star_particle", source, Color.White, 1);
                        source += delta;
                    }
                }

                //foreach (var bit in Translate(GetPathPoint(Step.SourceVoxel), GetPathPoint(Step.DestinationVoxel), actionSpeed))
                //{
                //    Agent.World.ParticleManager.Trigger("star_particle", Agent.Position, Color.White, 1);
                //    yield return Status.Running;
                //}

                SetAgentTranslation(GetPathPoint(Step.DestinationVoxel));
                //Agent.GetRoot().SetFlagRecursive(GameComponent.Flag.Visible, true);
                yield return(Status.Running);

                break;
            }
        }
Ejemplo n.º 14
0
        public void UpdateTradeEnvoys(Faction faction)
        {
            foreach (TradeEnvoy envoy in faction.TradeEnvoys)
            {
                if (envoy.DeathTimer.Update(faction.World.Time.CurrentDate))
                {
                    envoy.Creatures.ForEach((creature) => creature.GetRoot().Die());
                }

                Diplomacy.Politics politics = faction.World.Diplomacy.GetPolitics(faction, envoy.OtherFaction);
                if (politics.GetCurrentRelationship() == Relationship.Hateful)
                {
                    RecallEnvoy(envoy);
                }
                else
                {
                    if (envoy.Creatures.Any(
                            creature => envoy.OtherFaction.Designations.IsDesignation(creature.Physics, DesignationType.Attack)))
                    {
                        if (!politics.HasEvent("You attacked our trade delegates"))
                        {
                            politics.RecentEvents.Add(new Diplomacy.PoliticalEvent()
                            {
                                Change      = -1.0f,
                                Description = "You attacked our trade delegates",
                                Duration    = new TimeSpan(1, 0, 0, 0),
                                Time        = faction.World.Time.CurrentDate
                            });
                        }
                        else
                        {
                            politics.RecentEvents.Add(new Diplomacy.PoliticalEvent()
                            {
                                Change      = -2.0f,
                                Description = "You attacked our trade delegates more than once",
                                Duration    = new TimeSpan(1, 0, 0, 0),
                                Time        = faction.World.Time.CurrentDate
                            });
                        }
                    }
                }

                if (!envoy.ShouldRemove && envoy.ExpiditionState == Expedition.State.Arriving)
                {
                    foreach (CreatureAI creature in envoy.Creatures)
                    {
                        Room tradePort = envoy.OtherFaction.GetNearestRoomOfType(BalloonPort.BalloonPortName,
                                                                                 creature.Position);

                        if (tradePort == null)
                        {
                            World.MakeAnnouncement("We need a balloon trade port to trade.");
                            World.Tutorial("trade");
                            SoundManager.PlaySound(ContentPaths.Audio.Oscar.sfx_gui_negative_generic, 0.5f);
                            RecallEnvoy(envoy);
                            break;
                        }

                        if (creature.Tasks.Count == 0)
                        {
                            TradeEnvoy envoy1 = envoy;
                            creature.Tasks.Add(new TradeTask(tradePort, envoy1));
                        }

                        if (!tradePort.IsRestingOnZone(creature.Position))
                        {
                            continue;
                        }

                        envoy.ExpiditionState = Expedition.State.Trading;

                        World.Paused = true;
                        GameState.Game.StateManager.PushState(new Dialogue.DialogueState(
                                                                  GameState.Game,
                                                                  GameState.Game.StateManager,
                                                                  envoy,
                                                                  World.PlayerFaction,
                                                                  World));
                        //GameState.Game.StateManager.PushState(new DiplomacyState(GameState.Game,
                        //    GameState.Game.StateManager,
                        //    faction.World, envoy)
                        //{
                        //    Name = "DiplomacyState_" + faction.Name,
                        //    Envoy = envoy
                        //});
                        break;
                    }
                }
                else if (envoy.ExpiditionState == Expedition.State.Leaving)
                {
                    BoundingBox worldBBox = faction.World.ChunkManager.Bounds;

                    foreach (CreatureAI creature in envoy.Creatures)
                    {
                        if (creature.Tasks.Count == 0)
                        {
                            creature.LeaveWorld();
                        }
                    }

                    foreach (CreatureAI creature in envoy.Creatures)
                    {
                        if (MathFunctions.Dist2D(worldBBox, creature.Position) < 2.0f)
                        {
                            creature.GetRoot().Delete();
                        }
                    }
                }

                if (envoy.Creatures.All(creature => creature.IsDead))
                {
                    envoy.ShouldRemove = true;

                    World.GoalManager.OnGameEvent(new Goals.Events.TradeEnvoyKilled
                    {
                        PlayerFaction = envoy.OtherFaction,
                        OtherFaction  = envoy.OwnerFaction
                    });
                }
            }

            bool hadFactions = faction.TradeEnvoys.Count > 0;

            faction.TradeEnvoys.RemoveAll(t => t == null || t.ShouldRemove);

            if (hadFactions && faction.TradeEnvoys.Count == 0)
            {
                var music = World.Time.IsDay() ? "main_theme_day" : "main_theme_night";
                SoundManager.PlayMusic(music);
            }
        }
Ejemplo n.º 15
0
 public void PlayNoise(Vector3 position)
 {
     SoundManager.PlaySound(HitNoise, position, true);
 }