summaryrefslogtreecommitdiff
path: root/plugins/battlebot.py
blob: 5cba46755b71bb18fe6ae206a1e8056f3e53fb98 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
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 = '<no_target>'
    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)