Repository: PokemonGoF/PokemonGo-Bot

Issue:
Add Pokeball miss per pokemon to pokemon_catch_worker.py
### Expected Behavior

When we throw pokeball, sometimes we miss. Usually I use up to 5 balls to catch a Zubat, then I "run" if I couldn't get. 
### Actual Behavior

With the Bot, I can catch a Zubat at 100% success rate.
### Possible solution

Change the pokemon_catch_worker.py to add a throw miss rate and maximum numbers of pokeball before "run".
### How it would help others

It would be more human like. 



Discussion:

Resolving patch:
diff --git a/pokemongo_bot/cell_workers/pokemon_catch_worker.py b/pokemongo_bot/cell_workers/pokemon_catch_worker.py
--- a/pokemongo_bot/cell_workers/pokemon_catch_worker.py
+++ b/pokemongo_bot/cell_workers/pokemon_catch_worker.py
@@ -18,6 +18,7 @@
 CATCH_STATUS_SUCCESS = 1
 CATCH_STATUS_FAILED = 2
 CATCH_STATUS_VANISHED = 3
+CATCH_STATUS_MISSED = 4
 
 ENCOUNTER_STATUS_SUCCESS = 1
 ENCOUNTER_STATUS_NOT_IN_RANGE = 5
@@ -58,6 +59,7 @@ def initialize(self):
         self.catch_throw_parameters_great_rate = self.catch_throw_parameters.get('great_rate', 0.5)
         self.catch_throw_parameters_nice_rate = self.catch_throw_parameters.get('nice_rate', 0.3)
         self.catch_throw_parameters_normal_rate = self.catch_throw_parameters.get('normal_rate', 0.1)
+        self.catch_throw_parameters_hit_rate = self.catch_throw_parameters.get('hit_rate', 0.8)
 
         self.catchsim_config = self.config.get('catch_simulation', {})
         self.catchsim_catch_wait_min = self.catchsim_config.get('catch_wait_min', 2)
@@ -124,7 +126,7 @@ def work(self, response_dict=None):
         )
 
         # simulate app
-        sleep(3)
+        time.sleep(3)
 
         # check for VIP pokemon
         if is_vip:
@@ -393,12 +395,16 @@ def _do_catch(self, pokemon, encounter_id, catch_rate_by_ball, is_vip=False):
                 }
             )
 
+            hit_pokemon = 1
+            if random() >= self.catch_throw_parameters_hit_rate:
+                hit_pokemon = 0
+
             response_dict = self.api.catch_pokemon(
                 encounter_id=encounter_id,
                 pokeball=current_ball,
                 normalized_reticle_size=throw_parameters['normalized_reticle_size'],
                 spawn_point_id=self.spawn_point_guid,
-                hit_pokemon=1,
+                hit_pokemon=hit_pokemon,
                 spin_modifier=throw_parameters['spin_modifier'],
                 normalized_hit_position=throw_parameters['normalized_hit_position']
             )
@@ -493,6 +499,17 @@ def _do_catch(self, pokemon, encounter_id, catch_rate_by_ball, is_vip=False):
                 )
 
                 self.bot.softban = False
+
+            elif catch_pokemon_status == CATCH_STATUS_MISSED:
+                self.emit_event(
+                    'pokemon_capture_failed',
+                    formatted='Pokeball thrown to {pokemon} missed.. trying again!',
+                    data={'pokemon': pokemon.name}
+                )
+                # Take some time to throw the ball from config options
+                action_delay(self.catchsim_catch_wait_min, self.catchsim_catch_wait_max)
+                continue
+
             break
 
     def get_candy_gained_count(self, response_dict):


Test patch: