wowr 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,80 @@
1
+ module Wowr
2
+ module Classes
3
+ class ArenaTeam
4
+ attr_reader :name, :size, :battle_group, :faction, :faction_id, :realm, :realm_url,
5
+ :games_played, :games_won, :ranking, :rating,
6
+ :season_games_played, :season_games_won, :last_season_ranking,
7
+ :relevance, :url, :url_escape,
8
+ :characters, # can be blank on search results
9
+ :emblem
10
+ alias_method :to_s, :name
11
+
12
+ def initialize(elem)
13
+ @name = elem[:name]
14
+ @size = elem[:size].to_i
15
+ @battle_group = elem[:battleGroup]
16
+ @faction = elem[:faction]
17
+ @faction_id = elem[:factionId].to_i
18
+ @realm = elem[:realm]
19
+ @realm_url = elem[:realmUrl]
20
+
21
+ @games_played = elem[:gamesPlayed].to_i
22
+ @games_won = elem[:gamesWon].to_i
23
+ # @ranking = elem[:ranking].to_i # Ranking in the seach results is always 0
24
+ @rating = elem[:rating].to_i
25
+
26
+ @season_games_played = elem[:seasonGamesPlayed].to_i
27
+ @season_games_won = elem[:seasonGamesWon].to_i
28
+ @last_season_ranking = elem[:lastSeasonRanking].to_i
29
+
30
+ @relevance = elem[:relevance].to_i
31
+ @url = elem[:url]
32
+
33
+ @emblem = ArenaTeamEmblem.new(elem%'emblem')
34
+ end
35
+ end
36
+
37
+
38
+ class SearchArenaTeam < ArenaTeam
39
+ def initialize(elem)
40
+ super(elem)
41
+ end
42
+ end
43
+
44
+ # <teamInfo>
45
+ # <arenaTeam battleGroup="Vindication" faction="Alliance" factionId="0" gamesPlayed="6" gamesWon="1" lastSeasonRanking="4118" name="Monkey" ranking="6522" rating="1535" realm="Burning Blade" realmUrl="b=Vindication&amp;r=Burning+Blade&amp;ts=2&amp;t=Monkey&amp;ff=realm&amp;fv=Burning+Blade&amp;select=Monkey" relevance="0" seasonGamesPlayed="66" seasonGamesWon="34" size="2" url="r=Burning+Blade&amp;ts=2&amp;t=Monkey&amp;select=Monkey" urlEscape="r=Burning+Blade&amp;ts=2&amp;t=Monkey&amp;select=Monkey">
46
+ # <emblem background="ff70de56" borderColor="ffcc73eb" borderStyle="6" iconColor="ffe3b320" iconStyle="44"/>
47
+ # <members>
48
+ # <character battleGroup="Vindication" charUrl="r=Burning+Blade&amp;n=Fandiar" class="Priest" classId="5" contribution="1380" gamesPlayed="0" gamesWon="0" gender="Male" genderId="0" guild="Legends" guildId="916" guildUrl="r=Burning+Blade&amp;n=Legends&amp;p=1" name="Fandiar" race="Night Elf" raceId="4" realm="Burning Blade" seasonGamesPlayed="18" seasonGamesWon="1" teamRank="0"/>
49
+ # <character battleGroup="Vindication" charUrl="r=Burning+Blade&amp;n=Stayfrosty" class="Mage" classId="8" contribution="1460" gamesPlayed="6" gamesWon="1" gender="Male" genderId="0" guild="Legends" guildId="916" guildUrl="r=Burning+Blade&amp;n=Legends&amp;p=1" name="Stayfrosty" race="Human" raceId="1" realm="Burning Blade" seasonGamesPlayed="6" seasonGamesWon="1" teamRank="1"/>
50
+ # <character battleGroup="Vindication" charUrl="r=Burning+Blade&amp;n=Step" class="Rogue" classId="4" contribution="1688" gamesPlayed="2" gamesWon="1" gender="Female" genderId="1" guild="Legends" guildId="916" guildUrl="r=Burning+Blade&amp;n=Legends&amp;p=1" name="Step" race="Human" raceId="1" realm="Burning Blade" seasonGamesPlayed="44" seasonGamesWon="33" teamRank="1"/>
51
+ # </members>
52
+ # </arenaTeam>
53
+ # </teamInfo>
54
+ class FullArenaTeam < ArenaTeam
55
+
56
+ def initialize(elem)
57
+ super(elem)
58
+ # @ranking = elem[:ranking].to_i
59
+
60
+ @members = {}
61
+ (elem%'members'/:character).each do |character|
62
+ @members[character[:name]] = SearchCharacter.new(character)
63
+ end
64
+ end
65
+ end
66
+
67
+ # An arena team's logo
68
+ class ArenaTeamEmblem
69
+ attr_reader :background, :border_color, :border_style, :icon_colour, :icon_style
70
+
71
+ def initialize(elem)
72
+ @background = elem[:background]
73
+ @border_color = elem[:borderColor]
74
+ @border_style = elem[:borderStyle].to_i
75
+ @icon_color = elem[:iconColor]
76
+ @icon_style = elem[:iconStyle].to_i
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,821 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+
4
+ require 'wowr/item.rb'
5
+
6
+ module Wowr
7
+ module Classes
8
+
9
+ # Short character info, used in guild lists etc.
10
+ # Note that the way that searches and character listings within guilds works,
11
+ # there can be a variable amount of information filled in within the class.
12
+ # Guild listings and search results contain a smaller amount of information than
13
+ # single queries
14
+ # Attributes
15
+ # * name (String) - Full character name
16
+ # * level (Fixnum) - Level
17
+ # See Also: Guild
18
+ class Character
19
+ attr_reader :name, :level, :url, :rank,
20
+ :klass, :klass_id,
21
+ :gender, :gender_id,
22
+ :race, :race_id,
23
+ :guild, :guild_id, :guild_url,
24
+ :realm,
25
+ :battle_group, :last_login,
26
+ :relevance, :search_rank,
27
+
28
+ :season_games_played, :season_games_won, :team_rank, :contribution # From ArenaTeam info
29
+
30
+ alias_method :to_s, :name
31
+ alias_method :to_i, :level
32
+
33
+ @@race_icon_url_base = 'images/icons/race/'
34
+ @@class_icon_url_base = 'images/icons/class/'
35
+ @@portrait_url_base = 'images/portraits/'
36
+ @@icon_types = {:default => 'wow-default', 70 => 'wow-70', :other => 'wow'}
37
+
38
+ def initialize(elem, api = nil)
39
+ @api = api
40
+
41
+ @name = elem[:name]
42
+ @level = elem[:level].to_i
43
+ @url = elem[:url] || elem[:charUrl]
44
+ @rank = elem[:rank].to_i
45
+
46
+ @klass = elem[:class]
47
+ @klass_id = elem[:classId].to_i
48
+
49
+ @gender = elem[:gender]
50
+ @gender_id = elem[:genderId].to_i
51
+
52
+ @race = elem[:race]
53
+ @race_id = elem[:raceId].to_i
54
+
55
+ @guild = elem[:guild] == "" ? nil : elem[:guild]
56
+ @guild_id = elem[:guildId].to_i == 0 ? nil : elem[:guildId].to_i
57
+ @guild_url = elem[:guildUrl] == "" ? nil : elem[:guildUrl]
58
+
59
+ @realm = elem[:realm] == "" ? nil : elem[:realm]
60
+
61
+ @battle_group = elem[:battleGroup] == "" ? nil : elem[:battleGroup]
62
+ @battle_group_id = elem[:battleGroupId].to_i
63
+
64
+ @relevance = elem[:relevance].to_i
65
+ @search_rank = elem[:searchRank].to_i
66
+
67
+ # Incoming string is 2007-02-24 20:33:04.0, parse to datetime
68
+ #@last_login = elem[:lastLoginDate] == "" ? nil : DateTime.parse(elem[:lastLoginDate])
69
+ @last_login = elem[:lastLoginDate] == "" ? nil : elem[:lastLoginDate]
70
+
71
+ # From ArenaTeam info, can be blank on normal requests
72
+ #<character battleGroup="" charUrl="r=Draenor&amp;n=Lothaar" class="Paladin" classId="2"
73
+ # contribution="1602" gamesPlayed="10" gamesWon="7" gender="Male" genderId="0"
74
+ # guild="Passion" guildId="36659" guildUrl="r=Draenor&amp;n=Passion&amp;p=1" name="Lothaar"
75
+ # race="Human" raceId="1" seasonGamesPlayed="20" seasonGamesWon="13" teamRank="1"/>
76
+ @season_games_played = elem[:seasonGamesPlayed] == "" ? nil : elem[:seasonGamesPlayed].to_i
77
+ @season_games_won = elem[:seasonGamesWon] == "" ? nil : elem[:seasonGamesWon].to_i
78
+ @team_rank = elem[:teamRank] == "" ? nil : elem[:teamRank].to_i
79
+ @contribution = elem[:contribution] == "" ? nil : elem[:contribution].to_i
80
+ #@char_url = elem[:charUrl] # TODO: Merge with URL?
81
+ end
82
+
83
+
84
+ def icon(type = nil)
85
+ if !type.nil? && !@@icon_types.include?(type)
86
+ raise Wowr::Exceptions::InvalidIconType.new(@@icon_types)
87
+ end
88
+
89
+ if (type.nil?) && (@level == 70)
90
+ dir = @@icon_types[70]
91
+ elsif (type.nil?)
92
+ dir = @@icon_types[:other]
93
+ else
94
+ dir = @@icon_types[type]
95
+ end
96
+
97
+ # http://armory.worldofwarcraft.com/images/portraits/wow-70/1-7-8.gif
98
+ return base + @@portrait_url_base + dir + "/#{@gender_id}-#{@race_id}-#{@klass_id}.gif"
99
+ end
100
+
101
+
102
+ def race_icon
103
+ # http://armory.worldofwarcraft.com/images/icons/race/11-1.gif
104
+ return base + @@race_icon_url_base + "#{@race_id}-#{@gender_id.to_s}.gif"
105
+ end
106
+
107
+
108
+ def class_icon
109
+ # http://armory.worldofwarcraft.com/images/icons/class/8.gif
110
+ return base + @@class_icon_url_base + "#{@klass_id.to_s}.gif"
111
+ end
112
+
113
+
114
+ protected
115
+ def base
116
+ if @api
117
+ return @api.base_url
118
+ else
119
+ return 'http://www.wowarmory.com/'
120
+ end
121
+ end
122
+ end
123
+
124
+ class SearchCharacter < Character
125
+ end
126
+
127
+
128
+ # Full character details
129
+ # uses characterInfo element
130
+ # Made up of two parts, character and charactertab
131
+ class FullCharacter < Character
132
+
133
+ # character_info
134
+ attr_reader :char_url, :title,
135
+ :faction, :faction_id,
136
+ :arena_teams,
137
+ :last_modified
138
+
139
+ # character_tab
140
+ attr_reader :health, :second_bar,
141
+ :strength, :agility, :stamina, :intellect, :spirit
142
+ alias_method :str, :strength
143
+ alias_method :agi, :agility
144
+ alias_method :sta, :stamina
145
+ alias_method :int, :intellect
146
+ alias_method :spi, :spirit
147
+
148
+ attr_reader :melee, :ranged, :spell,
149
+ :defenses, :resistances,
150
+ :talent_spec, :pvp,
151
+ :professions,
152
+ :items,
153
+ :buffs, :debuffs,
154
+ :skill_categories,
155
+ :reputation_categories
156
+
157
+ alias_method :skills, :skill_categories
158
+ alias_method :rep, :reputation_categories
159
+ alias_method :reputation, :reputation_categories
160
+
161
+ # It's made up of two parts
162
+ # Don't care about battlegroups yet
163
+ # I don't think I can call stuff from the constructor?
164
+ def initialize(sheet, skills, reputation, api = nil)
165
+ @api = api
166
+
167
+ character_info(sheet%'character')
168
+ character_tab(sheet%'characterTab')
169
+ character_skills(skills)
170
+ character_reputation(reputation)
171
+ end
172
+
173
+ # <character
174
+ # battleGroup="Conviction"
175
+ # charUrl="r=Genjuros&amp;n=Jonlok"
176
+ # class="Warlock"
177
+ # classId="9"
178
+ # faction="Horde"
179
+ # factionId="1"
180
+ # gender="Male"
181
+ # genderId="0"
182
+ # guildName=""
183
+ # lastModified="12 February 2008"
184
+ # level="41"
185
+ # name="Jonlok"
186
+ # prefix=""
187
+ # race="Orc"
188
+ # raceId="2"
189
+ # realm="Genjuros"
190
+ # suffix=""/>
191
+
192
+ def character_info(elem)
193
+ # basic info
194
+ @name = elem[:name]
195
+ @level = elem[:level].to_i
196
+ @char_url = elem[:charUrl]
197
+
198
+ @klass = elem[:class]
199
+ @klass_id = elem[:classId].to_i
200
+
201
+ @gender = elem[:gender]
202
+ @gender_id = elem[:genderId].to_i
203
+
204
+ @race = elem[:race]
205
+ @race_id = elem[:raceId].to_i
206
+
207
+ @faction = elem[:faction]
208
+ @faction_id = elem[:factionId].to_i
209
+
210
+ @guild = elem[:guildName] == "" ? nil : elem[:guildName]
211
+ @guild_url = elem[:guildUrl] == "" ? nil : elem[:guildUrl]
212
+
213
+ @prefix = elem[:prefix] == "" ? nil : elem[:prefix]
214
+ @suffix = elem[:suffix] == "" ? nil : elem[:suffix]
215
+
216
+ @realm = elem[:realm]
217
+
218
+ @battle_group = elem[:battleGroup]
219
+
220
+ # format is February 11, 2008
221
+ # except when it's korean, and then it's 2008년 5월 11일 (일)
222
+ # tw is 2008&#24180;5&#26376;11&#26085; (2008年5月11日)
223
+ # TODO: Datetime doesn't parse other languages nicely
224
+ # Until then, just save it as a string
225
+ begin
226
+ @last_modified = elem[:lastModified] == "" ? nil : DateTime.parse(elem[:lastModified])
227
+ rescue
228
+ @last_modified = elem[:lastModified] == "" ? nil : elem[:lastModified]
229
+ end
230
+ #@last_modified = elem[:lastModified]#.to_time
231
+
232
+ @arena_teams = []
233
+ (elem/:arenaTeam).each do |arena_team|
234
+ @arena_teams << ArenaTeam.new(arena_team)
235
+ end
236
+
237
+ end
238
+
239
+ def character_tab(elem)
240
+
241
+ # <title value=""/>
242
+ @title = (elem%'title')[:value] == "" ? nil : (elem%'title')[:value]
243
+ #@known_titles = <knownTitles/>
244
+
245
+ @health = (elem%'characterBars'%'health')[:effective].to_i
246
+ @second_bar = SecondBar.new(elem%'characterBars'%'secondBar')
247
+
248
+ # base stats
249
+ @strength = Strength.new(elem%'baseStats'%'strength')
250
+ @agility = Agility.new(elem%'baseStats'%'agility')
251
+ @stamina = Stamina.new(elem%'baseStats'%'stamina')
252
+ @intellect = Intellect.new(elem%'baseStats'%'intellect')
253
+ @spirit = Spirit.new(elem%'baseStats'%'spirit')
254
+
255
+ # damage stuff
256
+ @melee = Melee.new(elem%'melee')
257
+ @ranged = Ranged.new(elem%'ranged')
258
+ @spell = Spell.new(elem.at(' > spell')) # TODO: hacky?
259
+ @defenses = Defenses.new(elem%'defenses')
260
+
261
+ # TODO: Massive problem, doesn't fill in resistances for some reason
262
+ resist_types = ['arcane', 'fire', 'frost', 'holy', 'nature', 'shadow']
263
+ @resistances = {}
264
+ resist_types.each do |res|
265
+ @resistances[res] = Resistance.new(elem%'resistances'%res)
266
+ end
267
+
268
+ @talent_spec = TalentSpec.new(elem%'talentSpec')
269
+
270
+ @pvp = Pvp.new(elem%'pvp')
271
+
272
+ # Also accessible from
273
+ # character.skills['professions']
274
+ @professions = []
275
+ (elem%'professions'/:skill).each do |skill|
276
+ @professions << Skill.new(skill)
277
+ end
278
+
279
+ @items = []
280
+ (elem%'items'/:item).each do |item|
281
+ @items << EquippedItem.new(item, @api)
282
+ end
283
+
284
+ @buffs = []
285
+ (elem%'buffs'/:spell).each do |buff|
286
+ @buffs << Buff.new(buff, @api)
287
+ end
288
+
289
+ @debuffs = []
290
+ (elem%'debuffs'/:spell).each do |debuff|
291
+ @debuffs << Buff.new(debuff, @api)
292
+ end
293
+ end
294
+
295
+ # character-skills.xml
296
+ def character_skills(elem)
297
+ @skill_categories = {}
298
+ (elem/:skillCategory).each do |category|
299
+ @skill_categories[category[:key]] = SkillCategory.new(category)
300
+ end
301
+ end
302
+
303
+ # character-reputation.xml
304
+ def character_reputation(elem)
305
+ @reputation_categories = {}
306
+ (elem/:factionCategory).each do |category|
307
+ @reputation_categories[category[:key]] = RepFactionCategory.new(category)
308
+ end
309
+ end
310
+ end
311
+
312
+
313
+ # Second stat bar, depends on character class
314
+ class SecondBar
315
+ attr_reader :effective, :casting, :not_casting, :type
316
+
317
+ def initialize(elem)
318
+ @effective = elem[:effective].to_i
319
+ @casting = elem[:casting].to_i == -1 ? nil : elem[:casting].to_i
320
+ @not_casting = elem[:notCasting].to_i == -1 ? nil : elem[:notCasting].to_i
321
+ @type = elem[:type]
322
+ end
323
+ end
324
+
325
+
326
+ class BaseStat # abstract?
327
+ attr_reader :base, :effective
328
+ end
329
+
330
+ class Strength < BaseStat
331
+ attr_reader :attack, :block
332
+ def initialize(elem)
333
+ @base = elem['base'].to_i
334
+ @effective = elem['effective'].to_i
335
+ @attack = elem['attack'].to_i
336
+ @block = elem['block'].to_i == -1 ? nil : elem['block'].to_i
337
+ end
338
+ end
339
+
340
+ class Agility < BaseStat
341
+ attr_reader :armor, :attack, :crit_hit_percent
342
+ def initialize(elem)
343
+ @base = elem[:base].to_i
344
+ @effective = elem[:effective].to_i
345
+ @armor = elem[:armor].to_i
346
+ @attack = elem[:attack].to_i == -1 ? nil : elem[:attack].to_i
347
+ @crit_hit_percent = elem[:critHitPercent].to_f
348
+ end
349
+ end
350
+
351
+ class Stamina < BaseStat
352
+ attr_reader :health, :pet_bonus
353
+ def initialize(elem)
354
+ @base = elem[:base].to_i
355
+ @effective = elem[:effective].to_i
356
+ @health = elem[:health].to_i
357
+ @pet_bonus = elem[:petBonus].to_i == -1 ? nil : elem[:petBonus].to_i
358
+ end
359
+ end
360
+
361
+ class Intellect < BaseStat
362
+ attr_reader :mana, :crit_hit_percent, :pet_bonus
363
+ def initialize(elem)
364
+ @base = elem[:base].to_i
365
+ @effective = elem[:effective].to_i
366
+ @mana = elem[:mana].to_i
367
+ @crit_hit_percent = elem[:critHitPercent].to_f
368
+ @pet_bonus = elem[:petBonus].to_i == -1 ? nil : elem[:petBonus].to_i
369
+ end
370
+ end
371
+
372
+ class Spirit < BaseStat
373
+ attr_reader :health_regen, :mana_regen
374
+ def initialize(elem)
375
+ @base = elem[:base].to_i
376
+ @effective = elem[:effective].to_i
377
+ @health_regen = elem[:healthRegen].to_i
378
+ @mana_regen = elem[:manaRegen].to_i
379
+ end
380
+ end
381
+
382
+ class Armor < BaseStat
383
+ attr_reader :percent, :pet_bonus
384
+ def initialize(elem)
385
+ @base = elem[:base].to_i
386
+ @effective = elem[:effective].to_i
387
+ @percent = elem[:percent].to_f
388
+ @pet_bonus = elem[:petBonus].to_i == -1 ? nil : elem[:petBonus].to_i
389
+ end
390
+ end
391
+
392
+
393
+
394
+ # <melee>
395
+ # <mainHandDamage dps="65.6" max="149" min="60" percent="0" speed="1.60"/>
396
+ # <offHandDamage dps="0.0" max="0" min="0" percent="0" speed="2.00"/>
397
+ # <mainHandSpeed hastePercent="0.00" hasteRating="0" value="1.60"/>
398
+ # <offHandSpeed hastePercent="0.00" hasteRating="0" value="2.00"/>
399
+ # <power base="338" effective="338" increasedDps="24.0"/>
400
+ # <hitRating increasedHitPercent="0.00" value="0"/>
401
+ # <critChance percent="4.16" plusPercent="0.00" rating="0"/>
402
+ # <expertise additional="0" percent="0.00" rating="0" value="0"/>
403
+ # </melee>
404
+ class Melee
405
+ attr_reader :main_hand_skill, :off_hand_skill,
406
+ :main_hand_damage, :off_hand_damage,
407
+ :main_hand_speed, :off_hand_speed,
408
+ :speed, :hit_rating, :crit_chance
409
+ :expertise
410
+
411
+ def initialize(elem)
412
+ # TODO: Do these not exist anymore?
413
+ @main_hand_skill = WeaponSkill.new(elem%'mainHandWeaponSkill') if (elem%'mainHandWeaponSkill')
414
+ @off_hand_skill = WeaponSkill.new(elem%'offHandWeaponSkill') if (elem%'offHandWeaponSkill')
415
+
416
+ @main_hand_damage = WeaponDamage.new(elem%'mainHandDamage')
417
+ @off_hand_damage = WeaponDamage.new(elem%'offHandDamage')
418
+
419
+ @main_hand_speed = WeaponSpeed.new(elem%'mainHandSpeed')
420
+ @off_hand_speed = WeaponSpeed.new(elem%'offHandSpeed')
421
+
422
+ @power = WeaponPower.new(elem%'power')
423
+ @hit_rating = WeaponHitRating.new(elem%'hitRating')
424
+ @crit_chance = WeaponCritChance.new(elem%'critChance')
425
+
426
+ @expertise = WeaponExpertise.new(elem%'expertise')
427
+ end
428
+ end
429
+
430
+ # <ranged>
431
+ # <weaponSkill rating="0" value="-1"/>
432
+ # <damage dps="0.0" max="0" min="0" percent="0" speed="0.00"/>
433
+ # <speed hastePercent="0.00" hasteRating="0" value="0.00"/>
434
+ # <power base="57" effective="57" increasedDps="4.0" petAttack="-1.00" petSpell="-1.00"/>
435
+ # <hitRating increasedHitPercent="0.00" value="0"/>
436
+ # <critChance percent="0.92" plusPercent="0.00" rating="0"/>
437
+ # </ranged>
438
+ class Ranged
439
+ attr_reader :weapon_skill, :damage, :speed, :power,
440
+ :hit_rating, :crit_chance
441
+
442
+ def initialize(elem)
443
+ @weapon_skill = WeaponSkill.new(elem%'weaponSkill')
444
+ @damage = WeaponDamage.new(elem%'damage')
445
+ @speed = WeaponSpeed.new(elem%'speed')
446
+ @power = WeaponPower.new(elem%'power')
447
+ @hit_rating = WeaponHitRating.new(elem%'hitRating')
448
+ @crit_chance = WeaponCritChance.new(elem%'critChance')
449
+ end
450
+ end
451
+
452
+ class WeaponSkill
453
+ attr_reader :rating, :value
454
+
455
+ def initialize(elem)
456
+ @value = elem[:value].to_i == -1 ? nil : elem[:value].to_i
457
+ @rating = elem[:rating].to_i
458
+ end
459
+ end
460
+
461
+ class WeaponDamage
462
+ attr_reader :dps, :max, :min, :percent, :speed
463
+
464
+ def initialize(elem)
465
+ @dps = elem[:dps].to_f
466
+ @max = elem[:max].to_i
467
+ @min = elem[:min].to_i
468
+ @percent = elem[:percent].to_f
469
+ @speed = elem[:speed].to_f
470
+ end
471
+ end
472
+
473
+ class WeaponSpeed
474
+ attr_reader :haste_percent, :haste_rating, :value
475
+
476
+ def initialize(elem)
477
+ @haste_percent = elem[:hastePercent].to_f
478
+ @haste_rating = elem[:hasteRating].to_f
479
+ @value = elem[:value].to_f
480
+ end
481
+ end
482
+
483
+ class WeaponPower
484
+ attr_reader :base, :effective, :increased_dps, :pet_attack, :pet_spell
485
+
486
+ def initialize(elem)
487
+ @base = elem[:base].to_i
488
+ @haste_rating = elem[:effective].to_i
489
+ @increased_dps = elem[:increasedDps].to_f
490
+ @pet_attack = (elem[:petAttack].to_f == -1 ? nil : elem[:petAttack].to_f)
491
+ @pet_spell = (elem[:petSpell].to_f == -1 ? nil : elem[:petSpell].to_f)
492
+ end
493
+ end
494
+
495
+ class WeaponHitRating
496
+ attr_reader :increased_hit_percent, :value
497
+
498
+ def initialize(elem)
499
+ @increased_hit_percent = elem[:increasedHitPercent].to_f
500
+ @value = elem[:value].to_f
501
+ end
502
+ end
503
+
504
+ class WeaponCritChance
505
+ attr_reader :percent, :plus_percent, :rating
506
+
507
+ def initialize(elem)
508
+ @percent = elem[:percent].to_f
509
+ @plus_percent = elem[:plusPercent].to_f
510
+ @rating = elem[:rating].to_i
511
+ end
512
+ end
513
+
514
+ # <expertise additional="0" percent="0.00" rating="0" value="0"/>
515
+ class WeaponExpertise
516
+ attr_reader :additional, :percent, :rating, :value
517
+
518
+ def initialize(elem)
519
+ @additional = elem[:additional].to_i
520
+ @percent = elem[:percent].to_f
521
+ @rating = elem[:rating].to_i
522
+ @value = elem[:value].to_i
523
+ end
524
+ end
525
+
526
+
527
+ # Decided to do funky stuff to the XML to make it more useful.
528
+ # instead of having two seperate lists of bonusDamage and critChance
529
+ # merged it into one set of objects for each thing
530
+ class Spell
531
+ attr_reader :arcane, :fire, :frost, :holy, :nature, :shadow,
532
+ :hit_rating, :bonus_healing, :penetration, :mana_regen
533
+
534
+ def initialize(elem)
535
+ @arcane = SpellDamage.new(elem%'bonusDamage'%'arcane', elem%'critChance'%'arcane')
536
+ @fire = SpellDamage.new(elem%'bonusDamage'%'fire', elem%'critChance'%'fire')
537
+ @frost = SpellDamage.new(elem%'bonusDamage'%'frost', elem%'critChance'%'frost')
538
+ @holy = SpellDamage.new(elem%'bonusDamage'%'holy', elem%'critChance'%'holy')
539
+ @nature = SpellDamage.new(elem%'bonusDamage'%'nature', elem%'critChance'%'nature')
540
+ @shadow = SpellDamage.new(elem%'bonusDamage'%'shadow', elem%'critChance'%'shadow')
541
+
542
+ @bonus_healing = (elem%'bonusHealing')[:value].to_i # is this right??
543
+ @penetration = (elem%'penetration')[:value].to_i
544
+ @hit_rating = WeaponHitRating.new(elem%'hitRating')
545
+ @mana_regen = ManaRegen.new(elem%'manaRegen')
546
+
547
+ # elements = %w[arcane fire frost holy nature shadow]
548
+ # elements.each do |element|
549
+ # # TODO: is this a good idea?
550
+ # #instance_variable_set("@#{element}", foo) #??
551
+ # #eval("@#{element} = SpellDamage.new(elem[:bonusDamage][element][:value], elem[:critChance][element][:percent]).to_f)")
552
+ # # eval("@#{element} = SpellDamage.new((elem%'bonusDamage'%element)[:value].to_i,
553
+ # # (elem%'critChance'%element)[:percent].to_f)")
554
+ # end
555
+ end
556
+ end
557
+
558
+ class SpellDamage
559
+ attr_reader :value, :crit_chance_percent
560
+ alias_method :percent, :crit_chance_percent
561
+
562
+ def initialize(bonusDamage_elem, critChance_elem)
563
+ @value = bonusDamage_elem[:value].to_i
564
+ @crit_chance_percent = critChance_elem[:percent].to_f
565
+ end
566
+ end
567
+
568
+ class ManaRegen
569
+ attr_reader :casting, :not_casting
570
+
571
+ def initialize(elem)
572
+ @casting = elem[:casting].to_f
573
+ @not_casting = elem[:notCasting].to_f
574
+ end
575
+ end
576
+
577
+ class PetBonus
578
+ attr_reader :attack, :damage, :from_Type
579
+
580
+ def initialize(elem)
581
+ @attack = elem[:attack].to_i == -1 ? nil : elem[:attack].to_i
582
+ @damage = elem[:damage].to_i == -1 ? nil : elem[:damage].to_i
583
+ @from_type = elem[:fromType] if elem[:fromType]
584
+ end
585
+ end
586
+
587
+
588
+
589
+ class Defenses
590
+ attr_reader :armor, :defense, :dodge, :parry, :block, :resilience
591
+
592
+ def initialize(elem)
593
+ @armor = Armor.new(elem%'armor')
594
+ @defense = Defense.new(elem%'defense')
595
+ @dodge = DodgeParryBlock.new(elem%'dodge')
596
+ @parry = DodgeParryBlock.new(elem%'parry')
597
+ @block = DodgeParryBlock.new(elem%'block')
598
+ @resilience = Resilience.new(elem%'resilience')
599
+ end
600
+ end
601
+
602
+ class Armor
603
+ attr_reader :base, :effective, :percent, :pet_bonus
604
+
605
+ def initialize(elem)
606
+ @base = elem[:base].to_i
607
+ @effective = elem[:effective].to_i
608
+ @percent = elem[:percent].to_f
609
+ @pet_bonus = elem[:petBonus].to_i == -1 ? nil : elem[:petBonus].to_i
610
+ end
611
+ end
612
+
613
+ class Defense
614
+ attr_reader :value, :increase_percent, :decrease_percent, :plus_defense, :rating
615
+
616
+ def initialize(elem)
617
+ @value = elem[:value].to_i
618
+ @increase_percent = elem[:increasePercent].to_f
619
+ @decrease_percent = elem[:decreasePercent].to_f
620
+ @plus_defense = elem[:plusDefense].to_i
621
+ @rating = elem[:rating].to_i
622
+ end
623
+ end
624
+
625
+ class DodgeParryBlock
626
+ attr_reader :percent, :increase_percent, :rating
627
+
628
+ def initialize(elem)
629
+ @percent = elem[:percent].to_f
630
+ @increase_percent = elem[:increasePercent].to_f
631
+ @rating = elem[:rating].to_i
632
+ end
633
+ end
634
+
635
+ class Resilience
636
+ attr_reader :damage_percent, :hit_percent, :value
637
+
638
+ def initialize(elem)
639
+ @damage_percent = elem[:damagePercent].to_f
640
+ @hit_percent = elem[:hitPercent].to_f
641
+ @value = elem[:value].to_f
642
+ end
643
+ end
644
+
645
+
646
+ class Resistance
647
+ attr_reader :value, :pet_bonus
648
+
649
+ def initialize(elem)
650
+ @value = elem[:value].to_i
651
+ @pet_bonus = elem[:petBonus].to_i == -1 ? nil : elem[:petBonus].to_i
652
+ end
653
+ end
654
+
655
+
656
+ # Note the list of talent trees starts at 1. This is quirky, but that's what's used in the XML
657
+ class TalentSpec
658
+ attr_reader :trees
659
+
660
+ def initialize(elem)
661
+ @trees = []
662
+ @trees[1] = elem[:treeOne].to_i
663
+ @trees[2] = elem[:treeTwo].to_i
664
+ @trees[3] = elem[:treeThree].to_i
665
+ end
666
+ end
667
+
668
+
669
+ # Player-versus-player data
670
+ class Pvp
671
+ attr_reader :lifetime_honorable_kills, :arena_currency
672
+
673
+ def initialize(elem)
674
+ @lifetime_honorable_kills = (elem%'lifetimehonorablekills')[:value].to_i
675
+ @arena_currency = (elem%'arenacurrency')[:value].to_i
676
+ end
677
+ end
678
+
679
+
680
+ # A buff
681
+ # TODO: Code duplication, see basic Item class. Make extend Icon class?
682
+ class Buff
683
+ attr_reader :name, :effect, :icon_base
684
+ alias_method :to_s, :name
685
+
686
+ @@icon_url_base = 'images/icons/'
687
+ @@icon_sizes = {:large => ['64x64', 'jpg'], :medium => ['43x43', 'png'], :small => ['21x21', 'png']}
688
+
689
+ def initialize(elem, api = nil)
690
+ @api = api
691
+
692
+ @name = elem[:name]
693
+ @effect = elem[:effect]
694
+ @icon_base = elem[:icon]
695
+ end
696
+
697
+ # http://armory.worldofwarcraft.com/images/icons/21x21/spell_holy_arcaneintellect.png
698
+ def icon(size = :medium)
699
+ if !@@icon_sizes.include?(size)
700
+ raise Wowr::Exceptions::InvalidIconSize.new(@@icon_sizes)
701
+ end
702
+
703
+ if @api
704
+ base = @api.base_url
705
+ else
706
+ base = 'http://www.wowarmory.com/'
707
+ end
708
+
709
+ # http://www.wowarmory.com/images/icons/64x64/blahblah.jpg
710
+ return base + @@icon_url_base + @@icon_sizes[size][0] + '/' + @icon_base + '.' + @@icon_sizes[size][1]
711
+ end
712
+ end
713
+
714
+
715
+ # An item equipped to a player
716
+ class EquippedItem < Item
717
+ attr_reader :durability, :max_durability, #:id, :item_id, :icon,
718
+ :gems, :permanent_enchant,
719
+ :random_properties_id, :seed, :slot
720
+
721
+ def initialize(elem, api = nil)
722
+ super(elem, api)
723
+ @durability = elem[:durability].to_i
724
+ @max_durability = elem[:maxDurability].to_i
725
+ @gems = []
726
+ @gems[0] = elem[:gem0Id].to_i == 0 ? nil : elem[:gem0Id].to_i
727
+ @gems[1] = elem[:gem1Id].to_i == 0 ? nil : elem[:gem1Id].to_i
728
+ @gems[2] = elem[:gem2Id].to_i == 0 ? nil : elem[:gem2Id].to_i
729
+ @permanent_enchant = elem[:permanentEnchant].to_i
730
+ @random_properties_id = elem[:randomPropertiesId] == 0 ? nil : elem[:randomPropertiesId].to_i
731
+ @seed = elem[:seed].to_i # not sure if seed is so big it's overloading
732
+ @slot = elem[:slot].to_i
733
+ end
734
+ end
735
+
736
+
737
+
738
+
739
+ # <skillCategory key="weaponskills" name="Weapon Skills">
740
+ # <skill key="defense" max="350" name="Defense" value="348"/>
741
+ # <skill key="maces" max="350" name="Maces" value="291"/>
742
+ # <skill key="staves" max="350" name="Staves" value="234"/>
743
+ # <skill key="two-handedmaces" max="350" name="Two-Handed Maces" value="189"/>
744
+ # <skill key="unarmed" max="350" name="Unarmed" value="13"/>
745
+ # </skillCategory>
746
+
747
+ # General skill category
748
+ # eg Weapon Skills, Languages
749
+ class SkillCategory
750
+ attr_reader :key, :name, :skills
751
+ alias_method :to_s, :name
752
+
753
+ def initialize(elem)
754
+ @key = elem[:key]
755
+ @name = elem[:name]
756
+
757
+ @skills = {}
758
+ (elem/:skill).each do |skill|
759
+ @skills[skill[:key]] = Skill.new(skill)
760
+ end
761
+ end
762
+ end
763
+
764
+ # eg Daggers, Riding, Fishing, language
765
+ class Skill
766
+ attr_reader :key, :name, :value, :max
767
+ alias_method :to_s, :name
768
+ alias_method :to_i, :value
769
+
770
+ def initialize(elem)
771
+ @key = elem[:key]
772
+ @name = elem[:name]
773
+ @value = elem[:value].to_i
774
+ @max = elem[:max].to_i
775
+ end
776
+ end
777
+
778
+
779
+ # Larger group of factions
780
+ # Used for faction information
781
+ # eg Alliance, Shattrath City, Steamwheedle Cartel
782
+ class RepFactionCategory
783
+ attr_reader :key, :name, :factions
784
+ alias_method :to_s, :name
785
+
786
+ def initialize(elem)
787
+ @key = elem[:key]
788
+ @name = elem[:name]
789
+
790
+ @factions = {}
791
+ (elem/:faction).each do |faction|
792
+ @factions[faction[:key]] = RepFaction.new(faction)
793
+ end
794
+ end
795
+
796
+ def total
797
+ total = 0
798
+ factions.each_value { |faction| total += faction.reputation }
799
+ return total
800
+ end
801
+ end
802
+
803
+
804
+ # Smaller NPC faction that is part of a FactionCategory
805
+ # eg Darnassus, Argent Dawn
806
+ class RepFaction
807
+ attr_reader :key, :name, :reputation
808
+ alias_method :to_s, :name
809
+ alias_method :to_i, :reputation
810
+
811
+ alias_method :rep, :reputation
812
+
813
+ def initialize(elem)
814
+ @key = elem[:key]
815
+ @name = elem[:name]
816
+ @reputation = elem[:reputation].to_i
817
+ end
818
+ end
819
+
820
+ end
821
+ end