Class NWN::Tlk::Tlk

  1. lib/nwn/tlk.rb
Parent: Object

Tlk wraps a File object that points to a .tlk file.

Methods

public class

  1. new

public instance

  1. []
  2. add
  3. highest_id
  4. write_to

Constants

HEADER_SIZE = 20
DATA_ELEMENT_SIZE = 4 + 16 + 4 + 4 + 4 + 4 + 4

Attributes

cache [R]
language [R] The language_id of this Tlk.

Public class methods

new (io)

Cereate

[show source]
    # File lib/nwn/tlk.rb, line 32
32:       def initialize io
33:         @io = io
34: 
35:         # Read the header
36:         @file_type, @file_version, language_id,
37:           string_count, string_entries_offset =
38:             @io.e_read(HEADER_SIZE, "header").unpack("A4 A4 I I I")
39: 
40:         raise IOError, "The given IO does not describe a valid tlk table" unless
41:           @file_type == "TLK" && @file_version == "V3.0"
42: 
43:         @size = string_count
44:         @language = language_id
45:         @entries_offset = string_entries_offset
46: 
47:         @cache = {}
48:       end

Public instance methods

[] (id)

Returns a TLK entry as a hash with the following keys:

:text          string: The text
:sound         string: A sound resref, or "" if no sound is specified.
:sound_length  float: Length of the given resref (or 0.0 if no sound is given).

id is the numeric offset within the Tlk, starting at 0. The maximum is Tlk#size - 1.

[show source]
    # File lib/nwn/tlk.rb, line 57
57:       def [](id)
58:         return { :text => "", :sound => "", :sound_length => 0.0, :volume_variance => 0, :pitch_variance => 0} if id == 0xffffffff
59: 
60:         return @cache[id] if @cache[id]
61: 
62:         raise ArgumentError, "No such string ID: #{id.inspect}" if id > self.highest_id || id < 0
63:         seek_to = HEADER_SIZE + (id) * DATA_ELEMENT_SIZE
64:         @io.seek(seek_to)
65:         data = @io.e_read(DATA_ELEMENT_SIZE, "tlk entry = #{id}")
66: 
67:         flags, sound_resref, v_variance, p_variance, offset,
68:           size, sound_length = data.unpack("I A16 I I I I f")
69:         flags = flags.to_i
70: 
71:         @io.seek(@entries_offset + offset)
72:         text = @io.e_read(size, "tlk entry = #{id}, offset = #{@entries_offset + offset}")
73: 
74:         text = flags & 0x1 > 0 ? text : ""
75:         sound = flags & 0x2 > 0 ? sound_resref : ""
76:         sound_length = flags & 0x4 > 0 ? sound_length.to_f : 0.0
77: 
78:         @cache[id] = {
79:           :text => text, :sound => sound, :sound_length => sound_length,
80:           :volume_variance => v_variance, :pitch_variance => p_variance
81:         }
82:       end
add (text, sound = "", sound_length = 0.0, v_variance = 0, p_variance = 0)

Add a new entry to this Tlk and return the strref given to it. To override existing entries, use tlk[][:text] = “..“

[show source]
    # File lib/nwn/tlk.rb, line 86
86:       def add text, sound = "", sound_length = 0.0, v_variance = 0, p_variance = 0
87:         next_id = self.highest_id + 1
88:         $stderr.puts "put in cache: #{next_id}"
89:         @cache[next_id] = {:text => text, :sound => sound, :sound_length => 0.0, :volume_variance => v_variance, :pitch_variance => p_variance}
90:         next_id
91:       end
highest_id ()

Return the highest ID in this Tlk table.

[show source]
    # File lib/nwn/tlk.rb, line 94
94:       def highest_id
95:         highest_cached = @cache.keys.sort[-1] || 0
96:         @size - 1 > highest_cached ? @size - 1 : highest_cached
97:       end
write_to (io)

Write this Tlk to io. Take care not to write it to the same IO object you are reading from.

[show source]
     # File lib/nwn/tlk.rb, line 101
101:       def write_to io
102:         text_block = []
103:         offsets = []
104:         offset = 0
105:         for i in 0..self.highest_id do
106:           entry = self[i]
107:           offsets[i] = offset
108:           text_block << entry[:text]
109:           offset += entry[:text].size
110:         end
111:         text_block = text_block.join("")
112: 
113:         header = [
114:           @file_type, @file_version,
115:           @language,
116:           self.highest_id + 1, HEADER_SIZE + (self.highest_id + 1) * DATA_ELEMENT_SIZE
117:         ].pack("A4 A4 I I I")
118: 
119:         entries = []
120:         for i in 0..self.highest_id do
121:           entry = self[i]
122:           text, sound, sound_length = entry[:text], entry[:sound], entry[:sound_length]
123:           flags = 0
124:           flags |= 0x01 if text.size > 0
125:           flags |= 0x02 if sound.size > 0
126:           flags |= 0x04 if sound_length > 0.0
127:           entries << [
128:             flags, sound, entry[:volume_variance], entry[:pitch_variance], offsets[i], text.size, sound_length
129:           ].pack("I a16 I I I I f")
130:         end
131:         entries = entries.join("")
132: 
133:         io.write(header)
134:         io.write(entries)
135:         io.write(text_block)
136:       end