class NWN::Tlk::Tlk

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

Constants

DATA_ELEMENT_SIZE
HEADER_SIZE

Attributes

cache[R]
language[R]

The language_id of this Tlk.

size[R]

The number of strings this Tlk holds.

Public Class Methods

new(io) click to toggle source

Cereate

# File lib/nwn/tlk.rb, line 32
def initialize io
  @io = io

  # Read the header
  @file_type, @file_version, language_id,
    string_count, string_entries_offset =
      @io.e_read(HEADER_SIZE, "header").unpack("A4 A4 I I I")

  raise IOError, "The given IO does not describe a valid tlk table" unless
    @file_type == "TLK" && @file_version == "V3.0"

  @size = string_count
  @language = language_id
  @entries_offset = string_entries_offset

  @cache = {}
end

Public Instance Methods

[](id) click to toggle source

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.

# File lib/nwn/tlk.rb, line 57
def [](id)
  return { :text => "", :sound => "", :sound_length => 0.0, :volume_variance => 0, :pitch_variance => 0} if id == 0xffffffff

  return @cache[id] if @cache[id]

  raise ArgumentError, "No such string ID: #{id.inspect} (size: #{@size})" if id > (self.size-1) || id < 0
  seek_to = HEADER_SIZE + (id) * DATA_ELEMENT_SIZE
  @io.seek(seek_to)
  data = @io.e_read(DATA_ELEMENT_SIZE, "tlk entry = #{id}")

  flags, sound_resref, v_variance, p_variance, offset,
    size, sound_length = data.unpack("I A16 I I I I f")
  flags = flags.to_i

  @io.seek(@entries_offset + offset)
  text = @io.e_read(size, "tlk entry = #{id}, offset = #{@entries_offset + offset}")

  text = flags & 0x1 > 0 ? text : ""
  sound = flags & 0x2 > 0 ? sound_resref : ""
  sound_length = flags & 0x4 > 0 ? sound_length.to_f : 0.0

  @cache[id] = {
    :text => text, :sound => sound, :sound_length => sound_length,
    :volume_variance => v_variance, :pitch_variance => p_variance
  }
end
add(text, sound = "", sound_length = 0.0, v_variance = 0, p_variance = 0) click to toggle source

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

# File lib/nwn/tlk.rb, line 86
def add text, sound = "", sound_length = 0.0, v_variance = 0, p_variance = 0
  next_id = self.size + 1
  $stderr.puts "put in cache: #{next_id}"
  @cache[next_id] = {:text => text, :sound => sound, :sound_length => 0.0, :volume_variance => v_variance, :pitch_variance => p_variance}
  @size += 1
  next_id
end
write_to(io) click to toggle source

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

# File lib/nwn/tlk.rb, line 96
def write_to io
  header = [
    @file_type,
    @file_version,
    @language,
    self.size,
    HEADER_SIZE + (self.size) * DATA_ELEMENT_SIZE
  ].pack("A4 A4 I I I")
  io.write(header)

  offsets = []
  offset = 0
  for i in 0...@size do
    entry = self[i]
    offsets[i] = offset
    offset += entry[:text].size
  end

  entries = []
  for i in 0...@size do
    entry = self[i]
    text, sound, sound_length = entry[:text], entry[:sound], entry[:sound_length]
    flags = 0
    flags |= 0x01 if text.size > 0
    flags |= 0x02 if sound.size > 0
    flags |= 0x04 if sound_length > 0.0

    ev_s = [
      flags,
      sound, #resref
      entry[:volume_variance],
      entry[:pitch_variance],
      offsets[i],
      text.size,
      sound_length
    ].pack("I a16 I I I I f")

    io.write(ev_s)
  end

  for i in 0...@size do
    io.write(self[i][:text])
  end
end