public override IEnumerable <Status> Run() { Creature.Sprite.ResetAnimations(Creature.AttackMode); // Block since we're in a coroutine. while (true) { var vox = OwnerTask.Voxel; // Somehow, there wasn't a voxel to mine. if (!vox.IsValid) { Creature.DrawIndicator(IndicatorManager.StandardIndicators.Question); Agent.SetMessage("Failed to dig. Invalid voxel."); yield return(Act.Status.Fail); break; } // If the voxel has already been destroyed, just ignore it and return. if (OwnerTask.VoxelHealth <= 0 || (CheckOwnership && !Creature.Faction.Designations.IsVoxelDesignation(vox, DesignationType.Dig))) { Creature.CurrentCharacterMode = CharacterMode.Idle; yield return(Act.Status.Success); break; } // Look at the block and slow your velocity down. Creature.Physics.Face(vox.WorldPosition + Vector3.One * 0.5f); Creature.Physics.Velocity *= 0.01f; // Play the attack animations. Creature.CurrentCharacterMode = Creature.AttackMode; Creature.OverrideCharacterMode = true; Creature.Sprite.ResetAnimations(Creature.CurrentCharacterMode); Creature.Sprite.PlayAnimations(Creature.CurrentCharacterMode); // Wait until an attack was successful... foreach (var status in Creature.Attacks[0].PerformOnVoxel(Creature, Creature.Physics.Position, OwnerTask, DwarfTime.LastTime, Creature.Stats.BaseDigSpeed, Creature.Faction.Name)) { if (status == Act.Status.Running) { Creature.Physics.Face(vox.WorldPosition + Vector3.One * 0.5f); Creature.Physics.Velocity *= 0.01f; // Debug drawing. //if (agent.AI.DrawPath) // Drawer3D.DrawLine(vox.WorldPosition, agent.AI.Position, Color.Green, 0.25f); yield return(Act.Status.Running); } } Creature.OverrideCharacterMode = false; // If the voxel has been destroyed by you, gather it. if (OwnerTask.VoxelHealth <= 0.0f) { var voxelType = VoxelLibrary.GetVoxelType(vox.Type.Name); if (MathFunctions.RandEvent(0.5f)) { Creature.AI.AddXP(Math.Max((int)(voxelType.StartingHealth / 4), 1)); } Creature.Stats.NumBlocksDestroyed++; Creature.World.GoalManager.OnGameEvent(new Goals.Triggers.DigBlock(voxelType, Creature)); var items = Creature.World.ChunkManager.KillVoxel(vox); if (items != null) { foreach (Body item in items) { Creature.Gather(item); } } yield return(Act.Status.Success); } // Wait until the animation is done playing before continuing. while (!Creature.Sprite.AnimPlayer.IsDone() && Creature.Sprite.AnimPlayer.IsPlaying) { Creature.Physics.Face(vox.WorldPosition + Vector3.One * 0.5f); Creature.Physics.Velocity *= 0.01f; yield return(Act.Status.Running); } // Pause the animation and wait for a recharge timer. Creature.Sprite.PauseAnimations(Creature.CurrentCharacterMode); // Wait for a recharge timer to trigger. Creature.Attacks[0].RechargeTimer.Reset(); while (!Creature.Attacks[0].RechargeTimer.HasTriggered) { Creature.Attacks[0].RechargeTimer.Update(DwarfTime.LastTime); Creature.Physics.Face(vox.WorldPosition + Vector3.One * 0.5f); Creature.Physics.Velocity *= 0.01f; yield return(Act.Status.Running); } Creature.CurrentCharacterMode = CharacterMode.Idle; yield return(Act.Status.Running); } }
/// <summary> /// This is the underlying Dig behavior that dwarves follow while digging. /// </summary> /// <param name="agent">The agent.</param> /// <param name="voxel">The voxel.</param> /// <param name="energyLoss">The energy loss the dwarf gets per block mined.</param> /// <returns>Success when the block is mined, fail if it fails to be mined, and running otherwise.</returns> public static IEnumerable <Act.Status> Dig(this Creature agent, string voxel, float energyLoss) { agent.Sprite.ResetAnimations(Creature.CharacterMode.Attacking); // Block since we're in a coroutine. while (true) { // Get the voxel stored in the agent's blackboard. Voxel blackBoardVoxel = agent.AI.Blackboard.GetData <Voxel>(voxel); // Somehow, there wasn't a voxel to mine. if (blackBoardVoxel == null) { agent.DrawIndicator(IndicatorManager.StandardIndicators.Question); yield return(Act.Status.Fail); break; } Voxel vox = blackBoardVoxel; // If the voxel has already been destroyed, just ignore it and return. if (vox.Health <= 0.0f || !agent.Faction.IsDigDesignation(vox)) { agent.CurrentCharacterMode = Creature.CharacterMode.Idle; yield return(Act.Status.Success); break; } // Look at the block and slow your velocity down. agent.Physics.Face(vox.Position + Vector3.One * 0.5f); agent.Physics.Velocity *= 0.9f; // Play the attack animations. agent.CurrentCharacterMode = Creature.CharacterMode.Attacking; agent.Sprite.ResetAnimations(agent.CurrentCharacterMode); agent.Sprite.PlayAnimations(agent.CurrentCharacterMode); // Wait until an attack was successful... foreach (var status in agent.Attacks[0].Perform(agent, agent.Physics.Position, vox, DwarfTime.LastTime, agent.Stats.BaseDigSpeed, agent.Faction.Name)) { if (status == Act.Status.Running) { agent.Physics.Face(vox.Position + Vector3.One * 0.5f); agent.Physics.Velocity *= 0.9f; // Debug drawing. if (agent.AI.DrawPath) { Drawer3D.DrawLine(vox.Position, agent.AI.Position, Color.Green, 0.25f); } yield return(Act.Status.Running); } } // If the voxel has been destroyed by you, gather it. if (vox.Health <= 0.0f) { List <Body> items = vox.Kill(); if (items != null) { foreach (Body item in items) { agent.Gather(item); } } agent.AI.AddXP(Math.Max((int)(VoxelLibrary.GetVoxelType(blackBoardVoxel.TypeName).StartingHealth / 4), 1)); agent.Stats.NumBlocksDestroyed++; } // Wait until the animation is done playing before continuing. while (!agent.Sprite.CurrentAnimation.IsDone() && agent.Sprite.CurrentAnimation.IsPlaying) { agent.Physics.Face(vox.Position + Vector3.One * 0.5f); agent.Physics.Velocity *= 0.9f; yield return(Act.Status.Running); } // Pause the animation and wait for a recharge timer. agent.Sprite.PauseAnimations(agent.CurrentCharacterMode); // Wait for a recharge timer to trigger. agent.Attacks[0].RechargeTimer.Reset(); while (!agent.Attacks[0].RechargeTimer.HasTriggered) { agent.Attacks[0].RechargeTimer.Update(DwarfTime.LastTime); agent.Physics.Face(vox.Position + Vector3.One * 0.5f); agent.Physics.Velocity *= 0.9f; yield return(Act.Status.Running); } agent.CurrentCharacterMode = Creature.CharacterMode.Idle; yield return(Act.Status.Running); } }
public override IEnumerable <Status> Run() { Creature.Sprite.ResetAnimations(Creature.Stats.CurrentClass.AttackMode); // Block since we're in a coroutine. while (true) { var vox = OwnerTask.Voxel; // Somehow, there wasn't a voxel to mine. if (!vox.IsValid) { Creature.DrawIndicator(IndicatorManager.StandardIndicators.Question); Agent.SetTaskFailureReason("Failed to dig. Invalid voxel."); yield return(Act.Status.Fail); break; } // If the voxel has already been destroyed, just ignore it and return. if (OwnerTask.VoxelHealth <= 0 || (CheckOwnership && !Creature.World.PersistentData.Designations.IsVoxelDesignation(vox, DesignationType.Dig))) { Creature.CurrentCharacterMode = CharacterMode.Idle; yield return(Act.Status.Success); break; } // Look at the block and slow your velocity down. Creature.Physics.Face(vox.WorldPosition + Vector3.One * 0.5f); Creature.Physics.Velocity *= 0.01f; // Play the attack animations. Creature.CurrentCharacterMode = Creature.Stats.CurrentClass.AttackMode; Creature.OverrideCharacterMode = true; Creature.Sprite.ResetAnimations(Creature.CurrentCharacterMode); Creature.Sprite.PlayAnimations(Creature.CurrentCharacterMode); // Wait until an attack was successful... foreach (var status in PerformOnVoxel(Creature, Creature.Physics.Position, OwnerTask, DwarfTime.LastTime, Creature.Stats.BaseDigSpeed, Creature.Faction.ParentFaction.Name)) { if (status == Act.Status.Running) { Creature.Physics.Face(vox.WorldPosition + Vector3.One * 0.5f); Creature.Physics.Velocity *= 0.01f; yield return(Act.Status.Running); } } Creature.OverrideCharacterMode = false; // If the voxel has been destroyed by you, gather it. if (OwnerTask.VoxelHealth <= 0.0f) { if (Library.GetVoxelType(vox.Type.Name).HasValue(out VoxelType voxelType)) { Creature.AI.AddXP(Math.Max((int)(voxelType.StartingHealth / 4), 1)); Creature.Stats.NumBlocksDestroyed++; ActHelper.ApplyWearToTool(Creature.AI, GameSettings.Current.Wear_Dig); var items = VoxelHelpers.KillVoxel(Creature.World, vox); if (items != null) { foreach (GameComponent item in items) { Creature.Gather(item, TaskPriority.Eventually); } } yield return(Act.Status.Success); } } // Wait until the animation is done playing before continuing. while (!Creature.Sprite.AnimPlayer.IsDone() && Creature.Sprite.AnimPlayer.IsPlaying) { Creature.Physics.Face(vox.WorldPosition + Vector3.One * 0.5f); Creature.Physics.Velocity *= 0.01f; yield return(Act.Status.Running); } // Pause the animation and wait for a recharge timer. Creature.Sprite.PauseAnimations(Creature.CurrentCharacterMode); Creature.CurrentCharacterMode = CharacterMode.Idle; yield return(Act.Status.Running); } }
public static IEnumerable <Act.Status> Dig(this Creature agent, string voxel, float energyLoss) { Vector3 LocalTarget = agent.AI.Position; agent.Sprite.ResetAnimations(Creature.CharacterMode.Attacking); while (true) { Voxel blackBoardVoxel = agent.AI.Blackboard.GetData <Voxel>(voxel); if (blackBoardVoxel == null) { agent.DrawIndicator(IndicatorManager.StandardIndicators.Question); yield return(Act.Status.Fail); break; } Voxel vox = blackBoardVoxel; if (vox.Health <= 0.0f || !agent.Faction.IsDigDesignation(vox)) { agent.AI.AddXP(Math.Max((int)(VoxelLibrary.GetVoxelType(blackBoardVoxel.TypeName).StartingHealth / 4), 1)); agent.Stats.NumBlocksDestroyed++; agent.CurrentCharacterMode = Creature.CharacterMode.Idle; yield return(Act.Status.Success); break; } agent.Physics.Face(vox.Position + Vector3.One * 0.5f); agent.Physics.Velocity *= 0.9f; agent.CurrentCharacterMode = Creature.CharacterMode.Attacking; agent.Sprite.ResetAnimations(agent.CurrentCharacterMode); agent.Sprite.PlayAnimations(agent.CurrentCharacterMode); while (!agent.Attacks[0].Perform(agent, agent.Physics.Position, vox, DwarfTime.LastTime, agent.Stats.BaseDigSpeed, agent.Faction.Name)) { agent.Physics.Face(vox.Position + Vector3.One * 0.5f); agent.Physics.Velocity *= 0.9f; yield return(Act.Status.Running); } if (vox.Health <= 0.0f) { List <Body> items = vox.Kill(); if (items != null) { foreach (Body item in items) { agent.Gather(item); } } } while (!agent.Sprite.CurrentAnimation.IsDone()) { agent.Physics.Face(vox.Position + Vector3.One * 0.5f); agent.Physics.Velocity *= 0.9f; yield return(Act.Status.Running); } agent.Sprite.PauseAnimations(agent.CurrentCharacterMode); agent.Attacks[0].RechargeTimer.Reset(); while (!agent.Attacks[0].RechargeTimer.HasTriggered) { agent.Attacks[0].RechargeTimer.Update(DwarfTime.LastTime); agent.Physics.Face(vox.Position + Vector3.One * 0.5f); agent.Physics.Velocity *= 0.9f; yield return(Act.Status.Running); } agent.CurrentCharacterMode = Creature.CharacterMode.Idle; yield return(Act.Status.Running); } }