204 lines
7.6 KiB
Ruby
204 lines
7.6 KiB
Ruby
module DFHack
|
|
class MaterialInfo
|
|
attr_accessor :mat_type, :mat_index
|
|
attr_accessor :mode, :material, :creature, :figure, :plant, :inorganic
|
|
def initialize(what, idx=nil)
|
|
case what
|
|
when Integer
|
|
@mat_type, @mat_index = what, idx
|
|
decode_type_index
|
|
when String
|
|
decode_string(what)
|
|
else
|
|
@mat_type, @mat_index = what.mat_type, what.mat_index
|
|
decode_type_index
|
|
end
|
|
end
|
|
|
|
CREATURE_BASE = 19
|
|
FIGURE_BASE = CREATURE_BASE+200
|
|
PLANT_BASE = FIGURE_BASE+200
|
|
END_BASE = PLANT_BASE+200
|
|
|
|
# interpret the mat_type and mat_index fields
|
|
def decode_type_index
|
|
if @mat_index < 0 or @mat_type >= END_BASE
|
|
@mode = :Builtin
|
|
@material = df.world.raws.mat_table.builtin[@mat_type]
|
|
|
|
elsif @mat_type >= PLANT_BASE
|
|
@mode = :Plant
|
|
@plant = df.world.raws.plants.all[@mat_index]
|
|
@material = @plant.material[@mat_type-PLANT_BASE] if @plant
|
|
|
|
elsif @mat_type >= FIGURE_BASE
|
|
@mode = :Figure
|
|
@figure = df.world.history.figures.binsearch(@mat_index)
|
|
@creature = df.world.raws.creatures.all[@figure.race] if @figure
|
|
@material = @creature.material[@mat_type-FIGURE_BASE] if @creature
|
|
|
|
elsif @mat_type >= CREATURE_BASE
|
|
@mode = :Creature
|
|
@creature = df.world.raws.creatures.all[@mat_index]
|
|
@material = @creature.material[@mat_type-CREATURE_BASE] if @creature
|
|
|
|
elsif @mat_type > 0
|
|
@mode = :Builtin
|
|
@material = df.world.raws.mat_table.builtin[@mat_type]
|
|
|
|
elsif @mat_type == 0
|
|
@mode = :Inorganic
|
|
@inorganic = df.world.raws.inorganics[@mat_index]
|
|
@material = @inorganic.material if @inorganic
|
|
end
|
|
end
|
|
|
|
def decode_string(str)
|
|
parts = str.split(':')
|
|
case parts[0].chomp('_MAT')
|
|
when 'INORGANIC', 'STONE', 'METAL'
|
|
decode_string_inorganic(parts)
|
|
when 'PLANT'
|
|
decode_string_plant(parts)
|
|
when 'CREATURE'
|
|
if parts[3] and parts[3] != 'NONE'
|
|
decode_string_figure(parts)
|
|
else
|
|
decode_string_creature(parts)
|
|
end
|
|
when 'INVALID'
|
|
@mat_type = parts[1].to_i
|
|
@mat_index = parts[2].to_i
|
|
else
|
|
decode_string_builtin(parts)
|
|
end
|
|
end
|
|
|
|
def decode_string_inorganic(parts)
|
|
@@inorganics_index ||= (0...df.world.raws.inorganics.length).inject({}) { |h, i| h.update df.world.raws.inorganics[i].id => i }
|
|
|
|
@mode = :Inorganic
|
|
@mat_type = 0
|
|
|
|
if parts[1] and parts[1] != 'NONE'
|
|
@mat_index = @@inorganics_index[parts[1]]
|
|
raise "invalid inorganic token #{parts.join(':').inspect}" if not @mat_index
|
|
@inorganic = df.world.raws.inorganics[@mat_index]
|
|
@material = @inorganic.material
|
|
end
|
|
end
|
|
|
|
def decode_string_builtin(parts)
|
|
@@builtins_index ||= (1...df.world.raws.mat_table.builtin.length).inject({}) { |h, i| b = df.world.raws.mat_table.builtin[i] ; b ? h.update(b.id => i) : h }
|
|
|
|
@mode = :Builtin
|
|
@mat_index = -1
|
|
@mat_type = @@builtins_index[parts[0]]
|
|
raise "invalid builtin token #{parts.join(':').inspect}" if not @mat_type
|
|
@material = df.world.raws.mat_table.builtin[@mat_type]
|
|
|
|
if parts[0] == 'COAL' and parts[1]
|
|
@mat_index = ['COKE', 'CHARCOAL'].index(parts[1]) || -1
|
|
end
|
|
end
|
|
|
|
def decode_string_creature(parts)
|
|
@@creatures_index ||= (0...df.world.raws.creatures.all.length).inject({}) { |h, i| h.update df.world.raws.creatures.all[i].creature_id => i }
|
|
|
|
@mode = :Creature
|
|
|
|
if parts[1] and parts[1] != 'NONE'
|
|
@mat_index = @@creatures_index[parts[1]]
|
|
raise "invalid creature token #{parts.join(':').inspect}" if not @mat_index
|
|
@creature = df.world.raws.creatures.all[@mat_index]
|
|
end
|
|
|
|
if @creature and parts[2] and parts[2] != 'NONE'
|
|
@mat_type = @creature.material.index { |m| m.id == parts[2] }
|
|
@material = @creature.material[@mat_type]
|
|
@mat_type += CREATURE_BASE
|
|
end
|
|
end
|
|
|
|
def decode_string_figure(parts)
|
|
@mode = :Figure
|
|
@mat_index = parts[3].to_i
|
|
@figure = df.world.history.figures.binsearch(@mat_index)
|
|
raise "invalid creature histfig #{parts.join(':').inspect}" if not @figure
|
|
|
|
@creature = df.world.raws.creatures.all[@figure.race]
|
|
if parts[1] and parts[1] != 'NONE'
|
|
raise "invalid histfig race #{parts.join(':').inspect}" if @creature.creature_id != parts[1]
|
|
end
|
|
|
|
if @creature and parts[2] and parts[2] != 'NONE'
|
|
@mat_type = @creature.material.index { |m| m.id == parts[2] }
|
|
@material = @creature.material[@mat_type]
|
|
@mat_type += FIGURE_BASE
|
|
end
|
|
end
|
|
|
|
def decode_string_plant(parts)
|
|
@@plants_index ||= (0...df.world.raws.plants.all.length).inject({}) { |h, i| h.update df.world.raws.plants.all[i].id => i }
|
|
|
|
@mode = :Plant
|
|
|
|
if parts[1] and parts[1] != 'NONE'
|
|
@mat_index = @@plants_index[parts[1]]
|
|
raise "invalid plant token #{parts.join(':').inspect}" if not @mat_index
|
|
@plant = df.world.raws.plants.all[@mat_index]
|
|
end
|
|
|
|
if @plant and parts[2] and parts[2] != 'NONE'
|
|
@mat_type = @plant.material.index { |m| m.id == parts[2] }
|
|
raise "invalid plant type #{parts.join(':').inspect}" if not @mat_type
|
|
@material = @plant.material[@mat_type]
|
|
@mat_type += PLANT_BASE
|
|
end
|
|
end
|
|
|
|
# delete the caches of raws id => index used in decode_string
|
|
def self.flush_raws_cache
|
|
@@inorganics_index = @@plants_index = @@creatures_index = @@builtins_index = nil
|
|
end
|
|
|
|
def token
|
|
out = []
|
|
case @mode
|
|
when :Builtin
|
|
out << (@material ? @material.id : 'NONE')
|
|
out << (['COKE', 'CHARCOAL'][@mat_index] || 'NONE') if @material and @material.id == 'COAL' and @mat_index >= 0
|
|
when :Inorganic
|
|
out << 'INORGANIC'
|
|
out << @inorganic.id if @inorganic
|
|
when :Plant
|
|
out << 'PLANT_MAT'
|
|
out << @plant.id if @plant
|
|
out << @material.id if @plant and @material
|
|
when :Creature, :Figure
|
|
out << 'CREATURE_MAT'
|
|
out << @creature.creature_id if @creature
|
|
out << @material.id if @creature and @material
|
|
out << @figure.id.to_s if @creature and @material and @figure
|
|
else
|
|
out << 'INVALID'
|
|
out << @mat_type.to_s
|
|
out << @mat_index.to_s
|
|
end
|
|
out.join(':')
|
|
end
|
|
|
|
def to_s ; token ; end
|
|
|
|
def ===(other)
|
|
other.mat_index == mat_index and other.mat_type == mat_type
|
|
end
|
|
end
|
|
|
|
class << self
|
|
def decode_mat(what, idx=nil)
|
|
MaterialInfo.new(what, idx)
|
|
end
|
|
end
|
|
end
|