-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathtargetid.lic
216 lines (171 loc) · 6.19 KB
/
targetid.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
=begin
TargetID adds 3-character-long 'tags' to monsters in the room to determine which monster is performing which actions
and responds accordingly. Instead of "a hill troll", you might see "a hill troll(ABC)"
While TargetID is running, it adds a few new 'commands' to the game, all beginning with the letter 'T'. All of these
are roughly equivalent to their 'real' in-game versions, but they accept a tag (or the first letter or two of it)
rather than a target name.
These commands will never target players, and only work when referring to a targetable critter that is in the room
and not dead. They are:
Full Minimum Notes
TTARGET TT Only works with 'ttarget <tag>', 'ttarget next' and similar do not work.
TATTACK TAT
TKILL TK
TCMAN TCM For combat maneuvers that accept targets
TJAB TJ
TPUNCH TP
TKICK TKIC
TGRAPPLE TG
TCAST TCA
TMSTRIKE TM For focused mstrike on a tagged critter. TMSTRIKE JAB <tag> and family also work.
author: LostRanger (thisgenericname@gmail.com)
game: Gemstone
tags: utility
required: Lich >= 4.6.0.
version: 0.1.2 (2019-06-18)
changelog:
version 0.1.2 (2019-06-18)
* He remembered more pronouns.
version 0.1.1 (2019-06-17)
* Actually properly avoid tagging pronouns. Searching will be less noisy.
* Add assorted formatting experiments.
version 0.1 (2019-06-17)
* Initial release
=end
module TargetIDScript
VERSION = "0.1.2 BETA (2019-06-18)"
# 1=entire match 2=exist ID 3=exist name/pronoun
PATTERN = /<pushBold\/>.*?<a exist=\"(\d+)\".+?>(.*?)<\/a>.*?<popBold\/>/
IGNORE_PATTERN = /^(?:he|she|his|her|him|it|its)$/i
B32_ALPHABET = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ"
B32_REVERSE = {}
B32_ALPHABET.chars.each_with_index do |char, index|
B32_REVERSE[char] = index
B32_REVERSE[char.downcase] = index
end
B32_PATTERN = /^[#{B32_ALPHABET}]*$/i
MASKS = [0]
4.times do |x|
MASKS[x+1] = (MASKS[x] << 5) | 31
end
TARGETED_COMMANDS = {}
def self._build_targets(command, sub, minlen=2)
n = minlen - 1
while n < command.length
TARGETED_COMMANDS[command[0..n]] = sub
n += 1
end
end
_build_targets("ttarget", "target", 2)
_build_targets("tattack", "attack", 3)
_build_targets("tambush", "ambush", 3)
_build_targets("tkill", "kill", 2)
_build_targets("tcast", "cast", 3)
_build_targets("tcman", "cman", 3)
_build_targets("tpunch", "punch", 2)
_build_targets("tgrapple", "grapple", 2)
_build_targets("tkick", "kick", 4)
_build_targets("tjab", "jab", 2)
_build_targets("tmstrike", "mstrike", 2)
COMMAND_PATTERN = /^(?:<c>)?\s*(#{TARGETED_COMMANDS.keys.join('|')})(?:\s+(.*?))?\s*$/i
# echo COMMAND_PATTERN
def self.run(script)
script.want_downstream_xml = true
script.want_downstream = false
hook_name = self.anon_hook
before_dying do
UpstreamHook.remove(hook_name)
DownstreamHook.remove(hook_name)
end
# We do a poor-man's LRU cache here, since we're not particular concerned about it staying at an exact size
# and would rather the performance.
recent = Set.new
less_recent = Set.new
DownstreamHook.add(hook_name, proc {|xml|
xml.gsub(PATTERN){|match|
id = $1
name = $2
next match if name =~ IGNORE_PATTERN
if GameObj.targets.find{|x| x.id == id}
if recent.add?(id) and recent.length > 20
less_recent = recent
recent = Set.new
end
elsif not (recent.include?(id) or less_recent.include?(id))
next match
end
next "#{match} (#{id_to_key(id.to_i,3)})"
}
})
UpstreamHook.add(hook_name, proc {|xml|
next xml unless xml =~ COMMAND_PATTERN
command = $1
verb = TARGETED_COMMANDS[command.downcase]
target = $2.strip
unless target
if verb == 'cman'
_respond "Usage: T#{verb.upcase} maneuver targetID"
else
_respond "Usage: T#{verb.upcase} targetID"
end
next nil
end
if verb == 'cman'
if target =~ /^(.*\s)\s*(\S+)\s*$/
verb = "cman #{$1}"
target = $2
else
_respond "Usage: T#{verb.upcase} maneuver targetID"
end
next nil
end
if verb == 'mstrike'
if target =~ /^(.*\s)\s*(\S+)\s*$/
verb = "mstrike #{$1}"
target = $2
end
end
if target =~ B32_PATTERN
if (id = key_to_id(target, GameObj.targets.map{|x| x.id}))
next "<c>#{verb} ##{id}"
end
end
_respond "Target with tag '#{target.upcase}' not found!"
next nil
})
echo "Version #{VERSION} running."
nil while get
end
def self.anon_hook(prefix = '')
now = Time.now
"TargetID::#{prefix}-#{now.tv_sec}.#{now.tv_usec}-#{Random.rand(10000)}"
end
def self.id_to_key(id, length=2)
id = id.to_i
s = B32_ALPHABET[id & 31]
(length-1).times do
s += B32_ALPHABET[(id >>= 5) & 31]
end
return s
end
def self.key_to_value(key)
value = 0
shift = 0
key.chars.each do |char|
value |= (B32_REVERSE[char] << shift)
shift += 5
end
return value
end
def self.key_to_id(key, candidates)
value = key_to_value(key)
mask = MASKS[key.length]
candidates.each do |x|
if (x.to_i & mask) == value
return x
end
end
return nil
end
end
echo "I don't really have proper documentation yet; for help see #{$lich_char}repo info #{script.name}"
TargetIDScript.run(script)