diff options
Diffstat (limited to '')
-rw-r--r-- | worldmap_gen.rb | 275 |
1 files changed, 275 insertions, 0 deletions
diff --git a/worldmap_gen.rb b/worldmap_gen.rb new file mode 100644 index 0000000..c8013e3 --- /dev/null +++ b/worldmap_gen.rb @@ -0,0 +1,275 @@ +require 'rexml/document' + +doc = nil +File::open("TestMap.xml") do |f| + doc = REXML::Document.new(f.read) +end + +class Exit + attr_accessor :path + attr_accessor :reverse + + def initialize(element) + @path = element.attribute('to').value + @reverse = false + + unless element.attribute('reverse').nil? + @reverse = true + end + end +end + +class Point + attr_accessor :exits + attr_accessor :type + attr_accessor :params + attr_accessor :position + attr_reader :id + + def initialize(element) + @exits = {} + @type = '' + @params = [0,0,0,0] + @position = [0,0,0] + + position = element.attribute 'position' + @position = position.value.split(',').collect { |v| v.to_f } + + type = element.attribute 'type' + params = element.attribute 'params' + + @type = type.value unless type.nil? + @params = params.value.split(',').collect { |v| v.to_i } unless params.nil? + + element.each_element 'exit' do |e| + @exits[e.attribute('direction').value] = Exit.new(e) + end + + @id = $point_id + $point_id += 1 + end +end + +class Segment + attr_accessor :start_pos + attr_accessor :end_pos + attr_accessor :speed + attr_accessor :anim + attr_accessor :anim_speed + attr_accessor :direction, :same_dir + attr_reader :id + # todo: actions + + def initialize(element) + @start_pos = element.attribute('from').value.split(',').collect { |v| v.to_f } + @end_pos = element.attribute('to').value.split(',').collect { |v| v.to_f } + + @speed = 4.5 + speed = element.attribute 'speed' + unless speed.nil? + @speed = speed.value.to_f + end + + @anim = 'run' + @anim_speed = 2.0 + + anim = element.attribute 'animation' + unless anim.nil? + @anim = anim.value + end + + anim_speed = element.attribute 'animation_speed' + unless anim_speed.nil? + @anim_speed = anim_speed.value.to_f + end + + @direction = nil + direction = element.attribute 'direction' + unless direction.nil? + val = direction.value + if val == 'last' + @direction = nil + elsif val == 'up' + @direction = 270 + elsif val == 'right' + @direction = 0 + elsif val == 'left' + @direction = 180 + elsif val == 'down' + @direction = 90 + else + @direction = val.to_f + end + else + #p @start_pos + #p @end_pos + if @start_pos[0] == @end_pos[0] and @start_pos[2] == @end_pos[2] + # special case + @direction = nil + else + @direction = Math.atan2(@end_pos[2]-@start_pos[2], @end_pos[0]-@start_pos[0]) + @direction *= 180 / Math::PI + end + end + + @same_dir = !(element.attribute('same_dir').nil?) + + @id = $segment_id + $segment_id += 1 + + $segments << self + end +end + +class Path + attr_accessor :segments + attr_accessor :segment_ids + attr_accessor :start_point + attr_accessor :end_point + attr_reader :id + + def initialize(element) + @start_point = element.attribute('start').value + @end_point = element.attribute('end').value + + @segments = [] + @segment_ids = [] + + element.each_element 'segment' do |e| + @segments << Segment.new(e) + @segment_ids << @segments.last.id + end + + @id = $path_id + $path_id += 1 + end +end + + + +point_types = {} +point_types[''] = 0 # default +point_types['level'] = 1 + +anim_types = {} +anim_types[''] = 1 # default + +open('player_anim_list.txt') do |f| + f.each do |line| + match = line.match /(\d+)=(.+)/ + if match + anim_types[match[2]] = match[1].to_i unless anim_types.include? match[2] + end + end +end + + +directions = {'left' => 0, 'right' => 1, 'up' => 2, 'down' => 3} + +# first, collect every point +$points = {} +$point_id = 0 + +puts "[[[ Getting points ]]]" + +doc.each_element 'map/point' do |p| + puts "Reading #{p.attribute 'name'}..." + $points[p.attribute('name').value] = Point.new(p) +end + +puts "[[[ Points done ]]]" + +# next, collect every path +$paths = {} +$path_id = 0 + +$segments = [] +$segment_id = 0 + +puts "[[[ Getting paths ]]]" + +doc.each_element 'map/path' do |p| + puts "Reading #{p.attribute 'name'}..." + $paths[p.attribute('name').value] = Path.new(p) +end + +puts "[[[ Paths done ]]]" + + +puts "Statistics: #{$points.count} points, #{$paths.count} paths, #{$segments.count} segments" + +# now write the file +File::open("TestMap.wm", "w") do |f| + f << 'NwWM' + + # calculate all this stuff + header_size = 0x24 + + path_list_offs = header_size + point_list_offs = path_list_offs + ($paths.count * 4) + segment_list_offs = point_list_offs + ($points.count * 4) + action_list_offs = segment_list_offs + ($segments.count * 4) + data_offset = action_list_offs # + ($actions.count * 4) + + f << [path_list_offs, $paths.count].pack('NN') + f << [point_list_offs, $points.count].pack('NN') + f << [segment_list_offs, $segments.count].pack('NN') + f << [action_list_offs, 0].pack('NN') + + # now work out the offsets for everything + current_offset = data_offset + $paths.each_value do |p| + f << [current_offset].pack('N') + current_offset += 0xC + (p.segments.count * 4) + end + + $points.each_value do |p| + f << [current_offset].pack('N') + current_offset += 0x40 + end + + $segments.each do |s| + f << [current_offset].pack('N') + current_offset += 0x2C + end + + # nothing for actions yet! + + # now write the data + $paths.each_value do |p| + f << [$points[p.start_point].id, $points[p.end_point].id].pack('NN') + f << [p.segments.count].pack('N') + f << p.segment_ids.pack('N*') + end + + $points.each_value do |p| + ['left', 'right', 'up', 'down'].each do |direction| + if p.exits.include? direction + e = p.exits[direction] + f << [$paths[e.path].id].pack('N') + f << [e.reverse ? 1 : 0].pack('Cxxx') + else + f << [-1,-1].pack('NN') + end + end + + f << [point_types[p.type]].pack('N') + f << p.params.pack('N*') + f << p.position.pack('g*') + end + + $segments.each do |s| + f << s.start_pos.pack('g*') + f << s.end_pos.pack('g*') + f << [s.speed].pack('g') + f << [anim_types[s.anim]].pack('N') + f << [s.anim_speed].pack('g') + if s.direction.nil? + f << [0, 1, 0].pack('nCC') + else + f << [((90.0 - s.direction) % 360) / (360.0 / 65536.0), 0, s.same_dir ? 1 : 0].pack('nCC') + end + f << [0].pack('N') + end +end + |