import time import net.mapserv as mapserv import net.charserv as charserv import net.stats as stats import walkto import logicmanager import commands from net.common import distance from net.inventory import get_item_index from utils import extends from loggers import debuglog from actor import find_nearest_being __all__ = [ 'PLUGIN', 'init', 'hp_healing_ids', 'hp_heal_at', 'mp_healing_ids', 'mp_heal_at', 'auto_attack', 'auto_pickup', 'auto_heal_self', 'auto_heal_others' ] PLUGIN = { 'name': 'battlebot', 'requires': (), 'blocks': (), } target = None # last_time_attacked = 0 aa_next_time = 0 hp_healing_ids = [ 535, 541 ] hp_heal_at = 0.3 hp_is_healing = False hp_prev_value = 0 mp_healing_ids = [ 826 ] mp_heal_at = 0.5 mp_is_healing = False mp_prev_value = 0 players_taken_damage = {} player_damage_heal = 300 aa_monster_types = [] auto_pickup = True auto_attack = False auto_heal_self = False auto_heal_others = False @extends('smsg_being_action') def being_action(data): # global last_time_attacked global aa_next_time if data.type in (0, 10): if data.src_id == charserv.server.account: # last_time_attacked = time.time() aa_next_time = time.time() + 5.0 if (auto_heal_others and data.dst_id != charserv.server.account and data.dst_id in mapserv.beings_cache and mapserv.beings_cache[data.dst_id].type == 'player'): players_taken_damage[data.dst_id] = players_taken_damage.get( data.dst_id, 0) + data.damage if players_taken_damage[data.dst_id] >= player_damage_heal: mapserv.cmsg_chat_message("#inma {}".format( mapserv.beings_cache[data.dst_id].name)) players_taken_damage[data.dst_id] = 0 @extends('smsg_item_dropped') @extends('smsg_item_visible') def flooritem_appears(data): if not auto_pickup: return item = mapserv.floor_items[data.id] px = mapserv.player_pos['x'] py = mapserv.player_pos['y'] if distance(px, py, item.x, item.y) > 3: return walkto.walkto_and_action(item, 'pickup') @extends('smsg_player_status_change') def player_status_change(data): global hp_is_healing if data.id == charserv.server.account: if data.effect == 256: hp_is_healing = True elif data.effect == 0: hp_is_healing = False @extends('smsg_player_stat_update_x') def player_stat_update(data): if not auto_heal_self: return global hp_prev_value, mp_prev_value if data.type == stats.HP: max_hp = mapserv.player_stats.get(stats.MAX_HP, 0) if data.stat_value < max_hp * hp_heal_at and not hp_is_healing: healing_found = False for item_id in hp_healing_ids: index = get_item_index(item_id) if index > 0: healing_found = True debuglog.info("Consuming %d", item_id) mapserv.cmsg_player_inventory_use(index, item_id) break if not healing_found: debuglog.info("Low health, but no HP healing item found") hp_prev_value = data.stat_value elif data.type == stats.MP: max_mp = mapserv.player_stats.get(stats.MAX_MP, 0) if data.stat_value < max_mp * mp_heal_at and not mp_is_healing: healing_found = False for item_id in mp_healing_ids: index = get_item_index(item_id) if index > 0: healing_found = True debuglog.info("Consuming %d", item_id) mapserv.cmsg_player_inventory_use(index, item_id) break if not healing_found: debuglog.info("Low mana, but no MP healing item found") mp_prev_value = data.stat_value @extends('smsg_being_remove') def being_remove(data): global target if target is not None and target.id == data.id: target = None aa_next_time = time.time() + 5.0 def battlebot_logic(ts): if not auto_attack: return global target # global last_time_attacked global aa_next_time if ts < aa_next_time: return if target is None: if walkto.state: return target = find_nearest_being(type='monster', ignored_ids=walkto.unreachable_ids, allowed_jobs=aa_monster_types) if target is not None: # last_time_attacked = time.time() aa_next_time = time.time() + 5.0 walkto.walkto_and_action(target, 'attack') elif ts > aa_next_time: walkto.walkto_and_action(target, 'attack') def startbot(_, arg): '''Start autoattacking and autolooting''' global auto_attack global auto_pickup global aa_monster_types auto_attack = True auto_pickup = True try: aa_monster_types = map(int, arg.split()) except ValueError: aa_monster_types = [] def stopbot(cmd, _): '''Stop battlebot''' global auto_attack global auto_pickup global auto_heal_self global auto_heal_others global target auto_attack = False auto_pickup = False auto_heal_self = False auto_heal_others = False if target is not None: mapserv.cmsg_player_stop_attack() target = None def debugbot(cmd, _): px = mapserv.player_pos['x'] py = mapserv.player_pos['y'] target_info = '' if target is not None: target_info = '{} at ({},{})'.format(target.name, target.x, target.y) debuglog.info('target = %s | player at (%d, %d)', target_info, px, py) bot_commands = { 'startbot' : startbot, 'stopbot' : stopbot, 'debugbot' : debugbot, } def init(config): logicmanager.logic_manager.add_logic(battlebot_logic) commands.commands.update(bot_commands)