public override bool CanContinue() { var target = _entity.Target; if (target == null) { return(false); } if (target.HealthManager.IsDead) { return(false); } if (!(target is Player)) { if (_entity.DistanceTo(target) > _targetDistance) { return(false); } } else { if (_entity.DistanceTo(target) > GetTargetDistance((Player)target)) { return(false); } if (_entity.CanSee(target)) { _targetUnseenTicks = 0; } else if (_targetUnseenTicks++ > 60) { return(false); } _entity.SetTarget(target); // This makes sense when we to attacked by targeting } return(true); }
public override bool CanContinue() { // Give the poor entity a chance to survive // Also makes it let go of unreachable targets if (_entity.Level.Random.Next(_attackChance) == 0) { return(false); } var target = _entity.Target; if (target == null) { return(false); } if (target.HealthManager.IsDead) { return(false); } if (_entity.DistanceTo(target) > _targetDistance) { return(false); } if (_entity.CanSee(target)) { _targetUnseenTicks = 0; } else if (_targetUnseenTicks++ > 60) { return(false); } _entity.SetTarget(target); // This makes sense when we to attacked by targeting return(true); }
public override void OnTick(Entity[] entities) { Entity target = _entity.Target; if (target == null) { return; } double distanceToPlayer = _entity.DistanceTo(target); --_delay; float deltaDistance = Vector3.Distance(_lastPlayerPos, target.KnownPosition); bool canSee = _entity.CanSee(target); if (canSee || _delay <= 0 || deltaDistance > 1 || _entity.Level.Random.NextDouble() < 0.05) { var pathfinder = new Pathfinder(); Stopwatch sw = Stopwatch.StartNew(); _currentPath = pathfinder.FindPath(_entity, target, _followRange); if (Log.IsDebugEnabled) { sw.Stop(); if (sw.ElapsedMilliseconds > 5) { Log.Warn($"A* search for {_entity.GetType()} on a distance of {_followRange}. Spent {sw.ElapsedMilliseconds}ms and lenght of path is {_currentPath.Current.Count}"); } // DEBUG //_currentPath.PrintPath(_entity.Level); } _lastPlayerPos = target.KnownPosition; _delay = 4 + _entity.Level.Random.Next(7); if (distanceToPlayer > 32) { _delay += 10; } else if (distanceToPlayer > 16) { _delay += 5; } if (_currentPath.NoPath()) { _delay += 15; } } // Movement if (_currentPath.HavePath()) { if (_currentPath.GetNextTile(_entity, out Tile next /*, true*/)) { _entity.Controller.RotateTowards(new Vector3(next.X + 0.5f, _entity.KnownPosition.Y, next.Y + 0.5f)); _entity.Controller.MoveForward(_speedMultiplier, entities); } // else something is really wrong } else { _entity.Velocity = Vector3.Zero; } _entity.Controller.LookAt(target); _attackCooldown = Math.Max(_attackCooldown - 1, 0); if (_attackCooldown <= 0 && distanceToPlayer < GetAttackReach()) { var damage = _entity.AttackDamage; target.HealthManager.TakeHit(_entity, damage, DamageCause.EntityAttack); _attackCooldown = 20; } }