public DigAct(CreatureAI creature, KillVoxelTask OwnerTask) : base(creature) { Name = "Dig!"; EnergyLoss = 10.0f; this.OwnerTask = OwnerTask; }
public bool CheckIsDigDesignation(CreatureAI creature, KillVoxelTask OwnerTask) { if (OwnerTask.Voxel.IsValid) { return(creature.World.PersistentData.Designations.IsVoxelDesignation(OwnerTask.Voxel, DesignationType.Dig)); } return(false); }
public IEnumerable <Act.Status> Cleanup(CreatureAI creature, KillVoxelTask OwnerTask) { if (creature.Blackboard.GetData <bool>("NoPath", false)) { if (creature.Faction == creature.World.PlayerFaction) { creature.World.MakeAnnouncement(String.Format("{0} cancelled dig task because it is unreachable", creature.Stats.FullName)); creature.World.TaskManager.CancelTask(OwnerTask); } } yield return(Act.Status.Success); }
public KillVoxelAct(CreatureAI creature, KillVoxelTask OwnerTask) : base(creature) { Name = "Kill DestinationVoxel " + OwnerTask.Voxel.WorldPosition; Tree = new Domain(() => CheckIsDigDesignation(creature, OwnerTask), new Sequence( new GoToVoxelAct(OwnerTask.Voxel, PlanAct.PlanType.Radius, creature) { Radius = 2.0f }, new DigAct(Agent, OwnerTask))) | new Wrap(() => Cleanup(creature, OwnerTask)); }
public KillVoxelAct(CreatureAI creature, KillVoxelTask OwnerTask) : base(creature) { Name = "Kill DestinationVoxel " + OwnerTask.Voxel.WorldPosition; Tree = new Select( new Domain(() => CheckIsDigDesignation(creature, OwnerTask), new Sequence( ActHelper.CreateEquipmentCheckAct(creature, "Tool", ActHelper.EquipmentFallback.AllowDefault, "Pick"), new GoToVoxelAct(OwnerTask.Voxel, PlanAct.PlanType.Radius, creature) { Radius = 2.0f }, new DigAct(Agent, OwnerTask))), new Wrap(() => Cleanup(creature, OwnerTask))); }
public override void OnVoxelsSelected(List <VoxelHandle> refs, InputManager.MouseButton button) { if (button == InputManager.MouseButton.Left) { Player.World.Tutorial("slice"); List <Task> assignments = new List <Task>(); foreach (var v in refs) { if (!v.IsValid || (v.IsEmpty && v.IsExplored) || v.Type.IsInvincible) { continue; } var boundingBox = v.GetBoundingBox().Expand(-0.1f); var entities = Player.World.EnumerateIntersectingObjects(boundingBox, CollisionType.Static); if (entities.OfType <IVoxelListener>().Any()) { continue; } if (!Player.Faction.Designations.IsVoxelDesignation(v, DesignationType.Dig) && !(Player.Faction.RoomBuilder.IsInRoom(v) || Player.Faction.RoomBuilder.IsBuildDesignation(v))) { var task = new KillVoxelTask(v); assignments.Add(task); } } Player.TaskManager.AddTasks(assignments); List <CreatureAI> minions = Faction.FilterMinionsWithCapability(Player.SelectedMinions, Task.TaskCategory.Dig); OnConfirm(minions); } else { foreach (var r in refs) { if (r.IsValid) { var designation = Player.Faction.Designations.GetVoxelDesignation(r, DesignationType.Dig); if (designation != null && designation.Task != null) { Player.TaskManager.CancelTask(designation.Task); } } } } }
public IEnumerable <Act.Status> PerformOnVoxel(Creature performer, Vector3 pos, KillVoxelTask DigAct, DwarfTime time, float bonus, string faction) { while (true) { if (!DigAct.Voxel.IsValid) { performer.AI.SetMessage("Failed to dig. Voxel was not valid."); yield return(Act.Status.Fail); yield break; } Drawer2D.DrawLoadBar(performer.World.Renderer.Camera, DigAct.Voxel.WorldPosition + Vector3.One * 0.5f, Color.White, Color.Black, 32, 1, (float)DigAct.VoxelHealth / DigAct.Voxel.Type.StartingHealth); switch (Weapon.TriggerMode) { case Weapon.AttackTrigger.Timer: RechargeTimer.Update(time); if (!RechargeTimer.HasTriggered) { yield return(Act.Status.Running); continue; } break; case Weapon.AttackTrigger.Animation: if (!performer.Sprite.AnimPlayer.HasValidAnimation() || performer.Sprite.AnimPlayer.CurrentFrame < Weapon.TriggerFrame) { if (performer.Sprite.AnimPlayer.HasValidAnimation()) { performer.Sprite.AnimPlayer.Play(); } yield return(Act.Status.Running); continue; } break; } DigAct.VoxelHealth -= (Weapon.DamageAmount + bonus); DigAct.Voxel.Type.HitSound.Play(DigAct.Voxel.WorldPosition); if (!String.IsNullOrEmpty(Weapon.HitParticles)) { performer.Manager.World.ParticleManager.Trigger(Weapon.HitParticles, DigAct.Voxel.WorldPosition, Color.White, 5); } if (Weapon.HitAnimation != null) { IndicatorManager.DrawIndicator(Weapon.HitAnimation, DigAct.Voxel.WorldPosition + Vector3.One * 0.5f, 10.0f, 1.0f, MathFunctions.RandVector2Circle() * 10, Weapon.HitColor, MathFunctions.Rand() > 0.5f); } yield return(Act.Status.Success); yield break; } }
public List <Task> CreateTasks() { List <Task> tasks = new List <Task>(); if (Faction.Stockpiles.Count > 0) { tasks.AddRange(Faction.GatherDesignations.Select(i => new GatherItemTask(i)).Where(g => !TaskIsAssigned(g) && IsFeasible(g, Faction.Minions))); } foreach (CreatureAI creature in Faction.Minions) { if (creature.Status.Hunger.IsUnhappy()) { Task g = new SatisfyHungerTask(); if (IsFeasible(g, Faction.Minions)) { tasks.Add(g); } } } foreach (CreatureAI creature in Faction.Minions) { if (creature.Status.Energy.IsUnhappy() && PlayState.Time.IsNight()) { Task g = new SatisfyTirednessTask(); if (IsFeasible(g, Faction.Minions)) { tasks.Add(g); } } } List <Creature> threatsToRemove = new List <Creature>(); foreach (Creature threat in Faction.Threats) { if (threat != null && !threat.IsDead) { Task g = new KillEntityTask(threat.Physics, KillEntityTask.KillType.Auto); if (!TaskIsAssigned(g) && IsFeasible(g, Faction.Minions)) { tasks.Add(g); } } else { threatsToRemove.Add(threat); } } foreach (Creature threat in threatsToRemove) { Faction.Threats.Remove(threat); } foreach (BuildOrder i in Faction.DigDesignations) { if (i == null || i.Vox == null || i.Vox.Health <= 0) { continue; } VoxelChunk chunk = PlayState.ChunkManager.ChunkData.GetVoxelChunkAtWorldLocation(i.Vox.Position); if (chunk != null) { if (chunk.IsCompletelySurrounded(i.Vox)) { continue; } } Task g = new KillVoxelTask(i.Vox); if (!TaskIsAssigned(g) && IsFeasible(g, Faction.Minions)) { tasks.Add(g); } } tasks.AddRange(Faction.GuardDesignations.Select(i => new GuardVoxelTask(i.Vox)).Where(g => !TaskIsAssigned(g) && IsFeasible(g, Faction.Minions))); tasks.AddRange(Faction.ChopDesignations.Select(i => new KillEntityTask(i, KillEntityTask.KillType.Chop)).Where(g => !TaskIsAssigned(g) && IsFeasible(g, Faction.Minions))); if (Faction.Stockpiles.Count <= 0) { return(tasks); } foreach (WallBuilder put in Faction.WallBuilder.Designations) { if (Faction.HasResources(new List <ResourceAmount>() { new ResourceAmount(put.Type.ResourceToRelease) })) { Task g = (new BuildVoxelTask(put.Vox, put.Type)); if (!TaskIsAssigned(g) && IsFeasible(g, Faction.Minions)) { tasks.Add(g); } } } return(tasks); }
public List<Task> CreateTasks() { List<Task> tasks = new List<Task>(); if(Faction.Stockpiles.Count > 0) { tasks.AddRange(Faction.GatherDesignations.Select(i => new GatherItemTask(i)).Where(g => !TaskIsAssigned(g) && IsFeasible(g, Faction.Minions))); } foreach(CreatureAI creature in Faction.Minions) { if(creature.Status.Hunger.IsUnhappy()) { Task g = new SatisfyHungerTask(); if(IsFeasible(g, Faction.Minions)) { tasks.Add(g); } } } foreach (CreatureAI creature in Faction.Minions) { if (creature.Status.Energy.IsUnhappy() && PlayState.Time.IsNight()) { Task g = new SatisfyTirednessTask(); if (IsFeasible(g, Faction.Minions)) { tasks.Add(g); } } } List<Creature> threatsToRemove = new List<Creature>(); foreach(Creature threat in Faction.Threats) { if(threat != null && !threat.IsDead) { Task g = new KillEntityTask(threat.Physics, KillEntityTask.KillType.Auto); if (!TaskIsAssigned(g) && IsFeasible(g, Faction.Minions)) { tasks.Add(g); } } else { threatsToRemove.Add(threat); } } foreach (Creature threat in threatsToRemove) { Faction.Threats.Remove(threat); } foreach(BuildOrder i in Faction.DigDesignations) { if (i == null || i.Vox == null || i.Vox.Health <= 0) { continue; } VoxelChunk chunk = PlayState.ChunkManager.ChunkData.GetVoxelChunkAtWorldLocation(i.Vox.Position); if(chunk != null) { if(chunk.IsCompletelySurrounded(i.Vox)) { continue; } } Task g = new KillVoxelTask(i.Vox); if(!TaskIsAssigned(g) && IsFeasible(g, Faction.Minions)) { tasks.Add(g); } } tasks.AddRange(Faction.GuardDesignations.Select(i => new GuardVoxelTask(i.Vox)).Where(g => !TaskIsAssigned(g) && IsFeasible(g, Faction.Minions))); tasks.AddRange(Faction.ChopDesignations.Select(i => new KillEntityTask(i, KillEntityTask.KillType.Chop)).Where(g => !TaskIsAssigned(g) && IsFeasible(g, Faction.Minions))); if(Faction.Stockpiles.Count <= 0) { return tasks; } foreach(WallBuilder put in Faction.WallBuilder.Designations) { if(Faction.HasResources(new List<ResourceAmount>() { new ResourceAmount(put.Type.ResourceToRelease) })) { Task g = (new BuildVoxelTask(put.Vox, put.Type)); if(!TaskIsAssigned(g) && IsFeasible(g, Faction.Minions)) { tasks.Add(g); } } } foreach(ShipOrder ship in Faction.ShipDesignations) { List<Body> componentsToShip = new List<Body>(); int remaining = ship.GetRemainingNumResources(); if(remaining == 0) { continue; } foreach(Stockpile s in Faction.Stockpiles) { for(int i = componentsToShip.Count; i < remaining; i++) { // TODO: Reimplement /* Body r = s.FindItemWithTag(ship.Resource.ResourceType.ResourceName, componentsToShip); if(r != null) { componentsToShip.Add(r); } */ } } foreach(Body loc in componentsToShip) { // TODO: Reimplement /* if(ship.Port.ContainsItem(loc)) { continue; } */ Task g = new PutItemInZoneTask(Item.FindItem(loc), ship.Port); if(TaskIsAssigned(g) || !IsFeasible(g, Faction.Minions)) { continue; } ship.Assignments.Add(g); tasks.Add(g); } } return tasks; }
public List <Task> CreateTasks() { List <Task> tasks = new List <Task>(); if (Faction.Stockpiles.Count > 0) { tasks.AddRange(Faction.GatherDesignations.Select(i => new GatherItemTask(i)).Where(g => !TaskIsAssigned(g) && IsFeasible(g, Faction.Minions))); } foreach (CreatureAI creature in Faction.Minions) { if (creature.Status.Hunger.IsUnhappy()) { Task g = new SatisfyHungerTask(); if (IsFeasible(g, Faction.Minions)) { tasks.Add(g); } } } foreach (CreatureAI creature in Faction.Minions) { if (creature.Status.Energy.IsUnhappy() && PlayState.Time.IsNight()) { Task g = new SatisfyTirednessTask(); if (IsFeasible(g, Faction.Minions)) { tasks.Add(g); } } } List <Creature> threatsToRemove = new List <Creature>(); foreach (Creature threat in Faction.Threats) { if (threat != null && !threat.IsDead) { Task g = new KillEntityTask(threat.Physics, KillEntityTask.KillType.Auto); if (!TaskIsAssigned(g) && IsFeasible(g, Faction.Minions)) { tasks.Add(g); } } else { threatsToRemove.Add(threat); } } foreach (Creature threat in threatsToRemove) { Faction.Threats.Remove(threat); } foreach (BuildOrder i in Faction.DigDesignations) { if (i == null || i.Vox == null || i.Vox.Health <= 0) { continue; } VoxelChunk chunk = PlayState.ChunkManager.ChunkData.GetVoxelChunkAtWorldLocation(i.Vox.Position); if (chunk != null) { if (chunk.IsCompletelySurrounded(i.Vox)) { continue; } } Task g = new KillVoxelTask(i.Vox); if (!TaskIsAssigned(g) && IsFeasible(g, Faction.Minions)) { tasks.Add(g); } } tasks.AddRange(Faction.GuardDesignations.Select(i => new GuardVoxelTask(i.Vox)).Where(g => !TaskIsAssigned(g) && IsFeasible(g, Faction.Minions))); tasks.AddRange(Faction.ChopDesignations.Select(i => new KillEntityTask(i, KillEntityTask.KillType.Chop)).Where(g => !TaskIsAssigned(g) && IsFeasible(g, Faction.Minions))); if (Faction.Stockpiles.Count <= 0) { return(tasks); } foreach (WallBuilder put in Faction.WallBuilder.Designations) { if (Faction.HasResources(new List <ResourceAmount>() { new ResourceAmount(put.Type.ResourceToRelease) })) { Task g = (new BuildVoxelTask(put.Vox, put.Type)); if (!TaskIsAssigned(g) && IsFeasible(g, Faction.Minions)) { tasks.Add(g); } } } foreach (ShipOrder ship in Faction.ShipDesignations) { List <Body> componentsToShip = new List <Body>(); int remaining = ship.GetRemainingNumResources(); if (remaining == 0) { continue; } foreach (Stockpile s in Faction.Stockpiles) { for (int i = componentsToShip.Count; i < remaining; i++) { // TODO: Reimplement /* * Body r = s.FindItemWithTag(ship.Resource.ResourceType.ResourceName, componentsToShip); * * if(r != null) * { * componentsToShip.Add(r); * } */ } } foreach (Body loc in componentsToShip) { // TODO: Reimplement /* * if(ship.Port.ContainsItem(loc)) * { * continue; * } */ Task g = new PutItemInZoneTask(Item.FindItem(loc), ship.Port); if (TaskIsAssigned(g) || !IsFeasible(g, Faction.Minions)) { continue; } ship.Assignments.Add(g); tasks.Add(g); } } return(tasks); }
private IEnumerable <Act.Status> PerformOnVoxel(Creature performer, Vector3 pos, KillVoxelTask DigAct, DwarfTime time, float bonus, string faction) { var tool = ActHelper.GetEquippedItem(performer, "Tool"); // Play the attack animations. Creature.CurrentCharacterMode = tool.Tool_AttackAnimation; Creature.OverrideCharacterMode = true; Creature.Sprite.ResetAnimations(Creature.CurrentCharacterMode); Creature.Sprite.PlayAnimations(Creature.CurrentCharacterMode); while (true) { if (!DigAct.Voxel.IsValid) { performer.AI.SetTaskFailureReason("Failed to dig. Voxel was not valid."); yield return(Act.Status.Fail); yield break; } Drawer2D.DrawLoadBar(performer.World.Renderer.Camera, DigAct.Voxel.WorldPosition + Vector3.One * 0.5f, Color.White, Color.Black, 32, 1, (float)DigAct.VoxelHealth / DigAct.Voxel.Type.StartingHealth); while (!performer.Sprite.AnimPlayer.HasValidAnimation() || performer.Sprite.AnimPlayer.CurrentFrame < tool.Tool_AttackTriggerFrame) { if (performer.Sprite.AnimPlayer.HasValidAnimation()) { performer.Sprite.AnimPlayer.Play(); } yield return(Act.Status.Running); } DigAct.VoxelHealth -= (tool.Tool_AttackDamage + bonus); DigAct.Voxel.Type.HitSound.Play(DigAct.Voxel.WorldPosition); if (!String.IsNullOrEmpty(tool.Tool_AttackHitParticles)) { performer.Manager.World.ParticleManager.Trigger(tool.Tool_AttackHitParticles, DigAct.Voxel.WorldPosition, Color.White, 5); } if (!String.IsNullOrEmpty(tool.Tool_AttackHitEffect)) { IndicatorManager.DrawIndicator(Library.CreateSimpleAnimation(tool.Tool_AttackHitEffect), DigAct.Voxel.WorldPosition + Vector3.One * 0.5f, 10.0f, 1.0f, MathFunctions.RandVector2Circle() * 10, tool.Tool_AttackHitColor, MathFunctions.Rand() > 0.5f); } yield return(Act.Status.Success); yield break; } }
public IEnumerable <Act.Status> PerformOnVoxel(Creature performer, Vector3 pos, KillVoxelTask DigAct, DwarfTime time, float bonus, string faction) { while (true) { if (!DigAct.Voxel.IsValid) { yield return(Act.Status.Fail); yield break; } Drawer2D.DrawLoadBar(performer.World.Camera, DigAct.Voxel.WorldPosition + Vector3.One * 0.5f, Color.White, Color.Black, 32, 1, (float)DigAct.VoxelHealth / DigAct.Voxel.Type.StartingHealth); switch (TriggerMode) { case AttackTrigger.Timer: RechargeTimer.Update(time); if (!RechargeTimer.HasTriggered) { yield return(Act.Status.Running); continue; } break; case AttackTrigger.Animation: if (!performer.Sprite.AnimPlayer.HasValidAnimation() || performer.Sprite.AnimPlayer.CurrentFrame < TriggerFrame) { if (performer.Sprite.AnimPlayer.HasValidAnimation()) { performer.Sprite.AnimPlayer.Play(); } yield return(Act.Status.Running); continue; } break; } switch (Mode) { case AttackMode.Melee: { DigAct.VoxelHealth -= (DamageAmount + bonus); DigAct.Voxel.Type.HitSound.Play(DigAct.Voxel.WorldPosition); if (HitParticles != "") { performer.Manager.World.ParticleManager.Trigger(HitParticles, DigAct.Voxel.WorldPosition, Color.White, 5); } if (HitAnimation != null) { IndicatorManager.DrawIndicator(HitAnimation, DigAct.Voxel.WorldPosition + Vector3.One * 0.5f, 10.0f, 1.0f, MathFunctions.RandVector2Circle() * 10, HitColor, MathFunctions.Rand() > 0.5f); } break; } case AttackMode.Ranged: { throw new InvalidOperationException("Ranged attacks should never be used for digging."); //LaunchProjectile(pos, DigAct.GetTargetVoxel().WorldPosition, null); //break; } } yield return(Act.Status.Success); yield break; } }
public override void OnVoxelsSelected(List <VoxelHandle> refs, InputManager.MouseButton button) { if (button == InputManager.MouseButton.Left) { int count = World.PersistentData.Designations.EnumerateDesignations(DesignationType.Dig).Count(); World.Tutorial("slice"); List <Task> assignments = new List <Task>(); foreach (var v in refs) { if (!v.IsValid || (v.IsEmpty && v.IsExplored) || v.Type.IsInvincible) { continue; } var boundingBox = v.GetBoundingBox().Expand(-0.1f); var entities = World.EnumerateIntersectingObjects(boundingBox, CollisionType.Static); if (entities.OfType <IVoxelListener>().Any()) { continue; } if (count >= GameSettings.Current.MaxVoxelDesignations) { World.UserInterface.ShowToolPopup("Too many dig designations!"); break; } // Todo: Should this be removed from the existing compound task and put in the new one? if (!World.PersistentData.Designations.IsVoxelDesignation(v, DesignationType.Dig) && !(World.IsInZone(v) || World.IsBuildDesignation(v))) { var task = new KillVoxelTask(v); task.Hidden = true; assignments.Add(task); count++; } } if (assignments.Count > 0) { World.TaskManager.AddTasks(assignments); var compoundTask = new CompoundTask("DIG A HOLE", TaskCategory.Dig, TaskPriority.Medium); compoundTask.AddSubTasks(assignments); World.TaskManager.AddTask(compoundTask); var minions = Faction.FilterMinionsWithCapability(World.PersistentData.SelectedMinions, TaskCategory.Dig); OnConfirm(minions); } } else { foreach (var r in refs) { if (r.IsValid) { if (World.PersistentData.Designations.GetVoxelDesignation(r, DesignationType.Dig).HasValue(out var designation) && designation.Task != null) // Todo: Is this necessary? { World.TaskManager.CancelTask(designation.Task); } } } } }
// This hack exists to find orphaned tasks not assigned to any dwarf, and to then // put them on the task list. public void UpdateOrphanedTasks() { orphanedTaskRateLimiter.Update(DwarfTime.LastTime); if (orphanedTaskRateLimiter.HasTriggered) { List <Task> orphanedTasks = new List <Task>(); foreach (var block in Faction.Designations.EnumerateDesignations()) { if (block.Type == DesignationType.Put) { var type = (short)(block.Tag); var task = new BuildVoxelTask(block.Voxel, VoxelLibrary.GetVoxelType(type).Name); if (!TaskManager.HasTask(task) && !Faction.Minions.Any(minion => minion.Tasks.Contains(task))) { orphanedTasks.Add(task); } } else if (block.Type == DesignationType.Dig) { var task = new KillVoxelTask(block.Voxel); if (!TaskManager.HasTask(task) && !Faction.Minions.Any(minion => minion.Tasks.Contains(task))) { orphanedTasks.Add(task); } } // TODO... other tasks here ? } foreach (var ent in Faction.Designations.EnumerateEntityDesignations()) { if (ent.Type == DesignationType.Attack) { var task = new KillEntityTask(ent.Body, KillEntityTask.KillType.Attack); if (!TaskManager.HasTask(task) && !Faction.Minions.Any(minion => minion.Tasks.Contains(task))) { orphanedTasks.Add(task); } } else if (ent.Type == DesignationType.Chop) { var task = new KillEntityTask(ent.Body, KillEntityTask.KillType.Chop); if (!TaskManager.HasTask(task) && !Faction.Minions.Any(minion => minion.Tasks.Contains(task))) { orphanedTasks.Add(task); } } else if (ent.Type == DesignationType.Wrangle) { var task = new WrangleAnimalTask(ent.Body.GetRoot().GetComponent <Creature>()); if (!TaskManager.HasTask(task) && !Faction.Minions.Any(minion => minion.Tasks.Contains(task))) { orphanedTasks.Add(task); } } else if (ent.Type == DesignationType.Gather) { var task = new GatherItemTask(ent.Body); if (!TaskManager.HasTask(task) && !Faction.Minions.Any(minion => minion.Tasks.Contains(task))) { orphanedTasks.Add(task); } } else if (ent.Type == DesignationType.Craft) { var task = new CraftItemTask(ent.Tag as CraftDesignation); if (!TaskManager.HasTask(task) && !Faction.Minions.Any(minion => minion.Tasks.Contains(task))) { orphanedTasks.Add(task); } } /// TODO ... other entity task types } if (orphanedTasks.Count > 0) { TaskManager.AssignTasksGreedy(orphanedTasks, Faction.Minions); } } }