d3_mpq 0.0.11 → 0.0.13
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/lib/d3_mpq/commands.rb +3 -0
- data/lib/d3_mpq/core_data/game_balance/monster_affixes.rb +11 -2
- data/lib/d3_mpq/core_data/game_balance/monster_levels.rb +15 -0
- data/lib/d3_mpq/core_data/game_balance/monster_names.rb +2 -2
- data/lib/d3_mpq/core_data/game_balance/power_formula_tables.rb +1 -1
- data/lib/d3_mpq/core_data/game_balance/rare_names.rb +15 -0
- data/lib/d3_mpq/core_data/game_balance.rb +2 -0
- data/lib/d3_mpq/csv_generator/base.rb +23 -15
- data/lib/d3_mpq/csv_generator/experience_table.rb +32 -0
- data/lib/d3_mpq/csv_generator/monster_affixes.rb +39 -0
- data/lib/d3_mpq/csv_generator/monster_levels.rb +14 -0
- data/lib/d3_mpq/csv_generator/monster_names.rb +16 -0
- data/lib/d3_mpq/csv_generator/power_formula_tables.rb +17 -0
- data/lib/d3_mpq/csv_generator/rare_names.rb +15 -0
- data/lib/d3_mpq/csv_generator.rb +6 -0
- data/lib/d3_mpq/mod_code.rb +196 -0
- data/lib/d3_mpq/mod_codes.rb +6 -0
- data/lib/d3_mpq/version.rb +1 -1
- data/lib/d3_mpq/version.rb~ +1 -1
- data/lib/d3_mpq.rb +2 -0
- data/spec/bindata_ext/mod_code_spec.rb +1 -1
- data/spec/unit/bindata_ext/mod_code_spec.rb +1 -1
- data/spec/unit/core_data/game_balance/affix_list_spec.rb +1 -1
- data/spec/unit/core_data/game_balance/monster_levels_spec.rb +14 -0
- data/spec/unit/core_data/game_balance/rare_names_spec.rb +14 -0
- data/spec/unit/csv_generator/experience_table_spec.rb +11 -0
- data/spec/unit/csv_generator/monster_affixes.rb +11 -0
- data/spec/unit/csv_generator/monster_levels_spec.rb +11 -0
- data/spec/unit/csv_generator/monster_names_spec.rb +11 -0
- data/spec/unit/csv_generator/power_formula_spec.rb +11 -0
- data/spec/unit/csv_generator/rare_names_spec.rb +11 -0
- metadata +39 -15
- data/lib/bindata_ext/mod_code.rb +0 -194
- data/lib/bindata_ext/mod_codes.rb +0 -4
data/lib/d3_mpq/commands.rb
CHANGED
@@ -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
|
@@ -4,13 +4,13 @@ module D3MPQ::CoreData::GameBalance
|
|
4
4
|
|
5
5
|
content do
|
6
6
|
zeroes
|
7
|
-
string :
|
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 :
|
13
|
+
string :name,
|
14
14
|
:read_length => 0x80,
|
15
15
|
:trim_padding => true
|
16
16
|
|
@@ -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
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
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
|
-
|
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
|
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,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
|
+
|
data/lib/d3_mpq/csv_generator.rb
CHANGED
@@ -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
|
+
|
data/lib/d3_mpq/version.rb
CHANGED
data/lib/d3_mpq/version.rb~
CHANGED
data/lib/d3_mpq.rb
CHANGED
@@ -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
|
+
|
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.
|
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: &
|
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: *
|
24
|
+
version_requirements: *78792250
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: nokogiri
|
27
|
-
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: *
|
35
|
+
version_requirements: *78792030
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: rspec
|
38
|
-
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: *
|
46
|
+
version_requirements: *78791800
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: guard
|
49
|
-
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: *
|
57
|
+
version_requirements: *78791480
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: guard-rspec
|
60
|
-
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: *
|
68
|
+
version_requirements: *78791160
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: libnotify
|
71
|
-
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: *
|
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
|
data/lib/bindata_ext/mod_code.rb
DELETED
@@ -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
|
-
|