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)
|