From e74f7b687c4d4196979933d73aaf54747fd0de85 Mon Sep 17 00:00:00 2001 From: Treeki Date: Fri, 17 Jun 2011 04:10:28 +0200 Subject: guess what? PATHS --- MMFullWorld.wm | Bin 1192 -> 1515 bytes MMFullWorld.xml | 48 +++++++++++++-------- src/wm_map.cpp | 3 ++ src/wm_path_manager.cpp | 47 ++++++++++++++++++++ src/worldmap.cpp | 1 + src/worldmap.h | 30 ++++++++++++- src/worldmapdata.cpp | 7 +++ src/worldmapdata.h | 9 +++- worldmap_gen.rb | 112 +++++++++++++++++++++++++++++++++++++++++++++++- 9 files changed, 234 insertions(+), 23 deletions(-) diff --git a/MMFullWorld.wm b/MMFullWorld.wm index ce430e9..d7c30b7 100644 Binary files a/MMFullWorld.wm and b/MMFullWorld.wm differ diff --git a/MMFullWorld.xml b/MMFullWorld.xml index 2c87199..99e3de6 100644 --- a/MMFullWorld.xml +++ b/MMFullWorld.xml @@ -1,44 +1,44 @@ - + - - + + - + - + - + - + - + - + @@ -46,39 +46,51 @@ - + + World2_PathstoColumns - + + World2_PathstoSinky - + + World2_PathsSinkytoPyramid - + + World2_PathstoOasis - + + World2_PathstoDeserted - + + World2_PathsDesertedtoPyramid - + + World2_PathstoToad1 + World2_PathstoToad2 - + + World2_PathstoPlumbing1 + World2_PathstoPlumbing2 + World2_PathstoPlumbing3 + World2_PathsPlumbing - + diff --git a/src/wm_map.cpp b/src/wm_map.cpp index 1fa4065..73ae1c8 100644 --- a/src/wm_map.cpp +++ b/src/wm_map.cpp @@ -48,6 +48,9 @@ int dWMMap_c::onCreate() { SpammyReport("Unlinking allocator\n"); allocator.unlink(); + SpammyReport("Loading paths\n"); + dWMPathManager_c::instance->setInitialPathVisibility(); + SpammyReport("dWMMap_c::onCreate() completed\n"); return true; } diff --git a/src/wm_path_manager.cpp b/src/wm_path_manager.cpp index d94e5be..03c11d4 100644 --- a/src/wm_path_manager.cpp +++ b/src/wm_path_manager.cpp @@ -209,3 +209,50 @@ void dWMPathManager_c::setup() { } + + +void dWMPathManager_c::setInitialPathVisibility() { + for (int i = 0; i < pathData.pathCount(); i++) { + WMPathDef *path = pathData.getPath(i); + + char **materials = path->getMaterialArray(); + u8 alphaToUse = 255; + if (path->eventRequired != 0xFFFF) { + if (!events[path->eventRequired]) + alphaToUse = 128; + } + + for (int j = 0; j < path->materialCount; j++) { + // TODO: fix this + dWMMap_c::instance->nodes[0].updateAlpha(materials[j], alphaToUse); + } + } +} + + + +void dWMPathManager_c::computeEvents() { + for (int i = 0; i < EVENT_COUNT; i++) + events[i] = false; + + SaveBlock *save = GetSaveFile()->GetBlock(-1); + + // loop through every point, and apply the event from it if necessary + for (int i = 0; i < pathData.pointCount(); i++) { + WMPathPoint *point = pathData.getPoint(i); + + if (point->type == WMPathPoint::LEVEL_TYPE) { + // TODO: check if the world/level need to be -1 or not + u32 conds = save->GetLevelCondition(point->params[0], point->params[1]); + + if (conds & COND_NORMAL && point->params[2] != -1) + events[point->params[2]] = true; + if (conds & COND_SECRET && point->params[3] != -1) + events[point->params[3]] = true; + + OSReport("checking level %d-%d with events %d,%d set them to %d,%d\n", point->params[0], point->params[1], point->params[2], point->params[3], events[point->params[2]], events[point->params[3]]); + } + } +} + + diff --git a/src/worldmap.cpp b/src/worldmap.cpp index 288d2bb..50e82c7 100644 --- a/src/worldmap.cpp +++ b/src/worldmap.cpp @@ -175,6 +175,7 @@ bool WMInit_SetupExtra(void *ptr) { // since we've got all the resources, set up the path data too wm->pathManager->setup(); + wm->pathManager->computeEvents(); // and now Player setup wm->player = (daWMPlayer_c*)CreateParentedObject(WM_PLAYER, wm, 0, 2); diff --git a/src/worldmap.h b/src/worldmap.h index ef08b99..b356bac 100644 --- a/src/worldmap.h +++ b/src/worldmap.h @@ -14,6 +14,8 @@ #define WM_DEBUGGING //#define WM_SPAMMY_DEBUGGING +#include + #include #include #include @@ -70,6 +72,9 @@ class dWMHud_c : public dBase_c { }; + +#define EVENT_COUNT 512 + class dWMPathManager_c : public dBase_c { public: dWMPathManager_c(); @@ -81,6 +86,25 @@ class dWMPathManager_c : public dBase_c { dWMPathData_c pathData; + /* Paths */ + struct pathFadeInfo { + char *materialName; + u16 currentAlpha; + u16 framesRemaining; + int delta; + }; + + mDynArray_c fadingPaths; + + void setInitialPathVisibility(); + + /* Event Data - 512 events should be more than enough for everyone */ + mDynArray_c newlyActivatedEvents; + bool events[EVENT_COUNT]; + + void computeEvents(); + + /* Movement Data/Methods */ bool isMoving; WMPathPoint *currentPoint; WMPathPoint *nextPoint; @@ -90,15 +114,17 @@ class dWMPathManager_c : public dBase_c { int currentSegmentID; bool reverseThroughPath; // direction we are going through the path - void setup(); - void startMovementTo(WMDirection direction); void moveToSegment(int id); void moveThroughPath(); + /* Other Methods */ + void setup(); + void activatePoint(); + /* Process Housekeeping */ static dWMPathManager_c *build(); static dWMPathManager_c *instance; }; diff --git a/src/worldmapdata.cpp b/src/worldmapdata.cpp index 2f23afc..a8e0cf9 100644 --- a/src/worldmapdata.cpp +++ b/src/worldmapdata.cpp @@ -48,6 +48,13 @@ bool dWMPathData_c::load(void *data) { for (int j = 0; j < thisPath->segCount; j++) { thisPath->segments[j] = header->segmentList[(u32)thisPath->segments[j]]; } + + MapReport("Path @ %p\n", thisPath); + char **materialArray = thisPath->getMaterialArray(); + MapReport("Material Array @ %p, Count is %d\n", materialArray, thisPath->materialCount); + for (int j = 0; j < thisPath->materialCount; j++) { + materialArray[j] = (char*)((u32)materialArray[j] + ptr); + } } MapReport("Fixing up point pointers [%d]\n", header->pointCount); diff --git a/src/worldmapdata.h b/src/worldmapdata.h index a436114..71071f0 100644 --- a/src/worldmapdata.h +++ b/src/worldmapdata.h @@ -102,8 +102,15 @@ struct WMPathDef { WMPathPoint *endPoint; u16 eventRequired; - u16 segCount; + u8 segCount; + u8 materialCount; WMPathSegment *segments[1]; // variable-length array + + char **getMaterialArray() { + u8 *ptr = (u8*)(this + 1); + ptr += sizeof(segments[0]) * (segCount - 1); + return (char **)ptr; + } }; diff --git a/worldmap_gen.rb b/worldmap_gen.rb index e52eefc..6169acf 100644 --- a/worldmap_gen.rb +++ b/worldmap_gen.rb @@ -5,6 +5,75 @@ File::open("#{ARGV[0]}.xml") do |f| doc = REXML::Document.new(f.read) end + +# this code is a mess + + +$events = {} +$current_event_id = 0 + +def make_event_number(name) + return $events[name] if $events.key?(name) + + puts "making event for #{name}" + + $events[name] = $current_event_id + $current_event_id += 1 + + if /(?.+)_(?normal|special)/ =~ name + raise "level #{level_name} not known" unless $points.key?(level_name) + + point = $points[level_name] + point.params[2] = $events[name] if type == 'normal' + point.params[3] = $events[name] if type == 'special' + end + + $events[name] +end + + + +class StringTable + attr_reader :size + attr_accessor :start_offset + + def initialize + @strings = [] + @offset_hash = {} + @size = 0 + @start_offset = 0 + end + + def include?(str) + @offset_hash.key? str + end + + def push(str) + return if include? str + + str = str.dup + @strings << str + @offset_hash[str] = @size + @size += str.length + 1 + end + + def offset(str) + @start_offset + @offset_hash[str] + end + + def to_a + @strings.dup + end + + def to_s + out = [] + @strings.each {|str| out << str; out << "\0" } + out.join '' + end + + alias :<< :push +end + class Exit attr_accessor :path attr_accessor :reverse @@ -41,6 +110,20 @@ class Point @type = type.value unless type.nil? @params = params.value.split(',').collect { |v| v.to_i } unless params.nil? + if @type == 'level' + level = element.attribute('level').value.split('-').map(&:to_i) + #normal_event = element.attribute('event') + #special_event = element.attribute('special_event') + + #normal_event = normal_event.nil? ? 0xFFFF : normal_event.value.to_i + #special_event = special_event.nil? ? 0xFFFF : special_event.value.to_i + + # phased those out for now + normal_event, special_event = 0xFFFF, 0xFFFF + + @params = level + [normal_event, special_event] + end + element.each_element 'exit' do |e| @exits[e.attribute('direction').value] = Exit.new(e) end @@ -143,6 +226,8 @@ class Path attr_accessor :start_point attr_accessor :end_point attr_reader :id + attr_accessor :materials + attr_accessor :event def initialize(element) @start_point = element.attribute('start').value @@ -156,6 +241,17 @@ class Path @segment_ids << @segments.last.id end + @materials = [] + element.each_element 'material' do |m| + @materials << m.get_text.value.strip + end + + event_attrib = element.attribute('required') + @event = 0xFFFFFFFF + unless event_attrib.nil? + @event = make_event_number(event_attrib.value) + end + @id = $path_id $path_id += 1 end @@ -182,6 +278,8 @@ end directions = {'left' => 0, 'right' => 1, 'up' => 2, 'down' => 3} +$string_table = StringTable.new + # first, collect every point $points = {} $point_id = 0 @@ -236,7 +334,7 @@ File::open("#{ARGV[0]}.wm", "w") do |f| current_offset = data_offset $paths.each_value do |p| f << [current_offset].pack('N') - current_offset += 0xC + (p.segments.count * 4) + current_offset += 0xC + (p.segments.count * 4) + (p.materials.count * 4) end $points.each_value do |p| @@ -250,12 +348,20 @@ File::open("#{ARGV[0]}.wm", "w") do |f| end # nothing for actions yet! + + # write the string table + $string_table.start_offset = current_offset # 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.event, p.segments.count, p.materials.count].pack('ncc') f << p.segment_ids.pack('N*') + + p.materials.each do |mat| + $string_table << mat + f << [$string_table.offset(mat)].pack('N') + end end $points.each_value do |p| @@ -287,5 +393,7 @@ File::open("#{ARGV[0]}.wm", "w") do |f| end f << [0].pack('N') end + + f << $string_table.to_s end -- cgit v1.2.3