#include "koopatlas/pathmanager.h" #include "koopatlas/core.h" #include "koopatlas/hud.h" #include "koopatlas/player.h" void dWMPathManager_c::setup() { isMoving = false; currentPath = 0; reverseThroughPath = false; pathLayer = dScKoopatlas_c::instance->mapData.pathLayer; SaveBlock *save = GetSaveFile()->GetBlock(-1); // Figure out what path node to start at if (dScKoopatlas_c::instance->settings & 0x10000000) { // Start off from a "Change" u8 changeID = dScKoopatlas_c::instance->settings & 0xFF; bool found = false; for (int i = 0; i < pathLayer->nodeCount; i++) { dKPNode_s *node = pathLayer->nodes[i]; if (node->type == dKPNode_s::CHANGE && node->thisID == changeID) { found = true; currentNode = node; startMovementTo(node->getAnyExit()); } } if (!found) { OSReport("Couldn't find target node %d!\n", changeID); } } else { if (save->current_path_node >= pathLayer->nodeCount) { currentNode = pathLayer->nodes[0]; } else { currentNode = pathLayer->nodes[save->current_path_node]; } } // unlock all needed paths for (int i = 0; i < pathLayer->pathCount; i++) { dKPPath_s *path = pathLayer->paths[i]; if (path->unlockType > 0) { u32 conds = save->GetLevelCondition(path->unlockLevelNumber[0] - 1, path->unlockLevelNumber[1] - 1); if (path->unlockType == 1 && (conds & COND_NORMAL)) path->isAvailable = true; else if (path->unlockType == 2 && (conds & COND_SECRET)) path->isAvailable = true; } } } void dWMPathManager_c::execute() { int nowPressed = Remocon_GetPressed(GetActiveRemocon()); if (isMoving) { moveThroughPath(); } else { if (nowPressed & WPAD_LEFT && canUseExit(currentNode->leftExit)) startMovementTo(currentNode->leftExit); else if (nowPressed & WPAD_RIGHT && canUseExit(currentNode->rightExit)) startMovementTo(currentNode->rightExit); else if (nowPressed & WPAD_UP && canUseExit(currentNode->upExit)) startMovementTo(currentNode->upExit); else if (nowPressed & WPAD_DOWN && canUseExit(currentNode->downExit)) startMovementTo(currentNode->downExit); else if (nowPressed & WPAD_TWO) activatePoint(); } } void dWMPathManager_c::startMovementTo(dKPPath_s *path) { dWMHud_c::instance->hidePointBar(); isMoving = true; reverseThroughPath = (path->end == currentNode); currentPath = path; // calculate direction of the path short deltaX = path->end->x - path->start->x; short deltaY = path->end->y - path->start->y; u16 direction = (u16)(atan2(deltaX, deltaY) / ((M_PI * 2) / 65536.0)); if (reverseThroughPath) { direction += 0x8000; } daWMPlayer_c *player = daWMPlayer_c::instance; player->startAnimation(2, 2.0, 10.0, 0.0); player->rot.y = direction; } void dWMPathManager_c::moveThroughPath() { dKPNode_s *from, *to; from = reverseThroughPath ? currentPath->end : currentPath->start; to = reverseThroughPath ? currentPath->start : currentPath->end; Vec move = (Vec){to->x - from->x, to->y - from->y, 0}; VECNormalize(&move, &move); VECScale(&move, &move, 3.0f); daWMPlayer_c *player = daWMPlayer_c::instance; player->pos.x += move.x; player->pos.y -= move.y; // Check if we've reached the end yet if ( ((move.x > 0) ? (player->pos.x >= to->x) : (player->pos.x <= to->x)) && ((move.y > 0) ? (-player->pos.y >= to->y) : (-player->pos.y <= to->y)) ) { currentNode = to; player->pos.x = to->x; player->pos.y = -to->y; if (to->type == dKPNode_s::CHANGE) { // Go to another map isMoving = false; SaveBlock *save = GetSaveFile()->GetBlock(-1); save->current_world = dScKoopatlas_c::instance->getIndexForMapName(to->destMap); DoSceneChange(WORLD_MAP, 0x10000000 | to->foreignID, 0); } else if (to->type != dKPNode_s::PASS_THROUGH) { // Stop here player->startAnimation(0, 1.2, 10.0, 0.0); isMoving = false; SaveBlock *save = GetSaveFile()->GetBlock(-1); save->current_path_node = pathLayer->findNodeID(to); dWMHud_c::instance->showPointBar(); } else { startMovementTo(to->getOppositeExitTo(currentPath)); } } } void dWMPathManager_c::activatePoint() { if (currentNode->type == dKPNode_s::LEVEL) { daWMPlayer_c::instance->startAnimation(170, 1.2, 10.0, 0.0); int w = currentNode->levelNumber[0] - 1; int l = currentNode->levelNumber[1] - 1; dLevelInfo_c::entry_s *level = dScKoopatlas_c::instance->levelInfo.search(w, l); dScKoopatlas_c::instance->startLevel(level); } }