diff options
-rw-r--r-- | MMFullWorld.wm | bin | 1192 -> 1515 bytes | |||
-rw-r--r-- | MMFullWorld.xml | 48 | ||||
-rw-r--r-- | src/wm_map.cpp | 3 | ||||
-rw-r--r-- | src/wm_path_manager.cpp | 47 | ||||
-rw-r--r-- | src/worldmap.cpp | 1 | ||||
-rw-r--r-- | src/worldmap.h | 30 | ||||
-rw-r--r-- | src/worldmapdata.cpp | 7 | ||||
-rw-r--r-- | src/worldmapdata.h | 9 | ||||
-rw-r--r-- | worldmap_gen.rb | 112 |
9 files changed, 234 insertions, 23 deletions
diff --git a/MMFullWorld.wm b/MMFullWorld.wm Binary files differindex ce430e9..d7c30b7 100644 --- a/MMFullWorld.wm +++ b/MMFullWorld.wm diff --git a/MMFullWorld.xml b/MMFullWorld.xml index 2c87199..99e3de6 100644 --- a/MMFullWorld.xml +++ b/MMFullWorld.xml @@ -1,44 +1,44 @@ <map> - <point name="drydry" position="-266.624,61.122,244.628" type="level" params="2,9,0,0"> + <point name="drydry" position="-266.624,61.122,244.628" type="level" level="2-9"> <exit direction="up" to="drydry to columns" /> <exit direction="right" to="drydry to oasis" /> <exit direction="down" to="drydry to toadhouse" /> </point> - <!--<point name="toadhouse" position="-320.172,41.155,344.66" type="level" params="2,11,0,0">--> - <point name="toadhouse" position="-320.172,41.155,344.66" type="level" params="1,1,0,0"> + <!--<point name="toadhouse" position="-320.172,41.155,344.66" type="level" level="2-11">--> + <point name="toadhouse" position="-320.172,41.155,344.66" type="level" level="1-1"> <exit direction="up" to="drydry to toadhouse" reverse="yes" /> <exit direction="right" to="toadhouse to basement" /> <exit direction="down" to="toadhouse to basement" /> </point> - <point name="basement" position="-95.274,-35.167,385.463" type="level" params="2,14,0,0"> + <point name="basement" position="-95.274,-35.167,385.463" type="level" level="2-14"> <exit direction="left" to="toadhouse to basement" reverse="yes" /> <exit direction="down" to="toadhouse to basement" reverse="yes" /> <exit direction="up" to="basement to castle" /> </point> - <point name="columns" position="-168.286,61.122,165.593" type="level" params="2,10,0,0"> + <point name="columns" position="-168.286,61.122,165.593" type="level" level="2-10"> <exit direction="down" to="drydry to columns" reverse="yes" /> <exit direction="right" to="columns to sinkysand" /> </point> - <point name="sinkysand" position="-78.644,35.327,205.595" type="level" params="2,13,0,0"> + <point name="sinkysand" position="-78.644,35.327,205.595" type="level" level="2-13"> <exit direction="left" to="columns to sinkysand" reverse="yes" /> <exit direction="right" to="sinkysand to castle" /> </point> - <point name="gulch" position="-76.596,61.122,379.174" type="level" params="2,15,0,0"> + <point name="gulch" position="-76.596,61.122,379.174" type="level" level="2-15"> <exit direction="left" to="oasis to gulch" reverse="yes" /> <exit direction="up" to="gulch to castle" /> </point> - <point name="oasis" position="-154.073,52.178,322.023" type="level" params="2,12,0,0"> + <point name="oasis" position="-154.073,52.178,322.023" type="level" level="2-12"> <exit direction="left" to="drydry to oasis" reverse="yes" /> <exit direction="right" to="oasis to gulch" /> </point> - <point name="castle" position="-58.448,62.185,293.062" type="level" params="2,16,0,0"> + <point name="castle" position="-58.448,62.185,293.062" type="level" level="2-16"> <exit direction="up" to="sinkysand to castle" reverse="yes" /> <exit direction="left" to="basement to castle" reverse="yes" /> <exit direction="down" to="gulch to castle" reverse="yes" /> @@ -46,39 +46,51 @@ </point> - <path name="drydry to columns" start="drydry" end="columns"> + <path name="drydry to columns" start="drydry" end="columns" required="drydry_normal"> <segment from="drydry" to="columns" /> + <material>World2_PathstoColumns</material> </path> - <path name="columns to sinkysand" start="columns" end="sinkysand"> + <path name="columns to sinkysand" start="columns" end="sinkysand" required="columns_normal"> <segment from="columns" to="sinkysand" /> + <material>World2_PathstoSinky</material> </path> - <path name="sinkysand to castle" start="sinkysand" end="castle"> + <path name="sinkysand to castle" start="sinkysand" end="castle" required="sinkysand_normal"> <segment from="sinkysand" to="castle" /> + <material>World2_PathsSinkytoPyramid</material> </path> - <path name="drydry to oasis" start="drydry" end="oasis"> + <path name="drydry to oasis" start="drydry" end="oasis" required="drydry_normal"> <segment from="drydry" to="oasis" /> + <material>World2_PathstoOasis</material> </path> - <path name="oasis to gulch" start="oasis" end="gulch"> + <path name="oasis to gulch" start="oasis" end="gulch" required="oasis_normal"> <segment from="oasis" to="gulch" /> + <material>World2_PathstoDeserted</material> </path> - <path name="gulch to castle" start="gulch" end="castle"> + <path name="gulch to castle" start="gulch" end="castle" required="gulch_normal"> <segment from="gulch" to="castle" /> + <material>World2_PathsDesertedtoPyramid</material> </path> - <path name="drydry to toadhouse" start="drydry" end="toadhouse"> + <path name="drydry to toadhouse" start="drydry" end="toadhouse" required="drydry_secret"> <segment from="drydry" to="toadhouse" /> + <material>World2_PathstoToad1</material> + <material>World2_PathstoToad2</material> </path> - <path name="toadhouse to basement" start="toadhouse" end="basement"> + <path name="toadhouse to basement" start="toadhouse" end="basement" required="drydry_secret"> <segment from="toadhouse" to="basement" /> + <material>World2_PathstoPlumbing1</material> + <material>World2_PathstoPlumbing2</material> + <material>World2_PathstoPlumbing3</material> + <material>World2_PathsPlumbing</material> </path> - <path name="basement to castle" start="basement" end="castle"> + <path name="basement to castle" start="basement" end="castle" required="basement_normal"> <segment from="basement" to="castle" /> </path> </map> 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 <m_dynarray.h>
+
#include <common.h>
#include <game.h>
#include <g3dhax.h>
@@ -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<pathFadeInfo *,32> fadingPaths;
+
+ void setInitialPathVisibility();
+
+ /* Event Data - 512 events should be more than enough for everyone */
+ mDynArray_c<u16,32> 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 /(?<level_name>.+)_(?<type>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 |