#include "worldmap.h" dWMPathManager_c *dWMPathManager_c::instance = 0; dWMPathManager_c *dWMPathManager_c::build() { OSReport("Creating WM_PathManager\n"); void *buffer = AllocFromGameHeap1(sizeof(dWMPathManager_c)); dWMPathManager_c *c = new(buffer) dWMPathManager_c; OSReport("Created WM_PathManager @ %p\n", c); instance = c; return c; } dWMPathManager_c::dWMPathManager_c() { } int dWMPathManager_c::onCreate() { return true; } int dWMPathManager_c::onDelete() { return true; } int dWMPathManager_c::onExecute() { if (!dScNewerWorldMap_c::instance->canDoStuff()) return true; // A HACK // TODO: fix this / make it cleaner if (dScNewerWorldMap_c::instance->state != 6) return true; int heldButtons = Remocon_GetButtons(GetActiveRemocon()); int nowPressed = Remocon_GetPressed(GetActiveRemocon()); if (isMoving) { moveThroughPath(); } else { if (nowPressed & WPAD_LEFT && canUseEntrance(currentPoint->exits.asDirection.left)) startMovementTo(LEFT); else if (nowPressed & WPAD_RIGHT && canUseEntrance(currentPoint->exits.asDirection.right)) startMovementTo(RIGHT); else if (nowPressed & WPAD_UP && canUseEntrance(currentPoint->exits.asDirection.up)) startMovementTo(UP); else if (nowPressed & WPAD_DOWN && canUseEntrance(currentPoint->exits.asDirection.down)) startMovementTo(DOWN); else if (nowPressed & WPAD_TWO) activatePoint(); } return true; } bool dWMPathManager_c::canUseEntrance(WMPathEntrance &entrance) { if (!entrance.isValid()) return false; if (entrance.path->eventRequired != 0xFFFF) { if (!events[entrance.path->eventRequired]) return false; } return true; } void dWMPathManager_c::moveThroughPath() { // figure out how much to move on each step Vec from, to; if (reverseThroughPath) { from = currentSegment->end; to = currentSegment->start; } else { from = currentSegment->start; to = currentSegment->end; } Vec move; move.x = to.x - from.x; move.y = to.y - from.y; move.z = to.z - from.z; VECNormalize(&move, &move); VECScale(&move, &move, currentSegment->stepsPerFrame); daWMPlayer_c *player = daWMPlayer_c::instance; player->pos.x += move.x; player->pos.y += move.y; player->pos.z += move.z; // have we reached the end? bool xAtEnd = false; bool yAtEnd = false; bool zAtEnd = false; if (move.x > 0) { xAtEnd = (player->pos.x >= to.x); } else { xAtEnd = (player->pos.x <= to.x); } if (move.y > 0) { yAtEnd = (player->pos.y >= to.y); } else { yAtEnd = (player->pos.y <= to.y); } if (move.z > 0) { zAtEnd = (player->pos.z >= to.z); } else { zAtEnd = (player->pos.z <= to.z); } if (xAtEnd && yAtEnd && zAtEnd) { MapReport("reached end of segment %d\n", currentSegmentID); int nextSegment = currentSegmentID + (reverseThroughPath ? -1 : 1); if (nextSegment == -1 || nextSegment == currentPath->segCount) { MapReport("reached end of path\n"); currentPoint = nextPoint; player->pos = currentPoint->position; player->startAnimation(0, 1.2, 10.0, 0.0); isMoving = false; SaveBlock *save = GetSaveFile()->GetBlock(-1); //save->current_world = newPage; ? save->current_path_node = pathData.getPointID(currentPoint); dWMHud_c::instance->showPointBar(); } else { moveToSegment(nextSegment); } } } void dWMPathManager_c::startMovementTo(WMDirection direction) { isMoving = true; WMPathEntrance *thisExit = ¤tPoint->exits.asArray[direction]; MapReport("Using an exit in direction %d\n", direction); currentPath = thisExit->path; if (thisExit->isEndSide) { nextPoint = thisExit->path->startPoint; reverseThroughPath = true; moveToSegment(thisExit->path->segCount - 1); } else { nextPoint = thisExit->path->endPoint; reverseThroughPath = false; moveToSegment(0); } dWMHud_c::instance->hidePointBar(); } void dWMPathManager_c::moveToSegment(int id) { MapReport("Moving to segment %d\n", id); currentSegmentID = id; currentSegment = currentPath->segments[id]; // calculate rotation Vec from, to; if (reverseThroughPath) { from = currentSegment->end; to = currentSegment->start; } else { from = currentSegment->start; to = currentSegment->end; } MapReport("From: %f,%f,%f To: %f,%f,%f\n", from.x, from.y, from.z, to.x, to.y, to.z); daWMPlayer_c *player = daWMPlayer_c::instance; player->pos = from; // update rotation if (!currentSegment->useLastDir) { player->rot.x = 0; player->rot.y = currentSegment->direction; player->rot.z = 0; if (reverseThroughPath && !currentSegment->alwaysSameDir) { player->rot.y = ((currentSegment->direction) + 0x8000) & 0xFFFF; } } player->startAnimation(currentSegment->animationType, currentSegment->animationSpeed, 10.0, 0.0); } void dWMPathManager_c::activatePoint() { MapReport("Point activated!\n"); daWMPlayer_c::instance->startAnimation(170, 1.2, 10.0, 0.0); if (currentPoint->type == WMPathPoint::LEVEL_TYPE) { int w = currentPoint->params[0] - 1; int l = currentPoint->params[1] - 1; LevelInfo::Entry *level = dScNewerWorldMap_c::instance->levelInfo.search(w, l); dScNewerWorldMap_c::instance->startLevel(level); } } int dWMPathManager_c::onDraw() { return true; } void dWMPathManager_c::setup() { pathData.load(dScNewerWorldMap_c::instance->resMng['PATH']); SaveBlock *save = GetSaveFile()->GetBlock(-1); if (save->current_path_node >= pathData.pointCount()) { currentPoint = pathData.getPath(0)->startPoint; } else { currentPoint = pathData.getPoint(save->current_path_node); } } 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 = 92; } for (int j = 0; j < path->materialCount; j++) { // TODO: fix this dWMMap_c::instance->nodes[0].updateAlpha(materials[j], alphaToUse); } } } void dWMPathManager_c::computeEvents() { // TODO: Change this! Testing code!! for (int i = 0; i < EVENT_COUNT; i++) events[i] = true; 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] - 1, point->params[1] - 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]]); } } }