summaryrefslogtreecommitdiff
path: root/worldmap_gen.rb
diff options
context:
space:
mode:
Diffstat (limited to 'worldmap_gen.rb')
-rw-r--r--worldmap_gen.rb275
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
+