/////////////////////////////////////////////////////////////////////////////
// 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;
}