pwood-wowr 0.5.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.
- data/README +41 -0
- data/VERSION.yml +4 -0
- data/lib/wowr.rb +1253 -0
- data/lib/wowr/achievements.rb +143 -0
- data/lib/wowr/arena_team.rb +80 -0
- data/lib/wowr/calendar.rb +78 -0
- data/lib/wowr/character.rb +832 -0
- data/lib/wowr/dungeon.rb +85 -0
- data/lib/wowr/exceptions.rb +163 -0
- data/lib/wowr/extensions.rb +67 -0
- data/lib/wowr/general.rb +39 -0
- data/lib/wowr/guild.rb +85 -0
- data/lib/wowr/guild_bank.rb +188 -0
- data/lib/wowr/item.rb +577 -0
- data/test/wowr_arena_team_test.rb +41 -0
- data/test/wowr_character_test.rb +88 -0
- data/test/wowr_dungeon_test.rb +63 -0
- data/test/wowr_guild_test.rb +27 -0
- data/test/wowr_item_test.rb +8 -0
- data/test/wowr_test.rb +456 -0
- data/test/xml/arena_team_search.xml +60 -0
- data/test/xml/arena_team_single.xml +25 -0
- data/test/xml/armory-search.xml +207 -0
- data/test/xml/armory_search.xml +126 -0
- data/test/xml/benedictt.xml +152 -0
- data/test/xml/character-reputation.xml +82 -0
- data/test/xml/character-sheet.xml +145 -0
- data/test/xml/character-skills.xml +60 -0
- data/test/xml/character-talents.xml +29 -0
- data/test/xml/character_info.xml +141 -0
- data/test/xml/character_search.xml +102 -0
- data/test/xml/dungeonStrings.xml +550 -0
- data/test/xml/dungeons.xml +1658 -0
- data/test/xml/example.xml +127 -0
- data/test/xml/guild-info.xml +302 -0
- data/test/xml/item-info.xml +20 -0
- data/test/xml/item-tooltip.xml +167 -0
- data/test/xml/itemSearch.xml +46 -0
- data/test/xml/item_search.xml +63 -0
- metadata +96 -0
data/lib/wowr/item.rb
ADDED
@@ -0,0 +1,577 @@
|
|
1
|
+
# TODO: Item sources - Vendors
|
2
|
+
# sourceType.vendor
|
3
|
+
# sourceType.questReward
|
4
|
+
# sourceType.createdBySpell
|
5
|
+
|
6
|
+
$:.unshift(File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
7
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
8
|
+
|
9
|
+
require 'general.rb'
|
10
|
+
|
11
|
+
module Wowr
|
12
|
+
module Classes
|
13
|
+
|
14
|
+
# Most basic
|
15
|
+
# Composed of an ItemInfo and
|
16
|
+
# Needs to be consolidated with ItemInfo and other stuff
|
17
|
+
# to be a parent class that they extend?
|
18
|
+
# TODO: At the moment needs a reference to the API in order to get the base URL for icons
|
19
|
+
# TODO: Make extend Icon class
|
20
|
+
class Item
|
21
|
+
attr_reader :id, :name, :icon_base
|
22
|
+
alias_method :item_id, :id
|
23
|
+
alias_method :to_s, :name
|
24
|
+
alias_method :to_i, :id
|
25
|
+
|
26
|
+
@@icon_url_base = 'images/icons/'
|
27
|
+
@@icon_url_base_tw = 'wow-icons/_images/'
|
28
|
+
@@icon_sizes = {:large => ['64x64', 'jpg'], :medium => ['43x43', 'png'], :small => ['21x21', 'png']}
|
29
|
+
|
30
|
+
def initialize(elem, api = nil)
|
31
|
+
@api = api
|
32
|
+
|
33
|
+
@id = elem[:id].to_i
|
34
|
+
@name = elem[:name]
|
35
|
+
@icon_base = elem[:icon]
|
36
|
+
end
|
37
|
+
|
38
|
+
def icon(size = :medium)
|
39
|
+
if !@@icon_sizes.include?(size)
|
40
|
+
raise Wowr::Exceptions::InvalidIconSize.new(@@icon_sizes)
|
41
|
+
end
|
42
|
+
|
43
|
+
if @api
|
44
|
+
base = @api.base_url
|
45
|
+
else
|
46
|
+
base = 'http://www.wowarmory.com/'
|
47
|
+
end
|
48
|
+
|
49
|
+
if @api && @api.locale == "tw"
|
50
|
+
url_base = @@icon_url_base_tw
|
51
|
+
else
|
52
|
+
url_base = @@icon_url_base
|
53
|
+
end
|
54
|
+
|
55
|
+
# http://www.wowarmory.com/images/icons/64x64/blahblah.jpg
|
56
|
+
return base + url_base + @@icon_sizes[size][0] + '/' + @icon_base + '.' + @@icon_sizes[size][1]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# Full data from item-info and item-tooltip
|
61
|
+
class FullItem < Item
|
62
|
+
|
63
|
+
def initialize(info, tooltip, api = nil)
|
64
|
+
super(info, api)
|
65
|
+
@info = ItemInfo.new(info, api)
|
66
|
+
@tooltip = ItemTooltip.new(tooltip, api)
|
67
|
+
end
|
68
|
+
|
69
|
+
def method_missing(m, *args)
|
70
|
+
begin
|
71
|
+
return @info.send(m, *args)
|
72
|
+
rescue NoMethodError => e
|
73
|
+
begin
|
74
|
+
return @tooltip.send(m, *args)
|
75
|
+
rescue
|
76
|
+
raise NoMethodError.new("undefined method '#{m}' for #{self.class}")
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
|
84
|
+
|
85
|
+
# uses item-info.xml
|
86
|
+
class ItemInfo < Item
|
87
|
+
attr_reader :level, :quality, :type,
|
88
|
+
:cost, :disenchant_items, :disenchant_skill_rank, :vendors,
|
89
|
+
:objective_of_quests,
|
90
|
+
:reward_from_quests,
|
91
|
+
:drop_creatures,
|
92
|
+
:plans_for, :created_by
|
93
|
+
|
94
|
+
alias_method :disenchants, :disenchant_items
|
95
|
+
|
96
|
+
def initialize(elem, api = nil)
|
97
|
+
super(elem, api)
|
98
|
+
|
99
|
+
@level = elem[:level].to_i
|
100
|
+
@quality = elem[:quality].to_i
|
101
|
+
@type = elem[:type]
|
102
|
+
|
103
|
+
# Cost can be in gold, or tokens
|
104
|
+
@cost = ItemCost.new(elem%'cost') if (elem%'cost')
|
105
|
+
|
106
|
+
|
107
|
+
# is costs really an array?
|
108
|
+
#@costs = []
|
109
|
+
#(elem/:cost).each do |cost|
|
110
|
+
# @costs << ItemCost.new(cost)
|
111
|
+
#end
|
112
|
+
|
113
|
+
etc = [
|
114
|
+
# xml element name, member variable item list class name, requires api link
|
115
|
+
['disenchantLoot', '@disenchant_items', 'item', DisenchantItem, true],
|
116
|
+
['objectiveOfQuests', '@objective_of_quests', 'quest', ItemQuest, false],
|
117
|
+
['rewardFromQuests', '@reward_from_quests', 'quest', ItemQuest, false],
|
118
|
+
['vendors', '@vendors', 'creature', ItemVendor, false],
|
119
|
+
['dropCreatures', '@drop_creatures', 'creature', ItemDropCreature, false],
|
120
|
+
['plansFor', '@plans_for', 'spell', ItemPlansFor, true],
|
121
|
+
['createdBy', '@created_by', 'spell', ItemCreatedBy, true],
|
122
|
+
]
|
123
|
+
|
124
|
+
etc.each do |b|
|
125
|
+
ele = b[0]
|
126
|
+
var = b[1]
|
127
|
+
list = b[2]
|
128
|
+
my_class = b[3]
|
129
|
+
requires_api = b[4]
|
130
|
+
|
131
|
+
if elem%ele
|
132
|
+
tmp_arr = []
|
133
|
+
(elem%ele/list).each do |x|
|
134
|
+
if requires_api
|
135
|
+
tmp_arr << my_class.new(x, api)
|
136
|
+
else
|
137
|
+
tmp_arr << my_class.new(x)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
self.instance_variable_set(var, tmp_arr)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
# Rest of disenchant contents is done in the method above
|
145
|
+
if (elem%'disenchantLoot')
|
146
|
+
@disenchant_skill_rank = (elem%'disenchantLoot')[:requiredSkillRank].to_i
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
|
152
|
+
|
153
|
+
# Provides detailed item information
|
154
|
+
# Note that the item-tooltip.xml just returns an empty document when the item
|
155
|
+
# can't be found.
|
156
|
+
class ItemTooltip < Item
|
157
|
+
attr_reader :desc, :overall_quality_id, :bonding, :max_count, #:id, :name, :icon,
|
158
|
+
:class_id, :bonuses, :item_source,
|
159
|
+
:resistances, :required_level,
|
160
|
+
:allowable_classes, :armor, :durability,
|
161
|
+
:sockets, :socket_match_enchant,
|
162
|
+
:gem_properties, :equip_data
|
163
|
+
alias_method :description, :desc
|
164
|
+
|
165
|
+
def initialize(elem, api = nil)
|
166
|
+
super(elem, api)
|
167
|
+
@id = (elem%'id').html.to_i
|
168
|
+
@name = (elem%'name').html
|
169
|
+
@icon_base = (elem%'icon').html
|
170
|
+
@desc = (elem%'desc').html if (elem%'desc')
|
171
|
+
@overall_quality_id = (elem%'overallQualityId').html.to_i
|
172
|
+
@bonding = (elem%'bonding').html.to_i
|
173
|
+
@stackable = (elem%'stackable').html.to_i if (elem%'stackable')
|
174
|
+
@max_count = (elem%'maxCount').html.to_i if (elem%'maxCount')
|
175
|
+
@class_id = (elem%'classId').html.to_i
|
176
|
+
@required_level = (elem%'requiredLevel').html.to_i if (elem%'requiredLevel')
|
177
|
+
|
178
|
+
@equip_data = ItemEquipData.new(elem%'equipData')
|
179
|
+
|
180
|
+
# TODO: This appears to be a plain string at the moment
|
181
|
+
#<gemProperties>+26 Healing +9 Spell Damage and 2% Reduced Threat</gemProperties>
|
182
|
+
@gem_properties = (elem%'gemProperties').html if (elem%'gemProperties')
|
183
|
+
|
184
|
+
# not all items have damage data
|
185
|
+
@damage = ItemDamageData.new(elem%'damageData') unless !(elem%'damageData') || (elem%'damageData').empty?
|
186
|
+
|
187
|
+
|
188
|
+
# TODO: Test socket data with a variety of items
|
189
|
+
# TODO: replace with socket Class?
|
190
|
+
if (elem%'socketData')
|
191
|
+
@sockets = []
|
192
|
+
(elem%'socketData'/:socket).each do |socket|
|
193
|
+
@sockets << socket[:color]
|
194
|
+
end
|
195
|
+
|
196
|
+
@socket_match_enchant = (elem%'socketData'%'socketMatchEnchant')
|
197
|
+
end
|
198
|
+
|
199
|
+
|
200
|
+
# When there is no data, stats are not present in @bonuses
|
201
|
+
# TODO: When there is no stats at all, @bonuses shouldn't be set
|
202
|
+
@bonuses = {}
|
203
|
+
|
204
|
+
bonus_stats = {
|
205
|
+
:strength => :bonusStrength,
|
206
|
+
:agility => :bonusAgility,
|
207
|
+
:stamina => :bonusStamina,
|
208
|
+
:intellect => :bonusIntellect,
|
209
|
+
:spirit => :bonusSpirit
|
210
|
+
}
|
211
|
+
bonus_stats.each do |stat, xml_elem|
|
212
|
+
@bonuses[stat] = test_stat(elem/xml_elem) if test_stat(elem/xml_elem)
|
213
|
+
end
|
214
|
+
|
215
|
+
# Resistances
|
216
|
+
@resistances = {}
|
217
|
+
|
218
|
+
resist_stats = {
|
219
|
+
:arcane => :arcaneResist,
|
220
|
+
:fire => :fireResist,
|
221
|
+
:frost => :frostResist,
|
222
|
+
:holy => :holyResist,
|
223
|
+
:nature => :natureResist,
|
224
|
+
:shadow => :shadowResist
|
225
|
+
}
|
226
|
+
resist_stats.each do |stat, xml_elem|
|
227
|
+
@resistances[stat] = test_stat(elem/xml_elem) if test_stat(elem/xml_elem)
|
228
|
+
end
|
229
|
+
|
230
|
+
|
231
|
+
if (elem%'allowableClasses')
|
232
|
+
@allowable_classes = []
|
233
|
+
(elem%'allowableClasses'/:class).each do |klass|
|
234
|
+
@allowable_classes << klass.html
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
# NOTE not representing armor bonus
|
239
|
+
@armor = (elem%'armor').html.to_i if (elem%'armor')
|
240
|
+
|
241
|
+
# NOTE not representing max
|
242
|
+
@durability = (elem%'durability')[:current].to_i if (elem%'durability')
|
243
|
+
|
244
|
+
if (elem%'spellData')
|
245
|
+
@spells = []
|
246
|
+
(elem%'spellData'/:spell).each do |spell|
|
247
|
+
@spells << ItemSpell.new(spell)
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
@setData = ItemSetData.new(elem%'setData') if (elem%'setData')
|
252
|
+
|
253
|
+
# @item_sources = []
|
254
|
+
# (elem/:itemSource).each do |source|
|
255
|
+
# @item_sources << ItemSource.new(source)
|
256
|
+
# end
|
257
|
+
@item_source = ItemSource.new(elem%'itemSource') if (elem%'itemSource') # TODO: More than once source?
|
258
|
+
end
|
259
|
+
|
260
|
+
private
|
261
|
+
def test_stat(elem)
|
262
|
+
if elem
|
263
|
+
if !elem.html.empty?
|
264
|
+
return elem.html.to_i
|
265
|
+
end
|
266
|
+
end
|
267
|
+
return nil
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
class ItemEquipData
|
272
|
+
attr_reader :inventory_type, :subclass_name, :container_slots
|
273
|
+
|
274
|
+
def initialize(elem)
|
275
|
+
@inventory_type = (elem%'inventoryType').html.to_i
|
276
|
+
@subclass_name = (elem%'subclassName').html if (elem%'subclassName')
|
277
|
+
@container_slots = (elem%'containerSlots').html.to_i if (elem%'containerSlots') # for baggies
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
class ItemSetData
|
282
|
+
attr_reader :name, :items, :set_bonuses
|
283
|
+
alias_method :to_s, :name
|
284
|
+
|
285
|
+
def initialize(elem)
|
286
|
+
@name = elem[:name]
|
287
|
+
|
288
|
+
@items = []
|
289
|
+
(elem/:item).each do |item|
|
290
|
+
@items << item[:name]
|
291
|
+
end
|
292
|
+
|
293
|
+
@set_bonuses = []
|
294
|
+
(elem/:setBonus).each do |bonus|
|
295
|
+
@set_bonuses << ItemSetBonus.new(bonus)
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
class ItemSetBonus
|
301
|
+
attr_reader :threshold, :description
|
302
|
+
alias_method :desc, :description
|
303
|
+
alias_method :to_s, :description
|
304
|
+
|
305
|
+
def initialize(elem)
|
306
|
+
@threshold = elem[:threshold].to_i
|
307
|
+
@description = elem[:desc]
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
class ItemSpell
|
312
|
+
attr_reader :trigger, :description
|
313
|
+
alias_method :desc, :description
|
314
|
+
alias_method :to_s, :description
|
315
|
+
|
316
|
+
def initialize(elem)
|
317
|
+
@trigger = (elem%'trigger').html.to_i
|
318
|
+
@description = (elem%'desc').html
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
class ItemDamageData
|
323
|
+
attr_reader :type, :min, :max, :speed, :dps
|
324
|
+
|
325
|
+
def initialize(elem)
|
326
|
+
@type = (elem%'damage'%'type').html.to_i
|
327
|
+
@min = (elem%'damage'%'min').html.to_i
|
328
|
+
@max = (elem%'damage'%'max').html.to_i
|
329
|
+
@speed = (elem%'speed').html.to_i if (elem%'speed')
|
330
|
+
@dps = (elem%'dps').html.to_f if (elem%'dps')
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
class ItemSource
|
335
|
+
attr_reader :value,
|
336
|
+
:area_id, :area_name,
|
337
|
+
:creature_id, :creature_name,
|
338
|
+
:difficulty, :drop_rate
|
339
|
+
|
340
|
+
def initialize(elem)
|
341
|
+
@value = elem[:value]
|
342
|
+
@area_id = elem[:areaId].to_i if elem[:areaId]
|
343
|
+
@area_name = elem[:areaName] if elem[:areaName]
|
344
|
+
@creature_id = elem[:creatureId].to_i if elem[:creatureId]
|
345
|
+
@creature_name = elem[:creatureName] if elem[:creatureName]
|
346
|
+
@difficulty = elem[:difficulty] if elem[:difficulty]
|
347
|
+
@drop_rate = elem[:dropRate].to_i if elem[:dropRate]
|
348
|
+
@required_level = elem[:reqLvl].to_i if elem[:reqLvl]
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
352
|
+
|
353
|
+
|
354
|
+
# A really basic item type returned by searches
|
355
|
+
class SearchItem < Item
|
356
|
+
attr_reader :url, :rarity,
|
357
|
+
:source, :item_level, :relevance
|
358
|
+
alias_method :level, :item_level
|
359
|
+
|
360
|
+
def initialize(elem, api = nil)
|
361
|
+
super(elem, api)
|
362
|
+
@rarity = elem[:rarity].to_i
|
363
|
+
@url = elem[:url]
|
364
|
+
|
365
|
+
@item_level = elem.at("filter[@name='itemLevel']")[:value].to_i
|
366
|
+
@source = elem.at("filter[@name='source']")[:value]
|
367
|
+
@relevance = elem.at("filter[@name='relevance']")[:value].to_i
|
368
|
+
end
|
369
|
+
end
|
370
|
+
|
371
|
+
|
372
|
+
|
373
|
+
|
374
|
+
# <rewardFromQuests>
|
375
|
+
# <quest name="Justice Dispensed" level="39" reqMinLevel="30" id="11206" area="Dustwallow Marsh" suggestedPartySize="0"></quest>
|
376
|
+
# <quest name="Peace at Last" level="39" reqMinLevel="30" id="11152" area="Dustwallow Marsh" suggestedPartySize="0"></quest>
|
377
|
+
# </rewardFromQuests>
|
378
|
+
# TODO: Rename
|
379
|
+
class ItemQuest
|
380
|
+
attr_reader :name, :id, :level, :min_level, :area, :suggested_party_size
|
381
|
+
|
382
|
+
def initialize(elem)
|
383
|
+
@name = elem[:name]
|
384
|
+
@id = elem[:id].to_i
|
385
|
+
@level = elem[:level].to_i
|
386
|
+
@min_level = elem[:min_level].to_i
|
387
|
+
@area = elem[:area]
|
388
|
+
@suggested_party_size = elem[:suggested_party_size].to_i
|
389
|
+
end
|
390
|
+
end
|
391
|
+
|
392
|
+
|
393
|
+
|
394
|
+
# Creatures that drop the item
|
395
|
+
# <creature name="Giant Marsh Frog" minLevel="1" type="Critter" maxLevel="1" dropRate="6" id="23979" classification="0" area="Dustwallow Marsh"></creature>
|
396
|
+
# <creature name="Nalorakk" minLevel="73" title="Bear Avatar" url="fl[source]=dungeon&fl[difficulty]=normal&fl[boss]=23576" type="Humanoid" maxLevel="73" dropRate="2" id="23576" classification="3" areaUrl="fl[source]=dungeon&fl[boss]=all&fl[difficulty]=normal&fl[dungeon]=3805" area="Zul'Aman"></creature>
|
397
|
+
class ItemDropCreature
|
398
|
+
attr_reader :name, :id, :type, :min_level, :max_level, :drop_rate, :classification, :area
|
399
|
+
|
400
|
+
def initialize(elem)
|
401
|
+
@name = elem[:name]
|
402
|
+
@id = elem[:id].to_i
|
403
|
+
@min_level = elem[:minLevel].to_i
|
404
|
+
@max_level = elem[:maxLevel].to_i
|
405
|
+
@drop_rate = elem[:dropRate].to_i
|
406
|
+
@classification = elem[:classification].to_i
|
407
|
+
@area = elem[:area]
|
408
|
+
|
409
|
+
# optional boss stuff
|
410
|
+
@title = elem[:title] if elem[:title] # TODO: not nil when no property?
|
411
|
+
@url = elem[:url] if elem[:url]
|
412
|
+
@type = elem[:type] if elem[:type] # Humanoid etc.
|
413
|
+
@area_url = elem[:areaUrl] if elem[:areaUrl]
|
414
|
+
end
|
415
|
+
end
|
416
|
+
|
417
|
+
# Cost can be gold or a set of required tokens
|
418
|
+
# See ItemCostToken
|
419
|
+
# <cost sellPrice="280" buyPrice="5600"></cost>
|
420
|
+
# <cost>
|
421
|
+
# <token icon="spell_holy_championsbond" id="29434" count="60"></token>
|
422
|
+
# </cost>
|
423
|
+
class ItemCost
|
424
|
+
attr_reader :buy_price, :sell_price, :tokens
|
425
|
+
|
426
|
+
def initialize(elem)
|
427
|
+
@buy_price = Money.new(elem[:buyPrice].to_i) if elem[:buyPrice]
|
428
|
+
@sell_price = Money.new(elem[:sellPrice].to_i) if elem[:sellPrice]
|
429
|
+
|
430
|
+
if (elem%'token')
|
431
|
+
@tokens = []
|
432
|
+
(elem/:token).each do |token|
|
433
|
+
@tokens << ItemCostToken.new(token)
|
434
|
+
end
|
435
|
+
end
|
436
|
+
end
|
437
|
+
end
|
438
|
+
|
439
|
+
# <token icon="spell_holy_championsbond" id="29434" count="60"></token>
|
440
|
+
class ItemCostToken < Item
|
441
|
+
attr_reader :count
|
442
|
+
|
443
|
+
def initialize(elem, api = nil)
|
444
|
+
super(elem)
|
445
|
+
# @id = elem[:id].to_i
|
446
|
+
# @icon_bse = elem[:icon]
|
447
|
+
@count = elem[:count].to_i
|
448
|
+
end
|
449
|
+
end
|
450
|
+
|
451
|
+
# <item name="Void Crystal" minCount="1" maxCount="2" icon="inv_enchant_voidcrystal" type="Enchanting" level="70" dropRate="6" id="22450" quality="4"></item>
|
452
|
+
class DisenchantItem < Item
|
453
|
+
attr_reader :level, :type, :drop_rate, :min_count, :max_count, :quality
|
454
|
+
# :name, :id, :icon,
|
455
|
+
|
456
|
+
def initialize(elem, api = nil)
|
457
|
+
super(elem, api)
|
458
|
+
# @name = elem[:name]
|
459
|
+
# @id = elem[:id].to_i
|
460
|
+
# @icon = elem[:icon]
|
461
|
+
@level = elem[:level].to_i
|
462
|
+
@type = elem[:type]
|
463
|
+
@drop_rate = elem[:dropRate].to_i
|
464
|
+
@min_count = elem[:minCount].to_i
|
465
|
+
@max_count = elem[:maxCount].to_i
|
466
|
+
@quality = elem[:quality].to_i
|
467
|
+
end
|
468
|
+
end
|
469
|
+
|
470
|
+
|
471
|
+
class ItemVendor
|
472
|
+
attr_reader :id, :name, :title, :type,
|
473
|
+
:area, :classification, :max_level, :min_level
|
474
|
+
alias_method :to_s, :name
|
475
|
+
alias_method :to_i, :id
|
476
|
+
|
477
|
+
def initialize(elem)
|
478
|
+
@id = elem[:id].to_i
|
479
|
+
@name = elem[:name]
|
480
|
+
@title = elem[:title]
|
481
|
+
@type = elem[:type]
|
482
|
+
@area = elem[:area]
|
483
|
+
@classification = elem[:classification].to_i
|
484
|
+
@max_level = elem[:maxLevel].to_i
|
485
|
+
@min_level = elem[:minLevel].to_i
|
486
|
+
end
|
487
|
+
end
|
488
|
+
|
489
|
+
|
490
|
+
|
491
|
+
# TODO rename
|
492
|
+
# There is some sort of opposite relationship between PlansFor and CreatedBy
|
493
|
+
class ItemCreation < Item
|
494
|
+
attr_reader :item, :reagents
|
495
|
+
|
496
|
+
def initialize(elem, api = nil)
|
497
|
+
super(elem, api)
|
498
|
+
|
499
|
+
if (elem%'reagent')
|
500
|
+
@reagents = []
|
501
|
+
(elem/:reagent).each do |reagent|
|
502
|
+
@reagents << Reagent.new(reagent, api)
|
503
|
+
end
|
504
|
+
end
|
505
|
+
end
|
506
|
+
end
|
507
|
+
|
508
|
+
# (fold)
|
509
|
+
# <plansFor>
|
510
|
+
# <spell name="Shadowprowler's Chestguard" icon="trade_leatherworking" id="42731">
|
511
|
+
# <item name="Shadowprowler's Chestguard" icon="inv_chest_plate11" type="Leather" level="105" id="33204" quality="4"></item>
|
512
|
+
# <reagent name="Heavy Knothide Leather" icon="inv_misc_leatherscrap_11" id="23793" count="10"></reagent>
|
513
|
+
# </spell>
|
514
|
+
# </plansFor>
|
515
|
+
# (end)
|
516
|
+
class ItemPlansFor < ItemCreation
|
517
|
+
def initialize(elem, api = nil)
|
518
|
+
super(elem, api)
|
519
|
+
# TODO: Multiple items?
|
520
|
+
@item = CreatedItem.new(elem%'item') if (elem%'item')
|
521
|
+
end
|
522
|
+
end
|
523
|
+
|
524
|
+
# <createdBy>
|
525
|
+
# <spell name="Bracing Earthstorm Diamond" icon="temp" id="32867">
|
526
|
+
# <item requiredSkill="Jewelcrafting" name="Design: Bracing Earthstorm Diamond" icon="inv_scroll_03" type="Jewelcrafting" level="73" id="25903" requiredSkillRank="365" quality="1"></item>
|
527
|
+
# <reagent name="Earthstorm Diamond" icon="inv_misc_gem_diamond_04" id="25867" count="1"></reagent>
|
528
|
+
# </spell>
|
529
|
+
# </createdBy>
|
530
|
+
class ItemCreatedBy < ItemCreation
|
531
|
+
def initialize(elem, api = nil)
|
532
|
+
super(elem, api)
|
533
|
+
# TODO: Multiple items?
|
534
|
+
@item = PlanItem.new(elem%'item') if (elem%'item')
|
535
|
+
end
|
536
|
+
end
|
537
|
+
|
538
|
+
|
539
|
+
# <item name="Shadowprowler's Chestguard" icon="inv_chest_plate11" type="Leather" level="105" id="33204" quality="4"></item>
|
540
|
+
class CreatedItem < Item
|
541
|
+
attr_reader :type, :level, :quality
|
542
|
+
|
543
|
+
def initialize(elem, api = nil)
|
544
|
+
super(elem, api)
|
545
|
+
@type = elem[:type]
|
546
|
+
@level = elem[:level].to_i
|
547
|
+
@quality = elem[:quality].to_i
|
548
|
+
end
|
549
|
+
end
|
550
|
+
|
551
|
+
# <item requiredSkill="Jewelcrafting" name="Design: Bracing Earthstorm Diamond" icon="inv_scroll_03" type="Jewelcrafting" level="73" id="25903" requiredSkillRank="365" quality="1"></item>
|
552
|
+
class PlanItem < Item
|
553
|
+
attr_reader :required_skill, :type, :required_skill_rank, :level, :quality
|
554
|
+
|
555
|
+
def initialize(elem, api = nil)
|
556
|
+
super(elem, api)
|
557
|
+
@type = elem[:type]
|
558
|
+
@level = elem[:level].to_i
|
559
|
+
@quality = elem[:quality].to_i
|
560
|
+
@required_skill = elem[:requiredSkill]
|
561
|
+
@required_skill_rank = elem[:requiredSkillRank].to_i
|
562
|
+
end
|
563
|
+
end
|
564
|
+
|
565
|
+
class Reagent < Item
|
566
|
+
attr_reader :count
|
567
|
+
|
568
|
+
def initialize(elem, api = nil)
|
569
|
+
super(elem, api)
|
570
|
+
# @id = elem[:id].to_i
|
571
|
+
# @name = elem[:name]
|
572
|
+
# @icon = elem[:icon]
|
573
|
+
@count = elem[:count].to_i
|
574
|
+
end
|
575
|
+
end
|
576
|
+
end
|
577
|
+
end
|