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); } }
/// <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; }
/// <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; } } }
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; }
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(); } }
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; } } }
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); } }
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); }
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; }
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); }
public void Play(Vector3 position, float pitch = 0.0f) { SoundManager.PlaySound(Datastructures.SelectRandom(Sounds), position, RandomPitch, Volume, pitch); }
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; } }
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; } }
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); } }
public void PlayNoise(Vector3 position) { SoundManager.PlaySound(HitNoise, position, true); }