Olib 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 57801fc8332955fb943a92598747f32d4e77550d
4
- data.tar.gz: 76f6062a91e234262c511a93351de8448c4a6e28
3
+ metadata.gz: d7c2221d775721ed099b5f6be06e8efe67af5f35
4
+ data.tar.gz: c246739bf3831d398082d545cdfbe4943f93dd0c
5
5
  SHA512:
6
- metadata.gz: b7bd539edcfff1e5053ec26c429781bfeae13c4f47393a12ad36528a62a73b60d2ef907154be75b737f1f0edb04df964508ac08bb7499f27741c1f497c58763e
7
- data.tar.gz: 524c52224491dcdafcf693c3a35e869662031a01927441e92d6e0287e3b30bdf063061adc72b7b3ee73ca9fd26f38a9c41dcff4b860ba7ec52397aee79f9574c
6
+ metadata.gz: b007940362e1ac0f1a2ebe3fd633a57e292bd1d08d13c9feca6562b7eda1586590e6804c4fc1e1c56f414559273a45723d02410ea7920d3c70250171e4f66a54
7
+ data.tar.gz: 375af61ffbb01c36258e2076013c6fb652c26aa321278d826c1922ad810ae0375183051f894f593044255709629ec1956ca1a3df83d7cda0cd87fc9fa9cce3b9
@@ -1,5 +1,40 @@
1
1
  require 'net/http'
2
2
  require 'json'
3
+ require "ostruct"
4
+
5
+ class String
6
+ def is_i?
7
+ !!(self =~ /\A[-+]?[0-9]+\z/)
8
+ end
9
+ end
10
+
11
+ class MatchData
12
+ def to_struct
13
+ OpenStruct.new to_hash
14
+ end
15
+
16
+ def to_hash
17
+ Hash[self.names.zip(self.captures.map(&:strip).map do |capture|
18
+ if capture.is_i? then capture.to_i else capture end
19
+ end)]
20
+ end
21
+ end
22
+
23
+ class Hash
24
+ def to_struct
25
+ OpenStruct.new self
26
+ end
27
+ end
28
+
29
+ class Regexp
30
+ def or(re)
31
+ Regexp.new self.to_s + "|" + re.to_s
32
+ end
33
+ # define union operator for regex instance
34
+ def |(re)
35
+ self.or(re)
36
+ end
37
+ end
3
38
 
4
39
  module Olib
5
40
 
@@ -9,8 +44,7 @@ module Olib
9
44
  # check version
10
45
  if Gem.loaded_specs["Olib"].version < Gem::Version.new(response['version'])
11
46
  puts "<pushBold/>You need to update the Olib gem with a `gem install Olib`<popBold/>"
12
- end
13
-
47
+ end
14
48
  rescue
15
49
  echo $!
16
50
  puts $!.backtrace[0..1]
@@ -18,7 +52,7 @@ module Olib
18
52
  end
19
53
 
20
54
  def Olib.methodize(str)
21
- str.downcase.strip.gsub(/-|\s+|'|"/, "_")
55
+ str.to_s.downcase.strip.gsub(/-|\s+|'|"/, "_").to_sym
22
56
  end
23
57
 
24
58
  # load core first
@@ -32,7 +66,7 @@ module Olib
32
66
  }
33
67
 
34
68
  # invoke update notifier immediately
35
- Olib.update_notifier
69
+ # Olib.update_notifier
36
70
 
37
71
  def Olib.do(action, re)
38
72
  dothistimeout action, 5, re
@@ -43,46 +77,6 @@ module Olib
43
77
  wait_while { running? script }
44
78
  end
45
79
 
46
- def Olib.install(g, v=nil)
47
- if !which("gem") then
48
- echo "Olib could not detect the `gem` executable in your $PATH"
49
- echo "when you installed Ruby did you forget to click the `modify $PATH` box?"
50
- raise Exception
51
- end
52
-
53
- begin
54
- unless v.nil?
55
- # make it a true instance of Gem::Version so we can compare
56
- raise UpdateGemError if Gem.loaded_specs[g].version < Gem::Version.new(v)
57
- gem g, v
58
- end
59
-
60
- Olib.reload g
61
-
62
- ##
63
- ## rescue missing gem and reload after install
64
- ##
65
- rescue LoadError
66
- echo "installing #{g}..."
67
- version = "--version '#{v}'" unless v.nil?
68
- worked = system("gem install #{g} #{version} --no-ri --no-rdoc")
69
- unless worked then raise "Could not install #{g} gem" end
70
- Olib.reload g
71
- echo "... installed #{g}!"
72
-
73
- ##
74
- ## rescue from too old of a gem version for a Ruby environment
75
- ##
76
- rescue UpdateGemError
77
- echo "updating #{g}@#{Gem.loaded_specs[g].version} => #{v}..."
78
- version = "--version '#{v}'" unless v.nil?
79
- worked = system("gem install #{g} #{version} --no-ri --no-rdoc")
80
- unless worked then raise "Could not install #{g} gem" end
81
- Olib.reload g
82
- echo "... updated #{g} to #{v}!"
83
- end
84
- end
85
-
86
80
  Vars.Olib ||= Hash.new
87
81
 
88
82
 
@@ -0,0 +1,117 @@
1
+ module Actor
2
+ def self.included(klass)
3
+ klass.class_variable_set(:@@supervisor, Supervisor.new(klass.name))
4
+ klass.class_variable_set(:@@states, Array.new)
5
+ klass.class_variable_set(:@@pre_hooks, Array.new)
6
+ klass.class_variable_set(:@@post_hooks, Array.new)
7
+ klass.class_variable_set(:@@state, nil)
8
+ klass.class_variable_set(:@@history, Array.new)
9
+ klass.extend Actor::Mixins
10
+ end
11
+
12
+ module Mixins
13
+
14
+ def states
15
+ self.class_variable_get(:@@states)
16
+ end
17
+
18
+ def pre_hooks
19
+ self.class_variable_get(:@@pre_hooks)
20
+ end
21
+
22
+ def post_hooks
23
+ self.class_variable_get(:@@post_hooks)
24
+ end
25
+
26
+ def state
27
+ self.class_variable_get(:@@state)
28
+ end
29
+
30
+ def history
31
+ self.class_variable_get(:@@history)
32
+ end
33
+
34
+ def supervisor
35
+ self.class_variable_get(:@@supervisor)
36
+ end
37
+
38
+ def state=(state)
39
+ class_variable_set(:@@state, state.to_sym)
40
+ end
41
+
42
+ def start(state)
43
+ class_variable_set(:@@state, state.to_sym)
44
+ end
45
+
46
+ def emit(state)
47
+ state = state.to_sym
48
+ validate! state
49
+ self
50
+ end
51
+
52
+ def to_s
53
+ "#{self.name}<state=#{state} last=#{last} history=#{history} states=#{states}>"
54
+ end
55
+
56
+ def yield(state)
57
+ emit(state)
58
+ Fiber.yield
59
+ end
60
+
61
+ def is?(state)
62
+ validate!(state)
63
+ state == state
64
+ end
65
+
66
+ def last
67
+ history[-2]
68
+ end
69
+
70
+ def validate!(state)
71
+ state = state.to_sym
72
+ raise Actor::InvalidState.new(state, self) unless states.include?(state)
73
+ end
74
+
75
+ def garbage_collect!
76
+ history.shift while history.size > states.size
77
+ end
78
+
79
+ def before_every(&hook)
80
+ pre_hooks << hook
81
+ self
82
+ end
83
+
84
+ def after_every(&hook)
85
+ post_hooks << hook
86
+ self
87
+ end
88
+
89
+ def add(state, &callback)
90
+ ref = self
91
+
92
+ states << state.to_sym
93
+ supervisor.add(state) do
94
+ Fiber.yield until ref.is?(state)
95
+ ref.history << state
96
+ garbage_collect!
97
+ pre_hooks.each do |hook| hook.call(ref) end
98
+ # did a pre_hook prempt this op?
99
+ if ref.is?(state)
100
+ callback.call(ref)
101
+ post_hooks.each do |hook| hook.call(ref) end
102
+ end
103
+ end
104
+ self
105
+ end
106
+
107
+ def link!
108
+ supervisor.link!
109
+ end
110
+ end
111
+
112
+ class InvalidState < Exception
113
+ def initialize(state, flow)
114
+ super "Actor::state cannot be #{state}, validate states: #{flow.states}"
115
+ end
116
+ end
117
+ end
@@ -1,13 +1,32 @@
1
1
  class Area < Olib::Container
2
+ def self.contents
3
+ GameObj.loot.map { |obj| Olib::Item.new(obj) }
4
+ end
5
+
6
+ def each
7
+ self.contents.each { |item|
8
+ yield item
9
+ }
10
+ end
11
+
12
+ class << self
13
+ Olib::Item.type_methods.each { |method, tag|
14
+ exp = /#{tag}/
15
+ define_method(method.to_sym) do
16
+ GameObj.loot
17
+ .select { |obj| obj.type =~ exp }
18
+ .map { |obj| Olib::Item.new(obj) }
19
+ end
20
+ }
21
+ end
2
22
 
3
- def Area.current
23
+ def Area.deep
4
24
  Area.new
5
25
  end
6
26
 
7
- attr_accessor :room, :contents, :objects
27
+ attr_accessor :room, :objects
8
28
 
9
29
  def initialize
10
- @contents = []
11
30
  @room = Room.current
12
31
  @objects = [ GameObj.loot, GameObj.room_desc ]
13
32
  .flatten
@@ -23,6 +42,7 @@ class Area < Olib::Container
23
42
  .reject { |container| container.name =~ /[A-Z][a-z]+ disk/ }
24
43
  .each { |container|
25
44
  check_container container
45
+ item = Olib::Item.new container
26
46
  unless container.nested?
27
47
  container.contents.each { |item|
28
48
  item.container = container
@@ -1,172 +1,217 @@
1
- module Olib
2
- class Bounty
3
- @@listeners = {}
4
- @@re = {}
5
- @@re[:herb] = /requires (?:a|an|some) (?<herb>[a-zA-Z '-]+) found (?:in|on|around) (?<area>[a-zA-Z '-]+). These samples must be in pristine condition. You have been tasked to retrieve (?<number>[\d]+)/
6
- @@re[:escort] = /Go to the (.*?) and WAIT for (?:him|her|them) to meet you there. You must guarantee (?:his|her|their) safety to (?<destiniation>[a-zA-Z '-]+) as soon as/
7
- @@re[:gem] = /has received orders from multiple customers requesting (?:a|an|some) (?<gem>[a-zA-Z '-]+). You have been tasked to retrieve (?<number>[0-9]+)/
8
- @@re[:heirloom] = /You have been tasked to recover ([a-zA-Z '-]+) that an unfortunate citizen lost after being attacked by (a|an|some) (?<creature>[a-zA-Z '-]+) (in|on|around|near|by) (?<area>[a-zA-Z '-]+)./
9
- @@re[:heirloom_found] = /^You have located the heirloom and should bring it back to/
10
- @@re[:succeeded] = /^You have succeeded in your task and can return to the Adventurer's/
11
- @@re[:report_to_guard] = /^You succeeded in your task and should report back to/
12
- @@re[:cull] = /^You have been tasked to suppress (?<creature>^((?!bandit).)*$) activity (?:in|on) (?:the )? (?<area>.*?)(?: near| between| under|\.) ([a-zA-Z' ]+). You need to kill (?<number>[0-9]+)/
13
- @@re[:bandits] = /^You have been tasked to suppress bandit activity (?:in |on )(?:the )(?<area>.*?)(?: near| between| under) ([a-zA-Z' ]+). You need to kill (?<number>[0-9]+)/
14
- @@re[:dangerous] = /You have been tasked to hunt down and kill a particularly dangerous (?<creature>.*) that has established a territory (?:in|on) (?:the )?(?<area>.*?)(?: near| between| under|\.)/
15
- @@re[:get_skin_bounty] = /The local furrier/
16
- @@re[:get_rescue] = /It appears that a local resident urgently needs our help in some matter/
17
- @@re[:get_bandits] = /It appears they have a bandit problem they'd like you to solve./
18
- @@re[:get_heirloom] = /It appears they need your help in tracking down some kind of lost heirloom/
19
- @@re[:get_herb_bounty] = /local herbalist|local healer|local alchemist/
20
- @@re[:get_gem_bounty] = /The local gem dealer, (?<npc>[a-zA-Z ]+), has an order to fill and wants our help/
21
- @@re[:creature_problem] = /It appears they have a creature problem they\'d like you to solve/
22
- @@re[:rescue] = /A local divinist has had visions of the child fleeing from (?:a|an) (?<creature>.*) (?:in|on) (?:the )?(?<area>.*?)(?: near| between| under|\.)/
23
- @@re[:failed] = /You have failed in your task/
24
- @@re[:none] = /You are not currently assigned a task/
25
-
26
- # convenience list to get all types of bounties
27
- def Bounty.types
28
- @@re.keys
29
- end
30
- ##
31
- ## @brief provides an accessor to the raw regular expression dictionary for Bounty logic
32
- ##
33
- ## @return Bounty Regex
34
- ##
35
- def Bounty.regex
36
- @@re
37
- end
1
+ require "ostruct"
2
+
3
+ class Bounty
4
+ NPCS = /guard|sergeant|clerk|taskmaster|gemcutter|jeweler|akrash|kris|Ghaerdish|Furryback|healer|dealer|Ragnoz|Maraene|Kelph|Areacne|Jhiseth|Gaedrein/i
5
+ HERBALIST_AREAS = /illistim|vaalor|legendary rest|solhaven/i
6
+ @@listeners = {}
7
+ # this should be refactored to use CONST
8
+ REGEX = OpenStruct.new(
9
+ creature_problem: /It appears they have a creature problem they\'d like you to solve/,
10
+ report_to_guard: /^You succeeded in your task and should report back to/,
11
+ get_skin_bounty: /The local furrier/,
12
+ heirloom_found: /^You have located the heirloom and should bring it back to/,
13
+ cooldown: /^You are not currently assigned a task. You will be eligible for new task assignment in about (?<minutes>.*?) minute(s)./,
14
+
15
+ dangerous: /You have been tasked to hunt down and kill a particularly dangerous (?<creature>.*) that has established a territory (?:in|on) (?:the )?(?<area>.*?)(?: near| between| under|\.)/,
16
+ succeeded: /^You have succeeded in your task and can return to the Adventurer's/,
17
+ heirloom: /^You have been tasked to recover (a|an|some) (?<heirloom>.*?) that an unfortunate citizen lost after being attacked by (a|an|some) (?<creature>.*?) (?:in|on|around|near|by) (?<area>.*?)(| near (?<realm>.*?))\./,
18
+
19
+
20
+ get_rescue: /It appears that a local resident urgently needs our help in some matter/,
21
+ get_bandits: /It appears they have a bandit problem they'd like you to solve./,
22
+ get_heirloom: /It appears they need your help in tracking down some kind of lost heirloom/,
23
+ get_herb_bounty: /local herbalist|local healer|local alchemist/,
24
+ get_gem_bounty: /The local gem dealer, (?<npc>[a-zA-Z ]+), has an order to fill and wants our help/,
25
+
26
+ herb: /requires (?:a |an |)(?<herb>.*?) found (?:in|on|around|near) (?<area>.*?)(| (near|between) (?<realm>.*?)). These samples must be in pristine condition. You have been tasked to retrieve (?<number>[\d]+)/,
27
+ escort: /Go to the (.*?) and WAIT for (?:him|her|them) to meet you there. You must guarantee (?:his|her|their) safety to (?<destination>.*?) as soon as/,
28
+ gem: /has received orders from multiple customers requesting (?:a|an|some) (?<gem>[a-zA-Z '-]+). You have been tasked to retrieve (?<number>[0-9]+)/,
29
+
30
+ cull: /^You have been tasked to suppress (?<creature>(?!bandit).*) activity (?:in|on|around) (?<area>.*?)(| (near|between) (?<realm>.*?)). You need to kill (?<number>[0-9]+)/,
31
+ bandits: /^You have been tasked to suppress bandit activity (?:in|on|around) (?<area>.*?) (?:near|between|under) (?<realm>.*?). You need to kill (?<number>[0-9]+)/,
32
+
33
+ rescue: /A local divinist has had visions of the child fleeing from (?:a|an) (?<creature>.*) (?:in|on) (?:the )?(?<area>.*?)(?: near| between| under|\.)/,
34
+ failed: /You have failed in your task/,
35
+ none: /You are not currently assigned a task/,
36
+ skin: /^You have been tasked to retrieve (?<number>\d+) (?<skin>.*?) of at least (?<quality>.*?) quality for (?<buyer>.*?) in (?<realm>.*?)\.\s+You can SKIN them off the corpse of (a|an|some) (?<creature>.*?) or/,
37
+
38
+ help_bandits: /You have been tasked to help (?<partner>.*?) suppress bandit activity (in|on|around) (?<area>.*?)(| near (?<realm>.*?)). You need to kill (?<number>[0-9]+)/
39
+ )
40
+
41
+ # convenience list to get all types of bounties
42
+ def Bounty.types
43
+ REGEX.keys
44
+ end
45
+ ##
46
+ ## @brief provides an accessor to the raw regular expression dictionary for Bounty logic
47
+ ##
48
+ ## @return Bounty Regex
49
+ ##
50
+ def Bounty.regex
51
+ REGEX
52
+ end
38
53
 
39
- def Bounty.town
40
- Bounty.current[:town]
41
- end
54
+ def Bounty.singularize(thing)
55
+ thing
56
+ .gsub("teeth", "tooth")
57
+ end
42
58
 
43
- def Bounty.area
44
- Bounty.current[:area]
45
- end
59
+ def Bounty.parse(str)
60
+ type, patt = Bounty.match str
61
+ unless patt
62
+ raise Exception.new "could not match Bounty: #{str}\nplease notify Ondreian"
63
+ else
64
+ bounty = patt.match(str).to_struct
65
+ bounty[:type] = type
66
+ if bounty[:skin]
67
+ bounty[:skin] = Bounty.singularize(bounty[:skin])
68
+ end
46
69
 
47
- def Bounty.destination
48
- Bounty.current[:destiniation]
49
- end
70
+ if bounty[:creature]
71
+ bounty[:tags] = Creature.tags(bounty.creature)
72
+ end
50
73
 
51
- def Bounty.gem
52
- Bounty.current[:gem]
74
+ bounty
53
75
  end
76
+ end
54
77
 
55
- def Bounty.creature
56
- Bounty.current[:creature]
57
- end
78
+ def Bounty.fetch!
79
+ checkbounty.strip
80
+ end
58
81
 
59
- def Bounty.herb
60
- Bounty.current[:herb]
82
+ def Bounty.match(bounty)
83
+ Bounty.regex.each_pair.find do |type, exp|
84
+ exp.match bounty
61
85
  end
86
+ end
62
87
 
63
- def Bounty.n
64
- Bounty.current[:number].to_i
65
- end
88
+ def Bounty.method_missing(method)
89
+ str = method.to_s
66
90
 
67
- def Bounty.type
68
- Bounty.current[:type]
91
+ if str.chars.last == "?"
92
+ return Bounty.type == str.chars.take(str.length-1).join.to_sym
69
93
  end
70
94
 
71
- def Bounty.task
72
- Bounty.current
95
+ unless current[method].nil?
96
+ current[method]
97
+ else
98
+ raise Exception.new "Bounty<#{Bounty.current.to_h}> does not respond to :#{method}"
73
99
  end
100
+ end
74
101
 
75
- def Bounty.current
76
- info = nil
77
- bounty_str = checkbounty.strip
78
- Bounty.regex.each do |type, exp|
79
- if data = exp.match(bounty_str) then
80
- info = data.names.length ? Hash[ data.names.map(&:to_sym).zip( data.captures ) ] : {}
81
- info[:type] = type
82
- end
83
- end
84
- return info || {}
85
- end
102
+ def Bounty.type
103
+ match(Bounty.fetch!).first
104
+ end
86
105
 
87
- def Bounty.ask_for_bounty
88
- fput "ask ##{Bounty.npc.id} for bounty"
89
- Bounty
90
- end
106
+ def Bounty.task
107
+ Bounty.current
108
+ end
91
109
 
92
- def Bounty.remove
93
- Go2.advguild
94
- 2.times do fput "ask ##{Bounty.npc.id} for remove" end
95
- Bounty
110
+ def Bounty.done?
111
+ succeeded?
112
+ end
113
+
114
+ def Bounty.current
115
+ Bounty.parse(checkbounty)
116
+ end
117
+
118
+ def Bounty.ask_for_bounty
119
+ if invisible?
120
+ fput "unhide"
96
121
  end
97
122
 
98
- def Bounty.to_s
99
- @@listeners.to_s
123
+ if hidden?
124
+ fput "unhide"
100
125
  end
101
126
 
102
- def Bounty.on(namespace, &block)
103
- @@listeners[namespace] = block
127
+ if Bounty.npc
128
+ fput "ask ##{Bounty.npc.id} for bounty"
104
129
  Bounty
130
+ else
131
+ raise Exception.new "could not find Bounty.npc here"
105
132
  end
133
+ # give the XML parser time to update
134
+ sleep 0.2
135
+ end
106
136
 
107
- def Bounty.listeners
108
- @@listeners
137
+ def Bounty.herbalist
138
+ if Room.current.location =~ HERBALIST_AREAS
139
+ Go2.herbalist
140
+ else
141
+ Go2.npchealer
109
142
  end
143
+ self
144
+ end
110
145
 
111
- def Bounty.cooldown?
112
- Spell[9003].active?
113
- end
146
+ def Bounty.remove
147
+ Go2.advguild
148
+ 2.times do fput "ask ##{Bounty.npc.id} for remove" end
149
+ Bounty
150
+ end
114
151
 
115
- def Bounty.cooldown!
116
- if Bounty.cooldown?
117
- Go2.origin
118
- wait_until { !Bounty.cooldown? }
119
- end
120
- Bounty
121
- end
152
+ def Bounty.on(namespace, &block)
153
+ @@listeners[namespace] = block
154
+ Bounty
155
+ end
156
+
157
+ def Bounty.listeners
158
+ @@listeners
159
+ end
122
160
 
123
- def Bounty.throw_missing_listener
124
- msg = "\n"
125
- msg.concat "\nBounty.dispatch called for `:#{Bounty.type}` without a defined listener\n\n"
126
- msg.concat "define a listener with:\n"
127
- msg.concat " \n"
128
- msg.concat " Bounty.on(:#{Bounty.type}) {\n"
129
- msg.concat " # do something\n"
130
- msg.concat " }\n"
131
- msg.concat " \n"
132
- msg.concat "or rescue this error (Olib::Errors::Fatal) gracefully\n"
133
- msg.concat " \n"
134
- raise Errors::Fatal.new msg
161
+ def Bounty.cooldown?
162
+ Spell[9003].active?
163
+ end
164
+
165
+ def Bounty.cooldown!
166
+ if Bounty.cooldown?
167
+ Go2.origin
168
+ wait_until { !Bounty.cooldown? }
135
169
  end
170
+ Bounty
171
+ end
136
172
 
137
- def Bounty.dispatch(listener=nil)
138
- if listener
139
- if @@listeners[listener]
140
- @@listeners[listener].call
141
- return Bounty
142
- else
143
- Bounty.throw_missing_listener
144
- end
145
- end
173
+ def Bounty.throw_missing_listener
174
+ msg = "\n"
175
+ msg.concat "\nBounty.dispatch called for `:#{Bounty.type}` without a defined listener\n\n"
176
+ msg.concat "define a listener with:\n"
177
+ msg.concat " \n"
178
+ msg.concat " Bounty.on(:#{Bounty.type}) {\n"
179
+ msg.concat " # do something\n"
180
+ msg.concat " }\n"
181
+ msg.concat " \n"
182
+ msg.concat "or rescue this error (Olib::Errors::Fatal) gracefully\n"
183
+ msg.concat " \n"
184
+ raise Olib::Errors::Fatal.new msg
185
+ end
146
186
 
147
- if @@listeners[Bounty.type]
148
- @@listeners[Bounty.type].call
187
+ def Bounty.dispatch(listener=nil)
188
+ if listener
189
+ if @@listeners[listener]
190
+ @@listeners[listener].call
149
191
  return Bounty
150
- else
192
+ else
151
193
  Bounty.throw_missing_listener
152
194
  end
153
195
  end
154
196
 
155
- def Bounty.find_guard
156
- Go2.advguard
157
- if Bounty.npc.nil? then Go2.advguard2 end
158
- if Bounty.npc.nil? then
159
- throw Olib::Errors::Fatal.new "could not find guard"
160
- end
197
+ if @@listeners[Bounty.type]
198
+ @@listeners[Bounty.type].call
161
199
  return Bounty
200
+ else
201
+ Bounty.throw_missing_listener
162
202
  end
203
+ end
163
204
 
164
- def Bounty.npc
165
- GameObj.npcs.select { |npc| npc.name =~ /guard|taskmaster|gemcutter|jeweler|akrash|kris|healer|dealer/i }.first
205
+ def Bounty.find_guard
206
+ Go2.advguard
207
+ if Bounty.npc.nil? then Go2.advguard2 end
208
+ if Bounty.npc.nil? then
209
+ throw Olib::Errors::Fatal.new "could not find guard"
166
210
  end
167
-
211
+ return Bounty
168
212
  end
169
- end
170
213
 
171
- class Bounty < Olib::Bounty
214
+ def Bounty.npc
215
+ GameObj.npcs.select { |npc| npc.name =~ NPCS }.first
216
+ end
172
217
  end