d3_mpq 0.0.11 → 0.0.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. data/lib/d3_mpq/commands.rb +3 -0
  2. data/lib/d3_mpq/core_data/game_balance/monster_affixes.rb +11 -2
  3. data/lib/d3_mpq/core_data/game_balance/monster_levels.rb +15 -0
  4. data/lib/d3_mpq/core_data/game_balance/monster_names.rb +2 -2
  5. data/lib/d3_mpq/core_data/game_balance/power_formula_tables.rb +1 -1
  6. data/lib/d3_mpq/core_data/game_balance/rare_names.rb +15 -0
  7. data/lib/d3_mpq/core_data/game_balance.rb +2 -0
  8. data/lib/d3_mpq/csv_generator/base.rb +23 -15
  9. data/lib/d3_mpq/csv_generator/experience_table.rb +32 -0
  10. data/lib/d3_mpq/csv_generator/monster_affixes.rb +39 -0
  11. data/lib/d3_mpq/csv_generator/monster_levels.rb +14 -0
  12. data/lib/d3_mpq/csv_generator/monster_names.rb +16 -0
  13. data/lib/d3_mpq/csv_generator/power_formula_tables.rb +17 -0
  14. data/lib/d3_mpq/csv_generator/rare_names.rb +15 -0
  15. data/lib/d3_mpq/csv_generator.rb +6 -0
  16. data/lib/d3_mpq/mod_code.rb +196 -0
  17. data/lib/d3_mpq/mod_codes.rb +6 -0
  18. data/lib/d3_mpq/version.rb +1 -1
  19. data/lib/d3_mpq/version.rb~ +1 -1
  20. data/lib/d3_mpq.rb +2 -0
  21. data/spec/bindata_ext/mod_code_spec.rb +1 -1
  22. data/spec/unit/bindata_ext/mod_code_spec.rb +1 -1
  23. data/spec/unit/core_data/game_balance/affix_list_spec.rb +1 -1
  24. data/spec/unit/core_data/game_balance/monster_levels_spec.rb +14 -0
  25. data/spec/unit/core_data/game_balance/rare_names_spec.rb +14 -0
  26. data/spec/unit/csv_generator/experience_table_spec.rb +11 -0
  27. data/spec/unit/csv_generator/monster_affixes.rb +11 -0
  28. data/spec/unit/csv_generator/monster_levels_spec.rb +11 -0
  29. data/spec/unit/csv_generator/monster_names_spec.rb +11 -0
  30. data/spec/unit/csv_generator/power_formula_spec.rb +11 -0
  31. data/spec/unit/csv_generator/rare_names_spec.rb +11 -0
  32. metadata +39 -15
  33. data/lib/bindata_ext/mod_code.rb +0 -194
  34. data/lib/bindata_ext/mod_codes.rb +0 -4
@@ -86,6 +86,9 @@ Example: d3_mpq --csv-input extracted_mpqs/StringList/ csv StringList
86
86
  * Items
87
87
  * ItemEnhancements
88
88
  * ItemTypes
89
+ * MonsterNames
90
+ * PowerFormulaTables
91
+ * RareNames
89
92
  * Recipes
90
93
  * RecipeDetails
91
94
  * SetItemBonuses
@@ -13,9 +13,18 @@ module D3MPQ::CoreData::GameBalance
13
13
  uint32 :ui3
14
14
  uint32 :ui4
15
15
  uint32 :ui5
16
+ uint32 :ui6
17
+ uint32 :ui7
18
+ uint32 :ui8
19
+ uint32 :ui9
20
+
21
+ mod_codes :mod_codes, :initial_length => 20
22
+
23
+ uint32 :ref1
24
+ uint32 :ref2
25
+ uint32 :ref3
26
+ uint32 :ref4
16
27
 
17
- # TODO
18
- skip :length => 0x210 - 16
19
28
  end
20
29
  end
21
30
  end
@@ -0,0 +1,15 @@
1
+ module D3MPQ::CoreData::GameBalance
2
+ class MonsterLevels < Base
3
+ self.struct_size = 0x230
4
+
5
+ content do
6
+ ffs
7
+ zeroes :length => 4
8
+
9
+ 135.times do |i|
10
+ float "fp_a_#{i}"
11
+ end
12
+ end
13
+ end
14
+ end
15
+
@@ -4,13 +4,13 @@ module D3MPQ::CoreData::GameBalance
4
4
 
5
5
  content do
6
6
  zeroes
7
- string :name,
7
+ string :affix_name,
8
8
  :read_length => 0x100,
9
9
  :trim_padding => true
10
10
 
11
11
  uint32 :is_suffix
12
12
 
13
- string :name2,
13
+ string :name,
14
14
  :read_length => 0x80,
15
15
  :trim_padding => true
16
16
 
@@ -10,7 +10,7 @@ module D3MPQ::CoreData::GameBalance
10
10
  zeroes :length => 192
11
11
 
12
12
  61.times do |i|
13
- float "fp#{i}".intern
13
+ float "level_#{i}".intern
14
14
  end
15
15
  end
16
16
  end
@@ -0,0 +1,15 @@
1
+ module D3MPQ::CoreData::GameBalance
2
+ class RareNames < Base
3
+ self.struct_size = 0x110
4
+
5
+ content do
6
+ zeroes
7
+ string :name, :length => 0x100, :trim_padding => true
8
+
9
+ uint32 :unknown
10
+ uint32 :stl_key_hash
11
+ unknown
12
+ end
13
+ end
14
+ end
15
+
@@ -14,8 +14,10 @@ module D3MPQ::CoreData
14
14
  require "d3_mpq/core_data/game_balance/item_types"
15
15
  require "d3_mpq/core_data/game_balance/labels_global"
16
16
  require "d3_mpq/core_data/game_balance/monster_affixes"
17
+ require "d3_mpq/core_data/game_balance/monster_levels"
17
18
  require "d3_mpq/core_data/game_balance/monster_names"
18
19
  require "d3_mpq/core_data/game_balance/power_formula_tables"
20
+ require "d3_mpq/core_data/game_balance/rare_names"
19
21
  require "d3_mpq/core_data/game_balance/recipes"
20
22
  require "d3_mpq/core_data/game_balance/set_item_bonuses"
21
23
  require "d3_mpq/core_data/game_balance/socketed_effects"
@@ -23,23 +23,21 @@ module D3MPQ::CSVGenerator
23
23
  class << self
24
24
  # TODO: refactor
25
25
  def map_to_csv(options = nil)
26
- if options
27
- if options.is_a?(Array)
28
- @map_to_csv = {}
29
- options.each do |e|
30
- if e.is_a?(String) || e.is_a?(Symbol)
31
- @map_to_csv[e.intern] = e.intern
32
- else
33
- @map_to_csv[e.to_a[0].intern] = e.to_a[1]
34
- end
26
+ return @map_to_csv unless options
27
+
28
+ if options.is_a?(Array)
29
+ @map_to_csv = {}
30
+ options.each do |e|
31
+ if e.is_a?(String) || e.is_a?(Symbol)
32
+ @map_to_csv[e.intern] = e.intern
33
+ else
34
+ @map_to_csv[e.to_a[0].intern] = e.to_a[1]
35
35
  end
36
- elsif options.is_a?(Hash)
37
- @map_to_csv = options
38
- else
39
- raise "Options must be an Array or Hash."
40
36
  end
37
+ elsif options.is_a?(Hash)
38
+ @map_to_csv = options
41
39
  else
42
- @map_to_csv
40
+ raise "Options must be an Array or Hash."
43
41
  end
44
42
  end
45
43
  end
@@ -99,9 +97,18 @@ module D3MPQ::CSVGenerator
99
97
  end
100
98
 
101
99
  def csv_keys
102
- map_to_csv.keys.join(SEPERATOR)
100
+ if map_to_csv
101
+ map_to_csv.keys.join(SEPERATOR)
102
+ else
103
+ raise "Not Implemented"
104
+ end
103
105
  end
104
106
 
107
+ # def fields_from_mpq_reader
108
+ # fields = MPQ_READER.fields.fields.map { |e| e.name }
109
+ # if fields.include?
110
+ # end
111
+
105
112
 
106
113
  def subject_to_csv_line(subject, filename, base = nil, index = nil)
107
114
  line = []
@@ -114,6 +121,7 @@ module D3MPQ::CSVGenerator
114
121
  entry = subject.send(opt)
115
122
  end
116
123
 
124
+ entry = entry.to_s if entry.is_a?(BinData::String)
117
125
  if entry.is_a?(String)
118
126
  entry.gsub!('"', '\"')
119
127
  entry = "\"#{entry}\""
@@ -0,0 +1,32 @@
1
+ module D3MPQ::CSVGenerator
2
+ class ExperienceTable < Base
3
+ MPQ_READER = D3MPQ::CoreData::GameBalance::ExperienceTable
4
+
5
+ map = [
6
+ :xp1,
7
+ :fp1,
8
+ :xp_given_1,
9
+ :xp_given_2,
10
+ :xp_given_3,
11
+ :xp_given_4,
12
+ :xp_given_5,
13
+ :ui1,
14
+ :ui2,
15
+ :ui3,
16
+ :ui4,
17
+ :ui5,
18
+ :ui1a,
19
+ :ui2a,
20
+ :ui3a,
21
+ :ui4a,
22
+ :ui5a
23
+ ]
24
+
25
+ 40.times do |i|
26
+ map << "u#{i}".intern
27
+ end
28
+
29
+ map_to_csv(map)
30
+ end
31
+ end
32
+
@@ -0,0 +1,39 @@
1
+ module D3MPQ::CSVGenerator
2
+ class MonsterAffixes < Base
3
+ MPQ_READER = D3MPQ::CoreData::GameBalance::MonsterAffixes
4
+
5
+ map = {
6
+ :name => :name,
7
+ :name_hash => Proc.new { |subject| subject.name.to_d3_hash },
8
+ :ui1 => :ui1,
9
+ :ui2 => :ui2,
10
+ :ui3 => :ui3,
11
+ :ui4 => :ui4,
12
+ :ui5 => :ui5,
13
+ :ui6 => :ui6,
14
+ :ui7 => :ui7,
15
+ :ui8 => :ui8,
16
+ :ui9 => :ui9,
17
+ }
18
+
19
+ 21.times do |i|
20
+ m = "modcode#{i}"
21
+ map["#{m}_mod_id".intern] = Proc.new { |subject| subject.mod_codes[i].mod_code }
22
+ map["#{m}_param1".intern] = Proc.new { |subject| subject.mod_codes[i].mod_param1 }
23
+ map["#{m}_param2".intern] = Proc.new { |subject| subject.mod_codes[i].mod_param2 }
24
+ map["#{m}_param3".intern] = Proc.new { |subject| subject.mod_codes[i].mod_param3 }
25
+ map["#{m}_opcode".intern] = Proc.new { |subject| subject.mod_codes[i].trace.join("|") }
26
+ map["#{m}_value_min".intern] = Proc.new { |subject| subject.mod_codes[i].min }
27
+ map["#{m}_value_max".intern] = Proc.new { |subject| subject.mod_codes[i].max }
28
+ end
29
+ map = map.merge({
30
+ :ref1 => :ref1,
31
+ :ref2 => :ref2,
32
+ :ref3 => :ref3,
33
+ :ref4 => :ref4
34
+ })
35
+
36
+ map_to_csv(map)
37
+ end
38
+ end
39
+
@@ -0,0 +1,14 @@
1
+ module D3MPQ::CSVGenerator
2
+ class MonsterLevels < Base
3
+ MPQ_READER = D3MPQ::CoreData::GameBalance::MonsterLevels
4
+
5
+ map = {}
6
+
7
+ 135.times do |i|
8
+ map["fp_a_#{i}".intern] = "fp_a_#{i}".intern
9
+ end
10
+
11
+ map_to_csv(map)
12
+ end
13
+ end
14
+
@@ -0,0 +1,16 @@
1
+ module D3MPQ::CSVGenerator
2
+ class MonsterNames < Base
3
+ MPQ_READER = D3MPQ::CoreData::GameBalance::MonsterNames
4
+
5
+ map = {
6
+ :affix_name => :affix_name,
7
+ :affix_name_hash => Proc.new { |subject| subject.affix_name.to_d3_hash },
8
+ :is_suffix => :is_suffix,
9
+ :name => :name,
10
+ :name_hash => Proc.new { |subject| subject.name.to_d3_hash }
11
+ }
12
+
13
+ map_to_csv(map)
14
+ end
15
+ end
16
+
@@ -0,0 +1,17 @@
1
+ module D3MPQ::CSVGenerator
2
+ class PowerFormulaTables < Base
3
+ MPQ_READER = D3MPQ::CoreData::GameBalance::PowerFormulaTables
4
+
5
+ map = {
6
+ :name => :name,
7
+ :hash => Proc.new { |subject| subject.name.to_d3_hash }
8
+ }
9
+
10
+ 61.times do |i|
11
+ map["level_#{i}".intern] = "level_#{i}".intern
12
+ end
13
+
14
+ map_to_csv(map)
15
+ end
16
+ end
17
+
@@ -0,0 +1,15 @@
1
+ module D3MPQ::CSVGenerator
2
+ class RareNames < Base
3
+ MPQ_READER = D3MPQ::CoreData::GameBalance::RareNames
4
+
5
+ map = {
6
+ :name => :name,
7
+ :hash => Proc.new { |subject| subject.name.to_d3_hash },
8
+ :unknown => :unknown,
9
+ :stl_key_hash => :stl_key_hash
10
+ }
11
+
12
+ map_to_csv(map)
13
+ end
14
+ end
15
+
@@ -4,9 +4,15 @@ module D3MPQ
4
4
 
5
5
  require 'd3_mpq/csv_generator/actor'
6
6
  require 'd3_mpq/csv_generator/affix_list'
7
+ require 'd3_mpq/csv_generator/experience_table'
7
8
  require 'd3_mpq/csv_generator/item_enhancements'
8
9
  require 'd3_mpq/csv_generator/items'
9
10
  require 'd3_mpq/csv_generator/item_types'
11
+ require 'd3_mpq/csv_generator/monster_affixes'
12
+ require 'd3_mpq/csv_generator/monster_levels'
13
+ require 'd3_mpq/csv_generator/monster_names'
14
+ require 'd3_mpq/csv_generator/power_formula_tables'
15
+ require 'd3_mpq/csv_generator/rare_names'
10
16
  require 'd3_mpq/csv_generator/recipe_details'
11
17
  require 'd3_mpq/csv_generator/recipes'
12
18
  require 'd3_mpq/csv_generator/set_item_bonuses'
@@ -0,0 +1,196 @@
1
+ module D3MPQ
2
+ class ModCode < BinData::Record
3
+ endian :little
4
+
5
+ uint32 :mod_code
6
+
7
+ uint32 :mod_param1
8
+ uint32 :mod_param2
9
+ uint32 :mod_param3
10
+
11
+ uint32 :mod_offset
12
+ uint32 :mod_length
13
+
14
+ # Returns: nil if mod_code is 0xFFFFFFFF, mod_code otherwise
15
+ def id
16
+ self.mod_code == 0xFFFFFFFF ? nil : self.mod_code.to_i
17
+ end
18
+
19
+ # HACK
20
+ # Returns: Instance of BinData::Record that respond to :variable_content
21
+ def base
22
+ parent.parent.parent.parent
23
+ end
24
+
25
+ def index
26
+ (mod_offset - base.data_num_bytes - base.data_offset) / 4
27
+ end
28
+
29
+ def count
30
+ mod_length / 4
31
+ end
32
+
33
+ def data
34
+ base.variable_content[index, count]
35
+ end
36
+
37
+ def empty?
38
+ mod_length == 0
39
+ end
40
+
41
+ def min
42
+ stack.min || 0.0
43
+ end
44
+
45
+ def max
46
+ stack.max || 0.0
47
+ end
48
+
49
+ def trace
50
+ stack.trace
51
+ end
52
+
53
+ def stack
54
+ @stack ||= Stack.new(data)
55
+ end
56
+
57
+ private
58
+
59
+ # Pseudo-Stack to compute min/max of current ModCode
60
+ class Stack
61
+ attr_reader :value, :trace
62
+
63
+ def initialize(data)
64
+ @stack = []
65
+ @trace = []
66
+ @data = *data
67
+ @value = nil
68
+ parse
69
+ end
70
+
71
+ def min
72
+ @value ? @value.min : nil
73
+ end
74
+
75
+ def max
76
+ @value ? @value.max : nil
77
+ end
78
+
79
+ def push(item)
80
+ @stack.push item
81
+ end
82
+
83
+ def pop
84
+ @stack.pop
85
+ end
86
+
87
+ def peek
88
+ @stack.last
89
+ end
90
+
91
+ def count
92
+ @stack.length
93
+ end
94
+
95
+ def empty?
96
+ count == 0
97
+ end
98
+
99
+ # Lets go
100
+ def parse
101
+ return @value if @value
102
+ return nil if @data.empty?
103
+
104
+ next_op = true
105
+ @data.each_with_index do |dword, index|
106
+ next_op = true and next unless next_op
107
+
108
+ case dword.bytes.first
109
+ when 0x00
110
+ # return the value at the top of the stack
111
+ raise "Return found, but Stack not empty!" if @data[index+1]
112
+ @value = pop
113
+ return @value
114
+ when 0x01
115
+ # call the function of the next op-code (just pass here)
116
+ when 0x03
117
+ # rand1(A,B); pop 2 numbers and push a random value between A and A+B
118
+ op { |a, b| ["rand", a, a + b] }
119
+ when 0x04
120
+ # rand2(A,B); pop 2 numbers and push a random value between A and B
121
+ op { |a, b| ["rand2", a, b] }
122
+ when 0x06
123
+ # push the next DWord onto the stack
124
+ v = @data[index+1].unpack('F').first
125
+ push(StackValue.new(v))
126
+ @trace << "#{v}"
127
+ next_op = false
128
+ when 0x0B
129
+ # add(A,B); pop 2 numbers and push the sum
130
+ op { |a, b| ["add", (a + b)] }
131
+ when 0x0C
132
+ # sub(A,B); pop 2 numbers and push the difference
133
+ op { |a, b| ["sub", (a - b)] }
134
+ when 0x0D
135
+ # mul(A,B); pop 2 numbers and push the product
136
+ op { |a, b| ["mul", (a * b)] }
137
+ when 0x0E
138
+ # div(A,B); pop 2 numbers and push the quotient
139
+ op { |a, b| ["div", (a / b)] }
140
+ else
141
+ raise "OP-Code not found: #{op} | #{@data.inspect}"
142
+ end
143
+ end
144
+
145
+ raise "No return found: #{@data.inspect}"
146
+ end
147
+
148
+ # Perform OP-Code
149
+ def op(&blk)
150
+ b = pop
151
+ a = pop
152
+
153
+ formula, min, max = blk.call(a, b)
154
+
155
+ push(StackValue.random(min, max || min))
156
+ @trace << formula
157
+ end
158
+
159
+ def inspect
160
+ { :value => @value, :trace => @trace}
161
+ end
162
+
163
+ # Wrapper for a Float that handles: current_value, min_value, max_value
164
+ class StackValue
165
+ attr_accessor :value, :min_max
166
+
167
+ def self.random(min, max)
168
+ StackValue.new(MinMax.new(min.min, max.max).random, min.min, max.max)
169
+ end
170
+
171
+ def initialize(value, min = nil, max = nil)
172
+ @value = value
173
+ min ||= @value
174
+ @min_max = MinMax.new(min, max)
175
+ end
176
+
177
+ [:min, :max].each { |m| define_method(m) { min_max.send(m) } }
178
+ ["-", "+", "*", "/"].each do |m|
179
+ define_method(m) { |sv| with_other(sv){ |a, b| a.send(m, b) } }
180
+ end
181
+
182
+ def to_s
183
+ (min == max) ? "#{min}" : "#{min}..#{max}"
184
+ end
185
+
186
+ private
187
+ def with_other(oth, &block)
188
+ mm = block.call(min_max, oth.min_max)
189
+ v = block.call(value, oth.value)
190
+ StackValue.new(v, mm.min, mm.max)
191
+ end
192
+ end
193
+ end
194
+ end
195
+ end
196
+
@@ -0,0 +1,6 @@
1
+ module D3MPQ
2
+ class ModCodes < BinData::Array
3
+ default_parameters :type => :mod_code, :initial_length => 1
4
+ end
5
+ end
6
+
@@ -1,4 +1,4 @@
1
1
  module D3MPQ
2
- VERSION = "0.0.11"
2
+ VERSION = "0.0.13"
3
3
  end
4
4
 
@@ -1,4 +1,4 @@
1
1
  module D3MPQ
2
- VERSION = "0.0.10"
2
+ VERSION = "0.0.12"
3
3
  end
4
4
 
data/lib/d3_mpq.rb CHANGED
@@ -9,6 +9,8 @@ require 'core_ext/string'
9
9
  module D3MPQ
10
10
  require 'd3_mpq/analyzer'
11
11
  require 'd3_mpq/attributes'
12
+ require 'd3_mpq/mod_code'
13
+ require 'd3_mpq/mod_codes'
12
14
  require 'd3_mpq/mod_code_analyzer'
13
15
  require 'd3_mpq/mpq'
14
16
 
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe ModCode do
3
+ describe D3MPQ::ModCode do
4
4
  subject { ModCode.new }
5
5
 
6
6
  specify { subject.respond_to?(:mod_code).should be_true }
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe ModCode do
3
+ describe D3MPQ::ModCode do
4
4
  io = File.open("spec/fixtures/CoreData/GameBalance/AffixList.gam")
5
5
 
6
6
  # TODO: We use Affixes as example ModCodes, change this
@@ -13,7 +13,7 @@ describe D3MPQ::CoreData::GameBalance::AffixList do
13
13
  its(:rest) { should == "" }
14
14
 
15
15
  describe "content#mod_codes" do
16
- specify { mod_codes.should be_kind_of(ModCodes) }
16
+ specify { mod_codes.should be_kind_of(D3MPQ::ModCodes) }
17
17
  end
18
18
  end
19
19
 
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+
3
+ describe D3MPQ::CoreData::GameBalance::MonsterLevels do
4
+ let(:io) { File.open("spec/fixtures/CoreData/GameBalance/MonsterLevels.gam") }
5
+
6
+ before(:all) do
7
+ subject.read(io)
8
+ # BinData::trace_reading { subject.read(io) }
9
+ end
10
+
11
+ its(:variable_content) { subject.size.should == 0 }
12
+ its(:rest) { should == "" }
13
+ end
14
+
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+
3
+ describe D3MPQ::CoreData::GameBalance::RareNames do
4
+ let(:io) { File.open("spec/fixtures/CoreData/GameBalance/RareNames.gam") }
5
+
6
+ before(:all) do
7
+ subject.read(io)
8
+ # BinData::trace_reading { subject.read(io) }
9
+ end
10
+
11
+ its(:variable_content) { subject.size.should == 0 }
12
+ its(:rest) { should == "" }
13
+ end
14
+
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe D3MPQ::CSVGenerator::ExperienceTable do
4
+ let(:dir) { "spec/fixtures/CoreData/GameBalance/ExperienceTable.gam" }
5
+
6
+ specify "#write" do
7
+ subject.files = dir
8
+ subject.write
9
+ end
10
+ end
11
+
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe D3MPQ::CSVGenerator::MonsterAffixes do
4
+ let(:dir) { "spec/fixtures/CoreData/GameBalance/MonsterAffixes.gam" }
5
+
6
+ specify "#write" do
7
+ subject.files = dir
8
+ subject.write
9
+ end
10
+ end
11
+
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe D3MPQ::CSVGenerator::MonsterLevels do
4
+ let(:dir) { "spec/fixtures/CoreData/GameBalance/MonsterLevels.gam" }
5
+
6
+ specify "#write" do
7
+ subject.files = dir
8
+ subject.write
9
+ end
10
+ end
11
+
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe D3MPQ::CSVGenerator::MonsterNames do
4
+ let(:dir) { "spec/fixtures/CoreData/GameBalance/MonsterNames.gam" }
5
+
6
+ specify "#write" do
7
+ subject.files = dir
8
+ subject.write
9
+ end
10
+ end
11
+
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe D3MPQ::CSVGenerator::PowerFormulaTables do
4
+ let(:dir) { "spec/fixtures/CoreData/GameBalance/PowerFormulaTables.gam" }
5
+
6
+ specify "#write" do
7
+ subject.files = dir
8
+ subject.write
9
+ end
10
+ end
11
+
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe D3MPQ::CSVGenerator::RareNames do
4
+ let(:dir) { "spec/fixtures/CoreData/GameBalance/RareNames.gam" }
5
+
6
+ specify "#write" do
7
+ subject.files = dir
8
+ subject.write
9
+ end
10
+ end
11
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: d3_mpq
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.11
4
+ version: 0.0.13
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2012-05-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bindata
16
- requirement: &69007620 !ruby/object:Gem::Requirement
16
+ requirement: &78792250 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *69007620
24
+ version_requirements: *78792250
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: nokogiri
27
- requirement: &69007210 !ruby/object:Gem::Requirement
27
+ requirement: &78792030 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *69007210
35
+ version_requirements: *78792030
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rspec
38
- requirement: &69006860 !ruby/object:Gem::Requirement
38
+ requirement: &78791800 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *69006860
46
+ version_requirements: *78791800
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: guard
49
- requirement: &69006500 !ruby/object:Gem::Requirement
49
+ requirement: &78791480 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *69006500
57
+ version_requirements: *78791480
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: guard-rspec
60
- requirement: &69006110 !ruby/object:Gem::Requirement
60
+ requirement: &78791160 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *69006110
68
+ version_requirements: *78791160
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: libnotify
71
- requirement: &69005780 !ruby/object:Gem::Requirement
71
+ requirement: &78790910 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,7 +76,7 @@ dependencies:
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *69005780
79
+ version_requirements: *78790910
80
80
  description: Parsing data out of Diablo 3.
81
81
  email:
82
82
  - deradon87@gmail.com
@@ -88,6 +88,7 @@ files:
88
88
  - bin/d3_mpq
89
89
  - lib/d3_mpq/commands/csv.rb
90
90
  - lib/d3_mpq/commands/extract.rb
91
+ - lib/d3_mpq/mod_codes.rb
91
92
  - lib/d3_mpq/csv_generator.rb
92
93
  - lib/d3_mpq/core_data/game_balance.rb
93
94
  - lib/d3_mpq/core_data/game_balance/item_types.rb
@@ -101,9 +102,11 @@ files:
101
102
  - lib/d3_mpq/core_data/game_balance/monster_names.rb
102
103
  - lib/d3_mpq/core_data/game_balance/elite_modifiers.rb
103
104
  - lib/d3_mpq/core_data/game_balance/affix_list.rb
105
+ - lib/d3_mpq/core_data/game_balance/monster_levels.rb
104
106
  - lib/d3_mpq/core_data/game_balance/labels_global.rb
105
107
  - lib/d3_mpq/core_data/game_balance/set_item_bonuses.rb
106
108
  - lib/d3_mpq/core_data/game_balance/monster_affixes.rb
109
+ - lib/d3_mpq/core_data/game_balance/rare_names.rb
107
110
  - lib/d3_mpq/core_data/game_balance/power_formula_tables.rb
108
111
  - lib/d3_mpq/core_data/game_balance/items.rb
109
112
  - lib/d3_mpq/core_data/actor.rb
@@ -122,16 +125,21 @@ files:
122
125
  - lib/d3_mpq/csv_generator/recipes.rb
123
126
  - lib/d3_mpq/csv_generator/socketed_effects.rb
124
127
  - lib/d3_mpq/csv_generator/string_list.rb
128
+ - lib/d3_mpq/csv_generator/experience_table.rb
125
129
  - lib/d3_mpq/csv_generator/base.rb
130
+ - lib/d3_mpq/csv_generator/monster_names.rb
126
131
  - lib/d3_mpq/csv_generator/affix_list.rb
132
+ - lib/d3_mpq/csv_generator/monster_levels.rb
127
133
  - lib/d3_mpq/csv_generator/set_item_bonuses.rb
134
+ - lib/d3_mpq/csv_generator/monster_affixes.rb
128
135
  - lib/d3_mpq/csv_generator/actor.rb
129
136
  - lib/d3_mpq/csv_generator/recipe_details.rb
137
+ - lib/d3_mpq/csv_generator/rare_names.rb
138
+ - lib/d3_mpq/csv_generator/power_formula_tables.rb
130
139
  - lib/d3_mpq/csv_generator/items.rb
131
140
  - lib/d3_mpq/version.rb~
141
+ - lib/d3_mpq/mod_code.rb
132
142
  - lib/bindata_ext/dsl.rb
133
- - lib/bindata_ext/mod_codes.rb
134
- - lib/bindata_ext/mod_code.rb
135
143
  - lib/d3_mpq.rb
136
144
  - lib/core_ext/min_max.rb
137
145
  - lib/core_ext/string.rb
@@ -6919,6 +6927,8 @@ files:
6919
6927
  - spec/unit/core_data/game_balance/monster_names_spec.rb
6920
6928
  - spec/unit/core_data/game_balance/elite_modifiers_spec.rb
6921
6929
  - spec/unit/core_data/game_balance/labels_global_spec.rb
6930
+ - spec/unit/core_data/game_balance/rare_names_spec.rb
6931
+ - spec/unit/core_data/game_balance/monster_levels_spec.rb
6922
6932
  - spec/unit/core_data/game_balance/item_enhancements_spec.rb
6923
6933
  - spec/unit/bindata_ext/mod_code_spec.rb
6924
6934
  - spec/unit/string_list_spec.rb
@@ -6928,9 +6938,15 @@ files:
6928
6938
  - spec/unit/csv_generator/item_types_spec.rb
6929
6939
  - spec/unit/csv_generator/set_item_bonuses_spec.rb
6930
6940
  - spec/unit/csv_generator/recipe_details_spec.rb
6941
+ - spec/unit/csv_generator/experience_table_spec.rb
6942
+ - spec/unit/csv_generator/power_formula_spec.rb
6931
6943
  - spec/unit/csv_generator/string_list_spec.rb
6944
+ - spec/unit/csv_generator/monster_names_spec.rb
6945
+ - spec/unit/csv_generator/monster_affixes.rb
6932
6946
  - spec/unit/csv_generator/item_spec.rb
6947
+ - spec/unit/csv_generator/rare_names_spec.rb
6933
6948
  - spec/unit/csv_generator/csv_generator_spec.rb
6949
+ - spec/unit/csv_generator/monster_levels_spec.rb
6934
6950
  - spec/unit/csv_generator/item_enhancements_spec.rb
6935
6951
  - spec/unit/analyzer_spec.rb
6936
6952
  - spec/unit/recipe_spec.rb
@@ -13743,6 +13759,8 @@ test_files:
13743
13759
  - spec/unit/core_data/game_balance/monster_names_spec.rb
13744
13760
  - spec/unit/core_data/game_balance/elite_modifiers_spec.rb
13745
13761
  - spec/unit/core_data/game_balance/labels_global_spec.rb
13762
+ - spec/unit/core_data/game_balance/rare_names_spec.rb
13763
+ - spec/unit/core_data/game_balance/monster_levels_spec.rb
13746
13764
  - spec/unit/core_data/game_balance/item_enhancements_spec.rb
13747
13765
  - spec/unit/bindata_ext/mod_code_spec.rb
13748
13766
  - spec/unit/string_list_spec.rb
@@ -13752,9 +13770,15 @@ test_files:
13752
13770
  - spec/unit/csv_generator/item_types_spec.rb
13753
13771
  - spec/unit/csv_generator/set_item_bonuses_spec.rb
13754
13772
  - spec/unit/csv_generator/recipe_details_spec.rb
13773
+ - spec/unit/csv_generator/experience_table_spec.rb
13774
+ - spec/unit/csv_generator/power_formula_spec.rb
13755
13775
  - spec/unit/csv_generator/string_list_spec.rb
13776
+ - spec/unit/csv_generator/monster_names_spec.rb
13777
+ - spec/unit/csv_generator/monster_affixes.rb
13756
13778
  - spec/unit/csv_generator/item_spec.rb
13779
+ - spec/unit/csv_generator/rare_names_spec.rb
13757
13780
  - spec/unit/csv_generator/csv_generator_spec.rb
13781
+ - spec/unit/csv_generator/monster_levels_spec.rb
13758
13782
  - spec/unit/csv_generator/item_enhancements_spec.rb
13759
13783
  - spec/unit/analyzer_spec.rb
13760
13784
  - spec/unit/recipe_spec.rb
@@ -1,194 +0,0 @@
1
- class ModCode < BinData::Record
2
- endian :little
3
-
4
- uint32 :mod_code
5
-
6
- uint32 :mod_param1
7
- uint32 :mod_param2
8
- uint32 :mod_param3
9
-
10
- uint32 :mod_offset
11
- uint32 :mod_length
12
-
13
- # Returns: nil if mod_code is 0xFFFFFFFF, mod_code otherwise
14
- def id
15
- self.mod_code == 0xFFFFFFFF ? nil : self.mod_code.to_i
16
- end
17
-
18
- # HACK
19
- # Returns: Instance of BinData::Record that respond to :variable_content
20
- def base
21
- parent.parent.parent.parent
22
- end
23
-
24
- def index
25
- (mod_offset - base.data_num_bytes - base.data_offset) / 4
26
- end
27
-
28
- def count
29
- mod_length / 4
30
- end
31
-
32
- def data
33
- base.variable_content[index, count]
34
- end
35
-
36
- def empty?
37
- mod_length == 0
38
- end
39
-
40
- def min
41
- stack.min || 0.0
42
- end
43
-
44
- def max
45
- stack.max || 0.0
46
- end
47
-
48
- def trace
49
- stack.trace
50
- end
51
-
52
- def stack
53
- @stack ||= Stack.new(data)
54
- end
55
-
56
- private
57
-
58
- # Pseudo-Stack to compute min/max of current ModCode
59
- class Stack
60
- attr_reader :value, :trace
61
-
62
- def initialize(data)
63
- @stack = []
64
- @trace = []
65
- @data = *data
66
- @value = nil
67
- parse
68
- end
69
-
70
- def min
71
- @value ? @value.min : nil
72
- end
73
-
74
- def max
75
- @value ? @value.max : nil
76
- end
77
-
78
- def push(item)
79
- @stack.push item
80
- end
81
-
82
- def pop
83
- @stack.pop
84
- end
85
-
86
- def peek
87
- @stack.last
88
- end
89
-
90
- def count
91
- @stack.length
92
- end
93
-
94
- def empty?
95
- count == 0
96
- end
97
-
98
- # Lets go
99
- def parse
100
- return @value if @value
101
- return nil if @data.empty?
102
-
103
- next_op = true
104
- @data.each_with_index do |dword, index|
105
- next_op = true and next unless next_op
106
-
107
- case dword.bytes.first
108
- when 0x00
109
- # return the value at the top of the stack
110
- raise "Return found, but Stack not empty!" if @data[index+1]
111
- @value = pop
112
- return @value
113
- when 0x01
114
- # call the function of the next op-code (just pass here)
115
- when 0x03
116
- # rand1(A,B); pop 2 numbers and push a random value between A and A+B
117
- op { |a, b| ["rand", a, a + b] }
118
- when 0x04
119
- # rand2(A,B); pop 2 numbers and push a random value between A and B
120
- op { |a, b| ["rand2", a, b] }
121
- when 0x06
122
- # push the next DWord onto the stack
123
- v = @data[index+1].unpack('F').first
124
- push(StackValue.new(v))
125
- @trace << "#{v}"
126
- next_op = false
127
- when 0x0B
128
- # add(A,B); pop 2 numbers and push the sum
129
- op { |a, b| ["add", (a + b)] }
130
- when 0x0C
131
- # sub(A,B); pop 2 numbers and push the difference
132
- op { |a, b| ["sub", (a - b)] }
133
- when 0x0D
134
- # mul(A,B); pop 2 numbers and push the product
135
- op { |a, b| ["mul", (a * b)] }
136
- when 0x0E
137
- # div(A,B); pop 2 numbers and push the quotient
138
- op { |a, b| ["div", (a / b)] }
139
- else
140
- raise "OP-Code not found: #{op} | #{@data.inspect}"
141
- end
142
- end
143
-
144
- raise "No return found: #{@data.inspect}"
145
- end
146
-
147
- # Perform OP-Code
148
- def op(&blk)
149
- b = pop
150
- a = pop
151
-
152
- formula, min, max = blk.call(a, b)
153
-
154
- push(StackValue.random(min, max || min))
155
- @trace << formula
156
- end
157
-
158
- def inspect
159
- { :value => @value, :trace => @trace}
160
- end
161
-
162
- # Wrapper for a Float that handles: current_value, min_value, max_value
163
- class StackValue
164
- attr_accessor :value, :min_max
165
-
166
- def self.random(min, max)
167
- StackValue.new(MinMax.new(min.min, max.max).random, min.min, max.max)
168
- end
169
-
170
- def initialize(value, min = nil, max = nil)
171
- @value = value
172
- min ||= @value
173
- @min_max = MinMax.new(min, max)
174
- end
175
-
176
- [:min, :max].each { |m| define_method(m) { min_max.send(m) } }
177
- ["-", "+", "*", "/"].each do |m|
178
- define_method(m) { |sv| with_other(sv){ |a, b| a.send(m, b) } }
179
- end
180
-
181
- def to_s
182
- (min == max) ? "#{min}" : "#{min}..#{max}"
183
- end
184
-
185
- private
186
- def with_other(oth, &block)
187
- mm = block.call(min_max, oth.min_max)
188
- v = block.call(value, oth.value)
189
- StackValue.new(v, mm.min, mm.max)
190
- end
191
- end
192
- end
193
- end
194
-
@@ -1,4 +0,0 @@
1
- class ModCodes < BinData::Array
2
- default_parameters :type => :mod_code, :initial_length => 1
3
- end
4
-