-
Notifications
You must be signed in to change notification settings - Fork 178
/
burgle.lic
598 lines (530 loc) · 23.8 KB
/
burgle.lic
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
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
=begin
Very simple Breaking and Entering script. Use at your own risk - there are VERY high fines if you get caught
Documentation: https://elanthipedia.play.net/Lich_script_repository#burgle
=end
custom_require.call(%w[common common-travel common-items equipmanager])
class Burgle
def initialize
arg_definitions = [
[
{ name: 'start', regex: /start/, optional: false, description: 'Required: prevents accidentally running burgle and protects against burgle typo for starting script' },
{ name: 'entry', options: %w[lockpick rope cycle prioritylockpick priorityrope], optional: true, description: 'Override yaml setting for entry_type.' },
{ name: 'roomid', regex: /\d+/, optional: true, description: 'Override yaml setting and go to room id (#) specified. The room should be chosen VERY carefully.' },
{ name: 'loot_type', options: %w[drop keep pawn bin trashcan], optional: true, description: 'Override yaml setting for loot. (items on item_whitelist are always kept.)' },
{ name: 'hometown', options: $HOMETOWN_LIST, optional: true, description: 'Override yaml hometown settings for bin and pawn. If no bin or pawnshop in that hometown, loot_type will revert to drop.' },
{ name: 'follow', options: %w[follow], optional: true, description: "Follow another player, don't actually burgle. You must group with them first." }
]
]
args = parse_args(arg_definitions)
# Ensure hometown is in sentence case if it's specified - fixes the fact parse_args is always lower case
args.hometown = args.hometown.gsub(/\b('?[a-z])/) { $1.capitalize } if args.hometown
# kludge fix for Mer'Kresh
args.hometown = "Mer'Kresh" if args.hometown == "Mer'kresh"
@follow = false
@follow = true if args.follow
# hash which maps directions to their reverse, for backing out of the house
@reverse_direction_map = {
'east' => 'west',
'west' => 'east',
'south' => 'north',
'north' => 'south',
'northeast' => 'southwest',
'southwest' => 'northeast',
'northwest' => 'southeast',
'southeast' => 'northwest'
}
# maps the searchable objects based on the room title
@room_searchable_objects_map = {
"Kitchen" => 'counter',
"Bedroom" => 'bed',
"Armory" => 'rack',
"Library" => 'bookshelf',
"Sanctum" => 'desk',
"Work Room" => 'table'
}
# Pause scripts to prevent interference
until (@scripts_to_unpause = DRC.safe_pause_list)
echo("Cannot pause, trying again in 30 seconds.")
pause 30
end
start_script('jail-buddy') unless Script.running?('jail-buddy')
@settings = get_settings
@burgle_settings = @settings.burgle_settings
@loot_container = @burgle_settings['loot_container']
@use_lockpick_ring = @burgle_settings['use_lockpick_ring']
@lockpick_container = @burgle_settings['lockpick_container']
@max_priority_mindstate = @burgle_settings['max_priority_mindstate'] || 26
@rope_adjective = @burgle_settings['rope_adjective'] || 'heavy'
@loot_room_id = nil
@worn_trashcan = @settings.worn_trashcan
@worn_trashcan_verb = @settings.worn_trashcan_verb
# set yaml settings unless being overridden from the command line arguments
@entry_type = args.entry || @burgle_settings['entry_type']
@burgle_room = args.roomid ? args.roomid.to_i : @burgle_settings['room']
@loot_type = args.loot_type || @burgle_settings['loot']
case @loot_type
when /trashcan/
if !@worn_trashcan || !@worn_trashcan_verb
echo("The `loot_type: trashcan` setting requires the base.yaml`worn_trashcan:` and `worn_trashcan_verb:` settings to be set in your yaml.")
exit
end
end
@hometown = args.hometown || @burgle_settings['hometown'] || @settings.burgle_town || @settings.fang_cove_override_town || @settings.hometown
@burgle_before_scripts = @burgle_settings['before']
@burgle_after_scripts = @burgle_settings['after']
if @entry_type =~ /lockpick|cycle/ && (@use_lockpick_ring == nil || @lockpick_container == nil)
DRC.message("Settings for lockpick rings are now in burgle_settings:use_lockpick_ring and burgle_settings:lockpick_container.")
DRC.message("Using old setting of use_lockpick_ring and lockpick_container from pick for now, but this will be removed in the future.")
DRC.message("To reuse the same settings, please use anchors: https://github.com/rpherbig/dr-scripts/wiki/YAML-Anchors")
@use_lockpick_ring = @settings.use_lockpick_ring if @use_lockpick_ring == nil
@lockpick_container = @settings.lockpick_container if @lockpick_container == nil
end
# setup an empty list for loot. used to store the loot you manage to get, to ether drop, pawn or bin.
@loot_list = []
# Add flag to watch for warning sign, unless safe mode is turned off - safe_mode is defaulted
# anywhere this flag is checked, it prevents further actions being taken and should force you out of the house
Flags.add('burgle-footsteps', "Footsteps nearby make you wonder if you're pushing your luck.") unless @burgle_settings['safe_mode'] == false
# Check minimal yaml settings before starting. Missing these can lead to staying in the house too long
# this is not a 100% check. it is still possible to mess up and get stuck in the house if you're not careful with your settings
if !valid_burgle_settings?
DRC.message("It is very important that you check the documentation before running: https://elanthipedia.play.net/Lich_script_repository#burgle ")
DRC.message("This is a dangerous script to run if it's not understood. If you get caught there are very high fines, and the loss of all your items is possible if you can't pay your debt.")
pause 10
end_burgle
end
burgle
end_burgle
end
def valid_burgle_settings?
if @burgle_settings.empty?
DRC.message("You have empty burgle_settings. These must be set before running.")
return false
end
if @burgle_room.is_a?(Array)
@burgle_room = DRCT.sort_destinations(@burgle_room)[0]
end
unless @burgle_room.is_a?(Integer)
DRC.message("Invalid burgle_settings:room setting. This must be room id of the room you want to burgle from.")
return false
end
if @entry_type == nil || @entry_type !~ /lockpick|rope|cycle|prioritylockpick|priorityrope/i
DRC.message("Invalid burgle_settings:entry_type setting.")
return false
end
if @burgle_settings['max_search_count'] > 0
case DRC.bput("open my #{@loot_container}", 'already open', '^You.+open', '^You spread your arms, carefully holding your bag well away from your body', 'Please rephrase that command', 'What were you referring', 'You can\'t do that', 'This is probably not the time nor place for that')
when 'This is probably not the time nor place for that'
if @follow
DRC.message("Couldn't verify your bag due to room restrictions. Allowing the script to continue assuming your #{@loot_container} is open and available.")
return true
else
travel_to_burgle_room
return valid_burgle_settings?
end
when 'Please rephrase that command', 'What were you referring', 'You can\'t do that'
DRC.message("You do not have a burgle_settings:loot_container set/set to container you have. Loot must have a place to be stored prior to exiting the house, even if dropping loot.")
return false
end
end
case @loot_type
when /bin/
validate_bin_settings
when /pawn/
validate_pawn_settings
else
@loot_room_id = nil
end
return true
end
def validate_bin_settings
# bin only works if you're a thief, and there is a bin in your hometown
# fall back to pawning if you can't bin for some reason, next best option since you don't want to keep the loot
if DRStats.thief?
@loot_room_id = DRCT.get_hometown_target_id(@hometown, 'thief_bin')
if !(@loot_room_id)
DRC.message("Binning not supported in #{@hometown}. Attempting fallback to pawning loot.")
pause 5
@loot_type = 'pawn'
validate_pawn_settings
end
else
DRC.message("You are not a thief. You can't use thief bins. Attempting fallback to pawning loot.")
pause 5
@loot_type = 'pawn'
validate_pawn_settings
end
end
def validate_pawn_settings
# pawn only works if there is a pawnshop in your hometown
# fall back to drop if you can't pawn, next best option since you don't want to keep the loot
@loot_room_id = DRCT.get_hometown_target_id(@hometown, 'pawnshop')
if !(@loot_room_id)
@loot_type = 'drop'
DRC.message("Pawning not supported in #{@hometown}. Fallback to dropping loot.")
end
end
def burgle
# check to make sure you aren't under cooldown. If you are, you will be instantly arrested, so return from script if this is the case
return unless /The heat has died down from your last caper/ =~ DRC.bput('burgle recall', '^You should wait at least \d+ roisaen for the heat to die down', '^The heat has died down from your last caper')
# don't bother with entry type checks if following
if !@follow
# check for entry method, and ensure you have the required items
case @entry_type
when /priorityrope/
if DRSkill.getxp('Athletics') <= @max_priority_mindstate || DRSkill.getxp('Athletics') < DRSkill.getxp('Locksmithing')
check_cycle_priority('rope')
else
check_cycle_priority('lockpick')
end
when /prioritylockpick/
if DRSkill.getxp('Locksmithing') <= @max_priority_mindstate || DRSkill.getxp('Locksmithing') < DRSkill.getxp('Athletics')
check_cycle_priority('lockpick')
else
check_cycle_priority('rope')
end
when /rope/i
if !check_entry?(@entry_type)
DRC.message("Couldn't find entry item: #{@rope_adjective} rope")
end_burgle
end
when /lockpick/i
if !check_entry?(@entry_type)
if @use_lockpick_ring
DRC.message("Couldn't find entry item: #{@lockpick_container}")
else
DRC.message("Couldn't find entry item: lockpick")
end
end_burgle
end
when /cycle/i
case DRSkill.getxp('Athletics') <=> DRSkill.getxp('Locksmithing')
when -1
check_cycle_priority("rope")
when 0
if DRSkill.getrank('Athletics') < DRSkill.getrank('Locksmithing')
check_cycle_priority("rope")
else
check_cycle_priority("lockpick")
end
when 1
check_cycle_priority("lockpick")
end
else
DRC.message("Unknown entry method: #{@entry_type}")
return
end
end
# entry method must be in your right hand, or have a worn lockpick ring
# the item in your takes priority, so store any items in your hands before beginning
EquipmentManager.new.empty_hands
if DRC.right_hand || DRC.left_hand
echo "Exited due to item that could not be stowed. Please check your hands and gear settings then try again."
end_burgle
end
# don't bother heading to the right area, if following
travel_to_burgle_room unless @follow
execute_extra_scripts(@burgle_before_scripts)
get_entry(@entry_type) unless @follow
# prevent race condition that can occur with bput and invisibility/stealth and playing music
DRC.bput('stop play', 'In the name of love', 'You stop playing', 'But you\'re not performing anything') if (Script.running?('performance') || Script.running?('play'))
DRC.wait_for_script_to_complete('buff', ['burgle']) if @settings.waggle_sets['burgle']
DRC.fix_standing
# ensure you're in hiding or invis before starting
if !invisible?
hide_attempts = 3
until DRC.hide?
hide_attempts -= 1
if hide_attempts <= 0
DRC.message("Couldn't hide. Find a better room.")
return
end
end
end
# setup flags for group burgle here
Flags.add('group-burgle-disband', 'With aid from your group')
Flags.add('group-burgle-leave', 'With aid from his group', 'With aid from her group')
# match is for room title, so that in rob_the_place the XMLData.room_title is already properly set
if @follow
waitfor("Someone Else's Home")
else
DRC.bput('burgle', "Someone Else's Home")
end
# leave the group/disband so you aren't carried around
if Flags['group-burgle-leave']
fput('leave')
elsif Flags['group-burgle-disband']
fput('disband stalk')
fput('disband group')
else
pause 1 # need a pause because there is no indicator if you are part of a group currently with 2 person rope entry
end
if @burgle_settings['max_search_count'] > 0
@search_count = 0
rob_the_place
end
DRC.bput('go window', 'You take a moment to reflect on the caper')
# likely to have invisibility up if you have access to it.
# be sure to release it since it breaks a lot of things
DRC.release_invisibility
# reset Flags so that store_loot fires correctly
Flags.reset('burgle-footsteps')
# make hands empty again, as they likely have loot/entry method in them
store_loot
execute_extra_scripts(@burgle_after_scripts)
process_loot
end
# ensures you have the proper entry methods accessible
def check_entry?(entry_type)
case entry_type
when /rope/i
return DRCI.exists?("#{@rope_adjective} rope")
when /lockpick/i
if @use_lockpick_ring
return DRCI.exists?(@lockpick_container)
else
return DRCI.exists?("lockpick")
end
end
return false # invalid entry type
end
def travel_to_burgle_room
unless DRCT.walk_to(@burgle_room)
DRC.message("Unable to get to your burgle room. Exiting to prevent errors.")
end_burgle
end
end
# selected cycle for entry_type, validate that you have the prioritized entry_type, and if not, fallback to other
def check_cycle_priority(entry_type)
case entry_type
when /rope/i
if !check_entry?("rope") # if you don't have a rope, fall back to lockpick
if !check_entry?("lockpick") # if you don't have a lockpick, after falling back from rope, you can't do anything
DRC.message("Couldn't find any entry method.")
end_burgle
else
DRC.message("Set to cycle or priority, but could only find lockpick.") # warn user that they are missing an entry method. cycle requires presence of both to work right
end
@entry_type = "lockpick"
else
@entry_type = "rope"
end
when /lockpick/i
if !check_entry?("lockpick") # if you don't have a lockpick, fall back to rope
if !check_entry?("rope") # if you don't have a rope, after falling back from lockpick, you can't do anything
DRC.message("Couldn't find any entry method.")
end_burgle
else
DRC.message("Set to cycle or priority, but could only find rope.") # warn user that they are missing an entry method. cycle requires presence of both to work right
end
@entry_type = "rope"
else
@entry_type = "lockpick"
end
else
DRC.message("Invalid priority type.")
end_burgle
end
end
# Should already have checked for entry type, now get it (right before buff/robbing), but this validates anyway to be safe
def get_entry(entry_type)
case entry_type
when /rope/i
if DRC.bput("get my #{@rope_adjective} rope", 'You get', 'You are already holding', 'What were you') =~ /What were you/
DRC.message("Couldn't find entry item: #{@rope_adjective} rope")
end_burgle
end
when /lockpick/i
if @use_lockpick_ring
return
elsif DRC.bput('get my lockpick', 'You get', 'You are already holding', 'What were you') =~ /What were you/
DRC.message("Couldn't find entry item: lockpick")
end_burgle
end
end
end
def end_burgle
DRC.safe_unpause_list(@scripts_to_unpause)
exit
end
# direction is the direction you came from to get to this room
def rob_the_place(direction = nil)
# empty array for directions you have already visited
visited = []
# if you came from a previous room, add it to the array so you don't loop
visited.push(direction) unless direction == nil
# get the room type, which is used to get searchable objects
if (room_match = XMLData.room_title.match(/\[\[Someone Else's Home, (?<room>.*)\]\]/))
current_room = room_match[:room]
# search the lootable objects unless the room type has been blacklisted
search_for_loot(@room_searchable_objects_map[current_room]) unless @burgle_settings['room_blacklist'].include?(current_room)
# while you still have other rooms from this room to visit, you haven't exhausted your search count, and you haven't seen footsteps in safe_mood:
while XMLData.room_exits.count > visited.count && @search_count < @burgle_settings['max_search_count'] && !(Flags['burgle-footsteps']) do
# pick a new room to go to
newdir = XMLData.room_exits.reject { |exit| visited.include?(exit) }.sample
# store that you're going to it
visited.push(newdir)
# store how to back out
reverse = @reverse_direction_map[newdir]
# go to the picked room
burgle_move(newdir)
# loot the new room, unless you've seen footsteps in safe_mode
rob_the_place(reverse) unless Flags['burgle-footsteps']
# backup to the original room
burgle_move(reverse)
end
end
end
def search_for_loot(target)
# don't hide/search if you've seen footsteps and are in safe_mode
return if Flags['burgle-footsteps']
# ensure you're in hiding or invis before looting -> only try once because of timer
if !invisible?
DRC.hide?
DRC.message("Couldn't hide. Searching to avoid delays.") unless hidden?
end
# don't search if you've seen footsteps and are in safe_mode
return if Flags['burgle-footsteps']
result = DRC.bput("search #{target}", 'It looks valuable', 'Roundtime', 'I could not')
@search_count += 1
if result =~ /It looks valuable/
store_loot if DRC.right_hand && DRC.left_hand
return
elsif @burgle_settings['retry'] && @search_count < @burgle_settings['max_search_count'] && !(Flags['burgle-footsteps'])
search_for_loot(target)
return
end
end
def store_loot
# if you've seen footsteps, don't bother storing items, and just get out if in safe mode
return if Flags['burgle-footsteps']
# store loot in your loot container, unless the item in your hands is a rope or lockpick
case DRC.right_hand
when /(?:lockpick|rope)$/
DRCI.stow_hand("right")
when *@burgle_settings['item_whitelist']
put_item?(DRC.right_hand)
else
case @loot_type
when 'drop', 'bin', 'pawn', 'keep'
temp_loot = DRC.right_hand
@loot_list.push(temp_loot) if put_item?(DRC.right_hand)
when 'trashcan'
DRCI.dispose_trash(DRC.right_hand, @worn_trashcan, @worn_trashcan_verb)
end
end
# if you've seen footsteps, don't bother still storing items, and just get out if in safe mode
return if Flags['burgle-footsteps']
# store loot in your loot container, unless the item in your hands is a rope or lockpick
case DRC.left_hand
when /(?:lockpick|rope)$/
DRCI.stow_hand("left")
when *@burgle_settings['item_whitelist']
put_item?(DRC.left_hand)
else
case @loot_type
when 'drop', 'bin', 'pawn', 'keep'
temp_loot = DRC.left_hand
@loot_list.push(temp_loot) if put_item?(DRC.left_hand)
when 'trashcan'
DRCI.dispose_trash(DRC.left_hand, @worn_trashcan, @worn_trashcan_verb)
end
end
end
# specialized move routine - sneaks when in hiding, when needed, moves when not to speed up script
def burgle_move(direction)
if !invisible? && hidden? && @search_count < @burgle_settings['max_search_count'] && !(Flags['burgle-footsteps'])
result = DRC.bput("sneak #{direction}", "Someone Else's Home", 'Sneaking is an', "You can't", 'In YOUR condition')
return if /Someone Else's Home/ =~ result
end
DRC.bput(direction, "Someone Else's Home") # don't use move as it can cause a race condition with invisibility and blacklisting kitchen
end
# ripped out of steal.lic
def put_item?(item)
case DRC.bput("put my #{item} in my #{@loot_container}", 'What were you', 'You put', 'You drop', "You can't do that", "You can't put that there", 'no matter how you arrange it', 'even after stuffing', 'The .* is *.* too \w+ to fit in', 'There isn\'t any more room', 'perhaps try doing that again', 'That\'s too heavy to go in there', "^Weirdly, you can't manage", "^There's no room")
when 'perhaps try doing that again'
return put_item?(item)
when 'You put', 'You drop'
return true
when 'What were you'
handheld = held_item(item)
drop_item(held_item(item)) if handheld
return false
else
drop_item(item)
return false
end
end
# ripped out of steal.lic
def drop_item(item)
case DRC.bput("drop my #{item}", 'You drop', 'You spread', 'You wince', 'would damage it', 'smashing it to bits', 'Something appears different about', 'What were you')
when 'would damage it', 'Something appears different about'
drop_item(item)
when 'What were you'
handheld = held_item(item)
return drop_item(held_item(item)) if handheld
end
end
# ripped out of steal.lic
def held_item(item)
[DRC.right_hand, DRC.left_hand].each do |hand_item|
hand_item.split.each do |item_word|
return hand_item if item.include?(item_word)
end
end
return nil
end
def pawn_item(item)
case DRC.bput("sell my #{item}",
'You sell your', # success
"You'll want to empty that first", # non-empty container
/shakes (his|her) head and says/, # not worth enough (generic)
'Relf briefly glances at your', # not worth enough (hib - special messaging)
'Ishh briefly glances at your', # not worth enough (aesry - special messaging)
'Oweede growls and says,', # not worth enough (Mer'Kresh)
"There's folk around here that'd slit", # Too expensive (Shard, Crossing)
"but it's much too fine for me.", # Too expensive (Riverhaven, Theren)
"Bynari laughs") # Not enough/too expensive (Langenfirth)
when 'You sell your'
return
else
drop_item(item)
end
end
# ripped out of hunting-buddy
def execute_extra_scripts(extra_scripts)
extra_scripts.each do |script|
DRC.message "***STATUS*** EXECUTE #{script}"
script_args = script.split(' ')
script_name = script_args.shift
DRC.wait_for_script_to_complete(script_name, script_args)
end
end
def process_loot
# return if loot_type isn't one of the supported process kind
return if @loot_type !~ /drop|pawn|bin|trashcan/
# return if loot_list is empty.
return if @loot_list.empty?
DRCT.walk_to(@loot_room_id) unless @loot_room_id == nil
@loot_list.each do |item|
case DRC.bput("get #{item} from my #{@loot_container}", 'You get', 'What were you referring to?')
when /^You get/
case @loot_type
when 'bin'
DRC.bput("put #{item} in bin", 'nods toward you as your .* falls into the .* bin')
when 'pawn'
pawn_item(item)
when 'drop'
drop_item(item)
end
when /^What were you referring to/ # handle items that stack/missing items
next
end
end
end
end
before_dying do
Flags.delete('burgle-footsteps')
Flags.delete('group-burgle-leave')
Flags.delete('group-burgle-disband')
end
Burgle.new