-
Notifications
You must be signed in to change notification settings - Fork 8
/
infomon.lic
1417 lines (1380 loc) · 58 KB
/
infomon.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
This script tracks a bunch of info about your character that isn't available as XML, such as your skills and stats, the spells you have on and their duration, gift of lumis, and other random things.
Use ;magic to see what spells you have on.
Use ;banks to see how poor you are.
Based on Shaelun's infomonitor.lic
Required: Lich 4.4.0
https://github.com/matt-lowe/lich-scripts
tillmen@lichproject.org
=end
# fixme: http://forum.gsplayers.com/showthread.php?83278-issue-with-infomon-and-cmans
unless $version.split('.').collect { |num| num.rjust(5, '0') }.join('.') >= '00004.00004.00000'
echo 'Your version of Lich is too old for this script.'
exit
end
unless XMLData.game =~ /^(?:GSF|GSIV|GSPlat|GSTest)$/
echo "This script is meant for Gemstone Prime, Platinum, or Shattered. It will likely cause problems on whatever game you're trying to run it on..."
exit
end
hide_me
setpriority(1)
get_lich_server = proc {
begin
lich_server = TCPSocket.open('216.224.171.85', 7153)
rescue
lich_server.close rescue()
lich_server = nil
echo "error connecting to server: #{$!}"
end
lich_server
}
sleep(0.1) until Char.name and not Char.name.empty?
CharSettings['active_spells'] = Hash.new unless CharSettings['active_spells'].class == Hash
CharSettings['bank_accounts'] = Hash.new unless CharSettings['bank_accounts'].class == Hash
CharSettings['show_circles'] = true if CharSettings['show_circles'].nil?
CharSettings['show_bonuses'] = false if CharSettings['show_bonuses'].nil?
CharSettings['show_messages'] = true if CharSettings['show_messages'].nil?
CharSettings['show_gift'] = true if CharSettings['show_gift'].nil?
bank_titles = {
"Wehnimer's Landing" => [ '[First Elanith Bank, Teller]', '[Clenchfist Bros. Banking, Lobby]'],
'Kharam-Dzu' => [ '[The Bank of Kharam-Dzu]' ],
'Icemule Trace' => [ '[Icemule Trace, Bank]' ],
'Vornavis' => [ '[Bank of Vornavis, Solhaven]' ],
"River's Rest" => [ "[River's Rest Bank, Teller]" ],
"Kharag 'doth Dzulthu" => [ '[Bank of Zul Logoth]' ],
'United City-States' => [ '[United Bank of City-States]', '[The United Bank of City-States]' ],
'Isle of the Four Winds Bank' => [ '[Mist Harbor Bank, Bank Windows]', '[Mist Harbor Bank, Windows]' ],
'Cysaegir' => [ '[Cysaegir Bank]' ],
}
#
# Load spell info
#
unless Spell.load
echo 'error: failed to load spell list'
exit
end
#
# Load or get character information
#
if CharSettings['Stats'] and CharSettings['Skills'] and CharSettings['Spells'] and CharSettings['Society'] and CharSettings['citizenship'] and CharSettings['cman']
begin
Stats.load_serialized = CharSettings['Stats']
Skills.load_serialized = CharSettings['Skills']
Spells.load_serialized = CharSettings['Spells']
Society.load_serialized = CharSettings['Society']
Char.citizenship = CharSettings['citizenship']
begin
CharSettings['cman'].each_pair { |cman,rank| CMan.send("#{cman}=", rank) }
rescue
nil
end
rescue
echo $!
echo $!.backtrace[0..1]
exit
end
else
silence_me
hide_lines = done = false
action = proc { |server_string|
if hide_lines
if server_string =~ /^\s*Mana\:|<prompt/
DownstreamHook.remove('infomon_info')
done = true
end
nil
elsif server_string =~ /^\s*Name\:/
hide_lines = true
nil
else
server_string
end
}
DownstreamHook.add('infomon_info', action)
echo 'checking stats...'
put 'info'
wait_until { done }
hide_lines = done = false
action = proc { |server_string|
if hide_lines
if server_string =~ /<output class=""\/>|<prompt/
DownstreamHook.remove('infomon_skills')
done = true
end
nil
elsif server_string =~ /^\s*(?:<.*?>)?#{Char.name}(?:<\/a>)? \(at level/o
hide_lines = true
nil
else
server_string
end
}
DownstreamHook.add('infomon_skills', action)
echo 'checking skills...'
put 'skills'
wait_until { done }
hide_lines = done = false
action = proc { |server_string|
if hide_lines
if server_string =~ /<prompt/
DownstreamHook.remove('infomon_society')
done = true
end
nil
elsif server_string == "<pushBold/>\r\n"
hide_lines = true
nil
else
server_string
end
}
DownstreamHook.add('infomon_society', action)
echo 'checking society...'
put 'society'
wait_until { done }
done = false
action = proc { |server_string|
if server_string =~ /You currently have .*? citizenship in|You don't seem to have citizenship\./
DownstreamHook.remove('infomon_citizenship')
done = true
nil
else
server_string
end
}
DownstreamHook.add('infomon_citizenship', action)
echo 'checking citizenship...'
put 'citizenship'
wait_until { done }
hide_lines = done = false
action = proc { |server_string|
if hide_lines
if server_string =~ /<output class=""\/>|<prompt/
DownstreamHook.remove('infomon_cman')
done = true
end
nil
else
if server_string =~ /You know absolutely nothing about Combat Maneuvers\./
DownstreamHook.remove('infomon_cman')
done = true
nil
elsif server_string =~ /#{Char.name}<\/a>, your Combat Maneuver training is as follows:/
hide_lines = true
nil
else
server_string
end
end
}
DownstreamHook.add('infomon_cman', action)
echo 'checking combat maneuvers...'
put 'cman info'
wait_until { done }
echo 'done'
silence_me
end
#
# Load spell timers
#
CharSettings['active_spells'].each_pair { |spell_num,timeleft|
if (spell = Spell[spell_num.to_i])
if defined?(spell.real_time) and spell.real_time
timeleft = (timeleft - Time.now.to_f)/60.0
if timeleft > 0
spell.timeleft = timeleft
spell.active = true
end
else
spell.timeleft = timeleft
spell.active = true
end
else
echo "spell not loaded: #{spell_num}"
end
}
Spellsong.load_serialized = CharSettings['Spellsong'] if CharSettings['Spellsong']
Gift.load_serialized = CharSettings['Gift'] if CharSettings['Gift']
#
# Register ;magic and ;banks commands
#
action = proc { |client_string|
if client_string =~ /^(?:<c>)?#{$lich_char}((?:magic|banks).*)/i
if scr = (Script.running + Script.hidden).find { |val| val.name == 'infomon' }
scr.downstream_buffer.shove("#{$clean_lich_char}#{$1}")
else
UpstreamHook.remove('infomon')
end
nil
else
client_string
end
}
UpstreamHook.add('infomon', action)
#
# Implement some status tracking functions
#
$infomon_sleeping = false
def checksleeping
return $infomon_sleeping
end
def sleeping?
return $infomon_sleeping
end
$infomon_bound = false
def checkbound
return $infomon_bound
end
def bound?
return $infomon_bound
end
$infomon_silenced = false
def checksilenced
$infomon_silenced
end
def silenced?
$infomon_silenced
end
$infomon_calmed = true
def checkcalmed
$infomon_calmed
end
def calmed?
$infomon_calmed
end
$infomon_cutthroat = false
def checkcutthroat
$infomon_cutthroat
end
def cutthroat?
$infomon_cutthroat
end
#
# Save function
#
save_proc = proc {
CharSettings['active_spells'] = Hash.new
Spell.active.each { |spell|
if defined?(spell.real_time) and spell.real_time
CharSettings['active_spells'][spell.num.to_s] = Time.now.to_f + (spell.timeleft * 60)
else
CharSettings['active_spells'][spell.num.to_s] = spell.timeleft
end
}
CharSettings['Spellsong'] = Spellsong.serialize
CharSettings['Gift'] = Gift.serialize
CharSettings.save
if not CharSettings['uploaded_spell_ranks'] and defined?(LNet.upload_spell_ranks)
if LNet.upload_spell_ranks
CharSettings['uploaded_spell_ranks'] = true
end
end
}
#
# Save current status every five minutes in case of crash
#
Thread.new {
begin
loop {
sleep 300
save_proc.call
}
rescue
echo $!
echo $!.backtrace[0..1]
end
}
#
# Save current status on exit
#
before_dying {
save_proc.call
UpstreamHook.remove('infomon')
undef checksleeping
undef sleeping?
undef checkbound
undef bound?
undef checksilenced
undef silenced?
undef checkcalmed
undef calmed?
undef checkcutthroat
undef cutthroat?
}
#
# Death
#
Thread.new {
begin
loop {
wait_until { dead? }
Spell.list.each { |killit|
if defined?(killit.clear_on_death)
killit.putdown if killit.clear_on_death
else
killit.putdown unless [6666,9009,920,9516,9003,9011].include?(killit.num)
end
}
Spellsong.renewed
wait_while { dead? }
Spell[6666].putdown
}
rescue
echo $!
echo $!.backtrace[0..1]
sleep 0.3
end
}
#
# Another workaround for Simu fail
#
fix_gameobj_status = proc { |server_string|
# false positive: shudders with sporadic convulsions as pearlescent ripples envelop .*? body
if server_string =~ /^(?:The fire in the|With a surprised grunt, the|A sudden blue fire bursts over the hair of a|You hear a sound like a weeping child as a white glow separates itself from the|A low gurgling sound comes from deep within the chest of the|The|A) (?:<pushBold\/>)?<a.*?exist=["'](\-?[0-9]+)["'].*?>.*?<\/a>(?:<popBold\/>)?(?:'s)? (?:body as it rises, disappearing into the heavens|falls to the ground and dies|falls back into a heap and dies|body goes rigid and collapses to the ground, dead|body goes rigid and collapses to the floor, dead|slowly settles to the ground and begins to dissipate|falls to the ground motionless|body goes rigid and <pushBold\/><a.*?>\w+<\/a><popBold\/> eyes roll back into <pushBold\/><a.*?>\w+<\/a><popBold\/> head as <pushBold\/><a.*?>\w+<\/a><popBold\/> dies|growls one last time, and crumples to the ground in a heap|spins backwards and collapses dead|falls to the ground as the stillness of death overtakes <pushBold\/><a.*?>(?:him|her|it)<\/a><popBold\/>|crumples to the ground motionless|howls in agony one last time and dies|howls in agony while falling to the ground motionless|moans pitifully as <pushBold\/><a.*?>(?:he|she|it)<\/a><popBold\/> is released|careens to the ground and crumples in a heap|hisses one last time and dies|flutters its wings one last time and dies|slumps to the ground with a final snarl|horn dims as (?:his|her) lifeforce fades away|blinks in astonishment, then collapses in a motionless heap|collapses in a heap, its huge girth shaking the floor around it|goes limp and .*? falls over as the fire slowly fades from .*? eyes|eyes slowly fades|sputters violently, cascading flames all around as .*? collapses in a final fiery display|falls to the ground in a clattering, motionless heap|goes limp and .*? falls over as the fire slowly fades from .*? eyes|collapses to the ground and shudders once before finally going still|crumbles into a pile of rubble|shudders once before .*? finally goes still|as .*? falls slack against the ground|totters for a moment and then falls to the ground like a pillar, breaking into pieces that fly out in every direction|collapses into a pile of rubble|rumbles in agony as .*? teeters for a moment, then falls directly at you|twists and coils violently in .*? death throes, finally going still|twitches one final time before falling still upon the floor|, consuming .*? form in the space of a breath|screams one last time and dies|breathes .*? last gasp and dies|rolls over and dies|as .*? falls slack against the floor|collapses to the ground, emits a final squeal, and dies|cries out in pain one last time and dies|crumples to a heap on the ground and dies|collapses to the ground, emits a final sigh, and dies|crumples to the ground and dies|lets out a final caterwaul and dies|screams evilly one last time and goes still|gurgles eerily and collapses into a puddle of water|shudders, then topples to the ground|shudders one last time before lying still|violently for a moment, then goes still|grumbles in pain one last time before lying still|rumbles in agony and goes still|falls to the ground dead|collapses to the ground, emits a final bleat, and dies|topples to the ground motionless|shudders violently for a moment, then goes still)[\.!]\r?\n?$/
npc_id = $1
if npc = GameObj.npcs.find { |obj| obj.id == npc_id }
npc.status = 'dead'
end
elsif server_string =~ /^A calm washes over <pushBold\/>(?:a|an|the) <a exist="(.*?)" noun=".*?">.*?<\/a><popBold\/>\.\r?\n?$/
npc_id = $1
if npc = GameObj.npcs.find { |obj| obj.id == npc_id }
npc.status = 'calm'
end
end
server_string
}
before_dying { DownstreamHook.remove('fix_gameobj_status') }
DownstreamHook.add('fix_gameobj_status', fix_gameobj_status)
#
# Spell tracking
#
spell_up_msgs_re = /^#{Spell.upmsgs.join('$|^')}$/o
spell_dn_msgs_re = /^#{Spell.dnmsgs.join('$|^')}$/o
caster = 'self'
multicast = false
activator = 'cast'
self_invoke = false
other_invoke = LimitedArray.new
other_invoke.max_size = 15
servant_type = nil
while line = get
begin
# fixme: invisible people casting at you
# fixme: bard renews his songs when you're in his group
# fixme: bard renew message shows up after spell message
if line =~ /^You (?:gesture|make a complex gesture|sing a melody|sing with renewed vigor|skillfully begin to weave another verse|weave another verse into your harmony)/
caster = 'self'
activator = 'cast'
if line =~ /^You make a complex gesture/
multicast = true
else
multicast = false
end
echo "caster = #{caster.inspect}; activator = #{activator.inspect}; multicast = #{multicast.inspect}" if $infomon_debug
elsif line =~ /^Sparks begin to fly between the .+ and your fingers. With a sudden burst of enthusiasm, the sparks jump into your hand and a charged feeling surrounds you\.$/
self_invoke = true
multicast = false
echo "self_invoke = true" if $infomon_debug
elsif line =~ /^Your spell is ready\./
self_invoke = false
echo "self_invoke = false" if $infomon_debug
elsif line =~ /^You (?:narrow your eyes in concentration as you |take a )?(rub|raise|wave|tap|drink|bite|gobble)/
caster = 'self'
multicast = false
activator = $1
echo "caster = #{caster.inspect}; activator = #{activator.inspect}; multicast = #{multicast.inspect}" if $infomon_debug
elsif line =~ /^([A-Z][a-z]+) (?:gestures|makes a complex gesture|sings a melody|sings with renewed vigor|skillfully begins to weave another verse|weave another verse into (?:his|her) harmony)/
caster = $1
activator = 'cast'
if line =~ /^([A-Z][a-z]+) makes a complex gesture/
multicast = true
else
multicast = false
end
echo "caster = #{caster.inspect}; activator = #{activator.inspect}; multicast = #{multicast.inspect}" if $infomon_debug
elsif line =~ /^([A-Z][a-z]+) (?:takes a )?(rubs|raises|waves|taps|drink|bite|gobbles)/
caster = $1
activator = $2.sub(/s$/, '')
multicast = false
echo "caster = #{caster.inspect}; activator = #{activator.inspect}; multicast = #{multicast.inspect}" if $infomon_debug
elsif line =~ /^Sparks begin to fly between .*? and ([A-Z][a-z]+)'s fingers\./
other_invoke.push($1)
multicast = false
echo "other_invoke.push(#{$1.inspect}) => #{other_invoke.inspect}" if $infomon_debug
elsif line =~ /^([A-Z][a-z]+) (begins drawing a faint, twisting symbol as he utters an arcane invocation in hushed tones|folds his hands and deeply intones a sonorous mantra|recites a series of mystical phrases while raising his hands|traces a sign while petitioning the spirits for cognition|gestures while calling upon the lesser spirits for aid|traces a series of glowing runes while chanting an arcane phrase|makes a quick gesture while calling upon the powers of the elements)/
# fixme: moar messages
other_invoke.delete($1)
echo "other_invoke.delete(#{$1.inspect}) => #{other_invoke.inspect}" if $infomon_debug
elsif line =~ /^Your songs? renews?/
Spellsong.renewed
elsif mobj = /^#{$lich_char}magic\s?(clear|set|reset|help|circles|bonus|bonuses|messages|update|load|save|gift|cleanup)?\s?([^\s]+|#{Spell.list.collect { |spell| Regexp.escape(spell.name) }.join('|')})?\s?(\d+\.?\d?\d?)?$/oi.match(line)
begin
if mobj.captures.first.nil? or mobj.captures.first =~ /cleanup/i
output = String.new
Spell.active.each { |spell| if spell.timeleft <= 0 then spell.putdown end } if mobj.captures.first =~ /cleanup/i
if Spell.active.empty?
output.concat("\n(no active spells)\n")
else
lastcircle = nil
Spell.active.compact!
total_boltAS, total_physicalAS, total_boltDS, total_physicalDS, total_elementalCS, total_mentalCS, total_spiritCS, total_sorcererCS, total_elementalTD, total_mentalTD, total_spiritTD, total_sorcererTD, total_strength, total_dodging = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
Spell.active.sort_by { |spell| spell.num.to_i }.each { |spell|
if CharSettings['show_circles'] and (spell.circle != lastcircle) then output.concat("\r\n- #{spell.circlename}:\r\n") end
bonus_string = ' - '
if CharSettings['show_bonuses']
if spell.bolt_as != 0
bonus_string.concat "#{spell.bolt_as} bAS, "
total_boltAS += spell.bolt_as
end
if spell.physical_as != 0
bonus_string.concat "#{spell.physical_as} pAS, "
total_physicalAS += spell.physical_as
end
if spell.bolt_ds != 0
bonus_string.concat "#{spell.bolt_ds} bDS, "
total_boltDS += spell.bolt_ds
end
if spell.physical_ds != 0
bonus_string.concat "#{spell.physical_ds} pDS, "
total_physicalDS += spell.physical_ds
end
if spell.elemental_cs != 0
bonus_string.concat "#{spell.elemental_cs} elemCS, "
total_elementalCS += spell.elemental_cs
end
# if spell.mental_cs != 0
# bonus_string.concat "#{spell.mental_cs} mentCS, "
# total_mentalCS += spell.mental_cs
# end
if spell.spirit_cs != 0
bonus_string.concat "#{spell.spirit_cs} spirCS, "
total_spiritCS += spell.spirit_cs
end
if spell.sorcerer_cs != 0
bonus_string.concat "#{spell.sorcerer_cs} sorcCS, "
total_sorcererCS += spell.sorcerer_cs
end
if spell.elemental_td != 0
bonus_string.concat "#{spell.elemental_td} elemTD, "
total_elementalTD += spell.elemental_td
end
if spell.mental_td != 0
bonus_string.concat "#{spell.mental_td} mentTD, "
total_mentalTD += spell.mental_td
end
if spell.spirit_td != 0
bonus_string.concat "#{spell.spirit_td} spirTD, "
total_spiritTD += spell.spirit_td
end
if spell.sorcerer_td != 0
bonus_string.concat "#{spell.sorcerer_td} sorcTD, "
total_sorcererTD += spell.sorcerer_td
end
if spell.strength.to_i != 0
bonus_string.concat "#{spell.strength} str, "
total_strength += spell.strength.to_i
end
if spell.dodging.to_i != 0
bonus_string.concat "#{spell.dodging} dodge, "
total_dodging += spell.dodging.to_i
end
end
output.concat(sprintf("%04s: %-023s - %s%s\n", spell.num.to_s, spell.name, spell.remaining, bonus_string.chop.chop))
lastcircle = spell.circle
}
output.concat("\n")
if CharSettings['show_bonuses']
total_string = ''
total_string = total_string + total_boltAS.to_s + ' bAS, ' if total_boltAS != 0
total_string = total_string + total_physicalAS.to_s + ' pAS, ' if total_physicalAS != 0
total_string = total_string + total_boltDS.to_s + ' bDS, ' if total_boltDS != 0
total_string = total_string + total_physicalDS.to_s + ' pDS, ' if total_physicalDS != 0
total_string = total_string + total_elementalCS.to_s + ' elemCS, ' if total_elementalCS != 0
total_string = total_string + total_mentalCS.to_s + ' mentCS, ' if total_mentalCS != 0
total_string = total_string + total_spiritCS.to_s + ' spirCS, ' if total_spiritCS != 0
total_string = total_string + total_sorcererCS.to_s + ' sorcCS, ' if total_sorcererCS != 0
total_string = total_string + total_elementalTD.to_s + ' elemTD, ' if total_elementalTD != 0
total_string = total_string + total_mentalTD.to_s + ' mentTD, ' if total_mentalTD != 0
total_string = total_string + total_spiritTD.to_s + ' spirTD, ' if total_spiritTD != 0
total_string = total_string + total_sorcererTD.to_s + ' sorcTD, ' if total_sorcererTD != 0
total_string = total_string + total_strength.to_s + ' str, ' if total_strength != 0
total_string = total_string + total_dodging.to_s + ' dodge, ' if total_dodging != 0
total_string = total_string.chop.chop
output.concat("Totals: #{total_string if total_string.length > 0}\n\n")
end
end
if CharSettings['show_gift']
giftleft = Gift.remaining
unless Time.now > Gift.restarts_on
cyclemins = (Gift.restarts_on.to_i - Time.now.to_i) / 60.00
days = cyclemins.as_time.slice(/\d+/).to_i / 24
hours = cyclemins.as_time.slice(/\d+/).to_i % 24
mins, secs = cyclemins.as_time.split(':')[-2..-1]
mins, secs = mins.to_i, secs.to_i
if days > 1
output.concat("Your Gift of Lumnis cycle will restart in #{days} days, ")
elsif days == 1
output.concat("Your Gift of Lumnis cycle will restart in #{days} day, ")
else
output.concat("Your Gift of Lumnis cycle will restart in 0 days, ")
end
if hours == 1
output.concat("#{hours} hour, ")
elsif hours > 1
output.concat("#{hours} hours, ")
else
output.concat("0 hours, ")
end
if mins == 1
output.concat("#{mins} minute, ")
elsif mins > 1
output.concat("#{mins} minutes, ")
else
output.concat("0 minutes, ")
end
if secs > 1
output.concat("#{secs} seconds.")
elsif secs == 1
output.concat("#{secs} second.")
else
output.concat("0 seconds.")
end
output.concat("\n\n")
if giftleft <= 0
nil
elsif giftleft < 10800
output.concat("Time remaining for double learning: #{(giftleft / 60).as_time}.\n\n")
else
giftleft -= 10800
output.concat("Time remaining for triple learning: #{(giftleft / 60).as_time}.\n\n")
end
else
output.concat("Your Gift of Lumnis cycle will begin when you next learn from an experience.\n\n")
end
end
respond output
elsif mobj.captures.first =~ /help/i
respond
respond 'Magic usage:'
respond ' ;magic - Shows your active spells and their durations.'
respond " ;magic set [spell#] [mins] - Sets a spell's duration."
respond ' ;magic clear [spell] - Remove a single spell.'
respond ' ;magic clear - Clears the whole list.'
respond ' ;magic circles - Toggles the display of spell circle labels with the active spell list.'
respond ' ;magic bonuses - Toggles the display of spell bonuses with the active spell list.'
respond ' ;magic gift - Toggles the display of Gift of Lumnis information with the active spell list.'
respond ' ;magic messages - Toggles the display of a duration message after each cast.'
respond ' ;magic save - Saves your currently active spells and currently tracked skills/stats on the Lich server.'
respond ' ;magic load - Load your currently active spells and skills/stats from the Lich server.'
respond
elsif mobj.captures.first =~ /clear|reset/i
if mobj.captures[1].nil? or mobj.captures[1].empty?
while spell = Spell.active.first
spell.putdown
end
Spell.active.clear
respond('Active spell list cleared.')
else
if mobj.captures[1].to_i == 0
spell = Spell[mobj.captures[1]]
else
spell = Spell[mobj.captures[1].to_i]
end
if spell.nil?
respond("Could not identify spell #{$1}")
else
spell.putdown
respond("#{spell} has been removed from the list.")
end
end
elsif mobj.captures.first =~ /circle/i
if CharSettings['show_circles'] == false
CharSettings['show_circles'] = true
echo('Spell circle labels will be displayed in the active spell list.')
else
CharSettings['show_circles'] = false
echo('Spell circle labels will not be displayed in the active spell list.')
end
elsif mobj.captures.first =~ /messages/i
if CharSettings['show_messages'] == false
CharSettings['show_messages'] = true
echo('Showing spell duration messages after each cast is now on.')
else
CharSettings['show_messages'] = false
echo('Showing spell duration messages after each cast is now off.')
end
elsif mobj.captures.first =~ /bonus/i
if CharSettings['show_bonuses'] == false
CharSettings['show_bonuses'] = true
echo('Spell bonuses will be displayed in the active spell list.')
else
CharSettings['show_bonuses'] = false
echo('Spell bonuses will not be displayed in the active spell list.')
end
elsif mobj.captures.first =~ /gift/i
if CharSettings['show_gift'] == false
CharSettings['show_gift'] = true
echo('Gift of Lumnis will be displayed in the active spell list.')
else
CharSettings['show_gift'] = false
echo('Gift of Lumnis will not be displayed in the active spell list.')
end
elsif mobj.captures.first =~ /update/i
echo 'this setting is no longer used'
elsif mobj.captures.first =~ /set/i
if (mobj.captures[1].nil? || mobj.captures[2].nil?)
echo("Magic error! Type ';magic help' for usage information.")
else
if mobj.captures[1].to_i == 0
spell = Spell[mobj.captures[1]]
else
spell = Spell[mobj.captures[1].to_i]
end
if spell.nil?
echo("Magic error! Type ';magic help' for usage information.")
else
spell.putup
spell.timeleft = mobj.captures[2].to_i
echo("Spell '#{spell.to_s}' is now set as having #{spell.timeleft} minutes left.")
end
end
elsif mobj.captures.first =~ /save/i
if $SAFE == 0
echo("Saving your current active spells on the Lich server for later use on a different computer... please be patient, it can sometimes take up to half a minute to initiate the connection...")
if lich_server = get_lich_server.call
lich_server.send('x',0)
lich_server.puts("#{XMLData.game}:#{XMLData.name}")
lich_server.binmode
remote_save = Hash.new
remote_save['active_spells'] = Hash.new
Spells.active.each { |spell|
if defined?(spell.real_time) and spell.real_time
remote_save['active_spells'][spell.num.to_s] = Time.now.to_f + (spell.timeleft * 60)
else
remote_save['active_spells'][spell.num.to_s] = spell.timeleft
end
}
remote_save['Spellsong'] = Spellsong.serialize
remote_save['Stats'] = Stats.serialize
remote_save['Skills'] = Skills.serialize
remote_save['Spells'] = Spells.serialize
remote_save['Gift'] = Gift.serialize
remote_save['Society'] = Society.serialize
remote_save['citizenship'] = Char.citizenship
lich_server.write(Marshal.dump(remote_save))
lich_server.close rescue()
echo
echo "Data has been cached remotely! Simply type '#{$clean_lich_char}magic load' when you wish to restore the current state of your character on the other computer."
echo
end
else
echo 'This script must be trusted to use this function.'
end
elsif mobj.captures.first =~ /load/i
if $SAFE == 0
echo("Loading your current active spells from the remote cache on the Lich server... please be patient, it can sometimes take up to half a minute to initiate the connection...")
if lich_server = get_lich_server.call
lich_server.send("z",0)
lich_server.puts("#{XMLData.game}:#{XMLData.name}")
lich_server.binmode
begin
remote_load = Marshal.load(lich_server.read)
Stats.load_serialized = remote_load['Stats']
Skills.load_serialized = remote_load['Skills']
Spells.load_serialized = remote_load['Spells']
Society.load_serialized = remote_load['Society']
Char.citizenship = remote_load['citizenship']
remote_load['active_spells'].each_pair { |num,timeleft|
if spell = Spell[num]
if defined?(spell.real_time) and spell.real_time
timeleft = (timeleft - Time.now.to_f)/60.0
if timeleft > 0
spell.timeleft = timeleft
spell.active = true
end
else
spell.timeleft = timeleft
spell.active = true
end
end
}
Spellsong.load_serialized = remote_load['Spellsong'] if remote_load['Spellsong']
Gift.load_serialized = remote_load['Gift'] if remote_load['Gift']
rescue
echo("There was an error loading your status information from the server. Are you certain you have status info saved on it? Type `;magic help' for more.")
lich_server.close rescue()
next
end
lich_server.close rescue()
echo
echo 'Data has been loaded!'
echo
end
else
echo 'This script must be trusted to use this function.'
end
else
echo "Magic error! Type ';magic help' for usage information."
end
rescue
echo $!
end
elsif line =~ /^#{$lich_char}banks$/
if CharSettings['bank_accounts'].empty?
respond
respond 'No bank account info recorded.'
respond
else
respond
total = 0
for town,amount in CharSettings['bank_accounts']
respond "#{town.rjust(27)}:#{amount.to_s.reverse.scan(/(?:\d*\.)?\d{1,3}-?/).join(',').reverse.rjust(13)}"
total += amount
end
respond ' -------------------'
respond " Total:#{total.to_s.reverse.scan(/(?:\d*\.)?\d{1,3}-?/).join(',').reverse.rjust(13)}"
respond
end
elsif line =~ /^(?:You hand your silvers? over to the|You hand your notes to the|You hand over your notes to the|You deposit [0-9]+ silvers? into your account. The|The) (?:teller|dwarf).*(?:balance is |balance of |balance to |balance up to |balance is currently at |New balance\: )([0-9]+)/
for town,titles in bank_titles
if titles.include?(checkroom)
CharSettings['bank_accounts'][town] = $1.to_i
break
end
end
elsif line =~ /^The (?:teller|dwarf) (?:carefully records the transaction,|scribbles the transaction into a book)(?: and)?(?: then)?(?: reluctantly)? hands you ([0-9]+)/
for town,titles in bank_titles
if titles.include?(checkroom)
CharSettings['bank_accounts'][town] = CharSettings['bank_accounts'][town].to_i - $1.to_i
break
end
end
elsif line =~ /^You deposit(?: your note worth| your chit worth)? ([0-9]+)/
for town,titles in bank_titles
if titles.include?(checkroom)
CharSettings['bank_accounts'][town] = CharSettings['bank_accounts'][town].to_i + $1.to_i
break
end
end
elsif line =~ /^The (?:teller|dwarf).* ([0-9]+) silver surchar?ge/
surcharge = $1.to_i
if line = $_CLIENTBUFFER_.reverse.find { |line| line =~ /^(?:\[.*?\]>)?(?:<c>)?(?:wit|with|withd|withr|withdra|withdraw)\s+[0-9]+/i }
amount = line.slice(/[0-9]+/).to_i
for town,titles in bank_titles
if titles.include?(checkroom)
CharSettings['bank_accounts'][town] = [ (CharSettings['bank_accounts'][town].to_i - amount - surcharge), 0 ].max
break
end
end
end
elsif line =~ /^The (?:teller|dwarf).*you don't(?: seem to)? have an (?:open )?account/
for town,titles in bank_titles
if titles.include?(checkroom)
CharSettings['bank_accounts'][town] = 0
break
end
end
elsif line == 'You study your current bank balances...'
15.times {
line = get
if line =~ /\s*(Wehnimer's Landing|Kharam-Dzu|Icemule Trace|Vornavis|River's Rest|Kharag 'doth Dzulthu|United City-States|Isle of the Four Winds Bank|Cysaegir):\s+([0-9]+)/
CharSettings['bank_accounts'][$1] = $2.to_i
elsif line =~ /Your total silvers/
break
end
}
# elsif line =~ /^You stop singing\.$|^But you are not singing any spellsongs\.$/
# Spell.list.each { |spell| spell.putdown if spell.circle.to_i == 10 }
elsif line =~ /^The soft feeling of serenity slowly dissipates from your mind\.$/
Gift.ended
CharSettings['Gift'] = Gift.serialize
elsif line =~ /^A soft feeling of serenity touches your mind, providing you with a clearer understanding of recent events\.$/
Gift.started
CharSettings['Gift'] = Gift.serialize
# elsif line =~ /^You feel a strange sense of serenity and find that you are able to reflect on recent events with uncommon clarity and understanding\.$/
elsif line == 'Repeating the sign has no effect!'
if spell_name = [ 'Sign of Striking', 'Sign of Smiting', 'Sign of Swords', 'Sign of Warding', 'Sign of Defending', 'Sign of Shields', 'Sign of Deflection', 'Sign of Dissipation' ].find { |name| (XMLData.active_spells[name] > Time.now) and not Spell[name].active? }
spell = Spell[spell_name]
spell.putup
respond "[ #{spell.name}: +#{spell.time_per.as_time}, #{spell.remaining} remaining. ]" if CharSettings['show_messages']
elsif mangled_name = $_CLIENTBUFFER_.reverse.find { |cmd| cmd =~ /^(?:\[[^\]]+\])?>?(?:<c>)?(?:si|sig|sign)\s+(?:of\s+)?(st|str|stri|strik|striki|strikin|striking|sm|smi|smit|smiti|smitin|smiting|sw|swo|swor|sword|swords|wa|war|ward|wardi|wardin|warding|de|def|defe|defen|defend|defendi|defendin|defending|sh|shi|shie|shiel|shield|shields|defl|defle|deflec|deflect|deflecti|deflectio|deflection|di|dis|diss|dissi|dissip|dissipa|dissipat|dissipati|dissipatio|dissipation)\s*$/i }
mangled_name =~ /^(?:\[[^\]]+\])?>?(?:<c>)?(?:si|sig|sign)\s+(?:of\s+)?(st|str|stri|strik|striki|strikin|striking|sm|smi|smit|smiti|smitin|smiting|sw|swo|swor|sword|swords|wa|war|ward|wardi|wardin|warding|defl|defle|deflec|deflect|deflecti|deflectio|deflection|de|def|defe|defen|defend|defendi|defendin|defending|sh|shi|shie|shiel|shield|shields|di|dis|diss|dissi|dissip|dissipa|dissipat|dissipati|dissipatio|dissipation)\s*$/i
spell = Spell["Sign of #{$1}"]
spell.putup
respond "[ #{spell.name}: +#{spell.time_per.as_time}, #{spell.remaining} remaining. ]" if CharSettings['show_messages']
end
elsif line =~ /^The High Taskmaster looks at you, consults her notes, and then announces in a loud voice\: "Congratulations, [A-Z][a-z]+! By the power invested in me by the Grand Poohbah, I declare you to be .*? of rank ([0-9]+)!/
Society.status = 'Council of Light'
Society.rank = $1.dup
CharSettings['Society'] = Society.serialize
elsif line =~ /^The monk concludes ceremoniously,|^The Grandmaster says, "Welcome to the Order/
hide_lines = done = false
action = proc { |server_string|
if hide_lines
if server_string =~ /<prompt/
DownstreamHook.remove('infomon_society')
done = true
end
nil
elsif server_string == "<pushBold/>\r\n"
hide_lines = true
nil
else
server_string
end
}
DownstreamHook.add('infomon_society', action)
# echo 'checking society...'
silence_me unless undo_silence = silence_me
put 'society'
silence_me if undo_silence
wait_until { done }
elsif line =~ /^\s+You are a (Master|member) (?:in|of) the (Order of Voln|Council of Light|Guardians of Sunfist)( at rank [0-9]+| at step [0-9]+)?\.$/
Society.status = $2.dup
if $1 == 'Master'
if $2 == 'Order of Voln'
Society.rank = '26'
else
Society.rank = '20'
end
else
Society.rank = $3.dup
end
CharSettings['Society'] = Society.serialize
elsif line == ' You are not a member of any society at this time.'
Society.status = 'None'
Society.rank = '0'
CharSettings['Society'] = Society.serialize
elsif line =~ /^\s#{Char.name} \(at level/o
begin
before_ranks = [ Spells.minorelemental, Spells.minormental, Spells.majorelemental, Spells.minorspiritual, Spells.majorspiritual, Spells.wizard, Spells.sorcerer, Spells.ranger, Spells.paladin, Spells.empath, Spells.cleric, Spells.bard, Skills.magicitemuse, Skills.arcanesymbols ]
Skills.armoruse, Skills.shielduse, Skills.combatmaneuvers, Skills.edgedweapons, Skills.bluntweapons, Skills.twohandedweapons, Skills.rangedweapons, Skills.thrownweapons, Skills.polearmweapons, Skills.brawling, Skills.ambush, Skills.multiopponentcombat, Skills.combatleadership, Skills.physicalfitness, Skills.dodging, Skills.arcanesymbols, Skills.magicitemuse, Skills.spellaiming, Skills.harnesspower, Skills.emc, Skills.mmc, Skills.smc, Skills.elair, Skills.elearth, Skills.elfire, Skills.elwater, Skills.slblessings, Skills.slreligion, Skills.slsummoning, Skills.sldemonology, Skills.slnecromancy, Skills.mldivination, Skills.mlmanipulation, Skills.mltelepathy, Skills.mltransference, Skills.mltransformation, Skills.survival, Skills.disarmingtraps, Skills.pickinglocks, Skills.stalkingandhiding, Skills.perception, Skills.climbing, Skills.swimming, Skills.firstaid, Skills.trading, Skills.pickpocketing, Spells.minorelemental, Spells.minormental, Spells.majorelemental, Spells.minorspiritual, Spells.majorspiritual, Spells.wizard, Spells.sorcerer, Spells.ranger, Spells.paladin, Spells.empath, Spells.cleric, Spells.bard = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
until (line = get) =~ /\(Use |[0-9]+ days? remain|You started this migration period|Further information can be found in the FAQs./
if line =~ /Two Weapon Combat/
Skills.twoweaponcombat = $'.split[2].to_i
elsif line =~ /Armor Use/
Skills.armoruse = $'.split[2].to_i
elsif line =~ /Shield Use/
Skills.shielduse = $'.split[2].to_i
elsif line =~ /Combat Maneuvers/
Skills.combatmaneuvers = $'.split[2].to_i
elsif line =~ /Edged Weapons/
Skills.edgedweapons = $'.split[2].to_i
elsif line =~ /Blunt Weapons/
Skills.bluntweapons = $'.split[2].to_i
elsif line =~ /Two-Handed Weapons/
Skills.twohandedweapons = $'.split[2].to_i
elsif line =~ /Ranged Weapons/
Skills.rangedweapons = $'.split[2].to_i
elsif line =~ /Thrown Weapons/
Skills.thrownweapons = $'.split[2].to_i
elsif line =~ /Polearm Weapons/
Skills.polearmweapons = $'.split[2].to_i
elsif line =~ /Brawling/
Skills.brawling = $'.split[2].to_i
elsif line =~ /Ambush/
Skills.ambush = $'.split[2].to_i
elsif line =~ /Multi Opponent Combat/
Skills.multiopponentcombat = $'.split[2].to_i
elsif line =~ /Combat Leadership/
Skills.combatleadership = $'.split[2].to_i
elsif line =~ /Physical Fitness/
Skills.physicalfitness = $'.split[2].to_i
elsif line =~ /Dodging/
Skills.dodging = $'.split[2].to_i
elsif line =~ /Arcane Symbols/
Skills.arcanesymbols = $'.split[2].to_i
elsif line =~ /Magic Item Use/
Skills.magicitemuse = $'.split[2].to_i
elsif line =~ /Spell Aiming/
Skills.spellaiming = $'.split[2].to_i
elsif line =~ /Harness Power/
Skills.harnesspower = $'.split[2].to_i
elsif line =~ /Elemental Mana Control/
Skills.emc = $'.split[2].to_i
elsif line =~ /Mental Mana Control/
Skills.mmc = $'.split[2].to_i
elsif line =~ /Spirit Mana Control/
Skills.smc = $'.split[2].to_i
elsif line =~ /Elemental Lore - ([A-Z][a-z]+)/
if $1 == "Air"
Skills.elair = $'.split[2].to_i
elsif $1 == "Earth"
Skills.elearth = $'.split[2].to_i
elsif $1 == "Fire"
Skills.elfire = $'.split[2].to_i
elsif $1 == "Water"
Skills.elwater = $'.split[2].to_i
end
elsif line =~ /Spiritual Lore - ([A-Z][a-z]+)/
if $1 == "Blessings"
Skills.slblessings = $'.split[2].to_i
elsif $1 == "Religion"
Skills.slreligion = $'.split[2].to_i
elsif $1 == "Summoning"
Skills.slsummoning = $'.split[2].to_i
end
elsif line =~ /Sorcerous Lore - ([A-Z][a-z]+)/
if $1 == "Demonology"
Skills.sldemonology = $'.split[2].to_i
elsif $1 == "Necromancy"
Skills.slnecromancy = $'.split[2].to_i
end
elsif line =~ /Mental Lore - ([A-Z][a-z]+)/
if $1 == "Divination"
Skills.mldivination = $'.split[2].to_i
elsif $1 == "Manipulation"
Skills.mlmanipulation = $'.split[2].to_i
elsif $1 == "Telepathy"
Skills.mltelepathy = $'.split[2].to_i
elsif $1 == "Transference"
Skills.mltransference = $'.split[2].to_i
elsif $1 == "Transformation"
Skills.mltransformation = $'.split[2].to_i
end
elsif line =~ /Survival/
Skills.survival = $'.split[2].to_i
elsif line =~ /Disarming Traps/
Skills.disarmingtraps = $'.split[2].to_i
elsif line =~ /Picking Locks/
Skills.pickinglocks = $'.split[2].to_i
elsif line =~ /Stalking and Hiding/
Skills.stalkingandhiding = $'.split[2].to_i
elsif line =~ /Perception/
Skills.perception = $'.split[2].to_i
elsif line =~ /Climbing/
Skills.climbing = $'.split[2].to_i
elsif line =~ /Swimming/
Skills.swimming = $'.split[2].to_i
elsif line =~ /First Aid/
Skills.firstaid = $'.split[2].to_i
elsif line =~ /Trading/
Skills.trading = $'.split[2].to_i
elsif line =~ /Pickpocketing/
Skills.pickpocketing = $'.split[2].to_i
elsif line =~ /Minor Elemental/
Spells.minorelemental = $'.split[1].to_i
elsif line =~ /Major Elemental/
Spells.majorelemental = $'.split[1].to_i
elsif line =~ /Minor Mental/
Spells.minormental = $'.split[1].to_i
elsif line =~ /Minor Spirit/
Spells.minorspiritual = $'.split[1].to_i
elsif line =~ /Major Spirit/
Spells.majorspiritual = $'.split[1].to_i
elsif line =~ /Wizard/
Spells.wizard = $'.split[1].to_i
elsif line =~ /Sorcerer/
Spells.sorcerer = $'.split[1].to_i
elsif line =~ /Ranger/
Spells.ranger = $'.split[1].to_i