Load shop keywords and gold, update shop gold
Gold is loaded into merchant chest after merchandise is loaded now. Gold is not saved to the merchandise list, but if owner takes or stores gold the change is saved to the shop separately. Gold refreshes after any transaction.
This commit is contained in:
parent
289ec598d4
commit
17d428d385
@ -286,9 +286,6 @@ void LoadRefsTask(FFIResult<RawInteriorRefData> result, RE::TESObjectREFR* targe
|
|||||||
RE::BGSKeyword* toggle_keyword = data_handler->LookupForm<RE::BGSKeyword>(KEYWORD_TOGGLE, MOD_NAME);
|
RE::BGSKeyword* toggle_keyword = data_handler->LookupForm<RE::BGSKeyword>(KEYWORD_TOGGLE, MOD_NAME);
|
||||||
RE::BGSKeyword* next_keyword = data_handler->LookupForm<RE::BGSKeyword>(KEYWORD_NEXT, MOD_NAME);
|
RE::BGSKeyword* next_keyword = data_handler->LookupForm<RE::BGSKeyword>(KEYWORD_NEXT, MOD_NAME);
|
||||||
RE::BGSKeyword* prev_keyword = data_handler->LookupForm<RE::BGSKeyword>(KEYWORD_PREV, MOD_NAME);
|
RE::BGSKeyword* prev_keyword = data_handler->LookupForm<RE::BGSKeyword>(KEYWORD_PREV, MOD_NAME);
|
||||||
RE::BGSKeyword* vendor_item_armor_keyword = RE::TESForm::LookupByID<RE::BGSKeyword>(KEYWORD_VENDOR_ITEM_ARMOR);
|
|
||||||
RE::BGSListForm* vendor_items = data_handler->LookupForm<RE::BGSListForm>(FORM_LIST_VENDOR_ITEMS, MOD_NAME);
|
|
||||||
RE::TESFaction* vendor_services_faction = data_handler->LookupForm<RE::TESFaction>(FACTION_SERVICES_VENDOR, MOD_NAME);
|
|
||||||
|
|
||||||
SKSE::RegistrationMap<bool, std::vector<RE::TESObjectREFR*>> successReg = SKSE::RegistrationMap<bool, std::vector<RE::TESObjectREFR*>>();
|
SKSE::RegistrationMap<bool, std::vector<RE::TESObjectREFR*>> successReg = SKSE::RegistrationMap<bool, std::vector<RE::TESObjectREFR*>>();
|
||||||
successReg.Register(quest, RE::BSFixedString("OnLoadInteriorRefListSuccess"));
|
successReg.Register(quest, RE::BSFixedString("OnLoadInteriorRefListSuccess"));
|
||||||
@ -462,11 +459,6 @@ void LoadRefsTask(FFIResult<RawInteriorRefData> result, RE::TESObjectREFR* targe
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: load shop vendor(s)
|
// TODO: load shop vendor(s)
|
||||||
|
|
||||||
// TODO: load these values from shop config data
|
|
||||||
vendor_items->ClearData();
|
|
||||||
vendor_items->AddForm(vendor_item_armor_keyword);
|
|
||||||
vendor_services_faction->vendorData.vendorValues.notBuySell = false;
|
|
||||||
} else {
|
} else {
|
||||||
const char * error = result.AsErr();
|
const char * error = result.AsErr();
|
||||||
logger::error(FMT_STRING("LoadInteriorRefList get_interior_ref_list error: {}"), error);
|
logger::error(FMT_STRING("LoadInteriorRefList get_interior_ref_list error: {}"), error);
|
||||||
|
@ -307,7 +307,6 @@ void FillShelf(
|
|||||||
std::tuple modifiers = CalculatePriceModifiers();
|
std::tuple modifiers = CalculatePriceModifiers();
|
||||||
float price_factor = std::get<0>(modifiers);
|
float price_factor = std::get<0>(modifiers);
|
||||||
float buy_price_modifier = std::get<1>(modifiers);
|
float buy_price_modifier = std::get<1>(modifiers);
|
||||||
float sell_price_modifier = std::get<2>(modifiers);
|
|
||||||
|
|
||||||
RE::NiPoint3 shelf_position = merchant_shelf->data.location;
|
RE::NiPoint3 shelf_position = merchant_shelf->data.location;
|
||||||
RE::NiPoint3 shelf_angle = merchant_shelf->data.angle;
|
RE::NiPoint3 shelf_angle = merchant_shelf->data.angle;
|
||||||
@ -981,7 +980,6 @@ void CreateMerchandiseListImpl(
|
|||||||
RE::TESObjectREFR* merchant_chest
|
RE::TESObjectREFR* merchant_chest
|
||||||
) {
|
) {
|
||||||
logger::info("Entered CreateMerchandiseListImpl");
|
logger::info("Entered CreateMerchandiseListImpl");
|
||||||
RE::TESDataHandler* data_handler = RE::TESDataHandler::GetSingleton();
|
|
||||||
std::vector<RawMerchandise> merch_records;
|
std::vector<RawMerchandise> merch_records;
|
||||||
std::vector<std::vector<const char*>> keyword_strings;
|
std::vector<std::vector<const char*>> keyword_strings;
|
||||||
|
|
||||||
@ -1015,6 +1013,10 @@ void CreateMerchandiseListImpl(
|
|||||||
uint32_t form_type = (uint32_t)base->GetFormType();
|
uint32_t form_type = (uint32_t)base->GetFormType();
|
||||||
uint32_t quantity = entry_data->countDelta;
|
uint32_t quantity = entry_data->countDelta;
|
||||||
RE::FormID form_id = base->GetFormID();
|
RE::FormID form_id = base->GetFormID();
|
||||||
|
if (form_id == 15) { // gold
|
||||||
|
logger::info("CreateMerchandiseList ignoring gold in merchant chest");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
logger::info(FMT_STRING("CreateMerchandiseList quantity: {:d}"), quantity);
|
logger::info(FMT_STRING("CreateMerchandiseList quantity: {:d}"), quantity);
|
||||||
logger::info(FMT_STRING("CreateMerchandiseList base form_id: {:x}, name: {}, type: {:x}"), (uint32_t)form_id, name, (uint32_t)form_type);
|
logger::info(FMT_STRING("CreateMerchandiseList base form_id: {:x}, name: {}, type: {:x}"), (uint32_t)form_id, name, (uint32_t)form_type);
|
||||||
|
|
||||||
|
240
src/BRShop.cpp
240
src/BRShop.cpp
@ -1,4 +1,5 @@
|
|||||||
#include "bindings.h"
|
#include "bindings.h"
|
||||||
|
#include "FormIds.h"
|
||||||
|
|
||||||
void CreateShopImpl(RE::BSFixedString api_url, RE::BSFixedString api_key, RE::BSFixedString name, RE::BSFixedString description, RE::TESQuest* quest) {
|
void CreateShopImpl(RE::BSFixedString api_url, RE::BSFixedString api_key, RE::BSFixedString name, RE::BSFixedString description, RE::TESQuest* quest) {
|
||||||
logger::info("Entered CreateShopImpl");
|
logger::info("Entered CreateShopImpl");
|
||||||
@ -7,7 +8,8 @@ void CreateShopImpl(RE::BSFixedString api_url, RE::BSFixedString api_key, RE::BS
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SKSE::RegistrationMap<int, RE::BSFixedString, RE::BSFixedString> successReg = SKSE::RegistrationMap<int, RE::BSFixedString, RE::BSFixedString>();
|
SKSE::RegistrationMap<int, RE::BSFixedString, RE::BSFixedString, int, RE::BSFixedString, std::vector<RE::BGSKeyword*>, bool> successReg =
|
||||||
|
SKSE::RegistrationMap<int, RE::BSFixedString, RE::BSFixedString, int, RE::BSFixedString, std::vector<RE::BGSKeyword*>, bool>();
|
||||||
successReg.Register(quest, RE::BSFixedString("OnCreateShopSuccess"));
|
successReg.Register(quest, RE::BSFixedString("OnCreateShopSuccess"));
|
||||||
SKSE::RegistrationMap<RE::BSFixedString> failReg = SKSE::RegistrationMap<RE::BSFixedString>();
|
SKSE::RegistrationMap<RE::BSFixedString> failReg = SKSE::RegistrationMap<RE::BSFixedString>();
|
||||||
failReg.Register(quest, RE::BSFixedString("OnCreateShopFail"));
|
failReg.Register(quest, RE::BSFixedString("OnCreateShopFail"));
|
||||||
@ -17,7 +19,24 @@ void CreateShopImpl(RE::BSFixedString api_url, RE::BSFixedString api_key, RE::BS
|
|||||||
if (result.IsOk()) {
|
if (result.IsOk()) {
|
||||||
RawShop shop = result.AsOk();
|
RawShop shop = result.AsOk();
|
||||||
logger::info(FMT_STRING("CreateShop success: {}"), shop.id);
|
logger::info(FMT_STRING("CreateShop success: {}"), shop.id);
|
||||||
successReg.SendEvent(shop.id, RE::BSFixedString(shop.name), RE::BSFixedString(shop.description));
|
std::vector<RE::BGSKeyword*> keyword_forms;
|
||||||
|
for (int i = 0; i < shop.vendor_keywords_len; i++) {
|
||||||
|
RE::BSFixedString keyword = shop.vendor_keywords[i];
|
||||||
|
logger::info(FMT_STRING("GetShop keyword {:d}: {}"), i, keyword);
|
||||||
|
|
||||||
|
RE::TESForm* form = RE::TESForm::LookupByEditorID(keyword);
|
||||||
|
if (!form) { // form is not found, might be in an uninstalled mod
|
||||||
|
logger::warn(FMT_STRING("GetShop could not find keyword form for: {}"), keyword);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
RE::BGSKeyword* keyword_form = static_cast<RE::BGSKeyword*>(form);
|
||||||
|
if (!keyword_form) {
|
||||||
|
logger::warn(FMT_STRING("GetShop could cast form to keyword with id {:x} for: {}"), (uint32_t)form->GetFormID(), keyword);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
keyword_forms.push_back(keyword_form);
|
||||||
|
}
|
||||||
|
successReg.SendEvent(shop.id, RE::BSFixedString(shop.name), RE::BSFixedString(shop.description), shop.gold, RE::BSFixedString(shop.shop_type), keyword_forms, shop.vendor_keywords_exclude);
|
||||||
} else {
|
} else {
|
||||||
const char* error = result.AsErr();
|
const char* error = result.AsErr();
|
||||||
logger::error(FMT_STRING("CreateShop failure: {}"), error);
|
logger::error(FMT_STRING("CreateShop failure: {}"), error);
|
||||||
@ -39,24 +58,58 @@ bool CreateShop(RE::StaticFunctionTag*, RE::BSFixedString api_url, RE::BSFixedSt
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateShopImpl(RE::BSFixedString api_url, RE::BSFixedString api_key, int32_t id, RE::BSFixedString name, RE::BSFixedString description, RE::TESQuest* quest) {
|
void UpdateShopImpl(
|
||||||
|
RE::BSFixedString api_url,
|
||||||
|
RE::BSFixedString api_key,
|
||||||
|
int32_t id,
|
||||||
|
RE::BSFixedString name,
|
||||||
|
RE::BSFixedString description,
|
||||||
|
int gold,
|
||||||
|
RE::BSFixedString shop_type,
|
||||||
|
std::vector<RE::BGSKeyword*> keywords,
|
||||||
|
bool keywords_exclude,
|
||||||
|
RE::TESQuest* quest
|
||||||
|
) {
|
||||||
logger::info("Entered UpdateShopImpl");
|
logger::info("Entered UpdateShopImpl");
|
||||||
if (!quest) {
|
if (!quest) {
|
||||||
logger::error("UpdateShopImpl quest is null!");
|
logger::error("UpdateShopImpl quest is null!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SKSE::RegistrationMap<int, RE::BSFixedString, RE::BSFixedString> successReg = SKSE::RegistrationMap<int, RE::BSFixedString, RE::BSFixedString>();
|
SKSE::RegistrationMap<int, RE::BSFixedString, RE::BSFixedString, int, RE::BSFixedString, std::vector<RE::BGSKeyword*>, bool> successReg =
|
||||||
|
SKSE::RegistrationMap<int, RE::BSFixedString, RE::BSFixedString, int, RE::BSFixedString, std::vector<RE::BGSKeyword*>, bool>();
|
||||||
successReg.Register(quest, RE::BSFixedString("OnUpdateShopSuccess"));
|
successReg.Register(quest, RE::BSFixedString("OnUpdateShopSuccess"));
|
||||||
SKSE::RegistrationMap<RE::BSFixedString> failReg = SKSE::RegistrationMap<RE::BSFixedString>();
|
SKSE::RegistrationMap<RE::BSFixedString> failReg = SKSE::RegistrationMap<RE::BSFixedString>();
|
||||||
failReg.Register(quest, RE::BSFixedString("OnUpdateShopFail"));
|
failReg.Register(quest, RE::BSFixedString("OnUpdateShopFail"));
|
||||||
|
|
||||||
logger::info(FMT_STRING("UpdateShop api_url: {}, api_key: {}, name: {}, description: {}"), api_url, api_key, name, description);
|
std::vector<const char*> keyword_strings;
|
||||||
FFIResult<RawShop> result = update_shop(api_url.c_str(), api_key.c_str(), id, name.c_str(), description.c_str());
|
for (auto keyword = keywords.begin(); keyword != keywords.end(); ++keyword) {
|
||||||
|
keyword_strings.push_back((*keyword)->GetFormEditorID());
|
||||||
|
}
|
||||||
|
|
||||||
|
logger::info(FMT_STRING("UpdateShop api_url: {}, api_key: {}, name: {}, description: {}, gold: {}, shop_type: {}, keywords.size(): {}, keywords_exclude: {}"), api_url, api_key, name, description, gold, shop_type, keywords.size(), keywords_exclude);
|
||||||
|
FFIResult<RawShop> result = update_shop(api_url.c_str(), api_key.c_str(), id, name.c_str(), description.c_str(), gold, shop_type.c_str(), &keyword_strings[0], keyword_strings.size(), keywords_exclude);
|
||||||
if (result.IsOk()) {
|
if (result.IsOk()) {
|
||||||
RawShop shop = result.AsOk();
|
RawShop shop = result.AsOk();
|
||||||
logger::info(FMT_STRING("UpdateShop success: {}"), shop.id);
|
logger::info(FMT_STRING("UpdateShop success: {}"), shop.id);
|
||||||
successReg.SendEvent(shop.id, RE::BSFixedString(shop.name), RE::BSFixedString(shop.description));
|
std::vector<RE::BGSKeyword*> keyword_forms;
|
||||||
|
for (int i = 0; i < shop.vendor_keywords_len; i++) {
|
||||||
|
RE::BSFixedString keyword = shop.vendor_keywords[i];
|
||||||
|
logger::info(FMT_STRING("GetShop keyword {:d}: {}"), i, keyword);
|
||||||
|
|
||||||
|
RE::TESForm* form = RE::TESForm::LookupByEditorID(keyword);
|
||||||
|
if (!form) { // form is not found, might be in an uninstalled mod
|
||||||
|
logger::warn(FMT_STRING("GetShop could not find keyword form for: {}"), keyword);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
RE::BGSKeyword* keyword_form = static_cast<RE::BGSKeyword*>(form);
|
||||||
|
if (!keyword_form) {
|
||||||
|
logger::warn(FMT_STRING("GetShop could cast form to keyword with id {:x} for: {}"), (uint32_t)form->GetFormID(), keyword);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
keyword_forms.push_back(keyword_form);
|
||||||
|
}
|
||||||
|
successReg.SendEvent(shop.id, RE::BSFixedString(shop.name), RE::BSFixedString(shop.description), shop.gold, RE::BSFixedString(shop.shop_type), keyword_forms, shop.vendor_keywords_exclude);
|
||||||
} else {
|
} else {
|
||||||
const char* error = result.AsErr();
|
const char* error = result.AsErr();
|
||||||
logger::error(FMT_STRING("UpdateShop failure: {}"), error);
|
logger::error(FMT_STRING("UpdateShop failure: {}"), error);
|
||||||
@ -66,14 +119,26 @@ void UpdateShopImpl(RE::BSFixedString api_url, RE::BSFixedString api_key, int32_
|
|||||||
failReg.Unregister(quest);
|
failReg.Unregister(quest);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UpdateShop(RE::StaticFunctionTag*, RE::BSFixedString api_url, RE::BSFixedString api_key, int32_t id, RE::BSFixedString name, RE::BSFixedString description, RE::TESQuest* quest) {
|
bool UpdateShop(
|
||||||
|
RE::StaticFunctionTag*,
|
||||||
|
RE::BSFixedString api_url,
|
||||||
|
RE::BSFixedString api_key,
|
||||||
|
int32_t id,
|
||||||
|
RE::BSFixedString name,
|
||||||
|
RE::BSFixedString description,
|
||||||
|
int gold,
|
||||||
|
RE::BSFixedString shop_type,
|
||||||
|
std::vector<RE::BGSKeyword*> keywords,
|
||||||
|
bool keywords_exclude,
|
||||||
|
RE::TESQuest* quest
|
||||||
|
) {
|
||||||
logger::info("Entered UpdateShop");
|
logger::info("Entered UpdateShop");
|
||||||
if (!quest) {
|
if (!quest) {
|
||||||
logger::error("UpdateShop quest is null!");
|
logger::error("UpdateShop quest is null!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::thread thread(UpdateShopImpl, api_url, api_key, id, name, description, quest);
|
std::thread thread(UpdateShopImpl, api_url, api_key, id, name, description, gold, shop_type, keywords, keywords_exclude, quest);
|
||||||
thread.detach();
|
thread.detach();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -85,7 +150,8 @@ void GetShopImpl(RE::BSFixedString api_url, RE::BSFixedString api_key, int32_t i
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SKSE::RegistrationMap<int, RE::BSFixedString, RE::BSFixedString> successReg = SKSE::RegistrationMap<int, RE::BSFixedString, RE::BSFixedString>();
|
SKSE::RegistrationMap<int, RE::BSFixedString, RE::BSFixedString, int, RE::BSFixedString, std::vector<RE::BGSKeyword*>, bool> successReg =
|
||||||
|
SKSE::RegistrationMap<int, RE::BSFixedString, RE::BSFixedString, int, RE::BSFixedString, std::vector<RE::BGSKeyword*>, bool>();
|
||||||
successReg.Register(quest, RE::BSFixedString("OnGetShopSuccess"));
|
successReg.Register(quest, RE::BSFixedString("OnGetShopSuccess"));
|
||||||
SKSE::RegistrationMap<RE::BSFixedString> failReg = SKSE::RegistrationMap<RE::BSFixedString>();
|
SKSE::RegistrationMap<RE::BSFixedString> failReg = SKSE::RegistrationMap<RE::BSFixedString>();
|
||||||
failReg.Register(quest, RE::BSFixedString("OnGetShopFail"));
|
failReg.Register(quest, RE::BSFixedString("OnGetShopFail"));
|
||||||
@ -95,7 +161,24 @@ void GetShopImpl(RE::BSFixedString api_url, RE::BSFixedString api_key, int32_t i
|
|||||||
if (result.IsOk()) {
|
if (result.IsOk()) {
|
||||||
RawShop shop = result.AsOk();
|
RawShop shop = result.AsOk();
|
||||||
logger::info(FMT_STRING("GetShop success: {}"), shop.id);
|
logger::info(FMT_STRING("GetShop success: {}"), shop.id);
|
||||||
successReg.SendEvent(shop.id, RE::BSFixedString(shop.name), RE::BSFixedString(shop.description));
|
std::vector<RE::BGSKeyword*> keyword_forms;
|
||||||
|
for (int i = 0; i < shop.vendor_keywords_len; i++) {
|
||||||
|
RE::BSFixedString keyword = shop.vendor_keywords[i];
|
||||||
|
logger::info(FMT_STRING("GetShop keyword {:d}: {}"), i, keyword);
|
||||||
|
|
||||||
|
RE::TESForm* form = RE::TESForm::LookupByEditorID(keyword);
|
||||||
|
if (!form) { // form is not found, might be in an uninstalled mod
|
||||||
|
logger::warn(FMT_STRING("GetShop could not find keyword form for: {}"), keyword);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
RE::BGSKeyword* keyword_form = static_cast<RE::BGSKeyword*>(form);
|
||||||
|
if (!keyword_form) {
|
||||||
|
logger::warn(FMT_STRING("GetShop could cast form to keyword with id {:x} for: {}"), (uint32_t)form->GetFormID(), keyword);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
keyword_forms.push_back(keyword_form);
|
||||||
|
}
|
||||||
|
successReg.SendEvent(shop.id, RE::BSFixedString(shop.name), RE::BSFixedString(shop.description), shop.gold, RE::BSFixedString(shop.shop_type), keyword_forms, shop.vendor_keywords_exclude);
|
||||||
} else {
|
} else {
|
||||||
const char* error = result.AsErr();
|
const char* error = result.AsErr();
|
||||||
logger::error(FMT_STRING("GetShop failure: {}"), error);
|
logger::error(FMT_STRING("GetShop failure: {}"), error);
|
||||||
@ -125,7 +208,8 @@ void ListShopsImpl(RE::BSFixedString api_url, RE::BSFixedString api_key, RE::TES
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Since Papyrus arrays are single-type, the array of shops from the API needs to be decomposed into multiple arrays for each shop field
|
// Since Papyrus arrays are single-type, the array of shops from the API needs to be decomposed into multiple arrays for each shop field
|
||||||
SKSE::RegistrationMap<std::vector<int>, std::vector<RE::BSFixedString>, std::vector<RE::BSFixedString>> successReg = SKSE::RegistrationMap<std::vector<int>, std::vector<RE::BSFixedString>, std::vector<RE::BSFixedString>>();
|
SKSE::RegistrationMap<std::vector<int>, std::vector<RE::BSFixedString>, std::vector<RE::BSFixedString>, std::vector<int>, std::vector<RE::BSFixedString>, std::vector<RE::BGSKeyword*>, std::vector<bool>> successReg =
|
||||||
|
SKSE::RegistrationMap<std::vector<int>, std::vector<RE::BSFixedString>, std::vector<RE::BSFixedString>, std::vector<int>, std::vector<RE::BSFixedString>, std::vector<RE::BGSKeyword*>, std::vector<bool>>();
|
||||||
successReg.Register(quest, RE::BSFixedString("OnListShopsSuccess"));
|
successReg.Register(quest, RE::BSFixedString("OnListShopsSuccess"));
|
||||||
SKSE::RegistrationMap<RE::BSFixedString> failReg = SKSE::RegistrationMap<RE::BSFixedString>();
|
SKSE::RegistrationMap<RE::BSFixedString> failReg = SKSE::RegistrationMap<RE::BSFixedString>();
|
||||||
failReg.Register(quest, RE::BSFixedString("OnListShopsFail"));
|
failReg.Register(quest, RE::BSFixedString("OnListShopsFail"));
|
||||||
@ -139,13 +223,41 @@ void ListShopsImpl(RE::BSFixedString api_url, RE::BSFixedString api_key, RE::TES
|
|||||||
std::vector<int> id_vec = std::vector<int>();
|
std::vector<int> id_vec = std::vector<int>();
|
||||||
std::vector<RE::BSFixedString> name_vec = std::vector<RE::BSFixedString>();
|
std::vector<RE::BSFixedString> name_vec = std::vector<RE::BSFixedString>();
|
||||||
std::vector<RE::BSFixedString> description_vec = std::vector<RE::BSFixedString>();
|
std::vector<RE::BSFixedString> description_vec = std::vector<RE::BSFixedString>();
|
||||||
|
std::vector<int> gold_vec = std::vector<int>();
|
||||||
|
std::vector<RE::BSFixedString> shop_type_vec = std::vector<RE::BSFixedString>();
|
||||||
|
std::vector<RE::BGSKeyword*> keywords_vec = std::vector<RE::BGSKeyword*>();
|
||||||
|
std::vector<bool> keywords_exclude_vec = std::vector<bool>();
|
||||||
for (int i = 0; i < vec.len; i++) {
|
for (int i = 0; i < vec.len; i++) {
|
||||||
RawShop shop = vec.ptr[i];
|
RawShop shop = vec.ptr[i];
|
||||||
id_vec.push_back(shop.id);
|
id_vec.push_back(shop.id);
|
||||||
name_vec.push_back(RE::BSFixedString(shop.name));
|
name_vec.push_back(RE::BSFixedString(shop.name));
|
||||||
description_vec.push_back(RE::BSFixedString(shop.description));
|
description_vec.push_back(RE::BSFixedString(shop.description));
|
||||||
|
gold_vec.push_back(shop.gold);
|
||||||
|
shop_type_vec.push_back(RE::BSFixedString(shop.shop_type));
|
||||||
|
std::vector<RE::BGSKeyword*> keyword_forms;
|
||||||
|
for (int j = 0; j < shop.vendor_keywords_len; j++) {
|
||||||
|
RE::BSFixedString keyword = shop.vendor_keywords[j];
|
||||||
|
logger::info(FMT_STRING("ListShop keyword {:d}: {}"), j, keyword);
|
||||||
|
|
||||||
|
RE::TESForm* form = RE::TESForm::LookupByEditorID(keyword);
|
||||||
|
if (!form) { // form is not found, might be in an uninstalled mod
|
||||||
|
logger::warn(FMT_STRING("ListShop could not find keyword form for: {}"), keyword);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
RE::BGSKeyword* keyword_form = static_cast<RE::BGSKeyword*>(form);
|
||||||
|
if (!keyword_form) {
|
||||||
|
logger::warn(FMT_STRING("ListShop could cast form to keyword with id {:x} for: {}"), (uint32_t)form->GetFormID(), keyword);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
keyword_forms.push_back(keyword_form);
|
||||||
|
}
|
||||||
|
// Since papyrus doesn't have multi-dimensional arrays, I have to fake it with one flat array with each keyword list separated by a nullptr
|
||||||
|
keywords_vec.insert(keywords_vec.end(), keyword_forms.begin(), keyword_forms.end());
|
||||||
|
keywords_vec.push_back(nullptr);
|
||||||
|
keywords_exclude_vec.push_back(shop.vendor_keywords_exclude);
|
||||||
|
|
||||||
}
|
}
|
||||||
successReg.SendEvent(id_vec, name_vec, description_vec);
|
successReg.SendEvent(id_vec, name_vec, description_vec, gold_vec, shop_type_vec, keywords_vec, keywords_exclude_vec);
|
||||||
} else {
|
} else {
|
||||||
const char* error = result.AsErr();
|
const char* error = result.AsErr();
|
||||||
logger::error(FMT_STRING("ListShops failure: {}"), error);
|
logger::error(FMT_STRING("ListShops failure: {}"), error);
|
||||||
@ -155,6 +267,27 @@ void ListShopsImpl(RE::BSFixedString api_url, RE::BSFixedString api_key, RE::TES
|
|||||||
failReg.Unregister(quest);
|
failReg.Unregister(quest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<RE::BGSKeyword*> GetKeywordsSubArray(RE::StaticFunctionTag*, std::vector<RE::BGSKeyword*> flat_keywords_array, int sub_array_index) {
|
||||||
|
int i = 0;
|
||||||
|
int current_sub_array = 0;
|
||||||
|
while (current_sub_array < sub_array_index) {
|
||||||
|
if (flat_keywords_array[i] == nullptr) {
|
||||||
|
current_sub_array += 1;
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
std::vector<RE::BGSKeyword*> sub_array = std::vector<RE::BGSKeyword*>();
|
||||||
|
while (true) {
|
||||||
|
if (flat_keywords_array[i] == nullptr) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
sub_array.push_back(flat_keywords_array[i]);
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
return sub_array;
|
||||||
|
}
|
||||||
|
|
||||||
bool ListShops(RE::StaticFunctionTag*, RE::BSFixedString api_url, RE::BSFixedString api_key, RE::TESQuest* quest) {
|
bool ListShops(RE::StaticFunctionTag*, RE::BSFixedString api_url, RE::BSFixedString api_key, RE::TESQuest* quest) {
|
||||||
logger::info("Entered ListShops");
|
logger::info("Entered ListShops");
|
||||||
if (!quest) {
|
if (!quest) {
|
||||||
@ -166,3 +299,84 @@ bool ListShops(RE::StaticFunctionTag*, RE::BSFixedString api_url, RE::BSFixedStr
|
|||||||
thread.detach();
|
thread.detach();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SetVendorKeywords(RE::StaticFunctionTag*, std::vector<RE::BGSKeyword*> keywords, bool keywords_exclude) {
|
||||||
|
logger::info("Entered SetVendorKeywords");
|
||||||
|
RE::TESDataHandler * data_handler = RE::TESDataHandler::GetSingleton();
|
||||||
|
RE::BGSListForm* vendor_items = data_handler->LookupForm<RE::BGSListForm>(FORM_LIST_VENDOR_ITEMS, MOD_NAME);
|
||||||
|
RE::TESFaction* vendor_services_faction = data_handler->LookupForm<RE::TESFaction>(FACTION_SERVICES_VENDOR, MOD_NAME);
|
||||||
|
if (!vendor_items) {
|
||||||
|
logger::error("SetVendorKeywords vendor_items could not be loaded!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!vendor_services_faction) {
|
||||||
|
logger::error("SetVendorKeywords vendor_services_faction could not be loaded!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
vendor_items->ClearData();
|
||||||
|
for (auto keyword = keywords.begin(); keyword != keywords.end(); ++keyword) {
|
||||||
|
vendor_items->AddForm(*keyword);
|
||||||
|
}
|
||||||
|
vendor_services_faction->vendorData.vendorValues.notBuySell = keywords_exclude;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RefreshShopGoldImpl(RE::BSFixedString api_url, RE::BSFixedString api_key, int32_t id, RE::TESObjectREFR* merchant_chest) {
|
||||||
|
logger::info("Entered RefreshShopGoldImpl");
|
||||||
|
if (!merchant_chest) {
|
||||||
|
logger::error("RefreshShopGoldImpl merch_chest is null!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SKSE::RegistrationMap<int> successReg = SKSE::RegistrationMap<int>();
|
||||||
|
successReg.Register(merchant_chest, RE::BSFixedString("OnRefreshShopGoldSuccess"));
|
||||||
|
SKSE::RegistrationMap<RE::BSFixedString> failReg = SKSE::RegistrationMap<RE::BSFixedString>();
|
||||||
|
failReg.Register(merchant_chest, RE::BSFixedString("OnRefreshShopGoldFail"));
|
||||||
|
|
||||||
|
RE::TESForm* gold_form = RE::TESForm::LookupByID(15);
|
||||||
|
if (!gold_form) {
|
||||||
|
logger::error("RefreshShopGoldImpl failed to lookup gold form");
|
||||||
|
failReg.SendEvent(RE::BSFixedString("Failed to lookup gold form"));
|
||||||
|
successReg.Unregister(merchant_chest);
|
||||||
|
failReg.Unregister(merchant_chest);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
RE::TESBoundObject* gold = static_cast<RE::TESBoundObject*>(gold_form);
|
||||||
|
if (!gold) {
|
||||||
|
logger::error("RefreshShopGoldImpl failed to cast gold form to gold bound object");
|
||||||
|
failReg.SendEvent(RE::BSFixedString("Failed to cast gold form to gold bound object"));
|
||||||
|
successReg.Unregister(merchant_chest);
|
||||||
|
failReg.Unregister(merchant_chest);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger::info(FMT_STRING("RefreshShopGold api_url: {}, api_key: {}, id: {}"), api_url, api_key, id);
|
||||||
|
FFIResult<RawShop> result = get_shop(api_url.c_str(), api_key.c_str(), id);
|
||||||
|
if (result.IsOk()) {
|
||||||
|
RawShop shop = result.AsOk();
|
||||||
|
logger::info(FMT_STRING("RefreshShopGold success id: {} gold: {}"), shop.id, shop.gold);
|
||||||
|
if (shop.gold > 0) {
|
||||||
|
merchant_chest->AddObjectToContainer(gold, nullptr, shop.gold, merchant_chest);
|
||||||
|
}
|
||||||
|
successReg.SendEvent(shop.gold);
|
||||||
|
} else {
|
||||||
|
const char* error = result.AsErr();
|
||||||
|
logger::error(FMT_STRING("RefreshShopGold failure: {}"), error);
|
||||||
|
failReg.SendEvent(RE::BSFixedString(error));
|
||||||
|
}
|
||||||
|
successReg.Unregister(merchant_chest);
|
||||||
|
failReg.Unregister(merchant_chest);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RefreshShopGold(RE::StaticFunctionTag*, RE::BSFixedString api_url, RE::BSFixedString api_key, int32_t id, RE::TESObjectREFR* merchant_chest) {
|
||||||
|
logger::info("Entered RefreshShopGold");
|
||||||
|
if (!merchant_chest) {
|
||||||
|
logger::error("RefreshShopGold merch_chest is null!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::thread thread(RefreshShopGoldImpl, api_url, api_key, id, merchant_chest);
|
||||||
|
thread.detach();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
17
src/BRShop.h
17
src/BRShop.h
@ -1,6 +1,21 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
bool CreateShop(RE::StaticFunctionTag*, RE::BSFixedString api_url, RE::BSFixedString api_key, RE::BSFixedString name, RE::BSFixedString description, RE::TESQuest* quest);
|
bool CreateShop(RE::StaticFunctionTag*, RE::BSFixedString api_url, RE::BSFixedString api_key, RE::BSFixedString name, RE::BSFixedString description, RE::TESQuest* quest);
|
||||||
bool UpdateShop(RE::StaticFunctionTag*, RE::BSFixedString api_url, RE::BSFixedString api_key, int32_t id, RE::BSFixedString name, RE::BSFixedString description, RE::TESQuest* quest);
|
bool UpdateShop(
|
||||||
|
RE::StaticFunctionTag*,
|
||||||
|
RE::BSFixedString api_url,
|
||||||
|
RE::BSFixedString api_key,
|
||||||
|
int32_t id,
|
||||||
|
RE::BSFixedString name,
|
||||||
|
RE::BSFixedString description,
|
||||||
|
int gold,
|
||||||
|
RE::BSFixedString shop_type,
|
||||||
|
std::vector<RE::BGSKeyword*> keywords,
|
||||||
|
bool keywords_exclude,
|
||||||
|
RE::TESQuest* quest
|
||||||
|
);
|
||||||
bool GetShop(RE::StaticFunctionTag*, RE::BSFixedString api_url, RE::BSFixedString api_key, int32_t id, RE::TESQuest* quest);
|
bool GetShop(RE::StaticFunctionTag*, RE::BSFixedString api_url, RE::BSFixedString api_key, int32_t id, RE::TESQuest* quest);
|
||||||
bool ListShops(RE::StaticFunctionTag*, RE::BSFixedString api_url, RE::BSFixedString api_key, RE::TESQuest* quest);
|
bool ListShops(RE::StaticFunctionTag*, RE::BSFixedString api_url, RE::BSFixedString api_key, RE::TESQuest* quest);
|
||||||
|
std::vector<RE::BGSKeyword*> GetKeywordsSubArray(RE::StaticFunctionTag*, std::vector<RE::BGSKeyword*> flat_keywords_array, int sub_array_index);
|
||||||
|
bool SetVendorKeywords(RE::StaticFunctionTag*, std::vector<RE::BGSKeyword*> keywords, bool keywords_exclude);
|
||||||
|
bool RefreshShopGold(RE::StaticFunctionTag*, RE::BSFixedString api_url, RE::BSFixedString api_key, int32_t id, RE::TESObjectREFR* merchant_chest);
|
||||||
|
@ -19,6 +19,9 @@ bool RegisterFuncs(RE::BSScript::IVirtualMachine* a_vm)
|
|||||||
a_vm->RegisterFunction("Update", "BRShop", UpdateShop);
|
a_vm->RegisterFunction("Update", "BRShop", UpdateShop);
|
||||||
a_vm->RegisterFunction("Get", "BRShop", GetShop);
|
a_vm->RegisterFunction("Get", "BRShop", GetShop);
|
||||||
a_vm->RegisterFunction("List", "BRShop", ListShops);
|
a_vm->RegisterFunction("List", "BRShop", ListShops);
|
||||||
|
a_vm->RegisterFunction("GetKeywordsSubArray", "BRShop", GetKeywordsSubArray);
|
||||||
|
a_vm->RegisterFunction("SetVendorKeywords", "BRShop", SetVendorKeywords);
|
||||||
|
a_vm->RegisterFunction("RefreshGold", "BRShop", RefreshShopGold);
|
||||||
a_vm->RegisterFunction("Create", "BRInteriorRefList", CreateInteriorRefList);
|
a_vm->RegisterFunction("Create", "BRInteriorRefList", CreateInteriorRefList);
|
||||||
a_vm->RegisterFunction("ClearCell", "BRInteriorRefList", ClearCell);
|
a_vm->RegisterFunction("ClearCell", "BRInteriorRefList", ClearCell);
|
||||||
a_vm->RegisterFunction("Load", "BRInteriorRefList", LoadInteriorRefList);
|
a_vm->RegisterFunction("Load", "BRInteriorRefList", LoadInteriorRefList);
|
||||||
|
Loading…
Reference in New Issue
Block a user