#include #include "gamefeatures.h" #include "qw_levelbuilder.h" #include "qw_eventfactory.h" #include "qw_dialoguefactory.h" #include "qw_globalmetadata.h" #include "view/qw_scene.h" #include "models/qw_location.h" #include "models/qw_trigger.h" QWLevelBuilder::QWLevelBuilder(QObject *parent) : QObject(parent), str_current_level(strInitLevel()) { // Dir for local save files if (!QDir("save").exists()) { QDir().mkdir("save"); } save_dir.setPath("save"); } template QJsonArray writeEntitesToJsonArray(const QHash> &hash_models) { // Writing in active save file all the game elements and their state QJsonArray json_array; for (const auto &model : hash_models) { QJsonObject model_data; model->writeToJson(model_data); json_array.append(model_data); } return json_array; } void QWLevelBuilder::initMenuLevel() { str_current_level = "menu"; QFile file(":/res/menu.json"); Q_ASSERT(file.open(QIODevice::ReadOnly)); const QByteArray json_arr = file.readAll(); file.close(); QJsonObject savefile = QJsonDocument::fromJson(json_arr).object(); init(savefile); } void QWLevelBuilder::initSaveProfile(const QString &filename, const QString &profilename) { Q_UNUSED(profilename) // Creating inital save file after beginning the new game: str_profile_filename = filename; str_current_level = strInitLevel(); QFile file; str_profile_filename.remove(".json"); // We move default game description to player's save file file.setFileName(save_dir.path() + "/" + str_profile_filename + ".json"); qDebug() << save_dir.path() + "/" + str_profile_filename + ".json"; if (!file.exists()) { qDebug() << "copy file"; QFile::copy(":/res/defaultsave.json", file.fileName()); } // Now we modify default json file to add the chosen profile name /*Q_ASSERT(file.open(QIODevice::ReadOnly)); const QByteArray json_arr = file.readAll(); file.close(); QJsonObject savefile = QJsonDocument::fromJson(json_arr).object(); // Pull the saved string from new game dialogue str_current_profile = profilename; savefile.insert("save_profile", str_current_profile); // Write it and resave Q_ASSERT(file.open(QIODevice::WriteOnly)); file.write(QJsonDocument(savefile).toJson()); file.close();*/ } void QWLevelBuilder::saveGame(/*QString filename*/) { qDebug() << "Save current game!"; QJsonObject savejson; QJsonArray json_entites; /* The first Trigger which moves player into its * needed location where the game starts */ savejson.insert("init", "spawn"); savejson.insert("save_profile", str_current_profile); qDebug() << "Save triggers!"; json_entites = writeEntitesToJsonArray(hash_triggers); savejson.insert("triggers", json_entites); qDebug() << "Save dialogues!"; json_entites = writeEntitesToJsonArray(hash_dialogues); savejson.insert("dialogues", json_entites); qDebug() << "Save locations!"; json_entites = writeEntitesToJsonArray(hash_locations); savejson.insert("locations", json_entites); qDebug() << "Save events!"; json_entites = writeEntitesToJsonArray(hash_events); // Creating the inital event where player must appear after game loading QJsonObject init_spawn_data; QStringList trs; for (auto & tr : ptr_scene->currentLocation()->triggers()) trs << tr->tag(); QList> list_triggers; init_spawn_data.insert("id", "spawn"); init_spawn_data.insert("type", 0); init_spawn_data.insert("trs", QJsonArray::fromStringList(trs)); json_entites.append(init_spawn_data); savejson.insert("events", json_entites); // - - - // QFile file(save_dir.dirName() + "/" + str_profile_filename + ".json"); Q_ASSERT(file.open(QIODevice::ReadOnly)); const QByteArray json_arr = file.readAll(); file.close(); QJsonObject savefile = QJsonDocument::fromJson(json_arr).object(); savefile[str_current_level] = savejson; Q_ASSERT(file.open(QIODevice::WriteOnly)); file.write(QJsonDocument(savejson).toJson()); file.close(); } void QWLevelBuilder::loadGame(/*QString filename*/) { QFile file; hash_events.clear(); hash_triggers.clear(); hash_dialogues.clear(); hash_locations.clear(); init_trigger.reset(); file.setFileName(save_dir.dirName() + "/" + str_profile_filename + ".json"); file.open(QIODevice::ReadOnly); const QByteArray json_arr = file.readAll(); file.close(); QJsonObject savefile = QJsonDocument::fromJson(json_arr).object(); str_current_level = savefile["init_level"].toString(); init(savefile); } void QWLevelBuilder::initLevel(const QString &lvlname) { str_current_level = lvlname; QFile file(save_dir.dirName() + "/" + str_profile_filename + ".json"); Q_ASSERT(file.open(QIODevice::ReadOnly)); const QByteArray json_arr = file.readAll(); file.close(); emit ptr_scene->signalLeaveMenu(); QJsonObject savefile = QJsonDocument::fromJson(json_arr).object(); init(savefile); } void QWLevelBuilder::init(const QJsonObject & savefile) { qDebug() << "Init " << str_current_level << " level!"; hash_events.clear(); hash_triggers.clear(); init_trigger.reset(); level = savefile[str_current_level].toObject(); Q_ASSERT(!level.isEmpty()); // Building level from current json if (level.contains("triggers")) setupTriggers(level["triggers"].toArray()); if (level.contains("dialogues")) setupDialogues(level["dialogues"].toArray()); if (level.contains("locations")) setupLocations(level["locations"].toArray()); if (level.contains("events")) setupEvents(level["events"].toArray()); linkEvents(level["triggers"].toArray()); init_trigger = level.contains("init") ? hash_triggers[level["init"].toString()] : nullptr; // Start the level Q_ASSERT(init_trigger); init_trigger->activate(); } QString QWLevelBuilder::strInitLevel() noexcept { return "start"; } void QWLevelBuilder::setGameFeatures(std::unique_ptr &features) { ptr_scene = features->ptr_scene; ptr_inventory = features->ptr_inventory; ptr_soundplayer = features->ptr_sound_player; ptr_text_dlg = features->ptr_text_dlg; ptr_widget_dlg = features->ptr_widget_dlg; } void QWLevelBuilder::linkEvents(const QJsonArray &array) { qDebug() << "Link the events to triggers!"; for (const QJsonValue &json_value : array) { QJsonObject json_object(json_value.toObject()); if (json_object.contains("evs")) { qDebug() << " Trigger " << json_object["id"].toString() << " contains events!"; QJsonArray evs = json_object["evs"].toArray(); for (const QJsonValue event : evs) { QString obj = event.toString(); qDebug() << " Inserting " << obj << " to its trigger!"; hash_triggers[json_object["id"].toString()]->addEvents(hash_events[obj]); qDebug() << " Success!"; } } if (json_object.contains("examine_dialogue")) { qDebug() << " Trigger " << json_object["id"].toString() << " contains examination dialogue!"; const QString dialogue_tag = json_object["examine_dialogue"].toString(); hash_triggers[json_object["id"].toString()]->setExaminationDialogueEvent(hash_events[dialogue_tag]); } } } // * * * * * * * * * * * * * * SETUP STUFF * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * void QWLevelBuilder::setupTriggers(const QJsonArray &array) { qDebug() << "Setup the triggers!"; QJsonObject json_object; for (const QJsonValue &json_value : array) { json_object = json_value.toObject(); std::shared_ptr new_trigger; // check if the picture exists! Q_ASSERT(json_object.contains("id")); QString mask = json_object.contains("mask") ? json_object["mask"].toString() : json_object["id"].toString(); new_trigger = std::make_shared(mask); new_trigger->setTag(json_object["id"].toString()); qDebug() << "! The trigger with id " << json_object["id"].toString() << " was created."; // setup the position on the scene if (json_object.contains("x") && json_object.contains("y")) { new_trigger->setPos(json_object["x"].toDouble(), json_object["y"].toDouble()); qDebug() << " The trigger was moved to " << new_trigger->x() << " " << new_trigger->y(); } hash_triggers.insert(json_object["id"].toString(), new_trigger); qDebug() << " The trigger was inserted into its map.\n - - -"; } } void QWLevelBuilder::setupEvents(const QJsonArray &array) { qDebug() << "Setup the events!"; std::unique_ptr factory = std::make_unique(this); QJsonObject json_object; QList list_later_events; for (const QJsonValue &json_value : array) { json_object = json_value.toObject(); std::shared_ptr new_event; // check if the id exists! Q_ASSERT(json_object.contains("id")); qDebug() << "! The event with id " << json_object["id"].toString() << " is about to create."; // independent events Q_ASSERT(json_object.contains("type")); int type = json_object["type"].toInt(); switch (type) { case (EVENT_TYPE::CHANGE_LOCATION): new_event = factory->createChangeLocEvent(json_object); break; case (EVENT_TYPE::DELETE_FROM_INVENTORY): new_event = factory->createDeleteItEvent(json_object); break; case (EVENT_TYPE::PICKUP_ITEM): new_event = factory->createPickupItEvent(json_object); break; case (EVENT_TYPE::END_LEVEL): new_event = factory->createEndLevelEvent(json_object); break; case (EVENT_TYPE::CHANGE_TRIGGER_PROPERTIES): new_event = factory->createChangeTrProperts(json_object); break; case (EVENT_TYPE::NEW_GAME): new_event = factory->createNewGameEvent(json_object); break; case (EVENT_TYPE::QUIT_GAME): new_event = factory->createQuitGameEvent(json_object); break; case (EVENT_TYPE::START_DIALOGUE): new_event = factory->createStartDlgEvent(json_object); break; case (EVENT_TYPE::ADD_TRIGGER): new_event = factory->createAddTrEvent(json_object); break; case (EVENT_TYPE::REMOVE_TRIGGER): new_event = factory->createRemoveTrEvent(json_object); break; default: list_later_events.append(json_object); continue; } new_event->setTag(json_object["id"].toString()); hash_events.insert(json_object["id"].toString(), new_event); } // Some events work with other events, so we need to initialize all // independent events earlier than these for (const auto &later_event : list_later_events) { int type = later_event["type"].toInt(); std::shared_ptr new_event; switch (type) { case (EVENT_TYPE::SWITCH_EVENTS): // switch events new_event = factory->createSwitchEventsEvent(later_event); break; default: Q_ASSERT(false); continue; } new_event->setTag(later_event["id"].toString()); hash_events.insert(later_event["id"].toString(), new_event); } } void QWLevelBuilder::setupDialogues(const QJsonArray &array) { qDebug() << "Setup the dialogues!"; std::unique_ptr factory = std::make_unique(this); QJsonObject json_object; for (const QJsonValue &json_value : array) { json_object = json_value.toObject(); std::shared_ptr new_dialogue; // check if the id exists! Q_ASSERT(json_object.contains("id")); qDebug() << "! The dialogue with id " << json_object["id"].toString() << " is about to create."; Q_ASSERT(json_object.contains("type")); int type = json_object["type"].toInt(); switch (type) { case (DIALOGUE_TYPE::TEXT): new_dialogue = factory->createTextDialogue(json_object); break; case (DIALOGUE_TYPE::WIDGET): new_dialogue = factory->createWidgetDialogue(json_object); break; default: Q_ASSERT(false); } new_dialogue->setTag(json_object["id"].toString()); hash_dialogues.insert(json_object["id"].toString(), new_dialogue); } } void QWLevelBuilder::setupLocations(const QJsonArray &array) { qDebug() << "Setup the locations!"; QJsonObject json_object; for (const QJsonValue & json_value : array) { json_object = json_value.toObject(); std::shared_ptr new_location; Q_ASSERT(json_object.contains("id")); qDebug() << "! The level with id " << json_object["id"].toString() << " was created."; new_location = std::make_shared(); new_location->setTag(json_object["id"].toString()); // check and add the pixmap triggers Q_ASSERT(json_object.contains("triggers")); if (json_object.contains("triggers")) { qDebug() << " Found triggers!"; QJsonArray loc_triggers = json_value["triggers"].toArray(); for (const QJsonValue trg : loc_triggers) { qDebug() << " Added the trigger " << trg.toString(); new_location->addTriggers( hash_triggers[trg.toString()] ); } } if (json_object.contains("triggers")) new_location->setDiscovered(json_object["discovered"].toBool()); // check if it has a background if (json_object.contains("background")) { qDebug() << " Here is a background."; QString b = json_value["background"].toString(); new_location->addTriggers(hash_triggers[b]); qDebug() << " Background was added."; } hash_locations.insert(json_object["id"].toString(), new_location); qDebug() << " The level was inserted into its map.\n - - -"; } }