gwdamcalc 0.1.0

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/bin/gwdamcalc ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require File.join(File.dirname(__FILE__), "..", "lib", "gwdamcalc")
3
+ GWTools::UI.new
data/bin/gwdamcalc.rb ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require File.join(File.dirname(__FILE__), "..", "lib", "gwdamcalc")
3
+ GWTools::UI.new
data/lib/gwdamcalc.rb ADDED
@@ -0,0 +1,628 @@
1
+ #!/usr/bin/env ruby
2
+ #--
3
+ # Copyright (c) 2007 Daniel Stevens
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person
6
+ # obtaining a copy of this software and associated documentation
7
+ # files (the "Software"), to deal in the Software without
8
+ # restriction, including without limitation the rights to use,
9
+ # copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the
11
+ # Software is furnished to do so, subject to the following
12
+ # conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be
15
+ # included in all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19
+ # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21
+ # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22
+ # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24
+ # OTHER DEALINGS IN THE SOFTWARE.
25
+ #++
26
+ # = gwdamcalc - The Guild Wars Damage Calculator
27
+ #
28
+ # _gwdamcalc_ is a damage calculator for the MMORPG/CORPG video game Guild
29
+ # Wars. The software can be used to determine the damage caused by
30
+ # a single attack by a character against a defending target, given a set of
31
+ # relevant statistics for the attacker and target. The implementation for the
32
+ # software was inspired by Guild Wars damage research documented at
33
+ # http://guildwars.incgamers.com/wiki/index.php/Damage_Explained and other
34
+ # sources.
35
+ #
36
+ # == Downloading
37
+ #
38
+ # The latest version of _gwdamcalc_ can be downloaded from http://rubyforge.org/frs/?group_id=4975.
39
+ #
40
+ # == Requirements
41
+ #
42
+ # _gwdamcalc_ is implemented in the scripting language _Ruby_. The Ruby
43
+ # interpreter is require in order to run the script and use the software.
44
+ # Information on downloading the Ruby interpreter for you platform is available at
45
+ # http://www.ruby-lang.org/en/downloads.
46
+ #
47
+ # == Usage
48
+ #
49
+ # _gwdamcalc_ is invoked from the command line, passing the statistics of the
50
+ # attacker and target as arguments. If gwdamcalc was installed from a gem, it
51
+ # should be possible to invoke it directly from the command line from any
52
+ # directory. Use the <tt>--help</tt> argument to see a list of arguments and
53
+ # their usage. Additional information can be found in the Rdoc for the
54
+ # following classes:
55
+ #
56
+ # GWTools::DamageCalc:: This contains detailed information on the workings of
57
+ # _gwdamcalc_. Read this if you're interested in using
58
+ # _gwdamcalc_ with your own code.
59
+ # GWTools::UI:: This contains more detailed information about _gwdamcalc_'s
60
+ # command line interface. Read this if you're having trouble
61
+ # figuring out how to use it.
62
+ #
63
+ # == License information
64
+ #
65
+ # Author:: Dan Stevens <dan.stevens.iamai@googlemail.com>
66
+ # License:: Copyright (c) 2007 Daniel Stevens. Released under a MIT/X11 style
67
+ # license. See the 'license' file.
68
+ #
69
+ # == Warranty
70
+ #
71
+ # This software is provided "as is" and without any express or
72
+ # implied warranties, including, without limitation, the implied
73
+ # warranties of merchantibility and fitness for a particular
74
+ # purpose.
75
+ #
76
+
77
+ require 'optparse'
78
+ require 'ostruct'
79
+
80
+ module GWTools
81
+
82
+ # A basic damage calculator for the MMORPG/CORPG video
83
+ # game <em>Guild Wars</em>. The class is based strongly around the damage
84
+ # calculation itself: only the relevant independent variables are expected, as
85
+ # opposed to them being encapsulated into classes that represent attack/target
86
+ # entities in an abstract form (this may be a future development).
87
+ #
88
+ # The class has been mostly derived from the contents of
89
+ # http://guildwars.incgamers.com/wiki/index.php/Damage_Explained. The
90
+ # calculation has been divided into a number of methods that reflect most of the
91
+ # components mentioned in the article, although most of the names of the terms
92
+ # have been changed.
93
+ #
94
+ # The Full equation for spell, signet, staff and wand attacks:
95
+ # * d = (bd � tda � (2 ^ (((3 � lvl) - (ttav � tap)) � 40))) + db
96
+ # The Full equation for <em>Martial Weapon</em> attacks:
97
+ # * d = (bd � tda � (2 ^ (((5 � min((lvl + 4) � 2 rank) + 2 � max(0, rank - ((lvl + 4) � 2))) - (ttav � tap)) � 40))) + db
98
+ class DamageCalc
99
+
100
+ # Version for gwdamcalc
101
+ VERSION = '0.1.0'
102
+
103
+ # PHYS_DAM_TYPES = [:blunt, :slashing, :piercing].freeze
104
+
105
+ # The set of weapon types that are classified as <em>martial weapons</em>.
106
+ MARTIAL_WEAPONS = [:axe, :bow, :daggers, :hammer, :scythe, :spear, :sword].freeze
107
+
108
+ # All weapon types.
109
+ WEAPONS = (MARTIAL_WEAPONS + [:staff, :wand, :spell, :signet]).freeze
110
+
111
+ # A regular expression that matches strings that express the damage range of
112
+ # a weapons in the form that is used in Guild Wars e.g. '11-25'.
113
+ BD_FORM = /(\d+)(-(\d+))?/.freeze
114
+
115
+ # call-seq: tofrac(percentage) -> Float
116
+ #
117
+ # Converts a value as a percentage (integer) into the fractional equivalent.
118
+ # Examples:
119
+ #
120
+ # DamageCalc.tofrac(20) -> 1.25
121
+ # DamageCalc.tofrac(-12) -> 0.88
122
+ def DamageCalc.tofrac(percent)
123
+ (100 + percent) / 100.0
124
+ end
125
+
126
+ # call-seq: topercent(fraction) -> Integer
127
+ #
128
+ # Converts a value as a fraction (float) into the equivalent percentage (and
129
+ # are rounded, if necessary).
130
+ # Examples:
131
+ #
132
+ # DamageCalc.topercent(1.25) -> 20
133
+ # DamageCalc.topercent(0.88) -> -12
134
+ def DamageCalc.topercent(fraction)
135
+ (fraction * 100 - 100).round
136
+ end
137
+
138
+ # The type of weapon causing the damage (:axe, :bow, :daggers, :hammer,
139
+ # :scythe, :spear, :sword, :staff, :wand, :spell, :signet). If the attack is
140
+ # caused by a spell or signet, use the symbols :spell and :signet
141
+ # respectively.
142
+ attr_accessor :wep_type
143
+
144
+ # The attacker's rank in the relevant skill attribute for the weapon. Not
145
+ # applicable for attacks caused by spells, signets, staves or wands.
146
+ attr_accessor :rank
147
+
148
+ # The attacker's level.
149
+ attr_accessor :lvl
150
+
151
+ # The <em>Base Damage</em> range of the weapon, or damage value of the skill.
152
+ # If a Range object is specified, a value from within the range is chosen
153
+ # automatically at random. A single value will be used outright.
154
+ attr_accessor :bd
155
+
156
+ # The <em>Total Damage Adjustment</em> for the weapon. This should be
157
+ # expressed as a fraction, with values greater than one for a positive
158
+ # adjustment and values between 0.0 and 0.99 for a negative adjustment e.g.
159
+ # +20% damage = 1.20, -15% damage = 0.85. Summate adjustments from multiple
160
+ # sources into this variable. Use the tofrac method convert whole percentage
161
+ # into fractions.
162
+ attr_accessor :tda
163
+
164
+ # The <em>Total Target Armor Value</em>. The sum of all the sources of
165
+ # armor for the target including body armor, shields (where appropriate),
166
+ # armor buffs and debuffs from skills (debuffs should have negative impact on
167
+ # the value).
168
+ attr_accessor :ttav
169
+
170
+ # The <em>Total Armor Penetration</em> of the attack. This should be
171
+ # expressed as a fraction, with the armor penetration acting as a reduction
172
+ # in the target's armor by multiplying it against the ttav. Therefore, the
173
+ # value of this variable should be between 0.0 (for complete penetration) up
174
+ # to 1.0 for no penetration. When using the tofrac method, specify the armor
175
+ # penetration as a negative number and the appropriate fraction will be
176
+ # returned.
177
+ attr_accessor :tap
178
+
179
+ # The <em>Damage Bonus</em> of the attack; additional damage which is added
180
+ # at the end of the <em>Net Damage</em> calculation.
181
+ attr_accessor :db
182
+
183
+ # call-seq:
184
+ # new(wep_type=:sword, bd=11..15, ttav=60, lvl=20, rank=12, tda=1.0, tap=1.0, db=0) -> DamageCalc
185
+ #
186
+ # Constructs a new DamageCalc object. Accepts the attributes defined above
187
+ # as parameters.
188
+ def initialize(wep_type=:sword, bd=11..25, ttav=60, lvl=20, rank=12, tda=1.0,
189
+ tap=1.0, db=0)
190
+ @wep_type = wep_type
191
+ @bd = bd
192
+ @ttav = ttav
193
+ @lvl = lvl
194
+ @rank = rank
195
+ @tda = tda
196
+ @tap = tap
197
+ @db = db
198
+ end
199
+
200
+ # call-seq: d -> Integer
201
+ #
202
+ # Returns the <em>Net Damage</em> (d); the final resultant damage taking
203
+ # into the account the attacker's stats and the target's armor. It is
204
+ # calculated as the product of the <em>Base Damage</em> (bd), the
205
+ # <em>Total Damage Adjustment</em> (tda) and the <em>Defensive
206
+ # Adjustment</em> (da), plus a <em>Damage Bonus</em> (db):
207
+ #
208
+ # d = (bd � tda � da) + db
209
+ #
210
+ # The end result is rounded to the nearest integer.
211
+ def d
212
+ ((bd.pick * tda * da) + db).round
213
+ end
214
+
215
+ # Alias for d
216
+ alias calc d
217
+
218
+ # call-seq: da -> Float
219
+ #
220
+ # Returns the <em>Defensive Adjustment</em> (da); a fraction that modifies
221
+ # damage with respect to the attacker's stance and targets armor. It is
222
+ # calculated as follows:
223
+ #
224
+ # 2^((atddm - eav) � 40)
225
+ #
226
+ # where:
227
+ # * <b>atddm</b> is the <em>Attack Type Dependant Damage Modifier</em>;
228
+ # * <b>eav</b> is the <em>Effective Armor Value</em> of the target.
229
+ def da
230
+ 2 ** ((atddm - eav) / 40.0)
231
+ end
232
+
233
+ # call-seq: atddm -> Integer
234
+ #
235
+ # Returns the <em>Attack Type Dependant Damage Modifier</em> (atddm). The
236
+ # value returned depends on the type of attack, which are attacks made with a
237
+ # martial weapon or attacks caused by a skill, staff or wand. The values
238
+ # <em>Damage Modified for Weapon Attacks</em> (dmwa) or <em>Damage Modified
239
+ # for Spell Attacks</em> (dmsa) will be returned, respectively.
240
+ def atddm
241
+ martial? ? dmwa : dmsa
242
+ end
243
+
244
+ # call-seq: martial? -> true or false
245
+ #
246
+ # Returns true if the attack is caused by a martial weapon i.e. axe, sword,
247
+ # daggers, hammer, scythe, spear, bow.
248
+ #
249
+ def martial?
250
+ MARTIAL_WEAPONS.include? wep_type
251
+ end
252
+
253
+ # call-seq: dmwa -> Integer or Float
254
+ #
255
+ # Returns the <em>Damage Modifier for Weapon Attacks</em> (dmwa); the
256
+ # modification made to the damage for attacks made with martial weapons.
257
+ # There is a threshold, dependant upon the level of the attacker, at which
258
+ # the rank for the weapon has a lesser influence when exceeding the
259
+ # threshold. dmwa is calculated as follows:
260
+ #
261
+ # 5 � min(threshold, rank) + 2 � max(0, rank - threshold)
262
+ def dmwa
263
+ 5 * [threshold, rank].min + 2 * [0, rank - threshold].max
264
+ end
265
+
266
+ # call-seq: threshold -> Float
267
+ #
268
+ # Returns the level dependant threshold past which the influence the rank has
269
+ # on the damage modifier is lower. It is calculated as follows:
270
+ #
271
+ # threshold = (lvl + 4) � 2
272
+ def threshold
273
+ (lvl + 4) / 2.0
274
+ end
275
+
276
+ # call-seq: dmsa -> Integer
277
+ #
278
+ # Returns the <em>Damage Modifier for Spell Attacks</em> (dmsa); the
279
+ # modification made to the damage for attacks made with spells, signets,
280
+ # staves or wands. It is calculated as follows:
281
+ #
282
+ # 3 � <em>Attacker's Level</em>
283
+ def dmsa
284
+ 3 * lvl
285
+ end
286
+
287
+ # call-seq: eav -> Float
288
+ #
289
+ # Returns the <em>Effective Armor Value</em> (eav) of the target; the product
290
+ # of the effective armor of the target taking into account its own total
291
+ # armor value (ttav) and the <em>Total Armor Penetration</em>
292
+ # of the attacker:
293
+ #
294
+ # ttav � tap
295
+ def eav
296
+ ttav * tap
297
+ end
298
+
299
+ end
300
+
301
+ # The following describes the command line interface for _gwdamcalc_ in more detail.
302
+ #
303
+ # == Invoking gwdamcalc
304
+ #
305
+ # If gwdamcalc was installed from a gem , it can be invoked directly from
306
+ # the command line from any directory:
307
+ #
308
+ # gwdamcalc
309
+ #
310
+ # If you did not install from a gem, you will need to locate the gwdamcalc.rb
311
+ # file, change the working directory to that of the file and enter the
312
+ # following in your command shell:
313
+ #
314
+ # ruby gwdamcalc.rb
315
+ #
316
+ # == Usage
317
+ #
318
+ # The damage calculation for Guild Wars depends on a set of statistics relating
319
+ # the attacking and defending characters. _gwdamcalc_ has a set of command line
320
+ # options that can be used to specify the value of these statistics for use in
321
+ # the calculation. If a option is not specified for a stat, a default value is a
322
+ # assumed in the calculation. You can get _gwdamcalc_ to list the set of
323
+ # statistics and their default values by using the <tt>--help</tt> arguments:
324
+ #
325
+ # $ gwdamcalc --help
326
+ # Usage: gwdamcalc [OPTIONS]...
327
+ # A basic damage calculator for the MMORPG/CORPG video game Guild Wars. The
328
+ # independent variables of the calculation are specified by the options below.
329
+ # See the rdoc for more details on each of the variables.
330
+ #
331
+ # gwdamcalc accepts one or more of the options below. If a option is not
332
+ # explicitely specified, the default value is assumed in the calculation.
333
+ # -w, --weptype=string The type of weapon. Choose from: axe, bow, sword, daggers, hammer,
334
+ # scythe, spear, staff, wand. If the attack is caused by a spell or
335
+ # signet, use 'spell' and 'signet' respectively. Default
336
+ # value: sword
337
+ # -d, --bd=int[-int] The Base Damage of the attack. Specified or a single value, or a
338
+ # range in the form 11-22. Default value: 11-25
339
+ # -a, --ttav=int The Total Target Armor Value. Default value: 60
340
+ # -l, --lvl=int The level of the attacker. Default value: 20
341
+ # -r, --rank=int The attacker's rank in the appropriate attribute for their weapon.
342
+ # Not required for attacks made with spells, signets, staves and wands.
343
+ # Default value: 12
344
+ # -j, --tda=float The Total Damage Adjustment. Expressed as a fraction (see rdoc).
345
+ # Default value: 1.0
346
+ # -p, --tap=float The Total Armor Penetration. Expressed as a fraction (see rdoc).
347
+ # Default value: 1.0
348
+ # -b, --db=int The Damage Bonus. Default value: 0
349
+ # -s, --summary Display a summary of the values of the variables of the calculation
350
+ # -q, --quiet Displays only the result of the calculation
351
+ # --help, --usage Displays this help message.
352
+ # --version Displays version information.
353
+ #
354
+ # The first eight options are for specifying values relating to the stats of the
355
+ # attacker and defender. The last four are support options. Each option has a
356
+ # short, single character version, prefixed with a single dash, and long
357
+ # version prefixd with two dashs. When specify a value using the short version,
358
+ # seperate the option and the value with a space, for example:
359
+ #
360
+ # gwdamcalc -d 50
361
+ #
362
+ # When specify a value using the long version, seperate the option and the value
363
+ # with an equals sign, for example:
364
+ #
365
+ # gwdamcalc --bd=50
366
+ #
367
+ # The following headings describe each of the options in more detail, in the above
368
+ # order.
369
+ #
370
+ # === Weapon type
371
+ #
372
+ # -w, --weptype=string
373
+ #
374
+ # Use this specify the means by which the attacker is attacking. Technically, in
375
+ # terms of how this value affects the calculation, there are two groups: 'Martial
376
+ # weapons', which include axe, bow, sword, dagger, hammer, scythe and spear, and
377
+ # 'magic', which include staff, wand, spell and signet. Changing the weapon type
378
+ # to another in the same group does not affect the calculation in anyway.
379
+ #
380
+ # === Base damage
381
+ #
382
+ # -d, --bd=int[-int]
383
+ #
384
+ # Use this to specify the damage rating for the weapon or skill. This can be
385
+ # discreet value or a range. If a range is specified, a whole value from within the
386
+ # range will be selected from within the range. If you are performing a
387
+ # calculation for a martial weapon, which typically have a range for its damage
388
+ # rating, you can set this value to its minimum or maximum value (or any value
389
+ # you want!) to get the minimum or maximum possible damage for the given
390
+ # remaining stats.
391
+ #
392
+ # If specifying a range, seperate the lower and upper values of the range with a
393
+ # dash, for example:
394
+ #
395
+ # gwdamcalc -bd 11-22
396
+ #
397
+ # === Total Target Armor Value
398
+ #
399
+ # -a, --ttav=int
400
+ #
401
+ # The <em>Total Target Armor Value</em> is the sum of all the sources of armor for the target
402
+ # including body armor, shields (where appropriate), armor buffs and debuffs from
403
+ # skills (debuffs should have negative impact on the value).
404
+ #
405
+ # === Level of attacker
406
+ #
407
+ # -l, --lvl=int
408
+ #
409
+ # Use this to specify the level of the attacker.
410
+ #
411
+ # === The attacker's rank
412
+ #
413
+ # Use this to specify the attacker's rank in the relevant skill attribute for the
414
+ # weapon. This is only relevant to attacks made with martial weapons.
415
+ #
416
+ # === Total Damage Adjustment
417
+ #
418
+ # Use this to specify a fractional modification of the base damage. Instances of
419
+ # where this would be used is where the weapon has +% damage modifier (e.g. +20%
420
+ # damage for a customized weapon). However this option expects this value as a
421
+ # fraction rather than a percentage, with values greater than one for a positive
422
+ # adjustment and values between 0.0 and 0.99 for a negative adjustment. If there
423
+ # are multiple damage modifies, total them together.
424
+ #
425
+ # Tip: If you don't want to convert a percentage into a fraction in your head,
426
+ # with Ruby installed you can enter the following in the command shell,
427
+ # replacing 'x' with the percentage, to get the fraction:
428
+ #
429
+ # ruby -e "puts (100 + x) / 100.0"
430
+ #
431
+ # === Total Armor Pentration
432
+ #
433
+ # Use this to specify the total of all sources of armor penetration against the
434
+ # target. Like the Total Damage Adjustment, with the armor penetration acting as a
435
+ # reduction in the target's armor by multiplying it against the Total Target Armor
436
+ # Value. Therefore, the value of this variable should be between 0.0 (for complete
437
+ # penetration) up to 1.0 for no penetration.
438
+ class UI
439
+
440
+ include GWTools
441
+
442
+ BANNER =
443
+ "Usage: gwdamcalc [OPTIONS]...
444
+ A basic damage calculator for the MMORPG/CORPG video game Guild Wars. The
445
+ independent variables of the calculation are specified by the options below.
446
+ See the rdoc for more details on each of the variables." # :nodoc:
447
+
448
+ WEP_TYPES = [:axe, :bow, :sword, :daggers, :hammer, :scythe, :spear, :staff,
449
+ :wand, :spell, :signet].freeze
450
+
451
+ def initialize
452
+
453
+ begin
454
+
455
+ @calc = DamageCalc.new()
456
+ @summary = false
457
+ @quiet = false
458
+
459
+ # Deal with command line paramters
460
+ parse(ARGV)
461
+
462
+ unless @quiet
463
+ if @summary
464
+ puts
465
+ puts "Calculation summary:"
466
+ print " Weapon type:\t\t\t", @calc.wep_type.id2name.capitalize, "\n"
467
+ print " Base Damage:\t\t\t", @calc.bd.begin, @calc.bd.is_a?(Range) ? "-#{@calc.bd.end}" : "", "\n"
468
+ print " Total Target Armor Value:\t", @calc.ttav, "\n"
469
+ print " Attacker's level:\t\t", @calc.lvl, "\n"
470
+ print " Attacker's rank:\t\t", @calc.rank, "\n"
471
+ printf " Total Damage Adjustment:\t%+d%% (%.2f)\n", DamageCalc.topercent(@calc.tda), @calc.tda
472
+ printf " Total Armor Penetration:\t%+d%% (%.2f)\n", DamageCalc.topercent(@calc.tap), @calc.tap, "\n"
473
+ print " Damage Bonus:\t\t\t", @calc.db, "\n"
474
+ end
475
+
476
+ puts
477
+ print "Calculated damage: "
478
+ end
479
+
480
+ puts @calc.d
481
+
482
+ rescue SystemCallError => err
483
+ $stderr.puts "Error: #{err}"
484
+ rescue OptionParser::InvalidArgument => err
485
+ $stderr.puts "Error: #{err}"
486
+ $stderr.puts "Please ensure option argument is in the correct format."
487
+ $stderr.puts "Use -h option for valid options and their argument's format."
488
+ rescue OptionParser::InvalidOption => err
489
+ $stderr.puts "Error: #{err}"
490
+ $stderr.puts "Use -h option for valid options."
491
+ end
492
+
493
+ end
494
+
495
+ # Returns a struct containing the options.
496
+ def parse(args) # :nodoc:
497
+ # Stores options
498
+ #opts = OpenStruct.new
499
+
500
+ OptionParser.new() do |optparser|
501
+ optparser.banner = BANNER
502
+
503
+ optparser.separator ""
504
+ optparser.separator "gwdamcalc accepts one or more of the options below. If a option is not"
505
+ optparser.separator "explicitely specified, the default value is assumed in the calculation."
506
+
507
+ optparser.on("-w", "--weptype=string", WEP_TYPES,
508
+ "The type of weapon. Choose from: axe, bow, sword, daggers, hammer,",
509
+ "scythe, spear, staff, wand. If the attack is caused by a spell or",
510
+ "signet, use 'spell' and 'signet' respectively. Default",
511
+ "value: sword") do |arg|
512
+ @calc.wep_type = arg
513
+ end
514
+
515
+ optparser.on("-d", "--bd=int[-int]",
516
+ "The Base Damage of the attack. Specified or a single value, or a",
517
+ "range in the form 11-22. Default value: 11-25") do |arg|
518
+ if arg =~ BD_FORM
519
+ if $3.nil?: @calc.bd = $1.to_i
520
+ else @calc.bd = $1.to_i..$3.to_i
521
+ end
522
+ else raise OptionParser::InvalidArgument
523
+ end
524
+ end
525
+
526
+ optparser.on("-a", "--ttav=int", Integer,
527
+ "The Total Target Armor Value. Default value: 60") do |arg|
528
+ @calc.ttav = arg
529
+ end
530
+
531
+ optparser.on("-l", "--lvl=int", Integer,
532
+ "The level of the attacker. Default value: 20") do |arg|
533
+ @calc.lvl = arg
534
+ end
535
+
536
+ optparser.on("-r", "--rank=int", Integer,
537
+ "The attacker's rank in the appropriate attribute for their weapon.",
538
+ "Not required for attacks made with spells, signets, staves and wands.",
539
+ "Default value: 12") do |arg|
540
+ @calc.rank = arg
541
+ end
542
+
543
+ optparser.on("-j", "--tda=float", Float,
544
+ "The Total Damage Adjustment. Expressed as a fraction (see rdoc).",
545
+ "Default value: 1.0") do |arg|
546
+ @calc.tda = arg
547
+ end
548
+
549
+ optparser.on("-p", "--tap=float", Float,
550
+ "The Total Armor Penetration. Expressed as a fraction (see rdoc).",
551
+ "Default value: 1.0") do |arg|
552
+ @calc.tap = arg
553
+ end
554
+
555
+ optparser.on("-b", "--db=int", Integer,
556
+ "The Damage Bonus. Default value: 0") do |arg|
557
+ @calc.db = arg
558
+ end
559
+
560
+ optparser.on("-s", "--summary",
561
+ "Display a summary of the values of the variables of the calculation") do |arg|
562
+ @summary = true
563
+ end
564
+
565
+ optparser.on("-q", "--quiet",
566
+ "Displays only the result of the calculation") do |arg|
567
+ @quiet = true
568
+ end
569
+
570
+ optparser.on_tail("--help", "--usage", "Displays this help message.") do
571
+ puts optparser
572
+ exit
573
+ end
574
+
575
+ optparser.on_tail("--version", "Displays version information.") do
576
+ puts "gwdamcalc #{DamageCalc::VERSION}"
577
+ exit
578
+ end
579
+
580
+ optparser.parse!(args)
581
+ end
582
+ end
583
+
584
+
585
+
586
+ end
587
+
588
+ end
589
+
590
+ class Integer
591
+ #class Fixnum
592
+
593
+ # Accommodate for duck typing.
594
+ def pick
595
+ self
596
+ end
597
+
598
+ # Accommodate for duck typing.
599
+ def begin
600
+ self
601
+ end
602
+
603
+ # Accommodate for duck typing.
604
+ def end
605
+ self
606
+ end
607
+
608
+ end
609
+
610
+ # call-seq: randran(min, max) -> Integer
611
+ #
612
+ # Returns a random number with in the range specified by min and max
613
+ # inclusively.
614
+ def randran(min, max)
615
+ rand(max + 1 - min) + min
616
+ end
617
+
618
+ class Range
619
+
620
+ # Randomly picks a value within the the boundries of the range, inclusively.
621
+ def pick
622
+ randran(self.begin, self.end)
623
+ end
624
+
625
+ end
626
+
627
+ GWTools::UI.new if $0 == __FILE__
628
+
@@ -0,0 +1,104 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
2
+ require 'test/unit'
3
+ require 'gwdamcalc'
4
+
5
+ include GWTools
6
+
7
+ # A set of tests for GWTools::DamageCalc, based on a number of examples from the
8
+ # web (that are assumed to be accurate). These are:
9
+ # * http://guildwars.incgamers.com/wiki/index.php/Damage_Explained#Examples
10
+ # * http://www.guildwarsguru.com/content/game-mechanics-id674.php
11
+ class TestDamageCalc < Test::Unit::TestCase
12
+
13
+ # A level 16 elementalist casts a fireball (71 damage) at a monk wearing the
14
+ # judge�s armor (60AL + 10AL vs physical). The monk has a defensive staff of
15
+ # defense (+10AL). The monk takes 48 fire damage.
16
+ def test1
17
+ result = DamageCalc.new(:spell, 71, 70, 16).d
18
+ assert_equal(48, result)
19
+ end
20
+
21
+ # A level 15 Elementalist butchering packs of level 7, 21 defense Charr with
22
+ # 69 damage, level 8 Fireballs. Each one you cast is going to deal 104.6
23
+ # (105).
24
+ def test2
25
+ result = DamageCalc.new(:spell, 69, 21, 15).d
26
+ assert_equal(105, result)
27
+ end
28
+
29
+ # A level 20 Ranger hunting level 28, 118 defense Rift Wardens in the Tombs.
30
+ # You have a customized, 15-28 Half Moon Bow, and a level 12 attribute to go
31
+ # with it. Minimum damage: 18.3 (18); Maximum damage: 34.2 (34).
32
+ # def test3
33
+ # result = DamageCalc.new(:bow, 15..28, 118, 12, 20, 1.2, 0.8).d
34
+ # assert((result >= 18) && (result <= 34))
35
+ # @summary << ["test3:", result]
36
+ # end
37
+
38
+ # Attacker level:: 20
39
+ # Weapon:: Sword 15-22 damage +20%
40
+ # Swordmanship rank:: 9
41
+ # Strength:: 0 (0% armor penetration)
42
+ # Target armor:: 60 points
43
+ # Expected minimum damage:: 14
44
+ # Expected maximum damage:: 20
45
+ def test4
46
+ result = DamageCalc.new(:sword, 15..22, 60, 20, 9, 1.2, 1.0).d
47
+ assert((result >= 14) && (result <= 20))
48
+ end
49
+
50
+ # Attacker level:: 20
51
+ # Weapon:: Sword 15-22 damage +20%
52
+ # Swordmanship rank:: 12
53
+ # Strength:: 0 (0% armor penetration)
54
+ # Target armor:: 60 points
55
+ # Expected minimum damage:: 18
56
+ # Expected maximum damage:: 26
57
+ def test5
58
+ result = DamageCalc.new(:sword, 15..22, 60, 20, 12, 1.2, 1.0).d
59
+ assert((result >= 18) && (result <= 26))
60
+
61
+ end
62
+
63
+ # Attacker level:: 6
64
+ # Spell:: Flare 22 damage (5 Fire Magic)
65
+ # Target armor:: 60 points
66
+ # Expected damage:: 11
67
+ def test6
68
+ result = DamageCalc.new(:spell, 22, 60, 6).d
69
+ assert_equal(11, result)
70
+
71
+ end
72
+
73
+ # Attacker level:: 73
74
+ # Spell:: Flare 22 damage (5 Fire Magic)
75
+ # Target armor:: 60 points
76
+ # Expected damage:: 11
77
+ def test7
78
+ result = DamageCalc.new(:spell, 22, 60, 7).d
79
+ assert_equal(11, result)
80
+
81
+ end
82
+
83
+ # Attacker level:: 30
84
+ # Spell:: Deep Freeze 76 damage (12 Water Magic)
85
+ # Target armor:: 60 points
86
+ # Expected damage:: 128
87
+ def test8
88
+ result = DamageCalc.new(:spell, 76, 60, 30).d
89
+ assert_equal(128, result)
90
+
91
+ end
92
+
93
+ # Attacker level:: 10
94
+ # Weapon:: Wand 6-10 damage + 20%
95
+ # Target armor:: 60 points
96
+ # Expected Minimum damage:: 4
97
+ # Expected Maximum damage:: 7
98
+ def test9
99
+ result = DamageCalc.new(:wand, 6..10, 60, 10, nil, 1.2).d
100
+ assert((result >= 4) && (result <= 7))
101
+
102
+ end
103
+
104
+ end
data/license ADDED
@@ -0,0 +1,23 @@
1
+ Copyright (c) 2007 Daniel Stevens
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
23
+
data/readme ADDED
@@ -0,0 +1,48 @@
1
+ = gwdamcalc - The Guild Wars Damage Calculator
2
+
3
+ _gwdamcalc_ is a damage calculator for the MMORPG/CORPG video game Guild
4
+ Wars. The software can be used to determine the damage caused by
5
+ a single attack by a character against a defending target, given a set of
6
+ relevant statistics for the attacker and target. The implementation for the
7
+ software was inspired by Guild Wars damage research documented at
8
+ http://guildwars.incgamers.com/wiki/index.php/Damage_Explained and other
9
+ sources.
10
+
11
+ == Downloading
12
+
13
+ The latest version of _gwdamcalc_ can be downloaded from http://rubyforge.org/frs/?group_id=4975.
14
+
15
+ == Requirements
16
+
17
+ _gwdamcalc_ is implemented in the scripting language _Ruby_. The Ruby
18
+ interpreter is require in order to run the script and use the software.
19
+ Information on downloading the Ruby interpreter for you platform is available at
20
+ http://www.ruby-lang.org/en/downloads.
21
+
22
+ == Usage
23
+
24
+ _gwdamcalc_ is invoked from the command line, passing the statistics of the
25
+ attacker and target as arguments. If gwdamcalc was installed from a gem, it
26
+ should be possible to invoke it directly from the command line from any
27
+ directory. Use the '--help' argument to see a list of arguments and their usage.
28
+ Additional information can be found in the Rdoc for the following classes:
29
+
30
+ GWTools::DamageCalc:: This contains detailed information on the workings of
31
+ _gwdamcalc_. Read this if you're interested in using
32
+ _gwdamcalc_ with your own code.
33
+ GWTools::UI:: This contains more detailed information about _gwdamcalc_'s
34
+ command line interface. Read this if you're having trouble
35
+ figuring out how to use it.
36
+
37
+ == License information
38
+
39
+ Author:: Dan Stevens <dan.stevens.iamai@googlemail.com>
40
+ License:: Copyright (c) 2007 Daniel Stevens. Released under a MIT/X11 style
41
+ license. See the 'license' file.
42
+
43
+ == Warranty
44
+
45
+ This software is provided "as is" and without any express or
46
+ implied warranties, including, without limitation, the implied
47
+ warranties of merchantibility and fitness for a particular
48
+ purpose.
metadata ADDED
@@ -0,0 +1,67 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gwdamcalc
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Dan 'IAmAI' Stevens
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-01-03 00:00:00 +00:00
13
+ default_executable: gwdamcalc.rb
14
+ dependencies: []
15
+
16
+ description: A basic damage calculator for the MMORPG/CORPG video game, Guild Wars.
17
+ email: dan.stevens.iamai@googlemail.com
18
+ executables:
19
+ - gwdamcalc.rb
20
+ - gwdamcalc
21
+ extensions: []
22
+
23
+ extra_rdoc_files:
24
+ - readme
25
+ - license
26
+ files:
27
+ - lib
28
+ - bin
29
+ - license
30
+ - readme
31
+ - lib/gwdamcalc.rb
32
+ - lib/test_gwdamcalc.rb
33
+ - bin/gwdamcalc
34
+ - bin/gwdamcalc.rb
35
+ has_rdoc: true
36
+ homepage: http://gwdamcalc.rubyforge.org
37
+ post_install_message:
38
+ rdoc_options:
39
+ - --title
40
+ - Guild Wars Damage Calculator Documentation
41
+ - --main
42
+ - readme
43
+ - --inline-source
44
+ - --line-numbers
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: "0"
52
+ version:
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: "0"
58
+ version:
59
+ requirements: []
60
+
61
+ rubyforge_project: gwdamcalc
62
+ rubygems_version: 1.0.1
63
+ signing_key:
64
+ specification_version: 2
65
+ summary: Guild Wars Damage Calculator
66
+ test_files:
67
+ - lib/test_gwdamcalc.rb