private bool ShouldTargetHuman <T>(Human otherHuman) where T : IResource { if (otherHuman.Dead) { return(false); } var isFoodSource = typeof(T) == typeof(IFoodSource); var aggression = Aggression.Get(_team, otherHuman._team); if (aggression == Aggression.Level.Neutral) { // Only if I'm starving return(isFoodSource && Hunger <= 5); } if (aggression == Aggression.Level.Aggressive) { // Only if I'm hungry return(isFoodSource && Hunger <= MAX_HUNGER / 2); } // If we're friendly we'll share, if we're murderous we'll kill return(true); }
public void TakeFood(Human taker) { if (Aggression.Get(_team, taker._team) == Aggression.Level.Friendly) { // Sharing is caring if (HasFood) { Food--; taker.Feed(1); } } else { // I have been killed Dead = true; SetAnimationState(AnimationState.Dying); taker.Feed(Food); Food = 0; // I shall be avenged Aggression.Adjust(_team, taker._team, 15); } }
public override void _Process(float delta) { if (Dead) { return; } Thirst -= delta; Hunger -= delta; if (Thirst < MAX_THIRST / 2) { var waterSource = _targetResource as IWaterSource; if (waterSource == null || !waterSource.HasWater) { // Seek water var waterSources = new List <IWaterSource>(); Group.CallGroup(GetTree(), Group.WaterSources, source => { if (source.HasWater) { waterSources.Add(source); } }); TargetClosestResource(waterSources); waterSource = _targetResource as IWaterSource; } if (waterSource != null && waterSource.HasWater && Position.DistanceSquaredTo(_targetPosition) <= INTERACTION_RADIUS_SQUARED) { waterSource.TakeWater(this); _targetResource = null; } } else if (Hunger < MAX_HUNGER / 2) { if (Food > 0) { // If we have food, eat Eat(); } else { // Otherwise, seek food var foodSource = _targetResource as IFoodSource; if (foodSource == null || !foodSource.HasFood) { var foodSources = new List <IFoodSource>(); Group.CallGroup(GetTree(), Group.FoodSources, source => { if (!source.HasFood) { return; } var humanSource = source as Human; if (humanSource != null) { if (!ShouldTargetHuman <IFoodSource>(humanSource)) { return; } } foodSources.Add(source); }); TargetClosestResource(foodSources); foodSource = _targetResource as IFoodSource; } if (foodSource != null && foodSource.HasFood && Position.DistanceSquaredTo(_targetPosition) <= INTERACTION_RADIUS_SQUARED) { foodSource.TakeFood(this); _targetResource = null; } } } else { // Not thirsty and not hungry. Anyone we wanna murder nearby? var murderTarget = _targetResource as Human; if (murderTarget == null || murderTarget.Dead) { var peopleIWantToKill = new List <Human>(); Group.Humans.Call(GetTree(), human => { if (human.Dead || Position.DistanceSquaredTo(human.Position) > RAGE_RADIUS_SQUARED) { return; } var aggression = Aggression.Get(_team, human._team); if (aggression == Aggression.Level.Murderous) { peopleIWantToKill.Add(human); } }); TargetClosestResource(peopleIWantToKill); } murderTarget = _targetResource as Human; if (murderTarget != null && !murderTarget.Dead && Position.DistanceSquaredTo(murderTarget.Position) <= RAGE_RADIUS_SQUARED) { // Humans can move, so update the target position regularly _targetPosition = murderTarget.Position; if (Position.DistanceSquaredTo(_targetPosition) <= INTERACTION_RADIUS_SQUARED) { // This will kill them and take all their stuff. Nice! murderTarget.TakeFood(this); _targetResource = null; } } } if (_targetResource != null) { SetAnimationState(AnimationState.Walking); var velocity = (_targetPosition - Position).Normalized() * SPEED * delta; Position += velocity; } else { SetAnimationState(AnimationState.Standing); } if (Thirst <= 0 || Hunger <= 0) { Dead = true; SetAnimationState(AnimationState.Dying); } }