nwn-lib 0.4.6 → 0.4.7
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/CHANGELOG +35 -0
- data/Rakefile +1 -1
- data/bin/nwn-erf +22 -14
- data/bin/nwn-gff +3 -3
- data/bin/nwn-irb +1 -2
- data/lib/nwn/all.rb +0 -1
- data/lib/nwn/erf.rb +62 -14
- data/lib/nwn/gff.rb +1 -1
- data/lib/nwn/gff/reader.rb +43 -16
- data/lib/nwn/gff/writer.rb +18 -9
- data/lib/nwn/res.rb +6 -4
- data/lib/nwn/scripting.rb +2 -2
- data/lib/nwn/settings.rb +12 -0
- data/lib/nwn/twoda.rb +7 -10
- data/scripts/extract_all_items.rb +1 -1
- data/scripts/reformat_2da +1 -1
- data/spec/bin_dsl_spec.rb +36 -0
- data/spec/bin_erf_spec.rb +118 -0
- data/spec/bin_gff_spec.rb +90 -0
- data/spec/erf_spec.rb +63 -46
- data/spec/gff_spec.rb +46 -3
- data/spec/spec_helper.rb +174 -0
- data/spec/struct_spec.rb +21 -0
- data/spec/tlk_spec.rb +0 -17
- data/spec/twoda_spec.rb +0 -68
- data/spec/{wellformed_gff.binary → wellformed_gff.bic} +0 -0
- metadata +6 -4
- data/lib/nwn/helpers.rb +0 -153
data/spec/gff_spec.rb
CHANGED
@@ -1,11 +1,38 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
2
|
|
3
|
-
|
3
|
+
describe "Gff.read/write API" do
|
4
|
+
it "reads correctly" do
|
5
|
+
i = StringIO.new WELLFORMED_GFF
|
6
|
+
g = Gff.read(i, :gff)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "writes correctly" do
|
10
|
+
i = StringIO.new WELLFORMED_GFF
|
11
|
+
gff = Gff.read(i, :gff)
|
12
|
+
|
13
|
+
out = StringIO.new
|
14
|
+
ret = Gff.write(out, :gff, gff)
|
15
|
+
ret.should == out.size
|
16
|
+
end
|
17
|
+
|
18
|
+
{
|
19
|
+
:gff => %w{utc utd ute uti utm utp uts utt utw git are gic mod ifo fac ssf dlg itp bic},
|
20
|
+
:yaml => %w{yml yaml},
|
21
|
+
:kivinen => %w{k kivinen},
|
22
|
+
:marshal => %w{marshal}
|
23
|
+
}.each {|expect, arr|
|
24
|
+
arr.each {|ext|
|
25
|
+
it "guesses the file format #{expect} for extension #{ext} correctly" do
|
26
|
+
Gff.guess_file_format("xxy.#{ext}").should == expect
|
27
|
+
end
|
28
|
+
}
|
29
|
+
}
|
30
|
+
end
|
4
31
|
|
5
32
|
describe "Gff::*" do
|
6
33
|
|
7
34
|
def wellformed_verify binary
|
8
|
-
t = Gff::Reader.read(binary)
|
35
|
+
t = Gff::Reader.read(StringIO.new binary)
|
9
36
|
end
|
10
37
|
|
11
38
|
it "reads wellformed GFF data" do
|
@@ -13,10 +40,26 @@ describe "Gff::*" do
|
|
13
40
|
end
|
14
41
|
|
15
42
|
it "reproduces correct GFF binary data" do
|
16
|
-
t = Gff::Reader.read(WELLFORMED_GFF)
|
43
|
+
t = Gff::Reader.read(StringIO.new WELLFORMED_GFF)
|
17
44
|
v = Gff::Writer.dump(t)
|
18
45
|
t2 = wellformed_verify v
|
19
46
|
t2.should == t
|
20
47
|
end
|
21
48
|
|
49
|
+
it "writes to io and returns the number of written bytes" do
|
50
|
+
t = Gff::Reader.read(StringIO.new WELLFORMED_GFF)
|
51
|
+
out = StringIO.new
|
52
|
+
v = Gff::Writer.dump(t, out)
|
53
|
+
v.should == out.size
|
54
|
+
out.seek(0)
|
55
|
+
v = out.read(v)
|
56
|
+
t2 = wellformed_verify v
|
57
|
+
t2.should == t
|
58
|
+
end
|
59
|
+
|
60
|
+
it "fails on not enough data" do
|
61
|
+
proc {wellformed_verify WELLFORMED_GFF[0 .. -2] }.should
|
62
|
+
raise_error IOError, "cannot read list_indices"
|
63
|
+
end
|
64
|
+
|
22
65
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
require 'rubygems'
|
2
|
+
require 'tempfile'
|
3
|
+
require 'open3'
|
2
4
|
|
3
5
|
Thread.abort_on_exception = true
|
4
6
|
|
@@ -22,3 +24,175 @@ GffFieldValidations = {
|
|
22
24
|
:short => [[-0x8000, 0x7fff], [-0x8001, 0x7fff + 1]],
|
23
25
|
:word => [[0, 0xffff], [-1, 0xffff + 1]],
|
24
26
|
}.freeze
|
27
|
+
|
28
|
+
WELLFORMED_GFF_PATH = File.join(File.expand_path(File.dirname(__FILE__)), "wellformed_gff.bic").freeze
|
29
|
+
WELLFORMED_GFF = IO.read(WELLFORMED_GFF_PATH).freeze
|
30
|
+
|
31
|
+
WELLFORMED_ERF = ([
|
32
|
+
"HAK", "V1.0",
|
33
|
+
locstr_count = 1, locstr_size = 14,
|
34
|
+
entry_count = 3,
|
35
|
+
offset_to_locstr = 160,
|
36
|
+
offset_to_keys = offset_to_locstr + locstr_size,
|
37
|
+
offset_to_res = offset_to_locstr + locstr_size + entry_count * (16 + 4 + 2 + 2),
|
38
|
+
|
39
|
+
100, 126, # year, dayofyear
|
40
|
+
0xdeadbeef, "" #description strref, 116 bytes 0-padding
|
41
|
+
].pack("A4 A4 VV VV VV VV V a116") + [
|
42
|
+
0, 6, "abcdef" # one locstr
|
43
|
+
].pack("V V a*") + [
|
44
|
+
"resref", 0, 10, 0, # keylist: resref.txt, id = 0
|
45
|
+
"help", 1, 1, 0, # keylist: help.bmp, id = 1
|
46
|
+
"yegods", 2, 4, 0, # keylist: yegods.wav, id = 2
|
47
|
+
].pack("a16 V v v" * entry_count) + [
|
48
|
+
offset_to_res + entry_count * 8, 6, # offset, size
|
49
|
+
offset_to_res + entry_count * 8 + 6, 4, # offset, size
|
50
|
+
offset_to_res + entry_count * 8 + 6 + 4, 6, # offset, size
|
51
|
+
].pack("II" * entry_count) + [
|
52
|
+
"resref", "help", "yegods"
|
53
|
+
].pack("a* a* a*")).freeze
|
54
|
+
|
55
|
+
WELLFORMED_ERF_11 = ([
|
56
|
+
"HAK", "V1.1",
|
57
|
+
locstr_count = 1, locstr_size = 14,
|
58
|
+
entry_count = 3,
|
59
|
+
offset_to_locstr = 160,
|
60
|
+
offset_to_keys = offset_to_locstr + locstr_size,
|
61
|
+
offset_to_res = offset_to_locstr + locstr_size + entry_count * (32 + 4 + 2 + 2),
|
62
|
+
|
63
|
+
100, 126, # year, dayofyear
|
64
|
+
0xdeadbeef, "" #description strref, 116 bytes 0-padding
|
65
|
+
].pack("A4 A4 VV VV VV VV V a116") + [
|
66
|
+
0, 6, "abcdef" # one locstr
|
67
|
+
].pack("V V a*") + [
|
68
|
+
"resref", 0, 10, 0, # keylist: resref.txt, id = 0
|
69
|
+
"help", 1, 1, 0, # keylist: help.bmp, id = 1
|
70
|
+
"yegods", 2, 4, 0, # keylist: yegods.wav, id = 2
|
71
|
+
].pack("a32 V v v" * entry_count) + [
|
72
|
+
offset_to_res + entry_count * 8, 6, # offset, size
|
73
|
+
offset_to_res + entry_count * 8 + 6, 4, # offset, size
|
74
|
+
offset_to_res + entry_count * 8 + 6 + 4, 6, # offset, size
|
75
|
+
].pack("II" * entry_count) + [
|
76
|
+
"resref", "help", "yegods"
|
77
|
+
].pack("a* a* a*")).freeze
|
78
|
+
|
79
|
+
WELLFORMED_TLK = ([
|
80
|
+
"TLK", "V3.0",
|
81
|
+
language_id = 0,
|
82
|
+
string_count = 5,
|
83
|
+
offset_to_str = 21,
|
84
|
+
].pack("a4 a4 I I I") + [ # string data table
|
85
|
+
# flags, soundresref, volvariance, pitchvariance, offset_to_str, sz, soundlen
|
86
|
+
0x1, "", 0, 0, -1 + 40 * string_count, 1, 0.0,
|
87
|
+
0x3, "textsnd", 0, 0, -1 + 40 * string_count + 1, 2, 0.0,
|
88
|
+
0x7, "textsndlen", 0, 0, -1 + 40 * string_count + 3, 3, 2.0,
|
89
|
+
0x1, "", 0, 0, -1 + 40 * string_count + 6, 4, 0.0,
|
90
|
+
0x2, "justsnd", 0, 0, -1 + 40 * string_count + 10, 0, 0.0,
|
91
|
+
].pack("I A16 I I I I f" * string_count) + [
|
92
|
+
"1", "22", "333", "4444"
|
93
|
+
].join("")).freeze
|
94
|
+
|
95
|
+
TWODA_WELLFORMED = <<-EOT
|
96
|
+
2DA V2.0
|
97
|
+
|
98
|
+
Col1 Col2
|
99
|
+
0 a b
|
100
|
+
1 c d
|
101
|
+
EOT
|
102
|
+
|
103
|
+
TWODA_MISALIGNED = <<-EOT
|
104
|
+
2DA V2.0
|
105
|
+
|
106
|
+
Col1
|
107
|
+
0 a
|
108
|
+
1 b
|
109
|
+
2 c
|
110
|
+
3 d
|
111
|
+
4 e
|
112
|
+
6 f
|
113
|
+
2 g
|
114
|
+
7 h
|
115
|
+
EOT
|
116
|
+
|
117
|
+
TWODA_WHITESPACE = <<-EOT
|
118
|
+
2DA V2.0
|
119
|
+
|
120
|
+
|
121
|
+
Col1
|
122
|
+
0 4
|
123
|
+
EOT
|
124
|
+
|
125
|
+
TWODA_MISSING_COLUMN = <<-EOT
|
126
|
+
2DA V2.0
|
127
|
+
|
128
|
+
Col1 Col2 Col3
|
129
|
+
0 a1 b1 c1
|
130
|
+
1 a2 b2
|
131
|
+
EOT
|
132
|
+
|
133
|
+
TWODA_TOO_MANY_CELLS = <<-EOT
|
134
|
+
2DA V2.0
|
135
|
+
|
136
|
+
Col1
|
137
|
+
0 a1 b1 c1
|
138
|
+
1 a2 b2
|
139
|
+
2 "a2 b2 c1"
|
140
|
+
EOT
|
141
|
+
|
142
|
+
|
143
|
+
TWODA_EMPTY_AND_QUOTES = <<-EOT
|
144
|
+
2DA V2.0
|
145
|
+
|
146
|
+
Col1 Col2
|
147
|
+
0 **** b
|
148
|
+
1 c d
|
149
|
+
2 "" f
|
150
|
+
3 "g g" h
|
151
|
+
EOT
|
152
|
+
|
153
|
+
TWODA_MISSING_ID = <<-EOT
|
154
|
+
2DA V2.0
|
155
|
+
|
156
|
+
Col1
|
157
|
+
a
|
158
|
+
0 b
|
159
|
+
1 c
|
160
|
+
2 d
|
161
|
+
EOT
|
162
|
+
|
163
|
+
describe "bin helper", :shared => true do
|
164
|
+
before do
|
165
|
+
@tmp = Dir.tmpdir
|
166
|
+
end
|
167
|
+
|
168
|
+
def run_bin *va
|
169
|
+
binary = File.join(File.expand_path(File.dirname(__FILE__)), "..", "bin", subject.to_s)
|
170
|
+
incl = File.join(File.expand_path(File.dirname(__FILE__)), "..", "lib")
|
171
|
+
old = Dir.pwd
|
172
|
+
begin
|
173
|
+
Dir.chdir(@tmp)
|
174
|
+
Open3.popen3(
|
175
|
+
"ruby", "-I#{incl}",
|
176
|
+
binary,
|
177
|
+
*va
|
178
|
+
) do |i,o,e|
|
179
|
+
yield i, o, e
|
180
|
+
end
|
181
|
+
ensure
|
182
|
+
Dir.chdir(old)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def run *va
|
187
|
+
run_bin *va do |i, o, e|
|
188
|
+
e = e.read
|
189
|
+
e.should == ""
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
def run_fail *va
|
194
|
+
run_bin *va do |i, o, e|
|
195
|
+
e.read.size.should > 0
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
data/spec/struct_spec.rb
CHANGED
@@ -58,4 +58,25 @@ describe "Gff::Struct" do
|
|
58
58
|
end
|
59
59
|
}
|
60
60
|
|
61
|
+
it "returns proper fields" do
|
62
|
+
t = Gff::Reader.read(StringIO.new WELLFORMED_GFF)
|
63
|
+
t['Plot'].should respond_to :t
|
64
|
+
t['Plot'].should respond_to :l
|
65
|
+
t['Plot'].should respond_to :v
|
66
|
+
t['Plot'].l.should == "Plot"
|
67
|
+
t['Plot'].t.should == :byte
|
68
|
+
end
|
69
|
+
|
70
|
+
it "yields all and correct values in each_by_flat_path" do
|
71
|
+
t = Gff::Reader.read(StringIO.new WELLFORMED_GFF)
|
72
|
+
t.each_by_flat_path do |k,v|
|
73
|
+
k.class.should == String
|
74
|
+
k.should =~ %r{^/}
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
it "responds_to to_gff" do
|
79
|
+
t = Gff::Reader.read(StringIO.new WELLFORMED_GFF)
|
80
|
+
Gff::Reader.read(StringIO.new t.to_gff).should == t
|
81
|
+
end
|
61
82
|
end
|
data/spec/tlk_spec.rb
CHANGED
@@ -1,22 +1,5 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
2
|
|
3
|
-
WELLFORMED_TLK = ([
|
4
|
-
"TLK", "V3.0",
|
5
|
-
language_id = 0,
|
6
|
-
string_count = 5,
|
7
|
-
offset_to_str = 21,
|
8
|
-
].pack("a4 a4 I I I") + [ # string data table
|
9
|
-
# flags, soundresref, volvariance, pitchvariance, offset_to_str, sz, soundlen
|
10
|
-
0x1, "", 0, 0, -1 + 40 * string_count, 1, 0.0,
|
11
|
-
0x3, "textsnd", 0, 0, -1 + 40 * string_count + 1, 2, 0.0,
|
12
|
-
0x7, "textsndlen", 0, 0, -1 + 40 * string_count + 3, 3, 2.0,
|
13
|
-
0x1, "", 0, 0, -1 + 40 * string_count + 6, 4, 0.0,
|
14
|
-
0x2, "justsnd", 0, 0, -1 + 40 * string_count + 10, 0, 0.0,
|
15
|
-
].pack("I A16 I I I I f" * string_count) + [
|
16
|
-
"1", "22", "333", "4444"
|
17
|
-
].join("")).freeze
|
18
|
-
|
19
|
-
|
20
3
|
describe "Tlk::Tlk" do
|
21
4
|
|
22
5
|
def wellformed_verify binary
|
data/spec/twoda_spec.rb
CHANGED
@@ -1,73 +1,5 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
2
|
|
3
|
-
TWODA_WELLFORMED = <<-EOT
|
4
|
-
2DA V2.0
|
5
|
-
|
6
|
-
Col1 Col2
|
7
|
-
0 a b
|
8
|
-
1 c d
|
9
|
-
EOT
|
10
|
-
|
11
|
-
TWODA_MISALIGNED = <<-EOT
|
12
|
-
2DA V2.0
|
13
|
-
|
14
|
-
Col1
|
15
|
-
0 a
|
16
|
-
1 b
|
17
|
-
2 c
|
18
|
-
3 d
|
19
|
-
4 e
|
20
|
-
6 f
|
21
|
-
2 g
|
22
|
-
7 h
|
23
|
-
EOT
|
24
|
-
|
25
|
-
TWODA_WHITESPACE = <<-EOT
|
26
|
-
2DA V2.0
|
27
|
-
|
28
|
-
|
29
|
-
Col1
|
30
|
-
0 4
|
31
|
-
EOT
|
32
|
-
|
33
|
-
TWODA_MISSING_COLUMN = <<-EOT
|
34
|
-
2DA V2.0
|
35
|
-
|
36
|
-
Col1 Col2 Col3
|
37
|
-
0 a1 b1 c1
|
38
|
-
1 a2 b2
|
39
|
-
EOT
|
40
|
-
|
41
|
-
TWODA_TOO_MANY_CELLS = <<-EOT
|
42
|
-
2DA V2.0
|
43
|
-
|
44
|
-
Col1
|
45
|
-
0 a1 b1 c1
|
46
|
-
1 a2 b2
|
47
|
-
2 "a2 b2 c1"
|
48
|
-
EOT
|
49
|
-
|
50
|
-
|
51
|
-
TWODA_EMPTY_AND_QUOTES = <<-EOT
|
52
|
-
2DA V2.0
|
53
|
-
|
54
|
-
Col1 Col2
|
55
|
-
0 **** b
|
56
|
-
1 c d
|
57
|
-
2 "" f
|
58
|
-
3 "g g" h
|
59
|
-
EOT
|
60
|
-
|
61
|
-
TWODA_MISSING_ID = <<-EOT
|
62
|
-
2DA V2.0
|
63
|
-
|
64
|
-
Col1
|
65
|
-
a
|
66
|
-
0 b
|
67
|
-
1 c
|
68
|
-
2 d
|
69
|
-
EOT
|
70
|
-
|
71
3
|
describe TwoDA::Table do
|
72
4
|
|
73
5
|
it "parses wellformed files" do
|
File without changes
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nwn-lib
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bernhard Stoeckner
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-05-
|
12
|
+
date: 2009-05-26 00:00:00 +02:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -39,9 +39,9 @@ files:
|
|
39
39
|
- bin/nwn-gff
|
40
40
|
- bin/nwn-irb
|
41
41
|
- bin/nwn-erf
|
42
|
+
- spec/wellformed_gff.bic
|
42
43
|
- spec/gff_spec.rb
|
43
44
|
- spec/res_spec.rb
|
44
|
-
- spec/wellformed_gff.binary
|
45
45
|
- spec/spec.opts
|
46
46
|
- spec/erf_spec.rb
|
47
47
|
- spec/field_spec.rb
|
@@ -49,7 +49,10 @@ files:
|
|
49
49
|
- spec/struct_spec.rb
|
50
50
|
- spec/spec_helper.rb
|
51
51
|
- spec/tlk_spec.rb
|
52
|
+
- spec/bin_dsl_spec.rb
|
53
|
+
- spec/bin_gff_spec.rb
|
52
54
|
- spec/rcov.opts
|
55
|
+
- spec/bin_erf_spec.rb
|
53
56
|
- spec/twoda_spec.rb
|
54
57
|
- lib/nwn
|
55
58
|
- lib/nwn/scripting.rb
|
@@ -62,7 +65,6 @@ files:
|
|
62
65
|
- lib/nwn/res.rb
|
63
66
|
- lib/nwn/kivinen.rb
|
64
67
|
- lib/nwn/all.rb
|
65
|
-
- lib/nwn/helpers.rb
|
66
68
|
- lib/nwn/gff
|
67
69
|
- lib/nwn/gff/field.rb
|
68
70
|
- lib/nwn/gff/reader.rb
|
data/lib/nwn/helpers.rb
DELETED
@@ -1,153 +0,0 @@
|
|
1
|
-
require 'nwn/gff'
|
2
|
-
require 'nwn/twoda'
|
3
|
-
|
4
|
-
module NWN
|
5
|
-
module Gff
|
6
|
-
|
7
|
-
module Helpers
|
8
|
-
# This sets up the IPRP cache. Used internally; no need to call this yourself.
|
9
|
-
def self._ip_cache_setup #:nodoc:
|
10
|
-
return if defined? @costtables
|
11
|
-
@costtables = {}
|
12
|
-
@paramtables = {}
|
13
|
-
@costtable_index = NWN::TwoDA::Cache.get('iprp_costtable')
|
14
|
-
@paramtable_index = NWN::TwoDA::Cache.get('iprp_paramtable')
|
15
|
-
@costtable_index.by_col('Name').each_with_index {|p,idx|
|
16
|
-
next if @costtables[p.downcase]
|
17
|
-
@costtables[p.downcase] = @costtables[idx] = NWN::TwoDA::Cache.get(p.downcase)
|
18
|
-
}
|
19
|
-
@paramtable_index.by_col('TableResRef').each_with_index {|p,idx|
|
20
|
-
next if @paramtables[p.downcase]
|
21
|
-
@paramtables[p.downcase] = @paramtables[idx] = NWN::TwoDA::Cache.get(p.downcase)
|
22
|
-
}
|
23
|
-
@properties = NWN::TwoDA::Cache.get('itemprops')
|
24
|
-
@propdef = NWN::TwoDA::Cache.get('itempropdef')
|
25
|
-
@subtypes = []
|
26
|
-
@propdef.by_col('SubTypeResRef').each_with_index {|st, idx|
|
27
|
-
@subtypes[idx] = NWN::TwoDA::Cache.get(st.downcase) if st != "****"
|
28
|
-
}
|
29
|
-
@prop_id_to_costtable = []
|
30
|
-
@propdef.by_col('CostTableResRef').each_with_index {|st, idx|
|
31
|
-
@prop_id_to_costtable[idx] = st.to_i if st != "****"
|
32
|
-
}
|
33
|
-
@prop_id_to_param1 = []
|
34
|
-
@propdef.by_col('Param1ResRef').each_with_index {|st, idx|
|
35
|
-
@prop_id_to_param1[idx] = st.to_i if st != "****"
|
36
|
-
}
|
37
|
-
end
|
38
|
-
|
39
|
-
def self.resolve_or_match_partial name_spec, list #:nodoc:
|
40
|
-
name_spec = name_spec.downcase
|
41
|
-
|
42
|
-
raise ArgumentError, "?-expand: #{list.inspect}" if name_spec == '?'
|
43
|
-
|
44
|
-
list.each {|l|
|
45
|
-
return l if l.downcase == name_spec
|
46
|
-
}
|
47
|
-
|
48
|
-
substrings = list.select {|l| l.downcase.index(name_spec) }
|
49
|
-
if substrings.size == 1
|
50
|
-
return substrings[0]
|
51
|
-
elsif substrings.size > 1
|
52
|
-
raise ArgumentError, "Cannot resolve #{name_spec}. Partial matches: #{substrings.inspect}."
|
53
|
-
end
|
54
|
-
|
55
|
-
raise ArgumentError, "Cannot resolve #{name_spec}."
|
56
|
-
end
|
57
|
-
|
58
|
-
# This creates a NWN::Gff::Struct describing the item property in question.
|
59
|
-
#
|
60
|
-
# [+name+] The iprp name to resolve, for example <tt>Damage_Bonus_vs_Racial_Group</tt>
|
61
|
-
# [+subtype+] The iprp subtype, for example <tt>Elf</tt>
|
62
|
-
# [+value+] The iprp value, for example <tt>2d12</tt>
|
63
|
-
# [+param+] The iprp param1, for example <tt>Acid</tt>
|
64
|
-
# [+chance+] The iprp appearance chance (whats this?)
|
65
|
-
#
|
66
|
-
# Depends on the 2da cache set up correctly.
|
67
|
-
#
|
68
|
-
# Note that the given arguments can be resolved with partial matches as well, as long
|
69
|
-
# as they are unique. (<tt>Fir -> Fire</tt>)
|
70
|
-
#
|
71
|
-
# Arguments are case-insensitive.
|
72
|
-
def self.item_property name, subtype = nil, value = nil, param1 = nil, chance_appear = 100
|
73
|
-
self._ip_cache_setup
|
74
|
-
|
75
|
-
struct = NWN::Gff::Struct.new
|
76
|
-
|
77
|
-
name = resolve_or_match_partial name, @properties.by_col('Label')
|
78
|
-
index = @properties.by_col('Label').index(name)
|
79
|
-
raise ArgumentError, "Cannot find property #{name}" unless index
|
80
|
-
|
81
|
-
raise ArgumentError, "Property #{name} needs subtype of type #{NWN::TwoDA::Cache.get('itempropdef').by_col('SubTypeResRef', index)}, but none given." if
|
82
|
-
@subtypes[index] && !subtype
|
83
|
-
raise ArgumentError, "Property #{name} does not need subtype, but subtype given." if
|
84
|
-
!@subtypes[index] && subtype
|
85
|
-
|
86
|
-
subindex = 255
|
87
|
-
|
88
|
-
if subtype
|
89
|
-
subtype = resolve_or_match_partial subtype, @subtypes[index].by_col('Label')
|
90
|
-
|
91
|
-
subindex = @subtypes[index].by_col('Label').index(subtype)
|
92
|
-
raise ArgumentError, "Cannot find subtype #{subtype} for property #{name}" unless
|
93
|
-
subindex
|
94
|
-
|
95
|
-
raise ArgumentError, "Property #{name} requires a cost value of type #{@costtable_index.by_row(@prop_id_to_costtable[index], 'Name')}, but none given" if
|
96
|
-
!value && @prop_id_to_costtable[index]
|
97
|
-
raise ArgumentError, "Property #{name} does not require a cost value, but value given" if
|
98
|
-
value && !@prop_id_to_costtable[index]
|
99
|
-
end
|
100
|
-
|
101
|
-
_cost = 255
|
102
|
-
_cost_value = 0
|
103
|
-
|
104
|
-
if value
|
105
|
-
ct = @prop_id_to_costtable[index]
|
106
|
-
value = resolve_or_match_partial value, @costtables[ct.to_i].by_col('Label')
|
107
|
-
|
108
|
-
costvalue = @costtables[ct.to_i].by_col('Label').index(value)
|
109
|
-
raise ArgumentError, "Cannot find CostValue for #{value}" unless costvalue
|
110
|
-
_cost = ct
|
111
|
-
_cost_value = costvalue
|
112
|
-
end
|
113
|
-
struct.merge!({
|
114
|
-
'CostTable' => Element.new('CostTable', :byte, _cost),
|
115
|
-
'CostValue' => Element.new('CostValue', :word, _cost_value)
|
116
|
-
})
|
117
|
-
|
118
|
-
|
119
|
-
raise ArgumentError, "Property #{name} requires a param1 value of type #{@paramtable_index.by_row(@prop_id_to_param1[index], 'TableResRef')}, but none given" if
|
120
|
-
!param1 && @prop_id_to_param1[index]
|
121
|
-
raise ArgumentError, "Property #{name} does not require a param1 value, but value given" if
|
122
|
-
param1 && !@prop_id_to_param1[index]
|
123
|
-
|
124
|
-
_param1 = 255
|
125
|
-
_param1_value = 0
|
126
|
-
|
127
|
-
if param1
|
128
|
-
pt = @prop_id_to_param1[index]
|
129
|
-
param1 = resolve_or_match_partial param1, @paramtables[pt.to_i].by_col('Label')
|
130
|
-
|
131
|
-
param1value = @paramtables[pt.to_i].by_col('Label').index(param1)
|
132
|
-
raise ArgumentError, "Cannot find Param1 for #{param1}" unless param1value
|
133
|
-
_param1 = pt
|
134
|
-
_param1_value = param1value
|
135
|
-
end
|
136
|
-
struct.merge!({
|
137
|
-
'Param1' => Element.new('Param1', :byte, _param1),
|
138
|
-
'Param1Value' => Element.new('Param1Value', :byte, _param1_value)
|
139
|
-
})
|
140
|
-
|
141
|
-
struct.merge!({
|
142
|
-
'PropertyName' => Element.new('PropertyName', :word, index),
|
143
|
-
'Subtype' => Element.new('Subtype', :word, subindex),
|
144
|
-
'ChanceAppear' => Element.new('ChanceAppear', :byte, chance_appear)
|
145
|
-
})
|
146
|
-
|
147
|
-
struct.struct_id = 0
|
148
|
-
struct
|
149
|
-
end
|
150
|
-
|
151
|
-
end
|
152
|
-
end
|
153
|
-
end
|