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 IEnumerable <Status> WaitAndHit(float time) { Body objectToHit = Creature.AI.Blackboard.GetData <Body>(ItemType.CraftLocation); Timer timer = new Timer(time, true); while (!timer.HasTriggered) { timer.Update(DwarfTime.LastTime); Creature.CurrentCharacterMode = Creature.CharacterMode.Attacking; Creature.Physics.Velocity = Vector3.Zero; Creature.Attacks[0].PerformNoDamage(Creature, DwarfTime.LastTime, Creature.AI.Position); Drawer2D.DrawLoadBar(Agent.Position + Vector3.Up, Color.White, Color.Black, 100, 16, timer.CurrentTimeSeconds / time); yield return(Status.Running); } Creature.CurrentCharacterMode = Creature.CharacterMode.Idle; Creature.AI.AddThought(Thought.ThoughtType.Crafted); Creature.AI.AddXP((int)(time * 5)); if (objectToHit != null) { objectToHit.IsReserved = false; objectToHit.ReservedFor = null; } yield return(Status.Success); }
public IEnumerable <Act.Status> HitAndWait(float f, bool loadBar) { Timer waitTimer = new Timer(f, true); CurrentCharacterMode = CharacterMode.Attacking; Sprite.ResetAnimations(Creature.CharacterMode.Attacking); Sprite.PlayAnimations(Creature.CharacterMode.Attacking); CurrentCharacterMode = Creature.CharacterMode.Attacking; while (!waitTimer.HasTriggered) { waitTimer.Update(DwarfTime.LastTime); if (loadBar) { Drawer2D.DrawLoadBar(AI.Position + Vector3.Up, Color.White, Color.Black, 100, 16, waitTimer.CurrentTimeSeconds / waitTimer.TargetTimeSeconds); } Attacks[0].PerformNoDamage(this, DwarfTime.LastTime, AI.Position); Physics.Velocity = Vector3.Zero; Sprite.ReloopAnimations(Creature.CharacterMode.Attacking); yield return(Act.Status.Running); } Sprite.PauseAnimations(Creature.CharacterMode.Attacking); CurrentCharacterMode = CharacterMode.Idle; yield return(Act.Status.Success); }
/// <summary> /// Basic Act that causes the creature to wait for the specified time. /// Also draws a loading bar above the creature's head when relevant. /// </summary> public IEnumerable <Act.Status> HitAndWait(float f, bool loadBar, Func <Vector3> pos) { var waitTimer = new Timer(f, true); CurrentCharacterMode = Stats.CurrentClass.AttackMode; Sprite.ResetAnimations(CurrentCharacterMode); Sprite.PlayAnimations(CurrentCharacterMode); while (!waitTimer.HasTriggered) { waitTimer.Update(DwarfTime.LastTime); if (loadBar) { Drawer2D.DrawLoadBar(Manager.World.Renderer.Camera, AI.Position + Vector3.Up, Color.LightGreen, Color.Black, 64, 4, waitTimer.CurrentTimeSeconds / waitTimer.TargetTimeSeconds); } Physics.Active = false; Attacks[0].PerformNoDamage(this, DwarfTime.LastTime, pos()); Physics.Velocity = Vector3.Zero; Sprite.ReloopAnimations(Stats.CurrentClass.AttackMode); yield return(Act.Status.Running); } Sprite.PauseAnimations(Stats.CurrentClass.AttackMode); CurrentCharacterMode = CharacterMode.Idle; Physics.Active = true; yield return(Act.Status.Success); yield break; }
public IEnumerable <Act.Status> HitAndWait(bool loadBar, Func <float> maxProgress, Func <float> progress, Action incrementProgress, Func <Vector3> pos, string playSound = "", Func <bool> continueHitting = null, bool maintainPos = true) { Vector3 currentPos = Physics.LocalTransform.Translation; CurrentCharacterMode = Stats.CurrentClass.AttackMode; Sprite.ResetAnimations(CurrentCharacterMode); Sprite.PlayAnimations(CurrentCharacterMode); var p_current = pos(); Timer incrementTimer = new Timer(1.0f, false); while (progress() < maxProgress()) { if (continueHitting != null && !continueHitting()) { yield break; } if (loadBar) { Drawer2D.DrawLoadBar(Manager.World.Renderer.Camera, AI.Position + Vector3.Up, Color.LightGreen, Color.Black, 64, 4, progress() / maxProgress()); } Physics.Active = false; Physics.Face(p_current); if (Attacks[0].PerformNoDamage(this, DwarfTime.LastTime, p_current)) { p_current = pos(); } Physics.Velocity = Vector3.Zero; if (!String.IsNullOrEmpty(playSound)) { NoiseMaker.MakeNoise(playSound, AI.Position, true); } incrementTimer.Update(DwarfTime.LastTime); if (incrementTimer.HasTriggered) { Sprite.ReloopAnimations(Stats.CurrentClass.AttackMode); incrementProgress(); } if (maintainPos) { var matrix = Physics.LocalTransform; matrix.Translation = currentPos; Physics.LocalTransform = matrix; } yield return(Act.Status.Running); } Sprite.PauseAnimations(Stats.CurrentClass.AttackMode); CurrentCharacterMode = CharacterMode.Idle; Physics.Active = true; yield return(Act.Status.Success); yield break; }
public IEnumerable <Status> FarmATile() { FarmTool.FarmTile tile = FarmToWork; if (tile == null) { yield return(Status.Fail); } else if (tile.PlantExists()) { tile.Farmer = null; yield return(Status.Success); } else { if (tile.Plant != null && tile.Plant.IsDead) { tile.Plant = null; } Creature.CurrentCharacterMode = Creature.CharacterMode.Attacking; Creature.Sprite.ResetAnimations(Creature.CharacterMode.Attacking); Creature.Sprite.PlayAnimations(Creature.CharacterMode.Attacking); while (tile.Progress < 100.0f && !Satisfied()) { Creature.Physics.Velocity *= 0.1f; tile.Progress += Creature.Stats.BaseFarmSpeed; Drawer2D.DrawLoadBar(Agent.Position + Vector3.Up, Color.White, Color.Black, 100, 16, tile.Progress / 100.0f); if (tile.Progress >= 100.0f && !Satisfied()) { tile.Progress = 0.0f; if (Mode == FarmAct.FarmMode.Plant) { FarmToWork.CreatePlant(PlantToCreate); DestroyResources(); } else { FarmToWork.Vox.Type = VoxelLibrary.GetVoxelType("TilledSoil"); FarmToWork.Vox.Chunk.NotifyTotalRebuild(true); } } if (MathFunctions.RandEvent(0.01f)) { PlayState.ParticleManager.Trigger("dirt_particle", Creature.AI.Position, Color.White, 1); } yield return(Status.Running); Creature.Sprite.ReloopAnimations(Creature.CharacterMode.Attacking); } Creature.CurrentCharacterMode = Creature.CharacterMode.Idle; Creature.AI.AddThought(Thought.ThoughtType.Farmed); Creature.AI.AddXP(1); tile.Farmer = null; Creature.Sprite.PauseAnimations(Creature.CharacterMode.Attacking); yield return(Status.Success); } }
public virtual void Render(DwarfTime time) { if (Recharges && !RechargeTimer.HasTriggered) { Drawer2D.DrawLoadBar(World.Camera, World.CursorLightPos - Vector3.Up, Color.White, Color.Black, 150, 20, RechargeTimer.CurrentTimeSeconds / RechargeTimer.TargetTimeSeconds); Drawer2D.DrawTextBox("Charging...", World.CursorLightPos + Vector3.Up * 2); } }
public virtual void Render(DwarfTime time) { // Todo: Do this with GUI stuff? if (Recharges && !RechargeTimer.HasTriggered) { Drawer2D.DrawLoadBar(World.Camera, World.CursorLightPos - Vector3.Up, Color.Cyan, Color.Black, 64, 4, RechargeTimer.CurrentTimeSeconds / RechargeTimer.TargetTimeSeconds); Drawer2D.DrawTextBox("Charging...", World.CursorLightPos + Vector3.Up * 2); } }
public override void Update(DwarfTime Time, ChunkManager Chunks, Camera Camera) { DrawLoadBarTimer.Update(Time); if (!DrawLoadBarTimer.HasTriggered) { Drawer2D.DrawLoadBar(World.Camera, (GetRoot() as Body).Position, Color.Cyan, Color.Black, 32, 4, (float)(_currentCharges) / MaxCharges); } base.Update(Time, Chunks, Camera); }
/// <summary> Updates the creature </summary> public void Update(DwarfTime gameTime, ChunkManager chunks, Camera camera) { if (FirstUpdate) { FirstUpdate = false; Faction.Minions.Add(AI); Physics.AllowPhysicsSleep = false; } if (!Active) { return; } DrawLifeTimer.Update(gameTime); if (!DrawLifeTimer.HasTriggered) { float val = Hp / MaxHealth; Color color = val < 0.75f ? (val < 0.5f ? Color.Red : Color.Orange) : Color.LightGreen; Drawer2D.DrawLoadBar(Manager.World.Camera, AI.Position - Vector3.Up * 0.5f, color, Color.Black, 32, 2, Hp / MaxHealth); } CheckNeighborhood(chunks, (float)gameTime.ElapsedGameTime.TotalSeconds); UpdateAnimation(gameTime, chunks, camera); Status.Update(this, gameTime, chunks, camera); JumpTimer.Update(gameTime); HandleBuffs(gameTime); if (Stats.LaysEggs) { if (EggTimer == null) { EggTimer = new Timer(1200f + MathFunctions.Rand(-30, 30), false); } EggTimer.Update(gameTime); if (EggTimer.HasTriggered) { LayEgg(); EggTimer = new Timer(1200f + MathFunctions.Rand(-30, 30), false); } } if (IsPregnant && World.Time.CurrentDate > CurrentPregnancy.EndDate) { var baby = EntityFactory.CreateEntity <GameComponent>(BabyType, Physics.Position); baby.GetRoot().GetComponent <CreatureAI>().PositionConstraint = AI.PositionConstraint; CurrentPregnancy = null; } if (MathFunctions.RandEvent(0.0001f)) { NoiseMaker.MakeNoise("Chirp", AI.Position, true, 0.25f); } }
private void UpdateHealthBar(DwarfTime gameTime) { DrawLifeTimer.Update(gameTime); if (!DrawLifeTimer.HasTriggered) { float val = Hp / MaxHealth; Color color = val < 0.75f ? (val < 0.5f ? GameSettings.Default.Colors.GetColor("Low Health", Color.Red) : GameSettings.Default.Colors.GetColor("Medium Health", Color.Orange)) : GameSettings.Default.Colors.GetColor("High Health", Color.LightGreen); Drawer2D.DrawLoadBar(Manager.World.Renderer.Camera, AI.Position - Vector3.Up * 0.5f, color, Color.Black, 32, 2, Hp / MaxHealth); } }
public IEnumerable <Status> FarmATile() { FarmTool.FarmTile tile = FarmToWork; if (tile == null) { yield return(Status.Fail); } else if (tile.PlantExists()) { tile.Farmer = null; yield return(Status.Success); } else { if (tile.Plant != null && tile.Plant.IsDead) { tile.Plant = null; } while (tile.Progress < 100.0f && !Satisfied()) { Creature.CurrentCharacterMode = Creature.CharacterMode.Attacking; Creature.Physics.Velocity *= 0.1f; tile.Progress += Creature.Stats.BaseFarmSpeed; Drawer2D.DrawLoadBar(Agent.Position + Vector3.Up, Color.White, Color.Black, 100, 16, tile.Progress / 100.0f); if (tile.Progress >= 100.0f && !Satisfied()) { tile.Progress = 0.0f; if (Mode == FarmAct.FarmMode.Plant) { FarmToWork.CreatePlant(PlantToCreate); DestroyResources(); } else { FarmToWork.Vox.Type = VoxelLibrary.GetVoxelType("TilledSoil"); FarmToWork.Vox.Chunk.ShouldRebuild = true; } } yield return(Status.Running); } Creature.CurrentCharacterMode = Creature.CharacterMode.Idle; Creature.AI.AddThought(Thought.ThoughtType.Farmed); Creature.AI.AddXP(10); tile.Farmer = null; yield return(Status.Success); } }
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> HitAndWait(bool loadBar, Func <float> maxProgress, Func <float> progress, Action incrementProgress, Func <Vector3> pos, string playSound = "", Func <bool> continueHitting = null) { CurrentCharacterMode = CharacterMode.Attacking; Sprite.ResetAnimations(CharacterMode.Attacking); Sprite.PlayAnimations(CharacterMode.Attacking); CurrentCharacterMode = CharacterMode.Attacking; Timer incrementTimer = new Timer(1.0f, false); while (progress() < maxProgress()) { if (continueHitting != null && !continueHitting()) { yield break; } if (loadBar) { Drawer2D.DrawLoadBar(Manager.World.Camera, AI.Position + Vector3.Up, Color.LightGreen, Color.Black, 64, 4, progress() / maxProgress()); } Attacks[0].PerformNoDamage(this, DwarfTime.LastTime, pos()); Physics.Velocity = Vector3.Zero; Sprite.ReloopAnimations(CharacterMode.Attacking); if (!String.IsNullOrEmpty(playSound)) { NoiseMaker.MakeNoise(playSound, AI.Position, true); } incrementTimer.Update(DwarfTime.LastTime); if (incrementTimer.HasTriggered) { incrementProgress(); } yield return(Act.Status.Running); } Sprite.PauseAnimations(CharacterMode.Attacking); CurrentCharacterMode = CharacterMode.Idle; yield return(Act.Status.Success); yield break; }
public IEnumerable <Status> FarmATile(string tileName) { Farm.FarmTile tile = Creature.AI.Blackboard.GetData <Farm.FarmTile>(tileName); if (tile == null) { yield return(Status.Fail); } else if (tile.PlantExists()) { tile.Farmer = null; yield return(Status.Success); } else { if (tile.Plant != null && tile.Plant.IsDead) { tile.Plant = null; } while (tile.Progress < 100.0f && !tile.PlantExists()) { Creature.CurrentCharacterMode = Creature.CharacterMode.Attacking; Creature.Physics.Velocity *= 0.1f; tile.Progress += Creature.Stats.BaseFarmSpeed; Drawer2D.DrawLoadBar(Agent.Position + Vector3.Up, Color.White, Color.Black, 100, 16, tile.Progress / 100.0f); if (tile.Progress >= 100.0f && !tile.PlantExists()) { tile.Progress = 0.0f; FarmToWork.CreatePlant(tile); } yield return(Status.Running); } Creature.CurrentCharacterMode = Creature.CharacterMode.Idle; Creature.AI.AddThought(Thought.ThoughtType.Farmed); Creature.AI.AddXP(10); tile.Farmer = null; yield return(Status.Success); } }
/// <summary> /// Basic Act that causes the creature to wait for the specified time. /// Also draws a loading bar above the creature's head when relevant. /// </summary> public IEnumerable <Act.Status> HitAndWait(float f, bool loadBar, Func <Vector3> pos, string playSound = "", Func <bool> continueHitting = null) { var waitTimer = new Timer(f, true); CurrentCharacterMode = AttackMode; Sprite.ResetAnimations(CurrentCharacterMode); Sprite.PlayAnimations(CurrentCharacterMode); while (!waitTimer.HasTriggered) { waitTimer.Update(DwarfTime.LastTime); if (continueHitting != null && !continueHitting()) { yield break; } Physics.Active = false; if (loadBar) { Drawer2D.DrawLoadBar(Manager.World.Camera, AI.Position + Vector3.Up, Color.LightGreen, Color.Black, 64, 4, waitTimer.CurrentTimeSeconds / waitTimer.TargetTimeSeconds); } Attacks[0].PerformNoDamage(this, DwarfTime.LastTime, pos()); Physics.Velocity = Vector3.Zero; Sprite.ReloopAnimations(AttackMode); if (!String.IsNullOrEmpty(playSound)) { NoiseMaker.MakeNoise(playSound, AI.Position, true); } yield return(Act.Status.Running); } Sprite.PauseAnimations(AttackMode); CurrentCharacterMode = CharacterMode.Idle; Physics.Active = true; yield return(Act.Status.Success); yield break; }
public IEnumerable <Act.Status> HitAndWait(float f, bool loadBar) { Timer waitTimer = new Timer(f, true); CurrentCharacterMode = CharacterMode.Attacking; while (!waitTimer.HasTriggered) { waitTimer.Update(DwarfTime.LastTime); if (loadBar) { Drawer2D.DrawLoadBar(AI.Position + Vector3.Up, Color.White, Color.Black, 100, 16, waitTimer.CurrentTimeSeconds / waitTimer.TargetTimeSeconds); } Attacks[0].PerformNoDamage(DwarfTime.LastTime, AI.Position); yield return(Act.Status.Running); } CurrentCharacterMode = CharacterMode.Idle; yield return(Act.Status.Success); }
public IEnumerable <Status> FarmATile() { if (FarmToWork == null) { yield return(Status.Fail); yield break; } if (FarmToWork.IsCanceled) { yield return(Status.Fail); yield break; } else if (FarmToWork.PlantExists()) { FarmToWork.Farmer = null; yield return(Status.Success); } else { if (FarmToWork.Plant != null && FarmToWork.Plant.IsDead) { FarmToWork.Plant = null; } Creature.CurrentCharacterMode = CharacterMode.Attacking; Creature.Sprite.ResetAnimations(CharacterMode.Attacking); Creature.Sprite.PlayAnimations(CharacterMode.Attacking); while (FarmToWork.Progress < 100.0f && !Satisfied()) { if (FarmToWork.IsCanceled) { yield return(Status.Fail); yield break; } Creature.Physics.Velocity *= 0.1f; FarmToWork.Progress += 3 * Creature.Stats.BaseFarmSpeed * DwarfTime.Dt; Drawer2D.DrawLoadBar(Agent.Manager.World.Camera, Agent.Position + Vector3.Up, Color.LightGreen, Color.Black, 64, 4, FarmToWork.Progress / 100.0f); if (FarmToWork.Progress >= 100.0f && !Satisfied()) { FarmToWork.Progress = 0.0f; if (Mode == FarmAct.FarmMode.Plant) { FarmToWork.CreatePlant(PlantToCreate, Creature.Manager.World); Creature.Faction.Designations.RemoveVoxelDesignation(FarmToWork.Voxel, DesignationType._AllFarms); Creature.Faction.Designations.AddVoxelDesignation(FarmToWork.Voxel, DesignationType._InactiveFarm, FarmToWork); DestroyResources(); } else { FarmToWork.Voxel.Type = VoxelLibrary.GetVoxelType("TilledSoil"); Creature.Faction.Designations.RemoveVoxelDesignation(FarmToWork.Voxel, DesignationType._AllFarms); Creature.Faction.Designations.AddVoxelDesignation(FarmToWork.Voxel, DesignationType._InactiveFarm, FarmToWork); } } 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(CharacterMode.Attacking); } Creature.CurrentCharacterMode = CharacterMode.Idle; Creature.AI.AddThought(Thought.ThoughtType.Farmed); Creature.AI.AddXP(1); FarmToWork.Farmer = null; Creature.Sprite.PauseAnimations(CharacterMode.Attacking); yield return(Status.Success); } }
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 IEnumerable <Status> Run() { Creature.IsCloaked = false; if (CurrentAttack == null) { yield return(Status.Fail); yield break; } Timeout.Reset(); FailTimer.Reset(); if (Target == null && TargetName != null) { Target = Agent.Blackboard.GetData <GameComponent>(TargetName); if (Target == null) { yield return(Status.Fail); yield break; } } if (Agent.Faction.Race.IsIntelligent) { var targetInventory = Target.GetRoot().GetComponent <Inventory>(); if (targetInventory != null) { targetInventory.SetLastAttacker(Agent); } } CharacterMode defaultCharachterMode = Creature.AI.Movement.CanFly ? CharacterMode.Flying : CharacterMode.Walking; bool avoided = false; while (true) { Timeout.Update(DwarfTime.LastTime); FailTimer.Update(DwarfTime.LastTime); if (FailTimer.HasTriggered) { Creature.Physics.Orientation = Physics.OrientMode.RotateY; Creature.OverrideCharacterMode = false; Creature.CurrentCharacterMode = defaultCharachterMode; yield return(Status.Fail); yield break; } if (Timeout.HasTriggered) { if (Training) { Agent.AddXP(1); Creature.Physics.Orientation = Physics.OrientMode.RotateY; Creature.OverrideCharacterMode = false; Creature.CurrentCharacterMode = defaultCharachterMode; yield return(Status.Success); yield break; } else { Creature.Physics.Orientation = Physics.OrientMode.RotateY; Creature.OverrideCharacterMode = false; Creature.CurrentCharacterMode = defaultCharachterMode; yield return(Status.Fail); yield break; } } if (Target == null || Target.IsDead) { Creature.CurrentCharacterMode = defaultCharachterMode; Creature.Physics.Orientation = Physics.OrientMode.RotateY; yield return(Status.Success); } // Find the location of the melee target Vector3 targetPos = new Vector3(Target.GlobalTransform.Translation.X, Target.GetBoundingBox().Min.Y, Target.GlobalTransform.Translation.Z); Vector2 diff = new Vector2(targetPos.X, targetPos.Z) - new Vector2(Creature.AI.Position.X, Creature.AI.Position.Z); Creature.Physics.Face(targetPos); bool intersectsbounds = Creature.Physics.BoundingBox.Intersects(Target.BoundingBox); float dist = diff.Length(); // If we are really far from the target, something must have gone wrong. if (DefensiveStructure == null && !intersectsbounds && dist > CurrentAttack.Weapon.Range * 4) { Creature.Physics.Orientation = Physics.OrientMode.RotateY; Creature.OverrideCharacterMode = false; Creature.CurrentCharacterMode = defaultCharachterMode; yield return(Status.Fail); yield break; } if (DefensiveStructure != null) { if (Creature.Hp < LastHp) { float damage = LastHp - Creature.Hp; Creature.Heal(Math.Min(5.0f, damage)); var health = DefensiveStructure.GetRoot().GetComponent <Health>(); if (health != null) { health.Damage(damage); Drawer2D.DrawLoadBar(health.World.Renderer.Camera, DefensiveStructure.Position, Color.White, Color.Black, 32, 1, health.Hp / health.MaxHealth, 0.1f); } LastHp = Creature.Hp; } if (dist > CurrentAttack.Weapon.Range) { float sqrDist = dist * dist; foreach (var threat in Creature.AI.Faction.Threats) { float threatDist = (threat.AI.Position - Creature.AI.Position).LengthSquared(); if (threatDist < sqrDist) { sqrDist = threatDist; Target = threat.Physics; break; } } dist = (float)Math.Sqrt(sqrDist); } if (dist > CurrentAttack.Weapon.Range * 4) { yield return(Status.Fail); yield break; } if (DefensiveStructure.IsDead) { DefensiveStructure = null; } } LastHp = Creature.Hp; // If we're out of attack range, run toward the target. if (DefensiveStructure == null && !Creature.AI.Movement.IsSessile && !intersectsbounds && diff.Length() > CurrentAttack.Weapon.Range) { Creature.CurrentCharacterMode = defaultCharachterMode; var greedyPath = new GreedyPathAct(Creature.AI, Target, CurrentAttack.Weapon.Range * 0.75f) { PathLength = 5 }; greedyPath.Initialize(); foreach (Act.Status stat in greedyPath.Run()) { if (stat == Act.Status.Running) { yield return(Status.Running); } else { break; } } } // If we have a ranged weapon, try avoiding the target for a few seconds to get within range. else if (DefensiveStructure == null && !Creature.AI.Movement.IsSessile && !intersectsbounds && !avoided && (CurrentAttack.Weapon.Mode == Weapon.AttackMode.Ranged && dist < CurrentAttack.Weapon.Range * 0.15f)) { FailTimer.Reset(); foreach (Act.Status stat in AvoidTarget(CurrentAttack.Weapon.Range, 3.0f)) { yield return(Status.Running); } avoided = true; } // Else, stop and attack else if ((DefensiveStructure == null && dist < CurrentAttack.Weapon.Range) || (DefensiveStructure != null && dist < CurrentAttack.Weapon.Range * 2.0)) { if (CurrentAttack.Weapon.Mode == Weapon.AttackMode.Ranged && VoxelHelpers.DoesRayHitSolidVoxel(Creature.World.ChunkManager, Creature.AI.Position, Target.Position)) { yield return(Status.Fail); yield break; } FailTimer.Reset(); avoided = false; Creature.Physics.Orientation = Physics.OrientMode.Fixed; Creature.Physics.Velocity = new Vector3(Creature.Physics.Velocity.X * 0.9f, Creature.Physics.Velocity.Y, Creature.Physics.Velocity.Z * 0.9f); CurrentAttack.RechargeTimer.Reset(CurrentAttack.Weapon.RechargeRate); Creature.Sprite.ResetAnimations(Creature.Stats.CurrentClass.AttackMode); Creature.Sprite.PlayAnimations(Creature.Stats.CurrentClass.AttackMode); Creature.CurrentCharacterMode = Creature.Stats.CurrentClass.AttackMode; Creature.OverrideCharacterMode = true; Timer timeout = new Timer(10.0f, true); while (!CurrentAttack.Perform(Creature, Target, DwarfTime.LastTime, Creature.Stats.Strength + Creature.Stats.Size, Creature.AI.Position, Creature.Faction.ParentFaction.Name)) { timeout.Update(DwarfTime.LastTime); if (timeout.HasTriggered) { break; } Creature.Physics.Velocity = new Vector3(Creature.Physics.Velocity.X * 0.9f, Creature.Physics.Velocity.Y, Creature.Physics.Velocity.Z * 0.9f); if (Creature.AI.Movement.CanFly) { Creature.Physics.ApplyForce(-Creature.Physics.Gravity * 0.1f, DwarfTime.Dt); } yield return(Status.Running); } timeout.Reset(); while (!Agent.Creature.Sprite.AnimPlayer.IsDone()) { timeout.Update(DwarfTime.LastTime); if (timeout.HasTriggered) { break; } if (Creature.AI.Movement.CanFly) { Creature.Physics.ApplyForce(-Creature.Physics.Gravity * 0.1f, DwarfTime.Dt); } yield return(Status.Running); } var targetCreature = Target.GetRoot().GetComponent <CreatureAI>(); if (targetCreature != null && Creature.AI.FightOrFlight(targetCreature) == CreatureAI.FightOrFlightResponse.Flee) { yield return(Act.Status.Fail); yield break; } Creature.CurrentCharacterMode = CharacterMode.Attacking; Vector3 dogfightTarget = Vector3.Zero; while (!CurrentAttack.RechargeTimer.HasTriggered && !Target.IsDead) { CurrentAttack.RechargeTimer.Update(DwarfTime.LastTime); if (CurrentAttack.Weapon.Mode == Weapon.AttackMode.Dogfight) { dogfightTarget += MathFunctions.RandVector3Cube() * 0.1f; Vector3 output = Creature.Controller.GetOutput(DwarfTime.Dt, dogfightTarget + Target.Position, Creature.Physics.GlobalTransform.Translation) * 0.9f; Creature.Physics.ApplyForce(output - Creature.Physics.Gravity, DwarfTime.Dt); } else { Creature.Physics.Velocity = Vector3.Zero; if (Creature.AI.Movement.CanFly) { Creature.Physics.ApplyForce(-Creature.Physics.Gravity, DwarfTime.Dt); } } yield return(Status.Running); } Creature.CurrentCharacterMode = defaultCharachterMode; Creature.Physics.Orientation = Physics.OrientMode.RotateY; if (Target.IsDead) { Target = null; Agent.AddXP(10); Creature.Physics.Face(Creature.Physics.Velocity + Creature.Physics.GlobalTransform.Translation); Creature.Stats.NumThingsKilled++; Creature.AddThought("I killed somehing!", new TimeSpan(0, 8, 0, 0), 1.0f); Creature.Physics.Orientation = Physics.OrientMode.RotateY; Creature.OverrideCharacterMode = false; Creature.CurrentCharacterMode = defaultCharachterMode; yield return(Status.Success); break; } } yield return(Status.Running); } }
public IEnumerable <Status> FarmATile() { if (Farm == null) { yield return(Status.Fail); yield break; } else if (Farm.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 (Farm.Progress < Farm.TargetProgress && !Farm.Finished) { Creature.Physics.Velocity *= 0.1f; Farm.Progress += 3 * Creature.Stats.BaseFarmSpeed * DwarfTime.Dt; Drawer2D.DrawLoadBar(Agent.Manager.World.Renderer.Camera, Agent.Position + Vector3.Up, Color.LightGreen, Color.Black, 64, 4, Farm.Progress / Farm.TargetProgress); if (Farm.Progress >= (Farm.TargetProgress * 0.5f) && Farm.Voxel.Type.Name != "TilledSoil" && Library.GetVoxelType("TilledSoil").HasValue(out VoxelType tilledSoil)) { Farm.Voxel.Type = tilledSoil; } if (Farm.Progress >= Farm.TargetProgress && !Farm.Finished) { if (Library.GetResourceType(Farm.SeedType).HasValue(out var seedType)) { var plant = EntityFactory.CreateEntity <Plant>(seedType.PlantToGenerate, Farm.Voxel.WorldPosition + new Vector3(0.5f, 1.0f, 0.5f)); plant.Farm = Farm; var 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, Farm.Voxel.WorldPosition, true); } Farm.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); ActHelper.ApplyWearToTool(Creature.AI, GameSettings.Current.Wear_Dig); Creature.Sprite.PauseAnimations(Creature.Stats.CurrentClass.AttackMode); yield return(Status.Success); } }
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.AttackMode; Creature.Sprite.ResetAnimations(Creature.AttackMode); Creature.Sprite.PlayAnimations(Creature.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.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 = VoxelLibrary.GetVoxelType("TilledSoil"); } if (FarmToWork.Progress >= FarmToWork.TargetProgress && !FarmToWork.Finished) { var plant = EntityFactory.CreateEntity <Plant>( ResourceLibrary.Resources[FarmToWork.SeedResourceType].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.AttackMode); } Creature.CurrentCharacterMode = CharacterMode.Idle; Creature.AddThought(Thought.ThoughtType.Farmed); Creature.AI.AddXP(1); Creature.Sprite.PauseAnimations(Creature.AttackMode); yield return(Status.Success); } }
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 = CharacterMode.Attacking; Creature.OverrideCharacterMode = true; Creature.Sprite.ReloopAnimations(CharacterMode.Attacking); 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.AI.AddThought(Thought.ThoughtType.Researched); Creature.OverrideCharacterMode = false; Creature.CurrentCharacterMode = CharacterMode.Idle; yield return(Status.Success); yield break; }