MerchantData MerchantLoader::loadMerchant(const std::string& merchantID) const { lua_State* L = luaL_newstate(); luaL_openlibs(L); MerchantData merchantData; std::string filename = MERCHANT_FOLDER + "ME_" + merchantID + ".lua"; if (luaL_dofile(L, filename.c_str()) != 0) { g_logger->logError("MerchantLoader", "Cannot read lua script: " + filename); return merchantData; } lua_pcall(L, 0, 0, 0); LuaRef multiplier = getGlobal(L, "multiplier"); if (multiplier.isNumber()) { float mult = multiplier.cast<float>(); if (mult < 1.f) { g_logger->logWarning("MerchantLoader", "Merchant multiplier is smaller than 1, this is not allowed, the default (1.5f) is taken instead."); } else { merchantData.multiplier = mult; } } LuaRef fraction = getGlobal(L, "fraction"); if (fraction.isString()) { merchantData.fraction = resolveFractionID(fraction.cast<std::string>()); } LuaRef wares = getGlobal(L, "wares"); if (wares.isTable()) { int i = 1; // in lua, the first element is 1, not 0. Like Eiffel haha. LuaRef element = wares[i]; while (!element.isNil()) { LuaRef name = element[1]; LuaRef amount = element[2]; if (!name.isString() || !amount.isNumber()) { g_logger->logError("MerchantLoader", "File [" + filename + "]: wares table not resolved, no name or amount or of wrong type."); return merchantData; } merchantData.wares.insert({ name.cast<std::string>(), amount.cast<int>() }); i++; element = wares[i]; } } return merchantData; }
QuestData QuestLoader::loadQuest(const std::string& questID) const { lua_State* L = luaL_newstate(); luaL_openlibs(L); QuestData questData; questData.id = ""; std::string filename = QUEST_FOLDER + questID + ".lua"; if (luaL_dofile(L, filename.c_str()) != 0) { g_logger->logError("QuestLoader", "Cannot read lua script: " + filename); return questData; } lua_pcall(L, 0, 0, 0); LuaRef title = getGlobal(L, "title"); LuaRef description = getGlobal(L, "description"); if (!title.isString() || !description.isString()) { g_logger->logError("QuestLoader", "Quest [" + filename + "] has no title or description tag or of wrong type."); return questData; } questData.title = title.cast<std::string>(); questData.description = description.cast<std::string>(); LuaRef targets = getGlobal(L, "targets"); if (targets.isTable()) { int i = 1; // in lua, the first element is 1, not 0. Like Eiffel haha. LuaRef element = targets[i]; while (!element.isNil()) { LuaRef name = element[1]; LuaRef amount = element[2]; if (!name.isString() || !amount.isNumber()) { g_logger->logError("QuestLoader", "Quest [" + filename + "]: target table not resolved, no name or amount or of wrong type."); return questData; } questData.targets.insert({name.cast<std::string>(), amount.cast<int>()}); i++; element = targets[i]; } } LuaRef collectibles = getGlobal(L, "collectibles"); if (collectibles.isTable()) { int i = 1; LuaRef element = collectibles[i]; while (!element.isNil()) { LuaRef id = element[1]; LuaRef amount = element[2]; if (!id.isString() || !amount.isNumber()) { g_logger->logError("QuestLoader", "Quest [" + filename + "]: collectibles table not resolved, no id or amount or of wrong type."); return questData; } questData.collectibles.insert({ id.cast<std::string>(), amount.cast<int>() }); i++; element = collectibles[i]; } } LuaRef conditions = getGlobal(L, "conditions"); if (conditions.isTable()) { int i = 1; LuaRef element = conditions[i]; while (element.isString()) { questData.conditions.insert(element.cast<std::string>()); i++; element = targets[i]; } } questData.id = questID; return questData; }
CutsceneData CutsceneLoader::loadCutscene(const std::string& cutsceneID) { lua_State* L = luaL_newstate(); luaL_openlibs(L); CutsceneData cutsceneData; cutsceneData.id = ""; std::string foldername = CUTSCENE_FOLDER + cutsceneID + "/"; std::string filename = foldername + cutsceneID + ".lua"; if (luaL_dofile(L, filename.c_str()) != 0) { g_logger->logError("CutsceneLoader", "Cannot read lua script: " + filename); return cutsceneData; } lua_pcall(L, 0, 0, 0); LuaRef steps = getGlobal(L, "steps"); if (steps.isTable()) { int i = 1; // in lua, the first element is 1, not 0. Like Eiffel haha. LuaRef step = steps[i]; while (!step.isNil()) { LuaRef texts = step[1]; LuaRef images = step[2]; if (!texts.isTable() || !images.isTable()) { g_logger->logError("CutsceneLoader", "Cutscene [" + filename + "]: step table not resolved, there must be one table for texts and one for images."); return cutsceneData; } CutsceneStep cutsceneStep; // resolve texts int j = 1; LuaRef text = texts[j]; while (!text.isNil()) { LuaRef textString = text[1]; LuaRef textTime = text[2]; if (!textString.isString() || !textTime.isNumber()) { g_logger->logError("CutsceneLoader", "Cutscene [" + filename + "]: text table not resolved, text string must be of type string and text time of type number."); return cutsceneData; } CutsceneText cutsceneText; cutsceneText.text = textString.cast<std::string>(); cutsceneText.time = sf::seconds(static_cast<float>(textTime.cast<int>())); cutsceneStep.texts.push_back(cutsceneText); j++; text = texts[j]; } // resolve images j = 1; LuaRef image = images[j]; while (!image.isNil()) { LuaRef imagePath = image[1]; LuaRef velocity = image[2]; LuaRef angle = image[3]; if (!imagePath.isString() || !velocity.isNumber() || !angle.isNumber()) { g_logger->logError("CutsceneLoader", "Cutscene [" + filename + "]: image table not resolved, image path must be of type string and velocity and angle of type number."); return cutsceneData; } float phi = degToRad(static_cast<float>(angle.cast<int>() - 90)); float speed = static_cast<float>(velocity.cast<int>()); CutsceneImage cutsceneImage; cutsceneImage.imagePath = foldername + imagePath.cast<std::string>(); cutsceneImage.velocity.x = std::round(speed * std::cos(phi)); cutsceneImage.velocity.y = std::round(speed * std::sin(phi)); cutsceneStep.images.push_back(cutsceneImage); j++; image = images[j]; } cutsceneData.steps.push_back(cutsceneStep); i++; step = steps[i]; } } cutsceneData.id = cutsceneID; return cutsceneData; }