///////////////////////////////////////////////////////////////////////////// // Name: pokemod/Map.cpp // Purpose: Define a map for the game // Author: Ben Boeckel // Modified by: Ben Boeckel // Created: Mon May 28 21:45:48 2007 // Copyright: ©2007-2008 Ben Boeckel and Nerdy Productions // Licence: // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTMap or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program. If not, see . ///////////////////////////////////////////////////////////////////////////// #include #include #include #include #include "Pokemod.h" #include "Map.h" const QStringList Map::TypeStr = QStringList() << "Outdoor" << "Dungeon" << "Building"; Map::Map(const Pokemod& par, const int _id) : Object("Map", par, _id), name(""), flyWarp(-1), type(-1) { } Map::Map(const Pokemod& par, const Map& m, const int _id) : Object("Map", par, _id) { *this = m; } Map::Map(const Pokemod& par, const QString& fname, const int _id) : Object("Map", par, _id) { load(fname, _id); } bool Map::validate() const { bool valid = true; pokemod.validationMsg(QString("---Map \"%1\" with id %2---").arg(name).arg(id), Pokemod::V_Msg); if (name == "") { pokemod.validationMsg("name is not defined"); valid = false; } if ((flyWarp != -1) && (getWarpIndex(flyWarp) == -1)) { pokemod.validationMsg("Invalid fly destination warp"); valid = false; } if (type < End) { pokemod.validationMsg("Invalid type"); valid = false; } QMap idChecker; QMap nameChecker; if (getEffectCount()) { for (QListIterator i(effects); i.hasNext(); i.next()) { if (!i.peekNext().isValid()) valid = false; if (getWidth() <= i.peekNext().getCoordinate().getX()) { pokemod.validationMsg("Invalid x coordinate"); valid = false; } if (getHeight() <= i.peekNext().getCoordinate().getY()) { pokemod.validationMsg("Invalid y coordinate"); valid = false; } ++idChecker[i.peekNext().getId()]; ++nameChecker[i.peekNext().getName()]; } for (QMapIterator i(idChecker); i.hasNext(); i.next()) { if (1 < i.value()) { pokemod.validationMsg(QString("There are %1 effects with id %2").arg(i.value()).arg(i.key())); valid = false; } } for (QMapIterator i(nameChecker); i.hasNext(); i.next()) { if (1 < i.value()) { pokemod.validationMsg(QString("There are %1 effects with the name \"%2\"").arg(i.value()).arg(i.key())); valid = false; } } idChecker.clear(); nameChecker.clear(); } else pokemod.validationMsg("There are no effects", Pokemod::V_Warn); if (getTrainerCount()) { for (QListIterator i(trainers); i.hasNext(); i.next()) { if (!i.peekNext().isValid()) valid = false; if (getWidth() <= i.peekNext().getCoordinate().getX()) { pokemod.validationMsg("Invalid x coordinate"); valid = false; } if (getHeight() <= i.peekNext().getCoordinate().getY()) { pokemod.validationMsg("Invalid y coordinate"); valid = false; } ++idChecker[i.peekNext().getId()]; ++nameChecker[i.peekNext().getName()]; } for (QMapIterator i(idChecker); i.hasNext(); i.next()) { if (1 < i.value()) { pokemod.validationMsg(QString("There are %1 trainers with id %2").arg(i.value()).arg(i.key())); valid = false; } } for (QMapIterator i(nameChecker); i.hasNext(); i.next()) { if (1 < i.value()) { pokemod.validationMsg(QString("There are %1 trainers with the name \"%2\"").arg(i.value()).arg(i.key())); valid = false; } } idChecker.clear(); nameChecker.clear(); } else pokemod.validationMsg("There are no trainers", Pokemod::V_Warn); if (getWarpCount()) { for (QListIterator i(warps); i.hasNext(); i.next()) { if (!i.peekNext().isValid()) valid = false; if (getWidth() <= i.peekNext().getCoordinate().getX()) { pokemod.validationMsg("Invalid x coordinate"); valid = false; } if (getHeight() <= i.peekNext().getCoordinate().getY()) { pokemod.validationMsg("Invalid y coordinate"); valid = false; } ++idChecker[i.peekNext().getId()]; ++nameChecker[i.peekNext().getName()]; } for (QMapIterator i(idChecker); i.hasNext(); i.next()) { if (1 < i.value()) { pokemod.validationMsg(QString("There are %1 warps with id %2").arg(i.value()).arg(i.key())); valid = false; } } for (QMapIterator i(nameChecker); i.hasNext(); i.next()) { if (1 < i.value()) { pokemod.validationMsg(QString("There are %1 warps with the name \"%2\"").arg(i.value()).arg(i.key())); valid = false; } } idChecker.clear(); nameChecker.clear(); } else { pokemod.validationMsg("There are no warps"); valid = false; } if (getWildListCount()) { for (QListIterator i(wildLists); i.hasNext(); i.next()) { if (!i.peekNext().isValid()) valid = false; ++idChecker[i.peekNext().getId()]; } for (QMapIterator i(idChecker); i.hasNext(); i.next()) { if (1 < i.value()) { pokemod.validationMsg(QString("There are %1 wild lists with id %2").arg(i.value()).arg(i.key())); valid = false; } } idChecker.clear(); } else pokemod.validationMsg("There are no effects", Pokemod::V_Warn); for (int i = 0; i < getWidth(); ++i) { for (int j = 0; j < getHeight(); ++j) { if (pokemod.getTileIndex(tiles(i, j)) == -1) { pokemod.validationMsg(QString("Invalid tile at (%1, %2)").arg(i).arg(j)); valid = false; } } } return valid; } int Map::getNewEffectId() const { int i = 0; for (; (i < getEffectCount()) && (getEffectIndex(i) != -1); ++i) ; return i; } int Map::getNewTrainerId() const { int i = 0; for (; (i < getTrainerCount()) && (getTrainerIndex(i) != -1); ++i) ; return i; } int Map::getNewWarpId() const { int i = 0; for (; (i < getWarpCount()) && (getWarpIndex(i) != -1); ++i) ; return i; } int Map::getNewWildListId() const { int i = 0; for (; (i < getWarpCount()) && (getWarpIndex(i) != -1); ++i) ; return i; } void Map::load(const QString& fname, const int _id) throw(Exception) { Ini ini(fname); if (_id == -1) ini.getValue("id", id); else id = _id; int i; int j; ini.getValue("name", name); ini.getValue("flyWarp", flyWarp); ini.getValue("type", type); ini.getValue("width", i, 0); ini.getValue("height", j, 0); tiles.resize(i, j, Frac(1, 1)); for (int i = 0; i < getWidth(); ++i) { for (int j = 0; j < getHeight(); ++j) ini.getValue(QString("tiles-%1-%2").arg(i).arg(j), tiles(i, j)); } QStringList path = pokemod.getPath().split('/'); path.removeLast(); QDir fdir(path.join("/")); effects.clear(); if (fdir.cd("effect")) { for (QStringListIterator i(fdir.entryList(QStringList("*.pini"), QDir::Files, QDir::Name)); i.hasNext(); ) newEffect(i.next()); fdir.cdUp(); } trainers.clear(); if (fdir.cd("trainer")) { for (QStringListIterator i(fdir.entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name)); i.hasNext(); ) newTrainer(QString("%1/data.pini").arg(i.next())); fdir.cdUp(); } warps.clear(); if (fdir.cd("warp")) { for (QStringListIterator i(fdir.entryList(QStringList("*.pini"), QDir::Files, QDir::Name)); i.hasNext(); ) newWarp(i.next()); fdir.cdUp(); } wildLists.clear(); if (fdir.cd("wildlist")) { for (QStringListIterator i(fdir.entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name)); i.hasNext(); ) newWildList(QString("%1/data.pini").arg(i.next())); } } void Map::save() const throw(Exception) { Ini ini; ini.addField("id", id); ini.addField("name", name); ini.addField("flyWarp", flyWarp); ini.addField("type", type); ini.addField("width", getWidth()); ini.addField("height", getHeight()); for (int i = 0; i < getWidth(); ++i) { for (int j = 0; j < getWidth(); ++j) ini.addField(QString("tiles-%1-%2").arg(i).arg(j), tiles(i, j)); } ini.save(QString("%1/map/%2/data.pini").arg(pokemod.getPath()).arg(name)); for (QListIterator i(effects); i.hasNext(); ) i.next().save(name); for (QListIterator i(trainers); i.hasNext(); ) i.next().save(name); for (QListIterator i(warps); i.hasNext(); ) i.next().save(name); for (QListIterator i(wildLists); i.hasNext(); ) i.next().save(name); } void Map::setName(const QString& n) { name = n; } void Map::setFlyWarp(const int f) throw(BoundsException) { if ((f != -1) && (getWarpIndex(f) == -1)) throw(BoundsException(className, "warp")); flyWarp = f; } void Map::setType(const int t) throw(BoundsException) { if (End <= t) throw(BoundsException(className, "type")); type = t; } QString Map::getName() const { return name; } int Map::getFlyWarp() const { return flyWarp; } int Map::getType() const { return type; } void Map::setTile(int x, int y, int _id) throw(BoundsException) { if (pokemod.getTileIndex(_id) == -1) throw(BoundsException(className, "tile")); tiles(x, y) = _id; } void Map::insertColumn(int x) { tiles.insertCol(x, 0); } void Map::insertRow(int y) { tiles.insertRow(y, 0); } void Map::addColumn() { tiles.addCol(0); } void Map::addRow() { tiles.addRow(0); } void Map::deleteColumn(int x) { tiles.deleteCol(x); } void Map::deleteRow(int y) { tiles.deleteRow(y); } const Matrix& Map::getMap() const { return tiles; } Matrix& Map::getMap() { return tiles; } int Map::getTile(int x, int y) const { return tiles(x, y); } int Map::getWidth() const { return tiles.getWidth(); } int Map::getHeight() const { return tiles.getHeight(); } const MapEffect& Map::getEffect(const int i) const throw(IndexException) { if (getEffectCount() <= i) throw(IndexException(className)); return effects.at(i); } MapEffect& Map::getEffect(const int i) throw(IndexException) { if (getEffectCount() <= i) throw(IndexException(className)); return effects[i]; } const MapEffect& Map::getEffectByID(const int i) const throw(IndexException) { return getEffect(getEffectIndex(i)); } MapEffect& Map::getEffectByID(const int i) throw(IndexException) { return getEffect(getEffectIndex(i)); } int Map::getEffectIndex(const int _id) const { for (int i = 0; i < getEffectCount(); ++i) { if (effects[i].getId() == _id) return i; } return -1; } int Map::getEffectCount() const { return effects.size(); } MapEffect& Map::newEffect() { effects.append(MapEffect(pokemod, getNewEffectId())); return effects[getEffectCount() - 1]; } MapEffect& Map::newEffect(const QString& fname) { effects.append(MapEffect(pokemod, fname, getNewEffectId())); return effects[getEffectCount() - 1]; } MapEffect& Map::newEffect(const MapEffect& e) { effects.append(MapEffect(pokemod, e, getNewEffectId())); return effects[getEffectCount() - 1]; } void Map::deleteEffect(const int i) throw(IndexException) { if (getEffectCount() <= i) throw(IndexException(className)); effects.removeAt(i); } const MapTrainer& Map::getTrainer(const int i) const throw(IndexException) { if (getTrainerCount() <= i) throw(IndexException(className)); return trainers.at(i); } MapTrainer& Map::getTrainer(const int i) throw(IndexException) { if (getTrainerCount() <= i) throw(IndexException(className)); return trainers[i]; } const MapTrainer& Map::getTrainerByID(const int i) const throw(IndexException) { return getTrainer(getTrainerIndex(i)); } MapTrainer& Map::getTrainerByID(const int i) throw(IndexException) { return getTrainer(getTrainerIndex(i)); } int Map::getTrainerIndex(const int _id) const { for (int i = 0; i < getTrainerCount(); ++i) { if (trainers[i].getId() == _id) return i; } return -1; } int Map::getTrainerCount() const { return trainers.size(); } MapTrainer& Map::newTrainer() { trainers.append(MapTrainer(pokemod, getNewTrainerId())); return trainers[getTrainerCount() - 1]; } MapTrainer& Map::newTrainer(const QString& fname) { trainers.append(MapTrainer(pokemod, fname, getNewTrainerId())); return trainers[getTrainerCount() - 1]; } MapTrainer& Map::newTrainer(const MapTrainer& t) { trainers.append(MapTrainer(pokemod, t, getNewTrainerId())); return trainers[getTrainerCount() - 1]; } void Map::deleteTrainer(const int i) throw(IndexException) { if (getTrainerCount() <= i) throw(IndexException(className)); trainers.removeAt(i); } const MapWarp& Map::getWarp(const int i) const throw(IndexException) { if (getWarpCount() <= i) throw(IndexException(className)); return warps.at(i); } MapWarp& Map::getWarp(const int i) throw(IndexException) { if (getWarpCount() <= i) throw(IndexException(className)); return warps[i]; } const MapWarp& Map::getWarpByID(const int i) const throw(IndexException) { return getWarp(getWarpIndex(i)); } MapWarp& Map::getWarpByID(const int i) throw(IndexException) { return getWarp(getWarpIndex(i)); } int Map::getWarpIndex(const int _id) const { for (int i = 0; i < getWarpCount(); ++i) { if (warps[i].getId() == _id) return i; } return -1; } int Map::getWarpCount() const { return warps.size(); } MapWarp& Map::newWarp() { warps.append(MapWarp(pokemod, getNewWarpId())); return warps[getWarpCount() - 1]; } MapWarp& Map::newWarp(const QString& fname) { warps.append(MapWarp(pokemod, fname, getNewWarpId())); return warps[getWarpCount() - 1]; } MapWarp& Map::newWarp(const MapWarp& w) { warps.append(MapWarp(pokemod, w, getNewWarpId())); return warps[getWarpCount() - 1]; } void Map::deleteWarp(const int i) throw(IndexException) { if (getWarpCount() <= i) throw(IndexException(className)); warps.removeAt(i); } const MapWildList& Map::getWildList(const int i) const throw(IndexException) { if (getWildListCount() <= i) throw(IndexException(className)); return wildLists.at(i); } MapWildList& Map::getWildList(const int i) throw(IndexException) { if (getWildListCount() <= i) throw(IndexException(className)); return wildLists[i]; } const MapWildList& Map::getWildListByID(const int i) const throw(IndexException) { return getWildList(getWildListIndex(i)); } MapWildList& Map::getWildListByID(const int i) throw(IndexException) { return getWildList(getWildListIndex(i)); } int Map::getWildListIndex(const int _id) const { for (int i = 0; i < getWildListCount(); ++i) { if (wildLists[i].getId() == _id) return i; } return -1; } int Map::getWildListCount() const { return wildLists.size(); } MapWildList& Map::newWildList() { wildLists.append(MapWildList(pokemod, getNewWildListId())); return wildLists[getWildListCount() - 1]; } MapWildList& Map::newWildList(const QString& fname) { wildLists.append(MapWildList(pokemod, fname, getNewWildListId())); return wildLists[getWildListCount() - 1]; } MapWildList& Map::newWildList(const MapWildList& w) { wildLists.append(MapWildList(pokemod, w, getNewWildListId())); return wildLists[getWildListCount() - 1]; } void Map::deleteWildList(const int i) throw(IndexException) { if (getWildListCount() <= i) throw(IndexException(className)); wildLists.removeAt(i); } Map& Map::operator=(const Map& rhs) { if (this == &rhs) return *this; name = rhs.name; flyWarp = rhs.flyWarp; type = rhs.type; tiles = rhs.tiles; effects.clear(); for (int i = 0; i < rhs.getEffectCount(); ++i) newEffect(rhs.getEffect(i)); trainers.clear(); for (int i = 0; i < rhs.getTrainerCount(); ++i) newTrainer(rhs.getTrainer(i)); warps.clear(); for (int i = 0; i < rhs.getWarpCount(); ++i) newWarp(rhs.getWarp(i)); wildLists.clear(); for (int i = 0; i < rhs.getWildListCount(); ++i) newWildList(rhs.getWildList(i)); return *this; }