mirror of
https://github.com/AquariaOSE/Aquaria.git
synced 2024-11-25 09:44:02 +00:00
improvements to gem storage
gems from old saves are still compatible but won't be associated to map tiles
This commit is contained in:
parent
4a71c5e12f
commit
de80af5612
5 changed files with 135 additions and 64 deletions
|
@ -2275,6 +2275,19 @@ void Continuity::upgradeHealth()
|
|||
a->heal(maxHealth - a->health);
|
||||
}
|
||||
|
||||
static Vector gemGlobalPos(const GemData& g)
|
||||
{
|
||||
if(g.global || g.mapName.empty())
|
||||
return g.pos;
|
||||
|
||||
// Legacy gem storage stores global position only, so tile-local coords need conversion
|
||||
const WorldMapTileContainer *tc = game->worldMapRender->getTileByName(g.mapName.c_str());
|
||||
if(!tc)
|
||||
return g.pos;
|
||||
|
||||
return tc->worldPosToMapPos(g.pos);
|
||||
}
|
||||
|
||||
void Continuity::saveFile(int slot, Vector position, unsigned char *scrShotData, int scrShotWidth, int scrShotHeight)
|
||||
{
|
||||
refreshAvatarData(game->avatar);
|
||||
|
@ -2326,7 +2339,8 @@ void Continuity::saveFile(int slot, Vector position, unsigned char *scrShotData,
|
|||
os << this->gems.size() << " ";
|
||||
for (Gems::iterator i = this->gems.begin(); i != this->gems.end(); i++)
|
||||
{
|
||||
os << (*i).name << " " << (*i).pos.x << " " << (*i).pos.y << " ";
|
||||
Vector gpos = gemGlobalPos(*i);
|
||||
os << (*i).name << " " << gpos.x << " " << gpos.y << " ";
|
||||
os << (*i).canMove << " ";
|
||||
|
||||
hasUserString = !(*i).userString.empty();
|
||||
|
@ -2345,13 +2359,15 @@ void Continuity::saveFile(int slot, Vector position, unsigned char *scrShotData,
|
|||
os << this->gems.size() << " ";
|
||||
for (Gems::iterator i = this->gems.begin(); i != this->gems.end(); i++)
|
||||
{
|
||||
Vector gpos = gemGlobalPos(*i);
|
||||
|
||||
os << (*i).name << " ";
|
||||
bool hasMapName = !(*i).mapName.empty();
|
||||
os << hasMapName << " ";
|
||||
if(hasMapName)
|
||||
os << (*i).mapName << " "; // warning: this will fail to load if the map name contains whitespace
|
||||
|
||||
os << (*i).pos.x << " " << (*i).pos.y << " ";
|
||||
os << gpos.x << " " << gpos.y << " ";
|
||||
os << (*i).canMove << " ";
|
||||
|
||||
bool hasUserString = !(*i).userString.empty();
|
||||
|
@ -2362,9 +2378,29 @@ void Continuity::saveFile(int slot, Vector position, unsigned char *scrShotData,
|
|||
gems->SetAttribute("d", os.str().c_str());
|
||||
}
|
||||
|
||||
// newest format; is aware if tile-relative position
|
||||
// newest format; is aware of tile-relative position
|
||||
for (Gems::iterator i = this->gems.begin(); i != this->gems.end(); i++)
|
||||
{
|
||||
const GemData& g = *i;
|
||||
XMLElement *gx = doc.NewElement("Gem");
|
||||
gems->InsertEndChild(gx);
|
||||
|
||||
gx->SetAttribute("name", g.name.c_str());
|
||||
gx->SetAttribute("x", g.pos.x); // always store position as-is
|
||||
gx->SetAttribute("y", g.pos.y);
|
||||
gx->SetAttribute("id", g.id);
|
||||
gx->SetAttribute("global", (unsigned)g.global);
|
||||
|
||||
if(g.blink)
|
||||
gx->SetAttribute("blink", (unsigned)g.blink);
|
||||
if(g.canMove)
|
||||
gx->SetAttribute("canMove", (unsigned)g.canMove);
|
||||
if(!g.mapName.empty())
|
||||
gx->SetAttribute("mapName", g.mapName.c_str());
|
||||
if(!g.userString.empty())
|
||||
gx->SetAttribute("userString", g.userString.c_str());
|
||||
if(g.isPlayer)
|
||||
gx->SetAttribute("isPlayer", (unsigned)g.isPlayer);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2768,10 +2804,49 @@ bool Continuity::loadFile(int slot)
|
|||
XMLElement *gems = doc.FirstChildElement("Gems");
|
||||
if (gems)
|
||||
{
|
||||
if (gems->Attribute("a"))
|
||||
bool needGemFix = true;
|
||||
// New gem storage. All other stores are ignored if a <Gem ...> tag is present,
|
||||
// since the old format is stored as well for backwards compat.
|
||||
// Old versions will not load this and instead use one of the fallbacks below
|
||||
XMLElement *gem = gems->FirstChildElement("Gem");
|
||||
if(gem)
|
||||
{
|
||||
std::string s = gems->Attribute("a");
|
||||
std::istringstream is(s);
|
||||
needGemFix = false;
|
||||
do
|
||||
{
|
||||
GemData g;
|
||||
g.blink = gem->IntAttribute("blink");
|
||||
g.canMove = gem->IntAttribute("canMove");
|
||||
g.global = true;
|
||||
if(const char *mapname = gem->Attribute("mapName"))
|
||||
{
|
||||
g.mapName = mapname;
|
||||
g.global = false;
|
||||
}
|
||||
if(gem->Attribute("global"))
|
||||
g.global = gem->IntAttribute("global");
|
||||
g.isPlayer = gem->IntAttribute("isPlayer");
|
||||
if(const char *name = gem->Attribute("name"))
|
||||
g.name = name;
|
||||
g.pos.x = gem->FloatAttribute("x");
|
||||
g.pos.y = gem->FloatAttribute("y");
|
||||
if(const char *user = gem->Attribute("userString"))
|
||||
g.userString = user;
|
||||
if(gem->Attribute("id"))
|
||||
g.id = gem->IntAttribute("id");
|
||||
|
||||
this->gems.push_back(g);
|
||||
|
||||
gem = gem->NextSiblingElement("Gem");
|
||||
}
|
||||
while(gem);
|
||||
|
||||
}
|
||||
// ---- Legacy formats -----
|
||||
// [name x y]...
|
||||
else if (const char *attr = gems->Attribute("a"))
|
||||
{
|
||||
SimpleIStringStream is(attr, SimpleIStringStream::REUSE);
|
||||
GemData g;
|
||||
while (is >> g.name)
|
||||
{
|
||||
|
@ -2779,10 +2854,10 @@ bool Continuity::loadFile(int slot)
|
|||
this->gems.push_back(g);
|
||||
}
|
||||
}
|
||||
else if (gems->Attribute("b"))
|
||||
// [name x y canMove hasUserString (userString)]...
|
||||
else if (const char *attr = gems->Attribute("b"))
|
||||
{
|
||||
std::string s = gems->Attribute("b");
|
||||
std::istringstream is(s);
|
||||
SimpleIStringStream is(attr, SimpleIStringStream::REUSE);
|
||||
GemData g;
|
||||
bool hasUserString = false;
|
||||
while (is >> g.name)
|
||||
|
@ -2804,11 +2879,11 @@ bool Continuity::loadFile(int slot)
|
|||
this->gems.push_back(g);
|
||||
}
|
||||
}
|
||||
// num [name mapX mapY canMove hasUserString (userString)]
|
||||
else if (gems->Attribute("c"))
|
||||
// This is the format used by the original PC release
|
||||
// num [name mapX mapY canMove hasUserString (userString)]...
|
||||
else if (const char *attr = gems->Attribute("c"))
|
||||
{
|
||||
std::string s = gems->Attribute("c");
|
||||
std::istringstream is(s);
|
||||
SimpleIStringStream is(attr, SimpleIStringStream::REUSE);
|
||||
|
||||
int num = 0;
|
||||
is >> num;
|
||||
|
@ -2816,11 +2891,6 @@ bool Continuity::loadFile(int slot)
|
|||
bool hasUserString = false;
|
||||
GemData g;
|
||||
|
||||
std::ostringstream os;
|
||||
os << "continuity num: [" << num << "]" << std::endl;
|
||||
os << "data: [" << s << "]" << std::endl;
|
||||
debugLog(os.str());
|
||||
|
||||
for (int i = 0; i < num; i++)
|
||||
{
|
||||
g.pos = Vector(0,0,0);
|
||||
|
@ -2847,11 +2917,11 @@ bool Continuity::loadFile(int slot)
|
|||
debugLog(os.str());
|
||||
}
|
||||
}
|
||||
// This is the format used by the android version
|
||||
// num [name hasMapName (mapName) mapX mapY canMove hasUserString (userString)]
|
||||
else if (gems->Attribute("d"))
|
||||
else if (const char *attr = gems->Attribute("d"))
|
||||
{
|
||||
std::string s = gems->Attribute("d");
|
||||
std::istringstream is(s);
|
||||
SimpleIStringStream is(attr, SimpleIStringStream::REUSE);
|
||||
|
||||
int num = 0;
|
||||
is >> num;
|
||||
|
@ -2860,11 +2930,6 @@ bool Continuity::loadFile(int slot)
|
|||
bool hasMapName = false;
|
||||
GemData g;
|
||||
|
||||
std::ostringstream os;
|
||||
os << "continuity num: [" << num << "]" << std::endl;
|
||||
os << "data: [" << s << "]" << std::endl;
|
||||
debugLog(os.str());
|
||||
|
||||
for (int i = 0; i < num; i++)
|
||||
{
|
||||
g.pos = Vector(0,0,0);
|
||||
|
@ -2880,7 +2945,7 @@ bool Continuity::loadFile(int slot)
|
|||
if(hasMapName)
|
||||
is >> g.mapName;
|
||||
|
||||
is >> g.pos.x >> g.pos.y;
|
||||
is >> g.pos.x >> g.pos.y; // FIXME: check whether this is local coords or global coords
|
||||
is >> g.canMove;
|
||||
is >> hasUserString;
|
||||
|
||||
|
@ -2895,6 +2960,25 @@ bool Continuity::loadFile(int slot)
|
|||
debugLog(os.str());
|
||||
}
|
||||
}
|
||||
|
||||
// Slightly shoddy fix because we need to figure out which gem is the player gem but we don't know
|
||||
if(needGemFix)
|
||||
{
|
||||
debugLog("Apply legacy gem fix");
|
||||
bool doPlayerGem = true;
|
||||
for(Gems::iterator it = this->gems.begin(); it != this->gems.end(); ++it)
|
||||
{
|
||||
GemData& g = *it;
|
||||
g.global = g.mapName.empty();
|
||||
if(doPlayerGem && !nocasecmp(g.name.c_str(), "Naija-Token")) // First gem with the special texture name is the player gem
|
||||
{
|
||||
g.isPlayer = true;
|
||||
g.blink = true;
|
||||
g.global = false;
|
||||
//g.mapName = ... // Don't need to set this now, it'll be set once map name is applied
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
XMLElement *wmap = doc.FirstChildElement("WorldMap");
|
||||
|
@ -2917,11 +3001,8 @@ bool Continuity::loadFile(int slot)
|
|||
SimpleIStringStream is(va, SimpleIStringStream::REUSE);
|
||||
|
||||
WorldMapTile dummy;
|
||||
|
||||
int idx;
|
||||
|
||||
|
||||
|
||||
while (is >> idx)
|
||||
{
|
||||
WorldMapTile *tile = worldMap.getWorldMapTileByIndex(idx);
|
||||
|
@ -3357,17 +3438,12 @@ GemData *Continuity::pickupGem(const std::string& name, bool effects)
|
|||
bool isPlayerGem = !effects && gems.empty() && !nocasecmp(name, "Naija-Token");
|
||||
if(isPlayerGem)
|
||||
{
|
||||
g.global = false; // the player is always on a map
|
||||
g.blink = true;
|
||||
g.isPlayer = true;
|
||||
}
|
||||
g.isplayer = isPlayerGem;
|
||||
|
||||
Vector avatarPos = game->avatar->getPositionForMap();
|
||||
if(!game->worldMapRender->getWorldToPlayerTile(g.pos, avatarPos, g.global))
|
||||
{
|
||||
debugLog("pickupgem failed, no worldmap tile for current map");
|
||||
return NULL;
|
||||
}
|
||||
// local gem, use position directly
|
||||
g.pos = game->avatar->getPositionForMap();
|
||||
|
||||
gems.push_back(g);
|
||||
|
||||
|
@ -3396,10 +3472,10 @@ void Continuity::setCurrentMap(const std::string& mapname)
|
|||
for (Gems::iterator i = this->gems.begin(); i != this->gems.end(); i++)
|
||||
{
|
||||
GemData& g = *i;
|
||||
if(g.isplayer)
|
||||
if(g.isPlayer)
|
||||
{
|
||||
g.mapName = mapname;
|
||||
game->worldMapRender->updateGem(&g);
|
||||
game->worldMapRender->refreshGem(&g);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,15 +21,16 @@ struct EmoteData
|
|||
|
||||
struct GemData
|
||||
{
|
||||
GemData() { canMove=false; blink = false; global = false; isplayer = false; }
|
||||
GemData() { canMove=false; blink = false; global = false; isPlayer = false; id = -1; }
|
||||
std::string name;
|
||||
std::string userString;
|
||||
std::string mapName;
|
||||
Vector pos;
|
||||
bool canMove;
|
||||
bool blink; // not saved
|
||||
bool blink; // not saved on older versions
|
||||
bool global; // local gems use their parent container's coordinate system, global gems are placed directly on the map screen
|
||||
bool isplayer;
|
||||
bool isPlayer;
|
||||
int id; // used to identify a gem via scripts
|
||||
};
|
||||
|
||||
struct BeaconData
|
||||
|
|
|
@ -8864,8 +8864,9 @@ luaFunc(setGemPosition)
|
|||
Continuity::Gems::iterator it = dsq->continuity.gems.begin();
|
||||
std::advance(it, gemId);
|
||||
GemData& gem = *it;
|
||||
gem.pos = gem.global ? tc->worldPosToMapPos(pos) : tc->worldPosToTilePos(pos);
|
||||
gem.pos = gem.global ? tc->worldPosToMapPos(pos) : pos;
|
||||
gem.mapName = mapname;
|
||||
game->worldMapRender->refreshGem(&gem);
|
||||
result = true;
|
||||
}
|
||||
else
|
||||
|
@ -8891,6 +8892,7 @@ luaFunc(setGemName)
|
|||
std::advance(it, gemId);
|
||||
GemData& gem = *it;
|
||||
gem.name = getString(L, 2);
|
||||
game->worldMapRender->refreshGem(&gem);
|
||||
result = true;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -257,9 +257,13 @@ public:
|
|||
void refresh()
|
||||
{
|
||||
setTexture("gems/" + gemData->name);
|
||||
position = gemData->pos;
|
||||
|
||||
WorldMapTileContainer *tc = dynamic_cast<WorldMapTileContainer*>(parent);
|
||||
position = tc ? tc->worldPosToTilePos(gemData->pos) : gemData->pos;
|
||||
text->setText(gemData->userString);
|
||||
textBG->setWidthHeight(text->getActualWidth() + 20, 25, 10);
|
||||
|
||||
this->update(0);
|
||||
}
|
||||
|
||||
void destroy()
|
||||
|
@ -604,17 +608,6 @@ void WorldMapRender::updateAllTilesColor()
|
|||
setProperTileColor(*tiles[i]);
|
||||
}
|
||||
|
||||
bool WorldMapRender::getWorldToPlayerTile(Vector& dst, const Vector& pos, bool global) const
|
||||
{
|
||||
if(!playerTile)
|
||||
return false;
|
||||
|
||||
dst = global
|
||||
? playerTile->worldPosToMapPos(pos)
|
||||
: playerTile->worldPosToTilePos(pos);
|
||||
return true;
|
||||
}
|
||||
|
||||
WorldMapTileContainer* WorldMapRender::getTileByName(const char* name) const
|
||||
{
|
||||
for(size_t i = 0; i < tiles.size(); ++i)
|
||||
|
@ -676,16 +669,16 @@ void WorldMapRender::onUpdate(float dt)
|
|||
if(playerTile && !gemMovers.empty())
|
||||
{
|
||||
Vector playerPos = game->avatar->getPositionForMap();
|
||||
Vector playerMapPos = playerTile->worldPosToTilePos(playerPos);
|
||||
Vector playerTilePos = playerTile->worldPosToTilePos(playerPos);
|
||||
for (GemMovers::iterator i = gemMovers.begin(); i != gemMovers.end(); i++)
|
||||
{
|
||||
GemMover *gm = *i;
|
||||
GemData *g = gm->getGemData();
|
||||
if(g->isplayer)
|
||||
if(g->isPlayer) // Don't want to call refresh() every frame, so just update position here
|
||||
{
|
||||
assert(!g->global);
|
||||
g->pos = playerMapPos;
|
||||
gm->position = playerMapPos;
|
||||
g->pos = playerPos;
|
||||
gm->position = playerTilePos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -994,11 +987,11 @@ GemMover *WorldMapRender::addGem(GemData *gemData)
|
|||
else
|
||||
addChild(g, PM_POINTER);
|
||||
gemMovers.push_back(g);
|
||||
g->update(0);
|
||||
g->refresh();
|
||||
return g;
|
||||
}
|
||||
|
||||
void WorldMapRender::updateGem(const GemData* gemData)
|
||||
void WorldMapRender::refreshGem(const GemData* gemData)
|
||||
{
|
||||
GemMover *m = getGem(gemData);
|
||||
if(!m)
|
||||
|
|
|
@ -53,7 +53,7 @@ public:
|
|||
void setProperTileColor(WorldMapTileContainer& wt);
|
||||
void action(int id, int state, int source, InputDevice device);
|
||||
GemMover* addGem(GemData *gemData);
|
||||
void updateGem(const GemData *gemData);
|
||||
void refreshGem(const GemData *gemData);
|
||||
void removeGem(GemMover *gemMover);
|
||||
void removeGem(const GemData *gemData);
|
||||
GemMover *getGem(const GemData *gemData) const;
|
||||
|
@ -64,7 +64,6 @@ public:
|
|||
bool isCursorOffHud();
|
||||
void updateAllTilesColor();
|
||||
WorldMapTileContainer *getCurrentTile() { return playerTile; }
|
||||
bool getWorldToPlayerTile(Vector& dst, const Vector& pos, bool global) const;
|
||||
WorldMapTileContainer *getTileByName(const char *name) const;
|
||||
WorldMapTileContainer * setCurrentMap(const char *mapname);
|
||||
|
||||
|
|
Loading…
Reference in a new issue