// Make the entity do its action. Checks if the action was completed. // If so, trys to set a new one from the stack or set to default WanderAction. public virtual void CarryOutAction(ObjectMesh objectMesh, GameTime gameTime) { if (Action != null) // Entity controller can set actions to null or change them if it wants. { if (Action is ICheckNearbyObjectsWithTime ct) { ct.DoWithSearchAndTime(this, objectMesh, gameTime); } else if (Action is EntityTimeAction t) { t.DoWithTime(this, gameTime); } else if (Action is ICheckNearbyObjects c) { c.DoWithSearch(this, objectMesh); } else // Action is normal EntityAction. { Action.Do(this); } if (!Action.IsActive) // The action has reached an ending condition. { ActionLocked = false; CanMove = true; // Allow the person to move here just in case I forget to reset this inside of an action... Action = null; } } }
public void DoWithSearch(Entity entity, ObjectMesh objectMesh) { List <GameObject> nearbyObjects = objectMesh.GetObjectsInRange((int)entity.Position.X, (int)entity.Position.Y, 100); foreach (GameObject o in nearbyObjects) { if (o is Person p && p.Sex == Sex.Female) { entity.SetColor(Color.Red); return; } } entity.SetBaseColor(); }
public void DoWithSearch(Entity entity, ObjectMesh objectMesh) { List <Plant> plants = objectMesh.GetTypedObjectsInRange <Plant>(entity, entity.Size); foreach (Plant plant in plants) { if (entity.GetRectangle().IntersectsWith(plant.GetRectangle())) // Entity needs to be touching the tree. { plant.Harvest(); } } IsActive = false; }
public void DoWithSearch(Entity entity, ObjectMesh objectMesh) { List <IMortal> nearbyObjects = objectMesh.GetMortalObjectsInRange(entity, entity.AttackRange); foreach (IMortal m in nearbyObjects) { // People can only attack animals and animals can only attack people. if (m != entity && (entity is Person && m is Animal || entity is Animal && m is Person)) { entity.Attack(m); //Console.WriteLine($"Health = {m.GetHealth()}"); } } End(); }
public void DoWithSearch(Entity entity, ObjectMesh objectMesh) { if (entity is Person person) { List <Item> pickups = objectMesh.GetTypedObjectsInRange <Item>(entity, entitySize); foreach (Item p in pickups) { if (person.GetRectangleF().IntersectsWith(p.GetRectangleF())) { person.Pickup(p); } } } End(); }
public void DoWithSearchAndTime(Entity entity, ObjectMesh objectMesh, GameTime time) { if (timerEnabled && stopTime != null) { if (time >= stopTime) { entity.SetCanMove(true); End(); } return; } if (entity is Person person) { int range = Person.mateRange; int mateRangeSquared = Person.mateRange * Person.mateRange; // Search all nearbyObjects for people to mate with. Then mate with all of them that are in range. List <GameObject> nearbyObjects = objectMesh.GetObjectsInRange(person.Position.X, person.Position.Y, range); foreach (GameObject gameObject in nearbyObjects) { if (gameObject is Person mate && mate.Sex != person.Sex && !person.IsPregnant && !mate.IsPregnant && Utilities.SquaredDistance(person.Position, mate.Position) < mateRangeSquared) { person.ReproduceWith(mate); // Start timer. Initialize stopTime to the current time plus x number of seconds. Start checking time to allow player to move. if (!timerEnabled) { timerEnabled = true; person.SetCanMove(false); stopTime = time.Copy(); stopTime.AddSeconds(Person.mateTime); } } } } if (!timerEnabled) { End(); } }
public void DoWithSearch(Entity entity, ObjectMesh objectMesh) { if (entity is Person person) { List <Item> pickups = objectMesh.GetTypedObjectsInRange <Item>(entity, entitySize); foreach (Item p in pickups) { if (person.GetRectangleF().IntersectsWith(p.GetRectangleF())) { person.Pickup(p); } } // If the person is inside the house, request the house's selected item. if (person.GetRectangleF().IntersectsWith(house.GetRectangleF()) && housePickup != null) { person.RequestItemByType(housePickup.Type); } } End(); }
// Update Cycle. public void EntityUpdate(GameTime gameTime, ObjectMesh objectMesh, int mouseX, int mouseY) { entityCount = Entities.Count; UpdateData(); if (Utilities.Rng.NextDouble() < animalSpawnChance && entityCount < maxEntityCount) { SpawnRandomAnimal(); } List <Entity> deadEntities = new List <Entity>(); // Player updates. if (Player.BasePerson != null) { if (Player.BasePerson.Hunger <= 0.0) { //Player.BasePerson.TakeDamage(1, null); } if (Player.IsAlive && Player.BasePerson.Health <= 0) { Player.OnCancelData(); // Player is dead and does not have data to display. Player.Kill(); deadEntities.Add(Player.BasePerson); Player.Move(); } else { Player.CarryOutAction(objectMesh, GameTime); Player.Move(); Player.UpdateData(); } } // Updates for the entities in the list. for (int i = 0; i < Entities.Count; i++) { Entity e = Entities[i]; List <GameObject> nearbyObjects = objectMesh .GetObjectsInRange(e.Position.X, e.Position.Y, e.VisionRange) .Where(o => o != e) .ToList(); if (e.GetHealth() <= 0) { deadEntities.Add(e); if (e is Person person) { person.DropAllItems(false); person.OnCancelData(); } else if (e is Animal animal) { animal.OnCancelData(); } } else { // -- Person Updates -- if (e is Person p && personBrainCounter == 0) // Only decide action after a certain period of time. 1 / personBrainPeriod times. { if (e.Hunger <= 0.0) { e.TakeDamage(1, null); } p.UpdateNeeds(); p.UpdateData(); // People that are close together will decrease their social need. if (nearbyObjects.OneSatisfies(g => g.ObjectID != p.ObjectID && g is Person)) { p.DecreaseSocialNeed(); } // People close to a campfire will be warmed up. if (nearbyObjects.OneSatisfies(g => g is Campfire)) { p.DecreaseWarmthNeed(); } if (!e.ActionLocked) // Locked actions will not be overwritten. Used to make entity wait. { personBrain.DecideAction(p, nearbyObjects, PersonCount, GetItemCount(ItemType.Apple), mouseX, mouseY); } } // -- Animal Updates -- if (e is Animal a && animalBrainCounter == 0) { if (!a.ActionLocked) { animalBrain.DecideAction(a, nearbyObjects); } a.UpdateNeeds(); } e.CarryOutAction(objectMesh, GameTime); } } // Update brain counters after all entities have been updated. personBrainCounter = (personBrainCounter + 1) % personBrainPeriod; animalBrainCounter = (animalBrainCounter + 1) % animalBrainPeriod; foreach (Entity e in deadEntities) { EntitiesRemove(e); } GameTime = gameTime; }
// Update Cycle. // Apply logic updates to everything in the world. public void Update(GameTime time, int mouseX, int mouseY) { GameTime = time; List <GameObject> allObjects = EntityController.Entities .Concat(new GameObject[] { EntityController.House }) .Concat(PlantController.Plants.Select(x => (GameObject)x)) .Concat(Items.Select(x => (GameObject)x)) .Concat(Miscellaneous) .ToList(); if (EntityController.Player.IsAlive) { allObjects.Add(EntityController.Player.BasePerson); } ObjectMesh = new ObjectMesh(Utilities.WorldWidth, Utilities.WorldHeight, gridSize, allObjects); // Send game time and object grid to entity controller to apply decision making and updates. Parallel.Invoke(new Action[] { () => { EntityController.EntityUpdate(GameTime, ObjectMesh, mouseX, mouseY); PlantController.PlantUpdate(GameTime); } }); // --- PickupArea --- // Spawn in pickups in random locations. if (++pickupSpawnCounter > 1000) { SpawnItem(ItemType.Apple); SpawnItem(ItemType.Rock); pickupSpawnCounter = 0; } // Check collisions on Items. Only people can pick up pickups. Stack <Item> clearedItems = new Stack <Item>(); foreach (Item pi in Items) { // O(n) action now. People pickup items, which removes some or all of the value of the pickup. // This part checks all pickups and removes those that have no value left. if (pi.Amount <= 0) { pi.SetPickedUp(); clearedItems.Push(pi); // Stack of pickups to remove. } } // Remove pickups from the list. while (clearedItems.Count > 0) { Item p = clearedItems.Pop(); Items.Remove(p); } // --- ScheduleArea --- // Check the schedule to apply actions. These are global events that are tied to the gametime. while (ScheduleQueue.Length > 0) { ActionGroup group = ScheduleQueue.PopMin(); if (group.time <= time) { // Apply scheduled action to entities. if (group.gameObject is Entity en && group.action is EntityAction ea) { // Entity actions done just once. en.TrySetAction(ea, true); } if (group.gameObject is Plant pl && group.action is PlantAction pa) { //Console.WriteLine("Assigning scheduled action to plant using pattern matching"); pl.TrySetAction(pa); } if (group.gameObject is Effect ef && group.action is EffectAction efa) { //Console.WriteLine("Assigning scheduled action to effect using pattern matching"); ef.TrySetAction(efa); } } else { ScheduleQueue.Insert(group); // Put action group back into the schedule. break; } } // Force clear effects that have expired. if (GameTime > ClearEffectTime) { Effects.Clear(); ClearEffectTime.AddSeconds(10); } }