From b20ae992a63a8cda69dc2dae18e710c5e91ca068 Mon Sep 17 00:00:00 2001 From: fgenesis Date: Sun, 18 Sep 2011 23:23:02 +0200 Subject: [PATCH] Added support for world maps in mods. Mods with a tag in their XML definition can now open a native world map like the original game. Fixed an oversight that the world map visited area was updated while the editor was open. Fixed missing field in worldmap.txt saving. Removed the limitation that world map tiles had to be 256x256 - all tile sizes work now. The game does now read _mods/#/data/stringbank.txt from a mod and merges it with the main stringbank.txt, and uses _mods/#/data/worldmap.txt as a full replacement. Load _mods/#/[map|premap]_mapname.lua scripts to properly initialize the Naija map token. Improved the builtin worldmap editor a little. --- Aquaria/Continuity.cpp | 4 +- Aquaria/DSQ.h | 12 ++- Aquaria/Game.cpp | 11 ++- Aquaria/GridRender.h | 1 + Aquaria/MiniMapRender.cpp | 2 +- Aquaria/Mod.cpp | 12 +++ Aquaria/StringBank.cpp | 12 ++- Aquaria/WorldMapRender.cpp | 152 +++++++++++++++++++++++-------------- Aquaria/WorldMapTiles.cpp | 43 ++++++++--- 9 files changed, 169 insertions(+), 80 deletions(-) diff --git a/Aquaria/Continuity.cpp b/Aquaria/Continuity.cpp index b99b7e2..5291d9a 100644 --- a/Aquaria/Continuity.cpp +++ b/Aquaria/Continuity.cpp @@ -3203,12 +3203,12 @@ void Continuity::reset() loadTreasureData(); - stringBank.load("data/stringbank.txt"); + stringBank.load(); gems.clear(); beacons.clear(); - worldMap.load("data/worldmap.txt"); + worldMap.load(); ingredients.clear(); diff --git a/Aquaria/DSQ.h b/Aquaria/DSQ.h index 36b9fa0..e4143a1 100644 --- a/Aquaria/DSQ.h +++ b/Aquaria/DSQ.h @@ -206,10 +206,11 @@ class StringBank { public: StringBank(); - void load(const std::string &file); + void load(); std::string get(int idx); protected: + void _load(const std::string &file); typedef std::map StringMap; StringMap stringMap; @@ -260,6 +261,7 @@ public: bool isActive(); bool isDebugMenu(); + bool hasWorldMap(); std::string getPath(); std::string getName(); @@ -269,6 +271,7 @@ public: protected: bool shuttingDown; bool active; + bool hasMap; int doRecache; int debugMenu; int enqueueModStart; @@ -581,8 +584,8 @@ protected: struct WorldMap { WorldMap(); - void load(const std::string &file); - void save(const std::string &file); + void load(); + void save(); void hideMap(); void revealMap(const std::string &name); WorldMapTile *getWorldMapTile(const std::string &name); @@ -595,6 +598,9 @@ struct WorldMap int gw, gh; typedef std::vector WorldMapTiles; WorldMapTiles worldMapTiles; + +private: + void _load(const std::string &file); }; class Path; diff --git a/Aquaria/Game.cpp b/Aquaria/Game.cpp index 4ced547..5ee8fc0 100644 --- a/Aquaria/Game.cpp +++ b/Aquaria/Game.cpp @@ -6983,8 +6983,10 @@ void Game::applyState() core->sort(); - - dsq->runScript("scripts/maps/premap_"+sceneName+".lua", "init", true); + if (dsq->mod.isActive()) + dsq->runScript(dsq->mod.getPath() + "scripts/premap_" + sceneName + ".lua", "init", true); + else + dsq->runScript("scripts/maps/premap_"+sceneName+".lua", "init", true); std::string musicToPlay = this->musicToPlay; if (!overrideMusic.empty()) @@ -7076,7 +7078,10 @@ void Game::applyState() dsq->subtitlePlayer.show(0.25); if (verbose) debugLog("loading map init script"); - dsq->runScript("scripts/maps/map_"+sceneName+".lua", "init", true); + if (dsq->mod.isActive()) + dsq->runScript(dsq->mod.getPath() + "scripts/map_" + sceneName + ".lua", "init", true); + else + dsq->runScript("scripts/maps/map_"+sceneName+".lua", "init", true); if (!dsq->doScreenTrans && (dsq->overlay->alpha != 0 && !dsq->overlay->alpha.isInterpolating())) { diff --git a/Aquaria/GridRender.h b/Aquaria/GridRender.h index 4ec88ac..6f7f9a9 100644 --- a/Aquaria/GridRender.h +++ b/Aquaria/GridRender.h @@ -102,6 +102,7 @@ protected: unsigned char *savedTexData; bool mb; Vector lastMousePosition; // See FIXME in WorldMapRender.cpp --achurch + void updateEditor(); }; class PathRender : public RenderObject diff --git a/Aquaria/MiniMapRender.cpp b/Aquaria/MiniMapRender.cpp index ad7f668..e69fd01 100644 --- a/Aquaria/MiniMapRender.cpp +++ b/Aquaria/MiniMapRender.cpp @@ -359,7 +359,7 @@ void MiniMapRender::onUpdate(float dt) } } - if (!btn && !dsq->mod.isActive() && !radarHide) + if (!btn && !radarHide && (!dsq->mod.isActive() || dsq->mod.hasWorldMap())) { if (dsq->game->worldMapRender->isOn()) { diff --git a/Aquaria/Mod.cpp b/Aquaria/Mod.cpp index 82b5d50..4b4e956 100644 --- a/Aquaria/Mod.cpp +++ b/Aquaria/Mod.cpp @@ -58,6 +58,7 @@ void Mod::clear() active = false; doRecache = 0; debugMenu = false; + hasMap = false; } bool Mod::isDebugMenu() @@ -65,6 +66,11 @@ bool Mod::isDebugMenu() return debugMenu; } +bool Mod::hasWorldMap() +{ + return hasMap; +} + void Mod::loadModXML(TiXmlDocument *d, std::string modName) { d->LoadFile(baseModPath + modName + ".xml"); @@ -112,6 +118,12 @@ void Mod::load(const std::string &p) if (props->Attribute("debugMenu")) { props->Attribute("debugMenu", &debugMenu); } + + if (props->Attribute("hasWorldMap")) { + int t; + props->Attribute("hasWorldMap", &t); + hasMap = t; + } } } diff --git a/Aquaria/StringBank.cpp b/Aquaria/StringBank.cpp index a37cb5b..f408304 100644 --- a/Aquaria/StringBank.cpp +++ b/Aquaria/StringBank.cpp @@ -24,10 +24,18 @@ StringBank::StringBank() { } -void StringBank::load(const std::string &file) +void StringBank::load() +{ + stringMap.clear(); + + _load("data/stringbank.txt"); + if (dsq->mod.isActive()) + _load(dsq->mod.getPath() + "data/stringbank.txt"); +} + +void StringBank::_load(const std::string &file) { //debugLog("StringBank::load("+file+")"); - stringMap.clear(); std::ifstream in(file.c_str()); diff --git a/Aquaria/WorldMapRender.cpp b/Aquaria/WorldMapRender.cpp index 8ba2a1a..6d43770 100644 --- a/Aquaria/WorldMapRender.cpp +++ b/Aquaria/WorldMapRender.cpp @@ -1029,59 +1029,61 @@ void WorldMapRender::onUpdate(float dt) internalOffset += mouseChange / scale.x; } - - float scrollSpeed = 2.0f; - float amt = (400*dt)/scale.x; - if (isActing(ACTION_SWIMLEFT)) - { - internalOffset += Vector(amt, 0); - } - if (isActing(ACTION_SWIMRIGHT)) - { - internalOffset += Vector(-amt, 0); - } - if (isActing(ACTION_SWIMDOWN)) - { - if (core->getShiftState()) - { - scale.stop(); - scale -= Vector(scrollSpeed*dt, scrollSpeed*dt); - } - else - { - internalOffset += Vector(0, -amt); - } - } - if (isActing(ACTION_SWIMUP)) - { - if (core->getShiftState()) - { - scale.stop(); - scale += Vector(scrollSpeed*dt, scrollSpeed*dt); - } - else - { - internalOffset += Vector(0, amt); - } - } + if(!editorActive) + { + float scrollSpeed = 2.0f; + float amt = (400*dt)/scale.x; + if (isActing(ACTION_SWIMLEFT)) + { + internalOffset += Vector(amt, 0); + } + if (isActing(ACTION_SWIMRIGHT)) + { + internalOffset += Vector(-amt, 0); + } + if (isActing(ACTION_SWIMDOWN)) + { + if (core->getShiftState()) + { + scale.stop(); + scale -= Vector(scrollSpeed*dt, scrollSpeed*dt); + } + else + { + internalOffset += Vector(0, -amt); + } + } + if (isActing(ACTION_SWIMUP)) + { + if (core->getShiftState()) + { + scale.stop(); + scale += Vector(scrollSpeed*dt, scrollSpeed*dt); + } + else + { + internalOffset += Vector(0, amt); + } + } - if (core->joystickEnabled) - { - if (isActing(ACTION_SECONDARY)) - { - if (core->joystick.position.y >= 0.6f) - scale.interpolateTo(scale / 1.2f, 0.1f); - else if (core->joystick.position.y <= -0.6f) - scale.interpolateTo(scale * 1.2f, 0.1f); - } - else - { - // The negative multiplier is deliberate -- it makes the - // map scroll as though the joystick was controlling the - // cursor (which is fixed in the center of the screen). - internalOffset += core->joystick.position * (-400*dt / scale.x); - } - } + if (core->joystickEnabled) + { + if (isActing(ACTION_SECONDARY)) + { + if (core->joystick.position.y >= 0.6f) + scale.interpolateTo(scale / 1.2f, 0.1f); + else if (core->joystick.position.y <= -0.6f) + scale.interpolateTo(scale * 1.2f, 0.1f); + } + else + { + // The negative multiplier is deliberate -- it makes the + // map scroll as though the joystick was controlling the + // cursor (which is fixed in the center of the screen). + internalOffset += core->joystick.position * (-400*dt / scale.x); + } + } + } if (activeTile && activeTile->layer == 1) { @@ -1136,11 +1138,22 @@ void WorldMapRender::onUpdate(float dt) if (core->getShiftState()) { + if (core->getCtrlState()) + a2 *= 10.0f; if (core->getKeyState(KEY_UP)) activeTile->scale2 += -a2; if (core->getKeyState(KEY_DOWN)) activeTile->scale2 += a2; } + else if (core->getAltState()) + { + if (core->getCtrlState()) + a2 *= 10.0f; + if (core->getKeyState(KEY_UP)) + activeTile->scale += -a2; + if (core->getKeyState(KEY_DOWN)) + activeTile->scale += a2; + } else { if (core->getCtrlState()) @@ -1159,19 +1172,23 @@ void WorldMapRender::onUpdate(float dt) if (core->getKeyState(KEY_F2)) { - dsq->continuity.worldMap.save("data/WorldMap.txt"); + dsq->continuity.worldMap.save(); } activeQuad->position = activeTile->gridPos; activeQuad->scale = Vector(0.25f*activeTile->scale2, 0.25f*activeTile->scale2); + if(activeQuad->texture) + activeQuad->setWidthHeight(activeQuad->texture->width*activeTile->scale, // FG: HACK force resize proper + activeQuad->texture->height*activeTile->scale); } + updateEditor(); } } } else { #ifdef AQUARIA_BUILD_MAPVIS - if (!dsq->isInCutscene() && dsq->game->avatar && activeTile) + if (!dsq->isInCutscene() && dsq->game->avatar && activeTile && !dsq->game->sceneEditor.isOn()) { const float screenWidth = core->getVirtualWidth() * core->invGlobalScale; const float screenHeight = core->getVirtualHeight() * core->invGlobalScale; @@ -1231,11 +1248,16 @@ Vector WorldMapRender::getAvatarWorldMapPosition() Vector WorldMapRender::getWorldToTile(WorldMapTile *tile, Vector position, bool fromCenter, bool tilePos) { + const float sizew = (float)tile->q->texture->width; + const float halfw = sizew / 2.0f; + const float sizeh = (float)tile->q->texture->height; + const float halfh = sizeh / 2.0f; Vector p; - p = (position/TILE_SIZE) / (256*tile->scale); - p *= 256*tile->scale*0.25f*tile->scale2; + p = Vector((position.x/TILE_SIZE) / (sizew*tile->scale), (position.y/TILE_SIZE) / (sizeh*tile->scale)); + p.x *= sizew*tile->scale*0.25f*tile->scale2; + p.y *= sizeh*tile->scale*0.25f*tile->scale2; if (fromCenter) - p -= Vector((128*tile->scale)*(0.25f*tile->scale2), (128*tile->scale)*(0.25f*tile->scale2)); + p -= Vector((halfw*tile->scale)*(0.25f*tile->scale2), (halfh*tile->scale)*(0.25f*tile->scale2)); if (tilePos) p += tile->gridPos; return p; @@ -1298,7 +1320,7 @@ void WorldMapRender::toggle(bool turnON) if (dsq->game->miniMapRender->isRadarHide()) return; if (alpha.isInterpolating()) return; - if (dsq->mod.isActive()) return; + if (dsq->mod.isActive() && !dsq->mod.hasWorldMap()) return; if (dsq->isNested()) return; @@ -1489,6 +1511,18 @@ void WorldMapRender::createGemHint(const std::string &gfx) } } +void WorldMapRender::updateEditor() +{ + std::ostringstream os; + os << "EDITING... "; + if(activeTile) + { + os << "x=" << activeTile->gridPos.x << "; y=" << activeTile->gridPos.y << std::endl; + os << "scale=" << activeTile->scale << "; scale2=" << activeTile->scale2; + } + areaLabel->setText(os.str()); +} + void WorldMapRender::action (int id, int state) { if (isOn()) @@ -1505,7 +1539,7 @@ void WorldMapRender::action (int id, int state) if (editorActive) { - areaLabel->setText("EDITING..."); + updateEditor(); } } } diff --git a/Aquaria/WorldMapTiles.cpp b/Aquaria/WorldMapTiles.cpp index f535a44..ea9d6b2 100644 --- a/Aquaria/WorldMapTiles.cpp +++ b/Aquaria/WorldMapTiles.cpp @@ -240,13 +240,21 @@ WorldMap::WorldMap() gw=gh=0; } -void WorldMap::load(const std::string &file) +void WorldMap::load() +{ + if (!dsq->mod.isActive()) + _load("data/worldmap.txt"); + else + _load(dsq->mod.getPath() + "data/worldmap.txt"); +} + +void WorldMap::_load(const std::string &file) { worldMapTiles.clear(); std::string line; - std::ifstream in(file.c_str()); + std::ifstream in(file.c_str()); while (std::getline(in, line)) { @@ -259,15 +267,30 @@ void WorldMap::load(const std::string &file) } } -void WorldMap::save(const std::string &file) +void WorldMap::save() { - std::ofstream out(file.c_str()); - - for (int i = 0; i < worldMapTiles.size(); i++) - { - WorldMapTile *t = &worldMapTiles[i]; - out << t->index << " " << t->name << " " << t->layer << " " << t->scale << " " << t->gridPos.x << " " << t->gridPos.y << " " << t->prerevealed << " " << t->scale2 << std::endl; - } + std::string fn; + + if (dsq->mod.isActive()) + fn = dsq->mod.getPath() + "data/worldmap.txt"; + else + fn = "data/worldmap.txt"; + + std::ofstream out(fn.c_str()); + + if (out) + { + for (int i = 0; i < worldMapTiles.size(); i++) + { + WorldMapTile *t = &worldMapTiles[i]; + out << t->index << " " << t->stringIndex << " " << t->name << " " << t->layer << " " << t->scale << " " << t->gridPos.x << " " << t->gridPos.y << " " << t->prerevealed << " " << t->scale2 << std::endl; + } + dsq->screenMessage("Saved worldmap data to " + fn); + } + else + { + dsq->screenMessage("Unable to save worldmap to " + fn); + } } void WorldMap::revealMap(const std::string &name)