protected override void OnTick() { base.OnTick(); GameCharacter controlledObj = Owner.ControlledObject; if (IsAllowUpdateControlledObject() && controlledObj.GetElapsedTimeSinceLastGroundContact() < .3f) //IsOnGround() ) { float targetDistance = (GetTargetPosition() - controlledObj.Position).Length(); //movement { Vec3 rayCastFrom; if (Owner.weapons.Length != 0) { rayCastFrom = Owner.weapons[0].Position; } else { rayCastFrom = controlledObj.Position; } Range optimalAttackDistanceRange = controlledObj.Type.OptimalAttackDistanceRange; if (targetDistance < optimalAttackDistanceRange.Maximum && CheckDirectVisibilityByRayCast(rayCastFrom, GetTargetPosition(), TaskEntity)) { //destination target is visible controlledObj.SetTurnToPosition(GetTargetPosition()); if (targetDistance < optimalAttackDistanceRange.Minimum) { //move backward Vec2 direction = GetTargetPosition().ToVec2() - controlledObj.Position.ToVec2(); if (direction != Vec2.Zero) { direction = -direction.GetNormalize(); } controlledObj.SetForceMoveVector(direction); } else { //sees the target and stay on optimal attack distance controlledObj.SetForceMoveVector(Vec2.Zero); } } else { //need move //update path controller Owner.pathController.Update(Entity.TickDelta, controlledObj.Position, GetTargetPosition(), false); //update character Vec3 nextPointPosition; if (Owner.pathController.GetNextPointPosition(out nextPointPosition)) { Vec2 vector = nextPointPosition.ToVec2() - controlledObj.Position.ToVec2(); if (vector != Vec2.Zero) { vector.Normalize(); } controlledObj.SetTurnToPosition(nextPointPosition); controlledObj.SetForceMoveVector(vector); } else { controlledObj.SetForceMoveVector(Vec2.Zero); } } } //shot foreach (Weapon weapon in Owner.weapons) { if (weapon.Ready) { Range normalRange = weapon.Type.WeaponNormalMode.UseDistanceRange; bool normalInRange = targetDistance >= normalRange.Minimum && targetDistance <= normalRange.Maximum; Range alternativeRange = weapon.Type.WeaponAlternativeMode.UseDistanceRange; bool alternativeInRange = targetDistance >= alternativeRange.Minimum && targetDistance <= alternativeRange.Maximum; if ((normalInRange || alternativeInRange) && CheckDirectVisibilityByRayCast(weapon.Position, GetTargetPosition(), TaskEntity)) { //update weapon fire orientation { Vec3 pos = GetTargetPosition(); Gun gun = weapon as Gun; if (gun != null) { gun.GetAdvanceAttackTargetPosition(false, TaskEntity, false, out pos); } weapon.SetForceFireRotationLookTo(pos); } controlledObj.SetTurnToPosition(GetTargetPosition()); if (normalInRange) { weapon.TryFire(false); } if (alternativeInRange) { weapon.TryFire(true); } } } } } else { controlledObj.SetForceMoveVector(Vec2.Zero); } }