void Game_Map::PlayBgm() { int parent_index = 0; int current_index = GetMapIndex(location.map_id); if ((current_index > -1) && !Data::treemap.maps[current_index].music.name.empty()) { switch(Data::treemap.maps[current_index].music_type) { case 0: // inherits music from parent parent_index = GetMapIndex(Data::treemap.maps[current_index].parent_map); if (Data::treemap.maps[parent_index].music.name != "(OFF)" && &Data::treemap.maps[parent_index].music != Game_Temp::map_bgm) { Game_Temp::map_bgm = &Data::treemap.maps[parent_index].music; Game_System::BgmPlay(*Game_Temp::map_bgm); } break; case 1: // No Change break; case 2: // specific map music if (&Data::treemap.maps[current_index].music != Game_Temp::map_bgm) { if (Game_Temp::map_bgm != NULL) { if (Data::treemap.maps[current_index].music.name == Game_Temp::map_bgm->name) { // TODO: Here the volume and pitch must be updated if the song is the same return; } } Game_Temp::map_bgm = &Data::treemap.maps[current_index].music; Game_System::BgmPlay(*Game_Temp::map_bgm); } } } }
bool Game_Map::PrepareEncounter() { if (GetEncounterRate() <= 0) { return false; } int x = Main_Data::game_player->GetX(); int y = Main_Data::game_player->GetY(); std::vector<int> encounters; GetEncountersAt(x, y, encounters); if (encounters.empty()) { // No enemies on this map :( return false; } Game_Temp::battle_terrain_id = Game_Map::GetTerrainTag(Main_Data::game_player->GetX(), Main_Data::game_player->GetY()); Game_Temp::battle_troop_id = encounters[rand() / (RAND_MAX / encounters.size() + 1)]; Game_Temp::battle_escape_mode = -1; int current_index = GetMapIndex(location.map_id); while (Data::treemap.maps[current_index].background_type == 0 && GetMapIndex(Data::treemap.maps[current_index].parent_map) != current_index) { current_index = GetMapIndex(Data::treemap.maps[current_index].parent_map); } if (Data::treemap.maps[current_index].background_type == 2) { Game_Temp::battle_background = Data::treemap.maps[current_index].background_name; } else { Game_Temp::battle_background = Data::terrains[Game_Temp::battle_terrain_id - 1].background_name; } Game_Temp::battle_calling = true; return true; }
void Game_Map::PlayBgm() { if (last_map_id == location.map_id) { // Don't change BGM when the map stayed the same // e.g. when returning from menu or teleporting on same map return; } int current_index = GetMapIndex(location.map_id); last_map_id = current_index; while (Data::treemap.maps[current_index].music_type == 0 && GetMapIndex(Data::treemap.maps[current_index].parent_map) != current_index) { current_index = GetMapIndex(Data::treemap.maps[current_index].parent_map); } if ((current_index > 0) && !Data::treemap.maps[current_index].music.name.empty()) { if (Data::treemap.maps[current_index].music_type == 1) { return; } auto& music = Data::treemap.maps[current_index].music; if (!Main_Data::game_player->IsAboard()) { Game_System::BgmPlay(music); } else { Main_Data::game_data.system.before_vehicle_music = music; } } }
void Game_Map::SetupBattle() { int x = Main_Data::game_player->GetX(); int y = Main_Data::game_player->GetY(); Game_Battle::SetTerrainId(GetTerrainTag(x, y)); Game_Temp::battle_escape_mode = -1; int current_index = GetMapIndex(location.map_id); while (Data::treemap.maps[current_index].background_type == 0 && GetMapIndex(Data::treemap.maps[current_index].parent_map) != current_index) { current_index = GetMapIndex(Data::treemap.maps[current_index].parent_map); } if (Data::treemap.maps[current_index].background_type == 2) { Game_Temp::battle_background = Data::treemap.maps[current_index].background_name; } }
UnitSyncMap SpringUnitSync::GetMapEx( const wxString& mapname ) { wxLogDebugFunc( _T("") ); int i = GetMapIndex( mapname ); ASSERT_LOGIC( i >= 0, _T("Map does not exist") ); return GetMapEx( i ); }
void Game_Map::SetupCommon(int _id) { // Execute remaining events (e.g. ones listed after a teleport) Update(); Dispose(); location.map_id = _id; // Try loading EasyRPG map files first, then fallback to normal RPG Maker std::stringstream ss; ss << "Map" << std::setfill('0') << std::setw(4) << location.map_id << ".emu"; std::string map_file = FileFinder::FindDefault(ss.str()); if (map_file.empty()) { ss.str(""); ss << "Map" << std::setfill('0') << std::setw(4) << location.map_id << ".lmu"; map = LMU_Reader::Load(FileFinder::FindDefault(ss.str()), Player::encoding); if (map.get() == NULL) { Output::ErrorStr(LcfReader::GetError()); } } else { map = LMU_Reader::LoadXml(map_file); if (map.get() == NULL) { Output::ErrorStr(LcfReader::GetError()); } } if (map->parallax_flag) { SetParallaxName(map->parallax_name); SetParallaxScroll(map->parallax_loop_x, map->parallax_loop_y, map->parallax_auto_loop_x, map->parallax_auto_loop_y, map->parallax_sx, map->parallax_sy); } else { SetParallaxName(""); } SetChipset(map->chipset_id); need_refresh = true; scroll_direction = 2; scroll_rest = 0; scroll_speed = 4; map_info.encounter_rate = Data::treemap.maps[GetMapIndex(location.map_id)].encounter_steps; for (int i = 0; i < 3; i++) vehicles[i]->Refresh(); pan_locked = false; pan_wait = false; pan_speed = 0; // Make RPG_RT happy // Otherwise current event not resumed after loading location.map_save_count = map->save_count; ResetEncounterSteps(); }
float HeightMap::InterpolateXY(uint32_t xIndex, uint32_t yIndex, float xFrac, float yFrac) const { const uint32_t indexX0Y0 = GetMapIndex(xIndex, yIndex); // (X0,Y0) const uint32_t indexX1Y0 = indexX0Y0 + 1; // (X1,Y0) const uint32_t indexX0Y1 = indexX0Y0 + def.numX; // (X0 Y1) const uint32_t indexX1Y1 = indexX0Y1 + 1; // (X1,Y1) const float xyFrac = xFrac * yFrac; return (gridHeights[indexX0Y0] * (1.0 - xFrac - yFrac + xyFrac)) + (gridHeights[indexX1Y0] * (xFrac - xyFrac)) + (gridHeights[indexX0Y1] * (yFrac - xyFrac)) + (gridHeights[indexX1Y1] * xyFrac); }
void Game_Map::PlayBgm() { int current_index = GetMapIndex(location.map_id); while (Data::treemap.maps[current_index].music_type == 0 && GetMapIndex(Data::treemap.maps[current_index].parent_map) != current_index) { current_index = GetMapIndex(Data::treemap.maps[current_index].parent_map); } if ((current_index > -1) && !Data::treemap.maps[current_index].music.name.empty()) { if (Data::treemap.maps[current_index].music_type == 1) { return; } if (&Data::treemap.maps[current_index].music != Game_Temp::map_bgm) { if (Game_Temp::map_bgm != NULL) { if (Data::treemap.maps[current_index].music.name == Game_Temp::map_bgm->name) { // TODO: Here the volume and pitch must be updated if the song is the same return; } } Game_Temp::map_bgm = &Data::treemap.maps[current_index].music; Game_System::BgmPlay(*Game_Temp::map_bgm); } } }
CWarMap::~CWarMap() { event_cancel(&m_pkBeginEvent); event_cancel(&m_pkEndEvent); event_cancel(&m_pkTimeoutEvent); event_cancel(&m_pkResetFlagEvent); sys_log(0, "WarMap::~WarMap : map index %d", GetMapIndex()); itertype(m_set_pkChr) it = m_set_pkChr.begin(); while (it != m_set_pkChr.end()) { LPCHARACTER ch = *(it++); if (ch->GetDesc()) { sys_log(0, "WarMap::~WarMap : disconnecting %s", ch->GetName()); DESC_MANAGER::instance().DestroyDesc(ch->GetDesc()); } } m_set_pkChr.clear(); }
std::vector<RPG::Encounter>& Game_Map::GetEncounterList() { return Data::treemap.maps[GetMapIndex(location.map_id)].encounters; }
RPG::MapInfo const& Game_Map::GetMapInfo() { auto idx = GetMapIndex(location.map_id); return Data::treemap.maps[idx]; }
void Game_Map::SetupCommon(int _id, bool is_load_savegame) { location.map_id = _id; // Try loading EasyRPG map files first, then fallback to normal RPG Maker std::stringstream ss; ss << "Map" << std::setfill('0') << std::setw(4) << location.map_id << ".emu"; std::string map_file = FileFinder::FindDefault(ss.str()); if (map_file.empty()) { ss.str(""); ss << "Map" << std::setfill('0') << std::setw(4) << location.map_id << ".lmu"; map_file = FileFinder::FindDefault(ss.str()); map = LMU_Reader::Load(map_file, Player::encoding); } else { map = LMU_Reader::LoadXml(map_file); } Output::Debug("Loading Map %s", ss.str().c_str()); if (map.get() == NULL) { Output::ErrorStr(LcfReader::GetError()); } refresh_type = Refresh_All; int current_index = GetMapIndex(location.map_id); ss.str(""); for (int cur = current_index; GetMapIndex(Data::treemap.maps[cur].parent_map) != cur; cur = GetMapIndex(Data::treemap.maps[cur].parent_map)) { if (cur != current_index) { ss << " < "; } ss << Data::treemap.maps[cur].name.c_str(); } Output::Debug("Tree: %s", ss.str().c_str()); if (!is_load_savegame) { for (auto& vehicle: vehicles) { vehicle->Refresh(); } } if (Main_Data::game_player->IsMoveRouteOverwritten()) pending.push_back(Main_Data::game_player.get()); pan_wait = false; auto map_save_count = map->save_count; if (Player::IsRPG2k3() && map->save_count_2k3e > 0) { map_save_count = map->save_count_2k3e; } //When loading a save game and versions have changed, we need to reset the running events. if (is_load_savegame) { if (location.map_save_count != map_save_count) { Main_Data::game_data.common_events = {}; Main_Data::game_data.events = {}; Main_Data::game_data.map_info.events = {}; Main_Data::game_data.panorama = {}; } else if (location.database_save_count != Data::system.save_count) { Main_Data::game_data.common_events = {}; } } // Update the save counts so that if the player saves the game // events will properly resume upon loading. location.map_save_count = map_save_count; location.database_save_count = Data::system.save_count; }
void Game_Map::Setup(int _id) { Dispose(); first_frame = true; SetupCommon(_id, false); map_info.encounter_rate = GetMapInfo().encounter_steps; SetEncounterSteps(0); reset_panorama_x_on_next_init = true; reset_panorama_y_on_next_init = true; panorama = {}; Parallax::ClearChangedBG(); SetChipset(map->chipset_id); for (size_t i = 0; i < map_info.lower_tiles.size(); i++) { map_info.lower_tiles[i] = i; } for (size_t i = 0; i < map_info.upper_tiles.size(); i++) { map_info.upper_tiles[i] = i; } events.reserve(map->events.size()); for (const RPG::Event& ev : map->events) { events.emplace_back(location.map_id, ev); } // pan_state does not reset when you change maps. location.pan_speed = default_pan_speed; location.pan_finish_x = default_pan_x; location.pan_finish_y = default_pan_y; location.pan_current_x = default_pan_x; location.pan_current_y = default_pan_y; // Save allowed int current_index = GetMapIndex(location.map_id); int can_save = Data::treemap.maps[current_index].save; int can_escape = Data::treemap.maps[current_index].escape; int can_teleport = Data::treemap.maps[current_index].teleport; while (can_save == RPG::MapInfo::TriState_parent || can_escape == RPG::MapInfo::TriState_parent || can_teleport == RPG::MapInfo::TriState_parent) { int parent_index = GetMapIndex(Data::treemap.maps[current_index].parent_map); if (parent_index == 0) { // If parent is 0 and flag is parent, it's implicitly enabled. break; } if (parent_index == current_index) { Output::Warning("Map %d has parent pointing to itself!", current_index); break; } if (parent_index < 0) { Output::Warning("Map %d has invalid parent id %d!", Data::treemap.maps[current_index].parent_map); break; } current_index = parent_index; if (can_save == RPG::MapInfo::TriState_parent) { can_save = Data::treemap.maps[current_index].save; } if (can_escape == RPG::MapInfo::TriState_parent) { can_escape = Data::treemap.maps[current_index].escape; } if (can_teleport == RPG::MapInfo::TriState_parent) { can_teleport = Data::treemap.maps[current_index].teleport; } } Game_System::SetAllowSave(can_save != RPG::MapInfo::TriState_forbid); Game_System::SetAllowEscape(can_escape != RPG::MapInfo::TriState_forbid); Game_System::SetAllowTeleport(can_teleport != RPG::MapInfo::TriState_forbid); }
void HeightMap::ExtrapolateMissing() { //1: calculating the bed plane by least squares fit //2: filling in missing points //algorithm: http://www.ilikebigbits.com/blog/2015/3/2/plane-from-points float sumX = 0, sumY = 0, sumZ = 0; int n = 0; for (uint32_t iY = 0; iY < def.numY; iY++) { for (uint32_t iX = 0; iX < def.numX; iX++) { const uint32_t index = GetMapIndex(iX, iY); if (IsHeightSet(index)) { const float fX = (def.spacing * iX) + def.xMin; const float fY = (def.spacing * iY) + def.yMin; const float fZ = gridHeights[index]; n++; sumX += fX; sumY += fY; sumZ += fZ; } } } const float invN = 1.0 / float(n); const float centX = sumX * invN, centY = sumY * invN, centZ = sumZ * invN; // Calc full 3x3 covariance matrix, excluding symmetries: float xx = 0.0; float xy = 0.0; float xz = 0.0; float yy = 0.0; float yz = 0.0; float zz = 0.0; for (uint32_t iY = 0; iY < def.numY; iY++) { for (uint32_t iX = 0; iX < def.numX; iX++) { const uint32_t index = GetMapIndex(iX, iY); if (IsHeightSet(index)) { const float fX = (def.spacing * iX) + def.xMin; const float fY = (def.spacing * iY) + def.yMin; const float fZ = gridHeights[index]; const float rX = fX - centX; const float rY = fY - centY; const float rZ = fZ - centZ; xx += rX * rX; xy += rX * rY; xz += rX * rZ; yy += rY * rY; yz += rY * rZ; zz += rZ * rZ; } } } const float detZ = xx*yy - xy*xy; if (detZ <= 0) { // Not a valid plane (or a vertical one) return; } // Plane equation: ax+by+cz=d -> z = (d-(ax+by))/c float a = (yz*xy - xz*yy) / detZ; float b = (xz*xy - yz*xx) / detZ; const float invC = sqrtf(a*a + b*b + 1.0); const float normLenInv = 1.0 / invC; a *= normLenInv; b *= normLenInv; const float c = normLenInv; const float d = centX*a + centY*b + centZ*c; // Fill in the blanks for (uint32_t iY = 0; iY < def.numY; iY++) { for (uint32_t iX = 0; iX < def.numX; iX++) { const uint32_t index = GetMapIndex(iX, iY); if (!IsHeightSet(index)) { const float fX = (def.spacing * iX) + def.xMin; const float fY = (def.spacing * iY) + def.yMin; const float fZ = (d - (a * fX + b * fY)) * invC; gridHeights[index] = fZ; // fill in Z but don't mark it as set so we can always differentiate between measured and extrapolated } } } }
MapData *P_OpenMapData(const char * mapname, bool justcheck) { MapData * map = new MapData; FileReader * wadReader = nullptr; bool externalfile = !strnicmp(mapname, "file:", 5); if (externalfile) { mapname += 5; if (!FileExists(mapname)) { delete map; return NULL; } map->resource = FResourceFile::OpenResourceFile(mapname, true); wadReader = map->resource->GetReader(); } else { FString fmt; int lump_wad; int lump_map; int lump_name = -1; // Check for both *.wad and *.map in order to load Build maps // as well. The higher one will take precedence. // Names with more than 8 characters will only be checked as .wad and .map. if (strlen(mapname) <= 8) lump_name = Wads.CheckNumForName(mapname); fmt.Format("maps/%s.wad", mapname); lump_wad = Wads.CheckNumForFullName(fmt); fmt.Format("maps/%s.map", mapname); lump_map = Wads.CheckNumForFullName(fmt); if (lump_name > lump_wad && lump_name > lump_map && lump_name != -1) { int lumpfile = Wads.GetLumpFile(lump_name); int nextfile = Wads.GetLumpFile(lump_name+1); map->lumpnum = lump_name; if (lumpfile != nextfile) { // The following lump is from a different file so whatever this is, // it is not a multi-lump Doom level so let's assume it is a Build map. map->MapLumps[0].Reader = Wads.ReopenLumpReader(lump_name); if (!P_IsBuildMap(map)) { delete map; return NULL; } return map; } // This case can only happen if the lump is inside a real WAD file. // As such any special handling for other types of lumps is skipped. map->MapLumps[0].Reader = Wads.ReopenLumpReader(lump_name); strncpy(map->MapLumps[0].Name, Wads.GetLumpFullName(lump_name), 8); map->Encrypted = Wads.IsEncryptedFile(lump_name); map->InWad = true; if (map->Encrypted) { // If it's encrypted, then it's a Blood file, presumably a map. if (!P_IsBuildMap(map)) { delete map; return NULL; } return map; } int index = 0; if (stricmp(Wads.GetLumpFullName(lump_name + 1), "TEXTMAP") != 0) { for(int i = 1;; i++) { // Since levels must be stored in WADs they can't really have full // names and for any valid level lump this always returns the short name. const char * lumpname = Wads.GetLumpFullName(lump_name + i); try { index = GetMapIndex(mapname, index, lumpname, !justcheck); } catch(...) { delete map; throw; } if (index == -2) { delete map; return NULL; } if (index == ML_BEHAVIOR) map->HasBehavior = true; // The next lump is not part of this map anymore if (index < 0) break; map->MapLumps[index].Reader = Wads.ReopenLumpReader(lump_name + i); strncpy(map->MapLumps[index].Name, lumpname, 8); } } else { map->isText = true; map->MapLumps[1].Reader = Wads.ReopenLumpReader(lump_name + 1); for(int i = 2;; i++) { const char * lumpname = Wads.GetLumpFullName(lump_name + i); if (lumpname == NULL) { I_Error("Invalid map definition for %s", mapname); } else if (!stricmp(lumpname, "ZNODES")) { index = ML_GLZNODES; } else if (!stricmp(lumpname, "BLOCKMAP")) { // there is no real point in creating a blockmap but let's use it anyway index = ML_BLOCKMAP; } else if (!stricmp(lumpname, "REJECT")) { index = ML_REJECT; } else if (!stricmp(lumpname, "DIALOGUE")) { index = ML_CONVERSATION; } else if (!stricmp(lumpname, "BEHAVIOR")) { index = ML_BEHAVIOR; map->HasBehavior = true; } else if (!stricmp(lumpname, "ENDMAP")) { break; } else continue; map->MapLumps[index].Reader = Wads.ReopenLumpReader(lump_name + i); strncpy(map->MapLumps[index].Name, lumpname, 8); } } return map; } else { if (lump_map > lump_wad) { lump_wad = lump_map; } if (lump_wad == -1) { delete map; return NULL; } map->lumpnum = lump_wad; auto reader = Wads.ReopenLumpReader(lump_wad); map->resource = FResourceFile::OpenResourceFile(Wads.GetLumpFullName(lump_wad), reader, true); wadReader = map->resource->GetReader(); } } uint32_t id; // Although we're using the resource system, we still want to be sure we're // reading from a wad file. wadReader->Seek(0, FileReader::SeekSet); wadReader->Read(&id, sizeof(id)); if (id == IWAD_ID || id == PWAD_ID) { char maplabel[9]=""; int index=0; map->MapLumps[0].Reader = map->resource->GetLump(0)->NewReader(); strncpy(map->MapLumps[0].Name, map->resource->GetLump(0)->Name, 8); for(uint32_t i = 1; i < map->resource->LumpCount(); i++) { const char* lumpname = map->resource->GetLump(i)->Name; if (i == 1 && !strnicmp(lumpname, "TEXTMAP", 8)) { map->isText = true; map->MapLumps[ML_TEXTMAP].Reader = map->resource->GetLump(i)->NewReader(); strncpy(map->MapLumps[ML_TEXTMAP].Name, lumpname, 8); for(int i = 2;; i++) { lumpname = map->resource->GetLump(i)->Name; if (!strnicmp(lumpname, "ZNODES",8)) { index = ML_GLZNODES; } else if (!strnicmp(lumpname, "BLOCKMAP",8)) { // there is no real point in creating a blockmap but let's use it anyway index = ML_BLOCKMAP; } else if (!strnicmp(lumpname, "REJECT",8)) { index = ML_REJECT; } else if (!strnicmp(lumpname, "DIALOGUE",8)) { index = ML_CONVERSATION; } else if (!strnicmp(lumpname, "BEHAVIOR",8)) { index = ML_BEHAVIOR; map->HasBehavior = true; } else if (!strnicmp(lumpname, "ENDMAP",8)) { return map; } else continue; map->MapLumps[index].Reader = map->resource->GetLump(i)->NewReader(); strncpy(map->MapLumps[index].Name, lumpname, 8); } } if (i>0) { try { index = GetMapIndex(maplabel, index, lumpname, !justcheck); } catch(...) { delete map; throw; } if (index == -2) { delete map; return NULL; } if (index == ML_BEHAVIOR) map->HasBehavior = true; // The next lump is not part of this map anymore if (index < 0) break; } else { strncpy(maplabel, lumpname, 8); maplabel[8]=0; } map->MapLumps[index].Reader = map->resource->GetLump(i)->NewReader(); strncpy(map->MapLumps[index].Name, lumpname, 8); } } else { // This is a Build map and not subject to WAD consistency checks. //map->MapLumps[0].Size = wadReader->GetLength(); if (!P_IsBuildMap(map)) { delete map; return NULL; } } return map; }