/// <summary> /// Called whenever the creature takes damage. /// </summary> public override float Damage(float amount, DamageType type = DamageType.Normal) { float damage = base.Damage(amount, type); string prefix = damage > 0 ? "-" : "+"; Color color = damage > 0 ? Color.Red : Color.Green; IndicatorManager.DrawIndicator(prefix + (int)amount + " HP", AI.Position + Vector3.Up + MathFunctions.RandVector3Cube() * 0.5f, 0.5f, color); if (damage > 0) { NoiseMaker.MakeNoise("Hurt", AI.Position); Sprite.Blink(0.5f); AI.AddThought(Thought.ThoughtType.TookDamage); var deathParticleTrigger = Parent.EnumerateAll().OfType <ParticleTrigger>().Where(p => p.Name == "Death Gibs").FirstOrDefault(); if (deathParticleTrigger != null) { Manager.World.ParticleManager.Trigger(deathParticleTrigger.EmitterName, AI.Position, Color.White, 2); } DrawLifeTimer.Reset(); } return(damage); }
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; }
/// <summary> /// Called whenever the creature takes damage. /// </summary> public override float Damage(float amount, DamageType type = DamageType.Normal) { IsCloaked = false; float damage = base.Damage(amount, type); string prefix = damage > 0 ? "-" : "+"; Color color = damage > 0 ? GameSettings.Default.Colors.GetColor("Negative", Color.Red) : GameSettings.Default.Colors.GetColor("Positive", Color.Green); if (AI != null) { IndicatorManager.DrawIndicator(prefix + (int)amount + " HP", AI.Position + Vector3.Up + MathFunctions.RandVector3Cube() * 0.5f, 0.5f, color); NoiseMaker.MakeNoise("Hurt", AI.Position); Sprite.Blink(0.5f); AddThought("I got hurt recently.", new TimeSpan(2, 0, 0, 0), -5.0f); var deathParticleTriggers = Parent.EnumerateAll().OfType <ParticleTrigger>().Where(p => p.Name == "Death Gibs"); foreach (var trigger in deathParticleTriggers) { Manager.World.ParticleManager.Trigger(trigger.EmitterName, AI.Position, Color.White, 2); } DrawLifeTimer.Reset(); } return(damage); }
/// <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); } }
public void LayEgg() { NoiseMaker.MakeNoise("Lay Egg", AI.Position, true, 1.0f); var eggResource = new Resource("Egg") { DisplayName = Stats.CurrentClass.Name + " Egg" }; var resourceEntity = Manager.RootComponent.AddChild(new ResourceEntity(Manager, eggResource, Physics.Position)); resourceEntity.AddChild(new Egg(resourceEntity, Stats.Species.BabyType, Manager, Physics.Position, AI.PositionConstraint)); }
private void MakeNoises() { if (AI == null) { return; } if (MathFunctions.RandEvent(0.0001f)) { NoiseMaker.MakeNoise("Chirp", AI.Position, true, 0.25f); } }
public override void Die() { if (World == null) { return; // WUT } if (Stats == null) { return; // SERIOUSLY WTF?? } World.RemoveFromSpeciesTracking(Stats.Species); NoiseMaker.MakeNoise("Die", Physics.Position, true); if (AI.Stats.Money > 0) { EntityFactory.CreateEntity <CoinPile>("Coins Resource", AI.Position, Blackboard.Create("Money", AI.Stats.Money)); } if (Stats.Species.HasMeat) { String type = Stats.CurrentClass.Name + " " + "Meat"; if (!Library.DoesResourceTypeExist(type)) { var r = Library.CreateResourceType(Library.GetResourceType(Stats.Species.BaseMeatResource)); r.Name = type; r.ShortName = type; Library.AddResourceType(r); } Inventory.AddResource(new ResourceAmount(type, 1)); } if (Stats.Species.HasBones) { String type = Stats.CurrentClass.Name + " Bone"; if (!Library.DoesResourceTypeExist(type)) { var r = Library.CreateResourceType(Library.GetResourceType("Bone")); r.Name = type; r.ShortName = type; Library.AddResourceType(r); } Inventory.AddResource(new ResourceAmount(type, 1)); } base.Die(); }
public void LayEgg() { NoiseMaker.MakeNoise("Lay Egg", AI.Position, true, 1.0f); if (ResourceLibrary.GetResourceByName(Species + " Egg") == null || !EntityFactory.EnumerateEntityTypes().Contains(Species + " Egg Resource")) { Resource newEggResource = new Resource(ResourceLibrary.GetResourceByName(ResourceType.Egg)); newEggResource.Name = Species + " Egg"; ResourceLibrary.Add(newEggResource); } var parent = EntityFactory.CreateEntity <Body>(this.Species + " Egg Resource", Physics.Position); parent.AddChild(new Egg(parent, this.Species, Manager, Physics.Position, AI.PositionConstraint)); }
public void LayEgg() { NoiseMaker.MakeNoise("Lay Egg", AI.Position, true, 1.0f); // Todo: Egg resource type and the baby made need to be in the species. if (!Library.DoesResourceTypeExist(Stats.CurrentClass.Name + " Egg") || !EntityFactory.EnumerateEntityTypes().Contains(Stats.CurrentClass.Name + " Egg Resource")) { var newEggResource = Library.CreateResourceType(Library.GetResourceType("Egg")); newEggResource.Name = Stats.CurrentClass.Name + " Egg"; Library.AddResourceType(newEggResource); } var parent = EntityFactory.CreateEntity <GameComponent>(Stats.CurrentClass.Name + " Egg Resource", Physics.Position); parent.AddChild(new Egg(parent, Stats.Species.BabyType, Manager, Physics.Position, AI.PositionConstraint)); }
/// <summary> /// Kills the creature and releases its resources. /// </summary> public override void Die() { // This is just a silly hack to make sure that creatures // carrying resources to a trade depot release their resources // when they die. CreateMeatAndBones(); NoiseMaker.MakeNoise("Die", Physics.Position, true); if (AI.Status.Money > 0) { EntityFactory.CreateEntity <CoinPile>("Coins Resource", AI.Position, Blackboard.Create("Money", AI.Status.Money)); } base.Die(); }
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 override void ReceiveMessageRecursive(Message messageToReceive) { switch (messageToReceive.Type) { case Message.MessageType.OnChunkModified: break; case Message.MessageType.OnHurt: NoiseMaker.MakeNoise("Hurt", AI.Position); this.Sprite.Blink(0.5f); AI.AddThought(Thought.ThoughtType.TookDamage); PlayState.ParticleManager.Trigger(DeathParticleTrigger.EmitterName, AI.Position, Color.White, 2); break; } base.ReceiveMessageRecursive(messageToReceive); }
public override float Damage(float amount, DamageType type = DamageType.Normal) { float damage = base.Damage(amount, type); string prefix = damage > 0 ? "-" : "+"; Color color = damage > 0 ? Color.Red : Color.Green; IndicatorManager.DrawIndicator(prefix + (int)amount + " HP", AI.Position + Vector3.Up + MathFunctions.RandVector3Cube() * 0.5f, 0.5f, color, Indicator.IndicatorMode.Indicator3D); if (damage > 0) { NoiseMaker.MakeNoise("Hurt", AI.Position); this.Sprite.Blink(0.5f); AI.AddThought(Thought.ThoughtType.TookDamage); PlayState.ParticleManager.Trigger(DeathParticleTrigger.EmitterName, AI.Position, Color.White, 2); } return(damage); }
/// <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 override void Die() { if (World == null) { return; // WUT } if (Stats == null) { return; // SERIOUSLY WTF?? } if (!FirstUpdate) { World.RemoveFromSpeciesTracking(Stats.Species); } NoiseMaker.MakeNoise("Die", Physics.Position, true); if (AI.Stats.Money > 0) { Manager.RootComponent.AddChild(new CoinPile(Manager, AI.Position) // I don't like how it's implictly added to manager. { Money = AI.Stats.Money }); } if (Stats.Species.HasMeat) { var meatResource = new Resource(Stats.Species.BaseMeatResource); meatResource.DisplayName = Stats.CurrentClass.Name + " Meat"; Inventory.AddResource(meatResource); } if (Stats.Species.HasBones) { var generatedResource = new Resource("Bone"); generatedResource.DisplayName = Stats.CurrentClass.Name + " Bone"; Inventory.AddResource(generatedResource); } base.Die(); }
/// <summary> /// Called when the creature receives an event message from another source. /// This somewhat janky messaging system is rarely used anymore and should /// probably be removed for clarity. /// </summary> public override void ReceiveMessageRecursive(Message messageToReceive) { switch (messageToReceive.Type) { case Message.MessageType.OnHurt: NoiseMaker.MakeNoise("Hurt", AI.Position); Sprite.Blink(0.5f); AddThought("I got hurt recently.", new TimeSpan(2, 0, 0, 0), -5.0f); var deathParticleTriggers = Parent.EnumerateAll().OfType <ParticleTrigger>().Where(p => p.Name == "Death Gibs"); foreach (var trigger in deathParticleTriggers) { Manager.World.ParticleManager.Trigger(trigger.EmitterName, AI.Position, Color.White, 2); } break; } base.ReceiveMessageRecursive(messageToReceive); }
/// <summary> /// Called when the creature receives an event message from another source. /// This somewhat janky messaging system is rarely used anymore and should /// probably be removed for clarity. /// </summary> public override void ReceiveMessageRecursive(Message messageToReceive) { switch (messageToReceive.Type) { case Message.MessageType.OnChunkModified: break; case Message.MessageType.OnHurt: NoiseMaker.MakeNoise("Hurt", AI.Position); Sprite.Blink(0.5f); AI.AddThought(Thought.ThoughtType.TookDamage); var deathParticleTrigger = Parent.EnumerateAll().OfType <ParticleTrigger>().Where(p => p.Name == "Death Gibs").FirstOrDefault(); if (deathParticleTrigger != null) { Manager.World.ParticleManager.Trigger(deathParticleTrigger.EmitterName, AI.Position, Color.White, 2); } break; } base.ReceiveMessageRecursive(messageToReceive); }
/// <summary> /// Checks the voxels around the creature and reacts to changes in its immediate environment. /// For example this function determines when the creature is standing on solid ground. /// </summary> public void CheckNeighborhood(ChunkManager chunks, float dt) { var below = new VoxelHandle(chunks, GlobalVoxelCoordinate.FromVector3(Physics.GlobalTransform.Translation - Vector3.UnitY * 0.8f)); var above = new VoxelHandle(chunks, GlobalVoxelCoordinate.FromVector3(Physics.GlobalTransform.Translation + Vector3.UnitY * 0.8f)); if (above.IsValid) { IsHeadClear = above.IsEmpty; } if (below.IsValid && Physics.IsInLiquid) { IsOnGround = false; } else if (below.IsValid) { IsOnGround = !below.IsEmpty; } else { IsOnGround = false; } if (!IsOnGround) { if (CurrentCharacterMode != CharacterMode.Flying) { if (Physics.Velocity.Y > 0.05) { CurrentCharacterMode = CharacterMode.Jumping; } else if (Physics.Velocity.Y < -0.05) { CurrentCharacterMode = CharacterMode.Falling; } } if (Physics.IsInLiquid) { CurrentCharacterMode = CharacterMode.Swimming; } } if (CurrentCharacterMode == CharacterMode.Falling && IsOnGround) { CurrentCharacterMode = CharacterMode.Idle; } if (Stats.IsAsleep) { CurrentCharacterMode = CharacterMode.Sleeping; if (MathFunctions.RandEvent(0.01f)) { NoiseMaker.MakeNoise("Sleep", AI.Position, true); } } else if (CurrentCharacterMode == CharacterMode.Sleeping) { CurrentCharacterMode = CharacterMode.Idle; } if (/*World.Time.IsDay() && */ Stats.IsAsleep && !Stats.Energy.IsDissatisfied() && !Stats.Health.IsCritical()) { Stats.IsAsleep = false; } }
public void LayEgg() { NoiseMaker.MakeNoise("Lay Egg", AI.Position, true, 1.0f); Manager.RootComponent.AddChild(new Egg(this.Species, Manager, Physics.Position, AI.PositionConstraint)); }