-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathwaggle.lic
1226 lines (1167 loc) · 53.9 KB
/
waggle.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
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
=begin
Spellup script for yourself and others
;waggle help
This script is a rewrite of ultrawaggle from SpiffyJr, which is
a heavily modified version of spellup from Shaelun and Blueland.
author: Tillmen ([email protected])
game: Gemstone
tags: magic
required: Lich >= 4.4.6
version: 0.14
changelog:
0.14 (2019-05-11):
fix --reserve-mana (austin-j)
0.13 (2019-03-03):
set refreshable_min value from CLI if present (sandersch)
0.12 (2018-04-20):
fix --refreshable-min command line option
=end
=begin
0.11 (2015-11-25):
fix max_multicast formula for bards
0.10 (2015-06-08):
fix multicast duration tracking (the cast every spell once and exit bug)
0.9 (2015-05-20):
add option to skip short duration spells on others
add option to use symbol of mana (Drafix)
0.8 (2015-04-20):
don't "cast <target> 1" for 1 multicast
0.7 (2015-03-31):
fix bug where wracking/power was used when there wasn't enough spirit/stamina for a sign/sigil
0.6 (2015-01-30):
do one cast of each stackable spell per round until spelled up, unless rapid-fire is active
0.5 (2014-10-16):
fix max_multicast bug
0.4 (2014-10-05):
typo
0.3 (2014-10-05):
fix (maybe) max_multicast
0.2 (2014-10-05):
fix wander-to-wrack option
=end
# fixme: option to cast high level spells first
# fixme: armor specialization
# fixme: option to not cast low duration spells on others
start_at = CharSettings['start_at'] || 180
stop_at = CharSettings['stop_at'] || 180
stop_at = [stop_at,250].min
stop_before = CharSettings['stop_before'] || 250
refreshable_min = CharSettings['unstackable_min'] || 15
use_multicast = CharSettings['use_multicast']
use_multicast = true if use_multicast.nil?
use_wracking = CharSettings['use_wracking'] || false
wander_to_wrack = CharSettings['wander_to_wrack'] || false
use_power = CharSettings['use_power'] || false
use_mana = CharSettings['use_mana'] || false
use_concentration = CharSettings['use_concentration'] || false
skip_jerks = CharSettings['skip_jerks'] || false
skip_short_spells = CharSettings['skip_short_spells'] || false
reserve_mana = CharSettings['reserve_mana'] || 0
retribution_spell = CharSettings['retribution_spell']
cast_list = CharSettings['cast_list'] || [ 101, 102, 103, 107, 115, 120, 202, 211, 215, 219, 303, 307, 310, 313, 401, 406, 414, 425, 430, 503, 507, 508, 509, 513, 520, 601, 602, 606, 613, 617, 618, 625, 640, 712, 905, 911, 913, 920, 1109, 1119, 1125, 1130, 1601, 1603, 1606, 1610, 1611, 1612, 1616 ]
did_something = false
fix_setting = { 'on' => true, 'off' => false }
short_spell_time = 3
if setting = script.vars.find { |var| var =~ /^\-\-start[_\-]at=[0-9]+$/ }
start_at = setting.slice(/[0-9]+/).to_i
script.vars.delete(setting)
end
if setting = script.vars.find { |var| var =~ /^\-\-stop[_\-]at=[0-9]+$/ }
stop_at = [setting.slice(/[0-9]+/).to_i,250].min
script.vars.delete(setting)
end
if setting = script.vars.find { |var| var =~ /^\-\-stop[_\-]before=[0-9]+$/ }
stop_before = setting.slice(/[0-9]+/).to_i
script.vars.delete(setting)
end
if setting = script.vars.find { |var| var =~ /^\-\-(?:unstackable|refreshable)[_\-]min=[0-9]+$/ }
refreshable_min = setting.slice(/[0-9]+/).to_i
script.vars.delete(setting)
end
if setting = script.vars.find { |var| var =~ /^\-\-cast[_\-]list=[0-9,]+$/ }
cast_list = setting.slice(/[0-9,]+/).split(',').collect { |num| num.to_i }
script.vars.delete(setting)
end
if setting = script.vars.find { |var| var =~ /^\-\-use[_\-]multicast=(?:on|off)$/ }
use_multicast = fix_setting[setting.slice(/on|off/)]
script.vars.delete(setting)
end
if setting = script.vars.find { |var| var =~ /^\-\-use[_\-]wracking=(?:on|off)$/ }
use_wracking = fix_setting[setting.slice(/on|off/)]
script.vars.delete(setting)
end
if setting = script.vars.find { |var| var =~ /^\-\-wander[_\-]to[_\-]wrack=(?:on|off)$/ }
wander_to_wrack = fix_setting[setting.slice(/on|off/)]
script.vars.delete(setting)
end
if setting = script.vars.find { |var| var =~ /^\-\-use[_\-]power=(?:on|off)$/ }
use_power = fix_setting[setting.slice(/on|off/)]
script.vars.delete(setting)
end
if setting = script.vars.find { |var| var =~ /^\-\-use[_\-]mana=(?:on|off)$/ }
use_mana = fix_setting[setting.slice(/on|off/)]
script.vars.delete(setting)
end
if setting = script.vars.find { |var| var =~ /^\-\-use[_\-]concentration=(?:on|off)$/ }
use_concentration = fix_setting[setting.slice(/on|off/)]
script.vars.delete(setting)
end
if setting = script.vars.find { |var| var =~ /^\-\-skip[_\-]jerks=(?:on|off)$/ }
skip_jerks = fix_setting[setting.slice(/on|off/)]
script.vars.delete(setting)
end
if setting = script.vars.find { |var| var =~ /^\-\-skip[_\-]short(?:[_\-]spells)?=(?:on|off)$/ }
skip_short_spells = fix_setting[setting.slice(/on|off/)]
script.vars.delete(setting)
end
if setting = script.vars.find { |var| var =~ /^\-\-retribution[_\-]spell=(?:[0-9]+|off)$/ }
if setting =~ /^\-\-retribution[_\-]spell=off$/
retribution_spell = nil
elsif setting =~ /^\-\-retribution[_\-]spell=([0-9]+)$/
retribution_spell = $1.to_i
end
script.vars.delete(setting)
end
if setting = script.vars.find { |var| var =~ /^\-\-reserve[_\-]mana=([0-9]+)$/ }
reserve_mana = $1.to_i
script.vars.delete(setting)
end
if script.vars.include?('--save')
CharSettings['use_wracking'] = use_wracking
CharSettings['use_multicast'] = use_multicast
CharSettings['wander_to_wrack'] = wander_to_wrack
CharSettings['use_power'] = use_power
CharSettings['use_mana'] = use_mana
CharSettings['use_concentration'] = use_concentration
CharSettings['skip_jerks'] = skip_jerks
CharSettings['skip_short_spells'] = skip_short_spells
CharSettings['start_at'] = start_at
CharSettings['stop_at'] = stop_at
CharSettings['stop_before'] = stop_before
CharSettings['unstackable_min'] = refreshable_min
CharSettings['retribution_spell'] = retribution_spell
CharSettings['reserve_mana'] = reserve_mana
CharSettings['cast_list'] = cast_list
exit
end
known_spells = Spells.known.collect { |spell| spell.num }
cast_list.delete_if { |spell| !(known_spells.include?(spell) and Spell[spell].time_per > 0) }
list_mode = false
if script.vars.empty?
target_list = [ Char.name ]
elsif script.vars[1].downcase == 'help'
respond
respond 'Usage:'
respond " #{$clean_lich_char}#{script.name} help show this message"
respond " #{$clean_lich_char}#{script.name} setup show setup window"
respond " #{$clean_lich_char}#{script.name} list show current settings"
respond
respond " #{$clean_lich_char}#{script.name} add [spell#] add one or more spells to the cast list"
respond " #{$clean_lich_char}#{script.name} delete [spell#] delete one or more spells from the cast list"
respond
respond " #{$clean_lich_char}#{script.name} start-at [minutes] stackable spells will be cast if they have less than (start_at) minutes remaining"
respond " #{$clean_lich_char}#{script.name} stop-at [minutes] when the script starts, and will be cast while the time left is less than"
respond " #{$clean_lich_char}#{script.name} stop-before [minutes] (stop_at) and the time left after another cast would be less than (stop before)"
respond
respond " #{$clean_lich_char}#{script.name} refreshable-min [minutes] minimum time for non-stacking spells"
respond
respond " #{$clean_lich_char}#{script.name} multicast [on/off] use multicast"
respond " #{$clean_lich_char}#{script.name} wracking [on/off] use sign of wracking when out of mana"
respond " #{$clean_lich_char}#{script.name} wander [on/off] wander up to 20 rooms to find an empty room to wrack in and return"
respond " #{$clean_lich_char}#{script.name} power [on/off] use sigil of power when out of mana"
respond " #{$clean_lich_char}#{script.name} concentration [on/off] use sigil of concentration when out of mana"
respond " #{$clean_lich_char}#{script.name} mana [on/off] use symbol of mana when out of mana"
respond " #{$clean_lich_char}#{script.name} skip-jerks [on/off] skip targets that don't share their current spell durations"
respond " #{$clean_lich_char}#{script.name} skip-short-spells [on/off] don't cast spells with a duration less than #{short_spell_time} minutes on others"
respond " #{$clean_lich_char}#{script.name} retribution-spell [#|none] spell number for chant retribution after casting cloak of shadows"
respond
respond " #{$clean_lich_char}#{script.name} spell yourself up"
respond " #{$clean_lich_char}#{script.name} [name1] [name2] ... spell up the given people (may include your own name)"
respond " #{$clean_lich_char}#{script.name} info show what will be cast and how much it will cost"
respond " #{$clean_lich_char}#{script.name} info [name1] [name2] ''"
respond
respond " Any or all saved options can be overridden on the command line without being saved using the following syntax:"
respond
respond " #{$clean_lich_char}#{script.name} --cast-list=401,406,503 --start-at=60 --stop-at=120 --stop-before=250 --refreshable-min=10 --use-wracking=on --wander-to-wrack=on --use-power=off --use-concentration=off --use-mana=off --skip-jerks=on --skip-short-spells=on --retribution-spell=717 Jim Joe Bob"
respond
exit
elsif script.vars[1] =~ /^setup$|^options$/i
if HAVE_GTK and defined?(Gtk.queue)
window = window_action = nil
window_width = CharSettings['window_width'] || 445
window_height = CharSettings['window_height'] || 490
Gtk.queue {
nocast_label = Gtk::Label.new('Spells not to Cast')
cast_label = Gtk::Label.new('Spells to Cast')
label_box = Gtk::HBox.new(true, 5)
label_box.pack_start(nocast_label, false, false, 0)
label_box.pack_start(cast_label, false, false, 0)
renderer = Gtk::CellRendererText.new
renderer.background = 'white'
nocast_ls = Gtk::ListStore.new(String, String)
nocast_ls.set_sort_column_id(0, Gtk::SORT_ASCENDING)
nocast_tv = Gtk::TreeView.new(nocast_ls)
nocast_tv.headers_visible = false
nocast_tv.height_request = 150
nocast_tv.append_column(Gtk::TreeViewColumn.new('', renderer, :text => 0, :background_set => 2))
nocast_tv.append_column(Gtk::TreeViewColumn.new('', renderer, :text => 1, :background_set => 2))
nocast_sw = Gtk::ScrolledWindow.new
nocast_sw.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_ALWAYS)
nocast_sw.add(nocast_tv)
cast_ls = Gtk::ListStore.new(String, String)
cast_ls.set_sort_column_id(0, Gtk::SORT_ASCENDING)
cast_tv = Gtk::TreeView.new(cast_ls)
cast_tv.headers_visible = false
cast_tv.height_request = 150
cast_tv.append_column(Gtk::TreeViewColumn.new('', renderer, :text => 0, :background_set => 2))
cast_tv.append_column(Gtk::TreeViewColumn.new('', renderer, :text => 1, :background_set => 2))
cast_sw = Gtk::ScrolledWindow.new
cast_sw.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_ALWAYS)
cast_sw.add(cast_tv)
tree_box = Gtk::HBox.new(true, 5)
tree_box.pack_start(nocast_sw, true, true, 0)
tree_box.pack_start(cast_sw, true, true, 0)
start_at_label = Gtk::Label.new('start casting if below:')
start_at_entry = Gtk::Entry.new
start_at_entry.text = start_at.to_s
start_at_entry.width_request = 50
stop_at_label = Gtk::Label.new('stop casting at:')
stop_at_entry = Gtk::Entry.new
stop_at_entry.text = stop_at.to_s
stop_at_entry.width_request = 50
stop_before_label = Gtk::Label.new("don't cast over:")
stop_before_entry = Gtk::Entry.new
stop_before_entry.text = stop_before.to_s
stop_before_entry.width_request = 50
stack_box = Gtk::VBox.new(false, 0)
temp_box = Gtk::HBox.new(false, 0)
temp_box.pack_end(start_at_entry, false, false, 5)
temp_box.pack_end(start_at_label, false, false, 5)
stack_box.pack_start(temp_box, false, false, 5)
temp_box = Gtk::HBox.new(false, 0)
temp_box.pack_end(stop_at_entry, false, false, 5)
temp_box.pack_end(stop_at_label, false, false, 5)
stack_box.pack_start(temp_box, false, false, 5)
temp_box = Gtk::HBox.new(false, 0)
temp_box.pack_end(stop_before_entry, false, false, 5)
temp_box.pack_end(stop_before_label, false, false, 5)
stack_box.pack_start(temp_box, false, false, 5)
stack_box_spacer = Gtk::VBox.new
stack_box_spacer.pack_start(stack_box, false, false, 4)
stack_frame = Gtk::Frame.new('Stackable Spells')
stack_frame.add(stack_box_spacer)
nonstack_min_label = Gtk::Label.new(' Minimum:')
nonstack_min_entry = Gtk::Entry.new
nonstack_min_entry.text = refreshable_min.to_s
nonstack_min_entry.width_request = 50
nonstack_box = Gtk::HBox.new(false, 0)
nonstack_box.pack_end(nonstack_min_entry, false, false, 4)
nonstack_box.pack_end(nonstack_min_label, false, false, 4)
nonstack_box_spacer = Gtk::VBox.new
nonstack_box_spacer.pack_start(nonstack_box, false, false, 4)
nonstack_frame = Gtk::Frame.new('Non-stackable Spells')
nonstack_frame.add(nonstack_box_spacer)
other_option_box = Gtk::VBox.new(false, 0)
retribution_spell_label = Gtk::Label.new('retribution spell:')
retribution_spell_entry = Gtk::Entry.new
retribution_spell_entry.text = retribution_spell.to_s
retribution_spell_entry.width_request = 50
temp_box = Gtk::HBox.new(false, 0)
temp_box.pack_end(retribution_spell_entry, false, false, 5)
temp_box.pack_end(retribution_spell_label, false, false, 5)
other_option_box.pack_start(temp_box, false, false, 4)
reserve_mana_label = Gtk::Label.new('reserve mana:')
reserve_mana_entry = Gtk::Entry.new
reserve_mana_entry.text = reserve_mana.to_s
reserve_mana_entry.width_request = 50
temp_box = Gtk::HBox.new(false, 0)
temp_box.pack_end(reserve_mana_entry, false, false, 5)
temp_box.pack_end(reserve_mana_label, false, false, 5)
other_option_box.pack_start(temp_box, false, false, 4)
other_option_box_spacer = Gtk::VBox.new
other_option_box_spacer.pack_start(other_option_box, false, false, 4)
other_option_frame = Gtk::Frame.new('Options')
other_option_frame.add(other_option_box_spacer)
left_box = Gtk::VBox.new(false, 0)
left_box.pack_start(stack_frame, false, false, 5)
left_box.pack_start(nonstack_frame, false, false, 5)
left_box.pack_start(other_option_frame, false, false, 5)
use_multicast_option = Gtk::CheckButton.new('multicast')
use_multicast_option.active = use_multicast
use_wracking_option = Gtk::CheckButton.new('wracking')
use_wracking_option.active = use_wracking
wander_to_wrack_option = Gtk::CheckButton.new('wander to wrack')
wander_to_wrack_option.active = wander_to_wrack
use_power_option = Gtk::CheckButton.new('power')
use_power_option.active = use_power
use_concentration_option = Gtk::CheckButton.new('concentration')
use_concentration_option.active = use_concentration
use_mana_option = Gtk::CheckButton.new('mana')
use_mana_option.active = use_mana
skip_jerks_option = Gtk::CheckButton.new('skip jerks')
skip_jerks_option.active = skip_jerks
skip_short_option = Gtk::CheckButton.new('skip short spells on others')
skip_short_option.active = skip_short_spells
option_box = Gtk::VBox.new(false, 0)
option_box.pack_start(use_multicast_option, false, false, 4)
option_box.pack_start(use_wracking_option, false, false, 4)
option_box.pack_start(wander_to_wrack_option, false, false, 4)
option_box.pack_start(use_power_option, false, false, 4)
option_box.pack_start(use_concentration_option, false, false, 4)
option_box.pack_start(use_mana_option, false, false, 4)
option_box.pack_start(skip_jerks_option, false, false, 4)
option_box.pack_start(skip_short_option, false, false, 4)
option_box_spacer = Gtk::VBox.new
option_box_spacer.pack_start(option_box, false, false, 4)
option_frame = Gtk::Frame.new('Options')
option_frame.add(option_box_spacer)
columns = Gtk::HBox.new(true, 0)
right_box = Gtk::VBox.new
right_box.pack_start(option_frame, false, false, 0)
columns.pack_start(left_box, false, false, 0)
columns.pack_start(right_box, false, false, 0)
save_button = Gtk::Button.new('Ok')
save_button.width_request = 75
cancel_button = Gtk::Button.new('Cancel')
cancel_button.width_request = 75
button_box = Gtk::HBox.new(false, 3)
button_box.pack_end(save_button, false, false, 4)
button_box.pack_end(cancel_button, false, false, 4)
main_box = Gtk::VBox.new(false, 4)
main_box.pack_start(label_box, false, false, 0)
main_box.pack_start(tree_box, true, true, 0)
main_box.pack_start(columns, false, false, 0)
main_box.pack_start(button_box, false, false, 0)
window = Gtk::Window.new
window.title = 'waggle setup'
window.border_width = 5
window.add(main_box)
window.resize(window_width, window_height)
Spells.known.each { |spell|
next unless (Spell[spell].time_per > 0)
if cast_list.include?(spell.num)
iter = cast_ls.append
iter[0] = spell.num.to_s
iter[1] = spell.name
else
iter = nocast_ls.append
iter[0] = spell.num.to_s
iter[1] = spell.name
end
}
Gtk::Drag.source_set(cast_tv, Gdk::Window::BUTTON1_MASK, [ [ 'text/plain', Gtk::Drag::TARGET_SAME_APP, 0 ] ], Gdk::DragContext::ACTION_MOVE)
Gtk::Drag.dest_set(cast_tv, Gtk::Drag::DEST_DEFAULT_ALL, [ [ 'text/plain', Gtk::Drag::TARGET_SAME_APP, 0 ] ], Gdk::DragContext::ACTION_MOVE)
Gtk::Drag.source_set(nocast_tv, Gdk::Window::BUTTON1_MASK, [ [ 'text/plain', Gtk::Drag::TARGET_SAME_APP, 0 ] ], Gdk::DragContext::ACTION_MOVE)
Gtk::Drag.dest_set(nocast_tv, Gtk::Drag::DEST_DEFAULT_ALL, [ [ 'text/plain', Gtk::Drag::TARGET_SAME_APP, 0 ] ], Gdk::DragContext::ACTION_MOVE)
cast_tv.signal_connect('drag-data-get') { |who, drag_context, data|
data.text = who.selection.selected[0] if who.selection.selected
}
cast_tv.signal_connect('drag-data-received') { |who, drag_context, x, y, data, info, time|
nocast_ls.each { |model,path,iter|
if iter[0] == data.text
new_iter = cast_ls.append
new_iter[0] = iter[0]
new_iter[1] = iter[1]
nocast_ls.remove(iter)
break
end
}
}
cast_tv.signal_connect('button-press-event') { |who, event|
if (event.event_type == Gdk::Event::BUTTON2_PRESS) and (source_iter = cast_tv.selection.selected)
dest_iter = nocast_ls.append
dest_iter[0] = source_iter[0]
dest_iter[1] = source_iter[1]
cast_ls.remove(source_iter)
end
}
nocast_tv.signal_connect('drag-data-get') { |who, drag_context, data|
data.text = who.selection.selected[0] if who.selection.selected
}
nocast_tv.signal_connect('drag-data-received') { |who, drag_context, x, y, data, info, time|
cast_ls.each { |model,path,iter|
if iter[0] == data.text
new_iter = nocast_ls.append
new_iter[0] = iter[0]
new_iter[1] = iter[1]
cast_ls.remove(iter)
break
end
}
}
nocast_tv.signal_connect('button-press-event') { |who, event|
if (event.event_type == Gdk::Event::BUTTON2_PRESS) and (source_iter = nocast_tv.selection.selected)
dest_iter = cast_ls.append
dest_iter[0] = source_iter[0]
dest_iter[1] = source_iter[1]
nocast_ls.remove(source_iter)
end
}
cancel_button.signal_connect('clicked') {
window_width = window.allocation.width
window_height = window.allocation.height
window_action = :cancel
}
save_button.signal_connect('clicked') {
Gtk.queue {
cast_list = Array.new
cast_ls.each { |model,path,iter| cast_list.push(iter[0].to_i) }
if start_at_entry.text =~ /^[0-9]+$/i
start_at = start_at_entry.text.to_i
else
respond "[waggle: ignoring invalid entry: #{start_at_entry.text}]"
end
if stop_at_entry.text =~ /^[0-9]+$/i
stop_at = stop_at_entry.text.to_i
else
respond "[waggle: ignoring invalid entry: #{stop_at_entry.text}]"
end
if stop_before_entry.text =~ /^[0-9]+$/i
stop_before = stop_before_entry.text.to_i
else
respond "[waggle: ignoring invalid entry: #{stop_before_entry.text}]"
end
if nonstack_min_entry.text =~ /^[0-9]+$/i
refreshable_min = nonstack_min_entry.text.to_i
else
respond "[waggle: ignoring invalid entry: #{nonstack_min_entry.text}]"
end
if retribution_spell_entry.text =~ /^[0-9]+$/i
retribution_spell = retribution_spell_entry.text
elsif retribution_spell_entry.text.empty? or retribution_spell_entry.text =~ /none|off/
retribution_spell = nil
else
respond "[waggle: ignoring invalid entry: #{retribution_spell_entry.text}]"
end
if reserve_mana_entry.text =~ /^[0-9]+$/i
reserve_mana = reserve_mana_entry.text.to_i
elsif reserve_mana_entry.text.empty?
reserve_mana = 0
else
respond "[waggle: ignoring invalid entry: #{reserve_mana_entry.text}]"
end
use_multicast = use_multicast_option.active?
use_wracking = use_wracking_option.active?
wander_to_wrack = wander_to_wrack_option.active?
use_power = use_power_option.active?
use_concentration = use_concentration_option.active?
use_mana = use_mana_option.active?
skip_jerks = skip_jerks_option.active?
skip_short_spells = skip_short_option.active?
window_width = window.allocation.width
window_height = window.allocation.height
window_action = :save
}
}
window.signal_connect('delete_event') {
window_width = window.allocation.width
window_height = window.allocation.height
window_action = :cancel
}
window.show_all
}
before_dying { Gtk.queue { window.destroy } }
wait_while { window_action.nil? }
undo_before_dying
Gtk.queue { window.destroy }
CharSettings['window_width'] = window_width
CharSettings['window_height'] = window_height
if window_action == :save
CharSettings['use_multicast'] = use_multicast
CharSettings['use_wracking'] = use_wracking
CharSettings['wander_to_wrack'] = wander_to_wrack
CharSettings['use_power'] = use_power
CharSettings['use_concentration'] = use_concentration
CharSettings['use_mana'] = use_mana
CharSettings['skip_jerks'] = skip_jerks
CharSettings['skip_short_spells'] = skip_short_spells
CharSettings['start_at'] = start_at
CharSettings['stop_at'] = stop_at
CharSettings['stop_before'] = stop_before
CharSettings['unstackable_min'] = refreshable_min
CharSettings['retribution_spell'] = retribution_spell
CharSettings['reserve_mana'] = reserve_mana
CharSettings['cast_list'] = cast_list
end
else
unless HAVE_GTK
echo 'GTK bindings are not installed or failed to load.'
echo "For command-line setup, see #{$clean_lich_char}#{script.name} help"
exit
end
unless defined?(Gtk.queue)
echo "GUI setup requires Lich v4."
echo "For command-line setup, see #{$clean_lich_char}#{script.name} help"
exit
end
end
exit
elsif script.vars[1].downcase == 'add'
add_list = script.vars[2..-1].collect { |spell| spell.to_i }
add_list.each { |spell|
cast_list.push(spell.to_i) unless cast_list.include?(spell.to_i)
}
echo "added these spells to the cast list: #{add_list.join(', ')}"
CharSettings['cast_list'] = cast_list
exit
elsif script.vars[1] =~ /^rem(?:ove)?$|^del(?:ete)?$/i
del_list = script.vars[2..-1].collect { |spell| spell.to_i }
del_list.each { |spell|
if cast_list.delete(spell)
echo "removed #{spell} from the cast list"
else
echo "did not find #{spell} in the cast list"
end
}
CharSettings['cast_list'] = cast_list
exit
elsif script.vars[1] =~ /^list$|^show$/i
fix_setting = { true => 'on', false => 'off' }
respond
respond " cast list: #{cast_list.join(', ')}"
respond " start at: #{start_at}"
respond " stop at: #{stop_at}"
respond " stop before: #{stop_before}"
respond " refreshable min: #{refreshable_min}"
respond " multicast: #{fix_setting[use_multicast]}"
respond " sign of wracking: #{fix_setting[use_wracking]}"
respond " wander to wrack: #{fix_setting[wander_to_wrack]}"
respond " sigil of power: #{fix_setting[use_power]}"
respond "sigil of concentration: #{fix_setting[use_concentration]}"
respond " symbol of mana: #{fix_setting[use_mana]}"
respond " skip jerks: #{fix_setting[skip_jerks]}"
respond " skip short spells: #{fix_setting[skip_short_spells]}"
respond " retribution spell: #{retribution_spell || 'none'}"
respond " reserve mana: #{reserve_mana}"
respond
exit
elsif script.vars[1].downcase == /^start[_\-]at$/
if script.vars[2] =~ /^[0-9]+$/
CharSettings['start_at'] = script.vars[2].to_i
echo "stackable spells with less than #{CharSettings['start_at']} minutes remaining when the script starts will be skipped"
else
echo "You're doing it wrong..."
end
exit
elsif script.vars[1].downcase =~ /^stop[_\-]at$/
if script.vars[2] =~ /^[0-9]+$/
CharSettings['stop_at'] = script.vars[2].to_i
echo "stackable spells will be cast until they have #{CharSettings['stop_at']} minutes remaining"
else
echo "You're doing it wrong..."
end
exit
elsif script.vars[1].downcase =~ /^stop[_\-]before$/
if script.vars[2] =~ /^[0-9]+$/
CharSettings['stop_before'] = script.vars[2].to_i
echo "stackable spells will not be cast if it would cause the spell to have more than #{CharSettings['stop_before']} minutes remaing"
else
echo "You're doing it wrong..."
end
exit
elsif script.vars[1].downcase == /^refreshable[_\-]?min$/
if script.vars[2] =~ /^[0-9]+$/
CharSettings['unstackable_min'] = script.vars[2].to_i
echo "non-stackable spells will be cast if they have less than #{CharSettings['unstackable_min']} minutes remaining"
else
echo "You're doing it wrong..."
end
exit
elsif script.vars[1].downcase =~ /^(?:use[_\-])?multicast$/
if script.vars[2].downcase == 'on'
CharSettings['use_multicast'] = true
echo "multicast will be used"
elsif script.vars[2].downcase == 'off'
CharSettings['use_multicast'] = false
echo "multicast will not be used"
else
echo "You're doing it wrong..."
end
exit
elsif script.vars[1].downcase =~ /^(?:use[_\-])?wracking$/
if script.vars[2].downcase == 'on'
CharSettings['use_wracking'] = true
echo "sign of wracking will be used"
elsif script.vars[2].downcase == 'off'
CharSettings['use_wracking'] = false
echo "sign of wracking will not be used"
else
echo "You're doing it wrong..."
end
exit
elsif script.vars[1].downcase =~ /^wander(?:[_\-]to[_\-]wrack)?$/
if script.vars[2].downcase == 'on'
CharSettings['wander_to_wrack'] = true
echo "wander will be used to wrack"
elsif script.vars[2].downcase == 'off'
CharSettings['wander_to_wrack'] = false
echo "wander will not be used to wrack"
else
echo "You're doing it wrong..."
end
exit
elsif script.vars[1].downcase =~ /^(?:use[_\-])?power$/
if script.vars[2].downcase == 'on'
CharSettings['use_power'] = true
echo "sigil of power will be used"
elsif script.vars[2].downcase == 'off'
CharSettings['use_power'] = false
echo "sigil of power will not be used"
else
echo "You're doing it wrong..."
end
exit
elsif script.vars[1].downcase =~ /^(?:use[_\-])?concentration$/
if script.vars[2].downcase == 'on'
CharSettings['use_concentration'] = true
echo "sigil of concentration will be used"
elsif script.vars[2].downcase == 'off'
CharSettings['use_concentration'] = false
echo "sigil of concentration will not be used"
else
echo "You're doing it wrong..."
end
exit
elsif script.vars[1].downcase =~ /^(?:use[_\-])?mana$/
if script.vars[2].downcase == 'on'
CharSettings['use_mana'] = true
echo "symbol of mana will be used"
elsif script.vars[2].downcase == 'off'
CharSettings['use_mana'] = false
echo "symbol of man will not be used"
else
echo "You're doing it wrong..."
end
exit
elsif script.vars[1].downcase =~ /^skip[_\-]jerks$/
if script.vars[2].downcase == 'on'
CharSettings['skip_jerks'] = true
echo "jerks that don't share spell durations will be skipped"
elsif script.vars[2].downcase == 'off'
CharSettings['skip_jerks'] = false
echo "jerks that don't share spell durations will not be skipped"
else
echo "You're doing it wrong..."
end
exit
elsif script.vars[1].downcase =~ /^skip[_\-]short(?:[_\-]spells)?/
if script.vars[2].downcase == 'on'
CharSettings['skip_short_spells'] = true
echo "spells with a duration of less than #{short_spell_time} minutes per cast will not be cast on others"
elsif script.vars[2].downcase == 'off'
CharSettings['skip_short_spells'] = false
echo "short spells will not be skipped"
else
echo "You're doing it wrong..."
end
exit
elsif script.vars[1].downcase =~ /^retribution[_\-]spell$/
if script.vars[2].downcase =~ /^(?:off|none)$/
CharSettings['retribution_spell'] = nil
echo "retribution spell cleared"
elsif script.vars[2] =~ /^[0-9]+$/
CharSettings['retribution_spell'] = script.vars[2]
echo "retribution spell set to #{script.vars[2]}"
else
echo "You're doing it wrong..."
end
exit
elsif script.vars[1].downcase =~ /^reserve[_\-]mana$/
if script.vars[2] =~ /^[0-9]+$/
CharSettings['reserve_mana'] = script.vars[2]
echo "reserve mana set to #{script.vars[2]}"
else
echo "You're doing it wrong..."
end
exit
elsif script.vars[1].downcase == 'info'
list_mode = true
target_list = Array.new
if script.vars[2]
script.vars[2..-1].each { |bad_name|
if pc = GameObj.pcs.find { |pc| pc.noun =~ /^#{bad_name}/i }
target_list.push(pc.noun)
elsif Char.name =~ /^#{bad_name}/i
target_list.push(Char.name)
else
echo "bad target: #{bad_name}"
end
}
else
target_list = [ Char.name ]
end
elsif script.vars[1]
target_list = Array.new
script.vars[1..-1].each { |bad_name|
if pc = GameObj.pcs.find { |pc| pc.noun =~ /^#{bad_name}/i }
target_list.push(pc.noun)
elsif Char.name =~ /^#{bad_name}/i
target_list.push(Char.name)
else
echo "bad target: #{bad_name}"
end
}
else
target_list = [ Char.name ]
end
fix_spell = proc { |spell|
if (spell.class == Fixnum) or (spell.class == String and spell =~ /^[0-9]+$/)
spell = Spell[spell.to_i]
end
unless spell.class == Spell
echo 'error: missing spell information'
exit
end
spell
}
wander_rooms = Array.new
wander = proc {
room = Room.current
next_room_options = room.wayto.keys
next_room = next_room_options.find_all { |r| ((room.timeto[r].class == Float && room.timeto[r] <= 3) or (room.timeto[r].class == Proc && room.timeto[r].call != nil && room.timeto[r].call <= 3)) and not wander_rooms.include?(r)}
if next_room.empty?
next_room = wander_rooms.find { |r| next_room_options.include?(r) }
else
next_room = next_room[rand(next_room.length)]
end
wander_rooms.delete(next_room)
wander_rooms.push(next_room)
way = room.wayto[next_room]
if way.class == String
move(way)
else
way.call
end
}
check_mana = proc { |spell, num_multicast|
unless spell.affordable?(:multicast => num_multicast) and ((spell.mana_cost == 0) or (mana >= spell.mana_cost(:multicast => num_multicast) + reserve_mana))
sigil_of_power = Spell[9718]
sign_of_wracking = Spell[9918]
symbol_of_mana = Spell[9813]
symbol_of_mana_cooldown = Spell[9048]
punishment = Spell[9012]
if use_power and sigil_of_power.known? and (spell.mana_cost > 0) and (mana < (spell.mana_cost(:multicast => num_multicast) + reserve_mana)) and (spell.stamina_cost == 0)
until spell.affordable?(:multicast => num_multicast) and (mana >= spell.mana_cost(:multicast => num_multicast) + reserve_mana)
if sigil_of_power.affordable?
sigil_of_power.cast
sleep 0.2
else
fput 'release' unless checkprep == 'None'
echo 'waiting for mana...'
wait_until { (spell.affordable?(:multicast => num_multicast) and (mana >= spell.mana_cost(:multicast => num_multicast) + reserve_mana)) or sigil_of_power.affordable? }
end
end
elsif use_mana and symbol_of_mana.known? and spell.mana_cost > 0
until spell.affordable?(:multicast => num_multicast) and (mana >= spell.mana_cost(:multicast => num_multicast) + reserve_mana)
waitrt?
waitcastrt?
if not symbol_of_mana_cooldown.active?
# fixme: might spam if out of favor
symbol_of_mana.cast
sleep 0.2
else
fput 'release' unless checkprep == 'None'
echo 'waiting for mana or mana cooldown...'
wait_until { (spell.affordable?(:multicast => num_multicast) and (mana >= spell.mana_cost(:multicast => num_multicast) + reserve_mana)) or not symbol_of_mana_cooldown.active? }
end
end
elsif use_wracking and sign_of_wracking.known? and not punishment.active? and (spell.mana_cost > 0) and (mana < (spell.mana_cost(:multicast => num_multicast) + reserve_mana))
until spell.affordable?(:multicast => num_multicast) and (mana >= spell.mana_cost(:multicast => num_multicast) + reserve_mana)
waitrt?
waitcastrt?
if sign_of_wracking.affordable? and not punishment.active?
if invisible? or hidden? or not checkpcs
sign_of_wracking.cast if checkspirit(6)
else
status_tags
evil_pcs = checkpcs
result = dothistimeout 'sign of recognition', 5, /^You (?:touch|scratch|rub|tap|point to) your (?:right|left) (?:eyebrow|nostril|earlobe|shoulder|cheek) with your (?:right|left) (?:pinky|forefinger|thumb|index finger)\.$/
unless result.nil?
while (line = get) and (line !~ /<prompt/)
if line =~ /<a.*?>([A-Z][a-z]+)<\/a> acknowledges your sign/
evil_pcs.delete($1)
end
end
end
status_tags
if sign_of_wracking.affordable? and (evil_pcs.nil? or evil_pcs.empty?)
sign_of_wracking.cast if checkspirit(6)
elsif sign_of_wracking.affordable? and wander_to_wrack
start_room = Room.current
20.times {
break if (checkpcs.nil? or invisible?) and not Room.current.tags.include?('no-magic')
wander.call
}
if (checkpcs.nil? or invisible?) and checkspirit(6) and not Room.current.tags.include?('no-magic')
sign_of_wracking.cast
unless start_room == Room.current
start_script 'go2', [ start_room.id.to_s ]
wait_while { running?('go2') }
end
else
unless start_room == Room.current
start_script 'go2', [ start_room.id.to_s ]
wait_while { running?('go2') }
end
fput 'release' unless checkprep == 'None'
echo 'waiting on mana... or evil people to go away...'
wait_until { (spell.affordable?(:multicast => num_multicast) and (spell.mana_cost == 0 or mana >= spell.mana_cost(:multicast => num_multicast) + reserve_mana)) or hidden? or invisible? or not checkpcs.to_a.any? { |pc| evil_pcs.include?(pc) } }
end
else
fput 'release' unless checkprep == 'None'
echo 'waiting on mana... or evil people to go away...'
wait_until { (spell.affordable?(:multicast => num_multicast) and (spell.mana_cost == 0 or mana >= spell.mana_cost(:multicast => num_multicast) + reserve_mana)) or hidden? or invisible? or not checkpcs.to_a.any? { |pc| evil_pcs.include?(pc) } }
end
end
else
fput 'release' unless checkprep == 'None'
echo 'waiting for mana or spirit...'
wait_until { (spell.affordable?(:multicast => num_multicast) and (spell.mana_cost == 0 or mana >= spell.mana_cost(:multicast => num_multicast) + reserve_mana)) or sign_of_wracking.affordable? }
end
end
else
fput 'release' unless checkprep == 'None'
echo 'waiting for mana...'
wait_until { spell.affordable?(:multicast => num_multicast) and (spell.mana_cost == 0 or mana >= spell.mana_cost(:multicast => num_multicast) + reserve_mana) }
end
end
}
release_spell = proc {
unless checkprep == 'None'
dothistimeout 'release', 5, /^You feel the magic of your spell rush away from you\.$|^You don't have a prepared spell to release!$/
end
}
cast_spell = proc { |spell, target, num_multicast|
did_something = true
spell = fix_spell.call(spell)
result = nil
loop {
check_mana.call(spell, num_multicast)
if target == Char.name
if num_multicast > 1
cast_result = spell.cast(num_multicast.to_s)
else
cast_result = spell.cast
end
else
if num_multicast > 1
cast_result = spell.cast("at #{target} #{num_multicast}")
else
cast_result = spell.cast("at #{target}")
end
end
if cast_result =~ /^Be at peace my child, there is no need for spells of war in here\.$|Spells of War cannot be cast/
result = :bad_spell
break
elsif cast_result == 'Cast at what?'
result = :bad_target
break
elsif cast_result =~ /^\[Spell Hindrance for/
nil # try again
else
result = :success
break
end
}
result
}
get_target_info = proc { |target|
if defined?(LNet.get_data)
LNet.get_data(target, 'spells')
else
nil
end
}
max_multicast = proc{ |spell|
ranks = 0
if Char.prof == 'Wizard'
ranks = Skills.emc
elsif Char.prof =~ /^Cleric$|^Ranger$|^Paladin$/
ranks = Skills.smc
elsif Char.prof =~ /^Empath$|^Monk$|^Bard$/
if [1,2].include?(spell.circle.to_i)
ranks = Skills.smc + (Skills.mmc / 2)
elsif spell.circle.to_i == 11
ranks = [Skills.mmc,Skills.smc].max + ([Skills.mmc,Skills.smc].min / 2)
elsif spell.circle.to_i == 12
ranks = Skills.mmc + (Skills.smc / 2)
elsif spell.circle.to_i == 4
ranks = Skills.emc + (Skills.mmc / 2)
end
elsif Char.prof =~ /^Sorcerer$|^Warrior$|^Rogue$/
if spell.circle.to_i == 4
ranks = Skills.emc + (Skills.smc / 2)
elsif spell.circle.to_i == 1
ranks = Skills.smc + (Skills.emc / 2)
elsif spell.circle.to_i == 7
ranks = [Skills.emc,Skills.smc].max + ([Skills.emc,Skills.smc].min / 2)
end
end
(ranks / 25) + 1
}
#
# gather current spell info for the targets
#
target_info = Hash.new
target_list.each { |name|
if name == Char.name
target_info[Char.name] = Hash.new
Spell.active.each { |spell| target_info[Char.name][spell.num.to_s] = spell.timeleft }
elsif skip_jerks
spell_info = get_target_info.call(name)
if spell_info.nil?
echo "skipping #{name}: spell info refused"
elsif spell_info == false
echo "skipping #{name}: spell info failure"
else
target_info[name] = spell_info
end
else
target_info[name] = get_target_info.call(name) || Hash.new
end
}
if list_mode
dry_run = Hash.new
max_spell_name = 0
cast_list.each { |spell|
spell = fix_spell.call(spell)
max_spell_name = [ max_spell_name, spell.name.length ].max
target_info.keys.each { |name|
next unless spell.stackable?(:target => name)
next unless spell.available?(:target => name)
next unless spell.time_per(:target => name) > short_spell_time
next if (name == Char.name) and (spell.circlename == 'Bard') and spell.active?
target_info[name][spell.num.to_s] ||= 0
dry_run[name] ||= Hash.new
if target_info[name][spell.num.to_s] < start_at
while ( (target_info[name][spell.num.to_s] < stop_at) and (target_info[name][spell.num.to_s] + spell.time_per(:target => name)) < stop_before )
dry_run[name][spell.num.to_s] = dry_run[name][spell.num.to_s] + 1
target_info[name][spell.num.to_s] += spell.time_per(:target => name)
end
end
}
}
cast_list.each { |spell|