Skip to content

Commit

Permalink
Merge pull request PokemonGoF#6086 from davidakachaos/heal_pokemon
Browse files Browse the repository at this point in the history
Introducing HealPokemon
  • Loading branch information
Jcolomar authored Jul 17, 2017
2 parents 7a7a379 + 78d3cc1 commit 12282cc
Show file tree
Hide file tree
Showing 3 changed files with 282 additions and 0 deletions.
30 changes: 30 additions & 0 deletions docs/configuration_files.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
- [BuddyPokemon](#buddypokemon)
- [PokemonHunter](#pokemonhunter)
- [BadPokemon](#badpokemon)
- [HealPokemon](#healpokemon)

# Configuration files

Expand Down Expand Up @@ -1486,3 +1487,32 @@ If you have any Pokemon that Niantic has marked as bad (red slashes) this will n
}
}
```

## HealPokemon
[[back to top](#table-of-contents)]

### Description
[[back to top](#table-of-contents)]

If you have any Pokemon that are dead or need healing, this task will try to do that.

### Options
[[back to top](#table-of-contents)]

* `heal`: `Default: True`. Should Pokemon be healed?
* `revive`: `Default: True`. Should dead Pokemon be revived?


### Sample configuration
[[back to top](#table-of-contents)]
```json
{
"type": "BadPokemon",
"config": {
"enabled": true,
"heal": true,
"revive": true
}
}
```

1 change: 1 addition & 0 deletions pokemongo_bot/cell_workers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,4 @@
from .catch_limiter import CatchLimiter
from .update_hash_stats import UpdateHashStats
from .bad_pokemon import BadPokemon
from .heal_pokemon import HealPokemon
251 changes: 251 additions & 0 deletions pokemongo_bot/cell_workers/heal_pokemon.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from __future__ import absolute_import

from datetime import datetime, timedelta
from pokemongo_bot.base_task import BaseTask
from pokemongo_bot.worker_result import WorkerResult
from pokemongo_bot import inventory
from pokemongo_bot.item_list import Item
from pokemongo_bot.human_behaviour import sleep, action_delay

class HealPokemon(BaseTask):
SUPPORTED_TASK_API_VERSION = 1

def __init__(self, bot, config):
super(HealPokemon, self).__init__(bot, config)
self.bot = bot
self.config = config
self.enabled = self.config.get("enabled", False)
self.revive_pokemon = self.config.get("revive", True)
self.heal_pokemon = self.config.get("heal", True)
self.next_update = None
self.to_heal = []

def work(self):

if not self.enabled:
return WorkerResult.SUCCESS

# Check for pokemon to heal or revive
to_revive = []
self.to_heal = []
pokemons = inventory.pokemons().all()
pokemons.sort(key=lambda p: p.hp)
for pokemon in pokemons:
if pokemon.hp < 1.0:
self.logger.info("Dead: %s (%s CP| %s/%s )" % (pokemon.name, pokemon.cp, pokemon.hp, pokemon.hp_max))
to_revive += [pokemon]
elif pokemon.hp < pokemon.hp_max:
self.logger.info("Heal: %s (%s CP| %s/%s )" % (pokemon.name, pokemon.cp, pokemon.hp, pokemon.hp_max))
self.to_heal += [pokemon]

if len(self.to_heal) == 0 and len(to_revive) == 0:
if self._should_print:
self.next_update = datetime.now() + timedelta(seconds=120)
#self.logger.info("No pokemon to heal or revive")
return WorkerResult.SUCCESS
# Okay, start reviving pokemons
# Check revives and potions
revives = inventory.items().get(Item.ITEM_REVIVE.value).count
max_revives = inventory.items().get(Item.ITEM_MAX_REVIVE.value).count
normal = inventory.items().get(Item.ITEM_POTION.value).count
super_p = inventory.items().get(Item.ITEM_SUPER_POTION.value).count
hyper = inventory.items().get(Item.ITEM_HYPER_POTION.value).count
max_p = inventory.items().get(Item.ITEM_MAX_POTION.value).count

self.logger.info("Healing %s pokemon" % len(self.to_heal))
self.logger.info("Reviving %s pokemon" % len(to_revive))

if self.revive_pokemon:
if len(to_revive) > 0 and revives == 0 and max_revives == 0:
self.logger.info("No revives left! Can't revive %s pokemons." % len(to_revive))
elif len(to_revive) > 0:
self.logger.info("Reviving %s pokemon..." % len(to_revive))
for pokemon in to_revive:
self._revive_pokemon(pokemon)

if self.heal_pokemon:
if len(self.to_heal) > 0 and (normal + super_p + hyper + max_p) == 0:
self.logger.info("No potions left! Can't heal %s pokemon" % len(self.to_heal))
elif len(self.to_heal) > 0:
self.logger.info("Healing %s pokemon" % len(self.to_heal))
for pokemon in self.to_heal:
self._heal_pokemon(pokemon)

if self._should_print:
self.next_update = datetime.now() + timedelta(seconds=120)
self.logger.info("Done healing/reviving pokemon")

def _revive_pokemon(self, pokemon):
item = Item.ITEM_REVIVE.value
amount = inventory.items().get(item).count
if amount == 0:
self.logger.info("No normal revives left, using MAX revive!")
item = Item.ITEM_MAX_REVIVE.value

amount = inventory.items().get(item).count
if amount > 0:
response_dict_revive = self.bot.api.use_item_revive(item_id=item, pokemon_id=pokemon.unique_id)
action_delay(2, 3)
if response_dict_revive:
result = response_dict_revive.get('responses', {}).get('USE_ITEM_REVIVE', {}).get('result', 0)
revive_item = inventory.items().get(item)
# Remove the revive from the iventory
revive_item.remove(1)
if result is 1: # Request success
self.emit_event(
'revived_pokemon',
formatted='Revived {name}.',
data={
'name': pokemon.name
}
)
if item == Item.ITEM_REVIVE.value:
pokemon.hp = int(pokemon.hp_max / 2)
self.to_heal.append(pokemon)
else:
# Set pokemon as revived
pokemon.hp = pokemon.hp_max
return True
else:
self.emit_event(
'revived_pokemon',
level='error',
formatted='Failed to revive {name}!',
data={
'name': pokemon.name
}
)
return False

def _heal_pokemon(self, pokemon):
if pokemon.hp == 0:
self.logger.info("Can't heal a dead %s" % pokemon.name)
return False
# normal = inventory.items().get(Item.ITEM_POTION.value).count
# super_p = inventory.items().get(Item.ITEM_SUPER_POTION.value).count
# hyper = inventory.items().get(Item.ITEM_HYPER_POTION.value).count
max_p = inventory.items().get(Item.ITEM_MAX_POTION.value).count
# Figure out how much healing needs to be done.
def hp_to_restore(pokemon):
pokemon = inventory.pokemons().get_from_unique_id(pokemon.unique_id)
return pokemon.hp_max - pokemon.hp

if hp_to_restore(pokemon) > 200 and max_p > 0:
# We should use a MAX Potion
self._use_potion(Item.ITEM_MAX_POTION.value, pokemon)
pokemon.hp = pokemon.hp_max
return True
# Okay, now we see to heal as effective as possible
potions = [103, 102, 101]
heals = [200, 50, 20]

for item_id, max_heal in zip(potions, heals):
if inventory.items().get(item_id).count > 0:
while hp_to_restore(pokemon) > max_heal:
if inventory.items().get(item_id).count == 0:
break
action_delay(2, 3)
# More than 200 to restore, use a hyper first
if self._use_potion(item_id, pokemon):
pokemon.hp += max_heal
if pokemon.hp > pokemon.hp_max:
pokemon.hp = pokemon.hp_max
else:
break
# return WorkerResult.ERROR

# Now we use the least
potion_id = 101 # Normals first
while hp_to_restore(pokemon) > 0:
action_delay(2, 4)
if inventory.items().get(potion_id).count > 0:
if potion_id == 104:
self.logger.info("Using MAX potion to heal a %s" % pokemon.name)
if self._use_potion(potion_id, pokemon):
if potion_id == 104:
pokemon.hp = pokemon.hp_max
else:
pokemon.hp += heals[potion_id - 101]
if pokemon.hp > pokemon.hp_max:
pokemon.hp = pokemon.hp_max
else:
if potion_id < 104:
self.logger.info("Failed with potion %s. Trying next." % potion_id)
potion_id += 1
else:
self.logger.info("Failed with MAX potion. Done.")
break
elif potion_id < 104:
potion_id += 1
else:
self.logger.info("Can't heal a %s" % pokemon.name)
break


def _use_potion(self, potion_id, pokemon):
potion_count = inventory.items().get(potion_id).count
healing = 0
if potion_count == 0:
return False
if potion_id == 101:
self.logger.info("Healing with a normal potion we have %s left." % (potion_count - 1))
healing = 20
if potion_id == 102:
self.logger.info("Healing with a Super potion we have %s left." % (potion_count - 1))
healing = 50
if potion_id == 103:
self.logger.info("Healing with a HYper potion we have %s left." % (potion_count - 1))
healing = 200
if potion_id == 104:
self.logger.info("Healing with a MAX potion we have %s left." % (potion_count - 1))
healing = pokemon.hp_max - pokemon.hp

response_dict_potion = self.bot.api.use_item_potion(item_id=potion_id, pokemon_id=pokemon.unique_id)
# Select potion
sleep(2)
if response_dict_potion:
result = response_dict_potion.get('responses', {}).get('USE_ITEM_POTION', {}).get('result', 0)
if result is 1 or result is 0: # Request success
potion_item = inventory.items().get(potion_id)
# Remove the potion from the iventory
potion_item.remove(1)
self.emit_event(
'healing_pokemon',
formatted='Healing {name} ({hp} -> {hp_new}/{hp_max}).',
data={
'name': pokemon.name,
'hp': pokemon.hp,
'hp_new': pokemon.hp + healing,
'hp_max': pokemon.hp_max
}
)
return True
elif result == 3:
# ERROR_CANNOT_USE
pokemon.hp = pokemon.hp_max
self.logger.info("Can't use this to heal the %s" % pokemon.name)
return False
else:
self.logger.info("Result was: %s" % result)
self.emit_event(
'healing_pokemon',
level='error',
formatted='Failed to heal {name} ({hp} -> {hp_new}/{hp_max})!',
data={
'name': pokemon.name,
'hp': pokemon.hp,
'hp_new': pokemon.hp + healing,
'hp_max': pokemon.hp_max
}
)
return False

def _should_print(self):
"""
Returns a value indicating whether the pokemon should be displayed.
:return: True if the stats should be displayed; otherwise, False.
:rtype: bool
"""
return self.next_update is None or datetime.now() >= self.next_update

0 comments on commit 12282cc

Please sign in to comment.