gwdamcalc 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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