Add CreateTransaction function

Also made some changes to the MerchandiseList functions to support the new buy item flow.
This commit is contained in:
Tyler Hallada 2020-11-02 10:36:17 -05:00
parent 5c03dace17
commit a0eea948fe
7 changed files with 255 additions and 46 deletions

View File

@ -223,6 +223,7 @@
<ClCompile Include="src\BRMerchandiseList.cpp" />
<ClCompile Include="src\BROwner.cpp" />
<ClCompile Include="src\BRShop.cpp" />
<ClCompile Include="src\BRTransaction.cpp" />
<ClCompile Include="src\main.cpp" />
<ClCompile Include="src\PCH.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
@ -241,6 +242,7 @@
<ClInclude Include="src\BRMerchandiseList.h" />
<ClInclude Include="src\BROwner.h" />
<ClInclude Include="src\BRShop.h" />
<ClInclude Include="src\BRTransaction.h" />
<ClInclude Include="src\NativeFunctions.h" />
<ClInclude Include="src\PCH.h" />
<ClInclude Include="src\version.h" />

View File

@ -27,6 +27,9 @@
<ClCompile Include="src\BRMerchandiseList.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="src\BRTransaction.cpp">
<Filter>src</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\PCH.h">
@ -53,6 +56,9 @@
<ClInclude Include="src\NativeFunctions.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="src\BRTransaction.h">
<Filter>src</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include=".clang-format" />

View File

@ -91,7 +91,8 @@ void LoadMerchTask(
RE::BGSKeyword* toggle_keyword,
RE::BGSKeyword* next_keyword,
RE::BGSKeyword* prev_keyword,
int page
int page,
bool loadMaxPageIfOver
) {
if (!merchant_shelf) {
logger::error("LoadMerchTask merchant_shelf is null!");
@ -106,7 +107,7 @@ void LoadMerchTask(
// Placing the refs must be done on the main thread otherwise disabling & deleting refs in ClearMerchandiseImpl causes a crash
auto task = SKSE::GetTaskInterface();
task->AddTask([result, merchant_shelf, activator_static, shelf_keyword, chest_keyword, item_keyword, activator_keyword, prev_keyword, next_keyword, page, toggle_ref]() {
task->AddTask([result, merchant_shelf, activator_static, shelf_keyword, chest_keyword, item_keyword, activator_keyword, prev_keyword, next_keyword, page, loadMaxPageIfOver, toggle_ref]() {
RE::TESDataHandler * data_handler = RE::TESDataHandler::GetSingleton();
RE::BSScript::Internal::VirtualMachine * a_vm = RE::BSScript::Internal::VirtualMachine::GetSingleton();
using func_t = decltype(&PlaceAtMe);
@ -136,14 +137,19 @@ void LoadMerchTask(
RawMerchandiseVec vec = result.AsOk();
logger::info(FMT_STRING("LoadMerchandise vec len: {:d}, cap: {:d}"), vec.len, vec.cap);
int max_page = std::ceil((float)(vec.len) / (float)9);
int load_page = page;
if (vec.len > 0 && page > max_page) {
if (loadMaxPageIfOver) {
load_page = max_page;
} else {
logger::info(FMT_STRING("LoadMerchandise page {:d} is greater than max_page {:d}, doing nothing"), page, max_page);
successReg.SendEvent(true);
successReg.Unregister(toggle_ref);
failReg.Unregister(toggle_ref);
return;
}
}
if (!ClearMerchandiseImpl(merchant_chest, merchant_shelf, activator_static, shelf_keyword, item_keyword, activator_keyword)) {
logger::error("LoadMerchandise ClearMerchandiseImpl returned a fail code");
@ -161,7 +167,7 @@ void LoadMerchTask(
for (int i = 0; i < vec.len; i++) {
RawMerchandise merch = vec.ptr[i];
logger::info(FMT_STRING("LoadMerchandise item: {:d}"), i);
if (i < (page - 1) * 9 || i >= (page - 1) * 9 + 9) {
if (i < (load_page - 1) * 9 || i >= (load_page - 1) * 9 + 9) {
continue;
}
@ -194,11 +200,6 @@ void LoadMerchTask(
RE::ExtraLinkedRef * item_extra_linked_ref = (RE::ExtraLinkedRef*)RE::BSExtraData::Create(sizeof(RE::ExtraLinkedRef), extra_linked_ref_vtbl.address());
ref->extraList.Add(item_extra_linked_ref);
// This extra count stored on the activator_ref indicates the quanity of the merchandise item it is linked to
RE::ExtraCount * extra_page_num = (RE::ExtraCount*)RE::BSExtraData::Create(sizeof(RE::ExtraCount), RE::Offset::ExtraCount::Vtbl.address());
extra_page_num->count = merch.quantity;
activator_ref->extraList.Add(extra_page_num);
float scale = 1;
int max_over_bound = 0;
if (max_over_bound < bound_x - 34) {
@ -253,11 +254,19 @@ void LoadMerchTask(
logger::info(FMT_STRING("LoadMerchandise absolute rotated position x: {:.2f}, y: {:.2f}, z: {:.2f}"), ref_position.x, ref_position.y, ref_position.z);
MoveTo_Native(ref, ref->CreateRefHandle(), cell, cell->worldSpace, ref_position - RE::NiPoint3(10000, 10000, 10000), ref_angle);
MoveTo_Native(activator_ref, activator_ref->CreateRefHandle(), cell, cell->worldSpace, ref_position, ref_angle);
RE::BSFixedString name = RE::BSFixedString::BSFixedString(ref->GetName());
RE::BSFixedString name = RE::BSFixedString::BSFixedString(fmt::format(FMT_STRING("{} for {:d}g ({:d})"), ref->GetName(), merch.price, merch.quantity));
activator_ref->SetDisplayName(name, true);
activator_ref->extraList.SetOwner(base); // I'm abusing "owner" to link the activator with the Form that should be bought once activated
activator_extra_linked_ref->linkedRefs.push_back({item_keyword, ref});
item_extra_linked_ref->linkedRefs.push_back({activator_keyword, activator_ref});
// I'm abusing the ExtraCount ExtraData type for storing the quantity and price of the merchandise the activator_ref is linked to
RE::ExtraCount * extra_quantity_price = activator_ref->extraList.GetByType<RE::ExtraCount>();
if (!extra_quantity_price) {
extra_quantity_price = (RE::ExtraCount*)RE::BSExtraData::Create(sizeof(RE::ExtraCount), RE::Offset::ExtraCount::Vtbl.address());
activator_ref->extraList.Add(extra_quantity_price);
}
extra_quantity_price->count = merch.quantity;
extra_quantity_price->pad14 = merch.price;
}
// I'm abusing the ExtraCount ExtraData type for storing the current page number state of the shelf
@ -266,7 +275,7 @@ void LoadMerchTask(
extra_page_num = (RE::ExtraCount*)RE::BSExtraData::Create(sizeof(RE::ExtraCount), RE::Offset::ExtraCount::Vtbl.address());
merchant_shelf->extraList.Add(extra_page_num);
}
extra_page_num->count = page;
extra_page_num->count = load_page;
logger::info(FMT_STRING("LoadMerchandise set shelf page to: {:d}"), merchant_shelf->extraList.GetCount());
// I'm abusing the ExtraCannotWear ExtraData type as a boolean marker which stores whether the shelf is in a loaded or cleared state
@ -296,15 +305,15 @@ void LoadMerchTask(
return;
}
toggle_ref->SetDisplayName("Clear merchandise", true);
if (page == max_page) {
if (load_page == max_page) {
next_ref->SetDisplayName("(No next page)", true);
} else {
next_ref->SetDisplayName(fmt::format("Advance to page {:d}", page + 1).c_str(), true);
next_ref->SetDisplayName(fmt::format("Advance to page {:d}", load_page + 1).c_str(), true);
}
if (page == 1) {
if (load_page == 1) {
prev_ref->SetDisplayName("(No previous page)", true);
} else {
prev_ref->SetDisplayName(fmt::format("Back to page {:d}", page - 1).c_str(), true);
prev_ref->SetDisplayName(fmt::format("Back to page {:d}", load_page - 1).c_str(), true);
}
} else {
const char * error = result.AsErr();
@ -333,12 +342,13 @@ void LoadMerchandiseImpl(
RE::BGSKeyword* toggle_keyword,
RE::BGSKeyword* next_keyword,
RE::BGSKeyword* prev_keyword,
int page
int page,
bool loadMaxPageIfOver
) {
logger::info("Entered LoadMerchandiseImpl");
logger::info(FMT_STRING("LoadMerchandise page: {:d}"), page);
LoadMerchTask(get_merchandise_list(api_url.c_str(), api_key.c_str(), merchandise_list_id), merchant_shelf, activator_static, shelf_keyword, chest_keyword, item_keyword, activator_keyword, toggle_keyword, next_keyword, prev_keyword, page);
LoadMerchTask(get_merchandise_list(api_url.c_str(), api_key.c_str(), merchandise_list_id), merchant_shelf, activator_static, shelf_keyword, chest_keyword, item_keyword, activator_keyword, toggle_keyword, next_keyword, prev_keyword, page, loadMaxPageIfOver);
}
void LoadMerchandiseByShopIdImpl(
@ -354,12 +364,13 @@ void LoadMerchandiseByShopIdImpl(
RE::BGSKeyword* toggle_keyword,
RE::BGSKeyword* next_keyword,
RE::BGSKeyword* prev_keyword,
int page
int page,
bool loadMaxPageIfOver
) {
logger::info("Entered LoadMerchandiseByShopIdImpl");
logger::info(FMT_STRING("LoadMerchandiseByShopIdImpl page: {:d}"), page);
LoadMerchTask(get_merchandise_list_by_shop_id(api_url.c_str(), api_key.c_str(), shop_id), merchant_shelf, activator_static, shelf_keyword, chest_keyword, item_keyword, activator_keyword, toggle_keyword, next_keyword, prev_keyword, page);
LoadMerchTask(get_merchandise_list_by_shop_id(api_url.c_str(), api_key.c_str(), shop_id), merchant_shelf, activator_static, shelf_keyword, chest_keyword, item_keyword, activator_keyword, toggle_keyword, next_keyword, prev_keyword, page, loadMaxPageIfOver);
}
bool ToggleMerchandise(
@ -418,7 +429,7 @@ bool ToggleMerchandise(
} else {
// Load merchandise
int page = merchant_shelf->extraList.GetCount();
std::thread thread(LoadMerchandiseByShopIdImpl, api_url, api_key, shop_id, merchant_shelf, activator_static, shelf_keyword, chest_keyword, item_keyword, activator_keyword, toggle_keyword, next_keyword, prev_keyword, page);
std::thread thread(LoadMerchandiseByShopIdImpl, api_url, api_key, shop_id, merchant_shelf, activator_static, shelf_keyword, chest_keyword, item_keyword, activator_keyword, toggle_keyword, next_keyword, prev_keyword, page, false);
thread.detach();
return true;
}
@ -451,7 +462,7 @@ bool LoadNextMerchandise(
page = page + 1;
}
std::thread thread(LoadMerchandiseByShopIdImpl, api_url, api_key, shop_id, merchant_shelf, activator_static, shelf_keyword, chest_keyword, item_keyword, activator_keyword, toggle_keyword, next_keyword, prev_keyword, page);
std::thread thread(LoadMerchandiseByShopIdImpl, api_url, api_key, shop_id, merchant_shelf, activator_static, shelf_keyword, chest_keyword, item_keyword, activator_keyword, toggle_keyword, next_keyword, prev_keyword, page, false);
thread.detach();
return true;
}
@ -487,7 +498,7 @@ bool LoadPrevMerchandise(
page = page - 1;
}
std::thread thread(LoadMerchandiseByShopIdImpl, api_url, api_key, shop_id, merchant_shelf, activator_static, shelf_keyword, chest_keyword, item_keyword, activator_keyword, toggle_keyword, next_keyword, prev_keyword, page);
std::thread thread(LoadMerchandiseByShopIdImpl, api_url, api_key, shop_id, merchant_shelf, activator_static, shelf_keyword, chest_keyword, item_keyword, activator_keyword, toggle_keyword, next_keyword, prev_keyword, page, false);
thread.detach();
return true;
}
@ -518,7 +529,7 @@ bool LoadMerchandiseByShopId(
if (!extra_is_loaded) {
// Load merchandise
int page = merchant_shelf->extraList.GetCount();
std::thread thread(LoadMerchandiseByShopIdImpl, api_url, api_key, shop_id, merchant_shelf, activator_static, shelf_keyword, chest_keyword, item_keyword, activator_keyword, toggle_keyword, next_keyword, prev_keyword, page);
std::thread thread(LoadMerchandiseByShopIdImpl, api_url, api_key, shop_id, merchant_shelf, activator_static, shelf_keyword, chest_keyword, item_keyword, activator_keyword, toggle_keyword, next_keyword, prev_keyword, page, true);
thread.detach();
return true;
} else {
@ -526,6 +537,37 @@ bool LoadMerchandiseByShopId(
}
}
bool RefreshMerchandise(
RE::StaticFunctionTag*,
RE::BSFixedString api_url,
RE::BSFixedString api_key,
uint32_t shop_id,
RE::TESObjectREFR* merchant_shelf,
RE::TESForm* activator_static,
RE::BGSKeyword* shelf_keyword,
RE::BGSKeyword* chest_keyword,
RE::BGSKeyword* item_keyword,
RE::BGSKeyword* activator_keyword,
RE::BGSKeyword* toggle_keyword,
RE::BGSKeyword* next_keyword,
RE::BGSKeyword* prev_keyword
) {
logger::info("Entered ClearMerchandise");
RE::TESObjectREFR * merchant_chest = merchant_shelf->GetLinkedRef(chest_keyword);
if (!merchant_chest) {
logger::error("ClearMerchandise could not find merchant_chest linked from merchant_shelf!");
return false;
}
int page = merchant_shelf->extraList.GetCount();
ClearMerchandiseImpl(merchant_chest, merchant_shelf, activator_static, shelf_keyword, item_keyword, activator_keyword);
std::thread thread(LoadMerchandiseByShopIdImpl, api_url, api_key, shop_id, merchant_shelf, activator_static, shelf_keyword, chest_keyword, item_keyword, activator_keyword, toggle_keyword, next_keyword, prev_keyword, page, true);
thread.detach();
return true;
}
bool ReplaceMerch3D(RE::StaticFunctionTag*, RE::TESObjectREFR* merchant_shelf, RE::TESForm* activator_static, RE::BGSKeyword* shelf_keyword, RE::BGSKeyword* item_keyword) {
logger::info("Entered ReplaceMerch3D");
@ -565,16 +607,6 @@ bool ReplaceMerch3D(RE::StaticFunctionTag*, RE::TESObjectREFR* merchant_shelf, R
return true;
}
RE::TESForm * BuyMerchandise(RE::StaticFunctionTag*, RE::TESObjectREFR * merchandise_activator) {
logger::info("Entered BuyMerchandise");
logger::info(FMT_STRING("BuyMerchandise activated ref: {}"), merchandise_activator->GetName());
RE::TESForm * owner = merchandise_activator->GetOwner();
logger::info(FMT_STRING("BuyMerchandise owner: {}"), owner->GetName());
logger::info(FMT_STRING("BuyMerchandise count: {:d}"), merchandise_activator->extraList.GetCount());
// TODO: do add item here
return owner;
}
void CreateMerchandiseListImpl(RE::BSFixedString api_url, RE::BSFixedString api_key, uint32_t shop_id, RE::TESObjectREFR* merchant_chest) {
logger::info("Entered CreateMerchandiseListImpl");
RE::TESDataHandler * data_handler = RE::TESDataHandler::GetSingleton();
@ -646,9 +678,9 @@ void CreateMerchandiseListImpl(RE::BSFixedString api_url, RE::BSFixedString api_
logger::info(FMT_STRING("CreateMerchandiseList base form file_name: {}, local_form_id"), mod_name, local_form_id);
// TODO: implement is_food
uint8_t is_food = 0;
// TODO: implement price
uint32_t price = 0;
bool is_food = false;
// TODO: allow user to set price
uint32_t price = base->GetGoldValue();
merch_records.push_back({
mod_name,
@ -691,3 +723,31 @@ bool CreateMerchandiseList(RE::StaticFunctionTag*, RE::BSFixedString api_url, RE
return true;
}
int GetMerchandiseQuantity(RE::StaticFunctionTag*, RE::TESObjectREFR* activator) {
logger::info("Entered GetMerchandiseQuantity");
if (!activator) {
logger::error("GetMerchandiseQuantity activator is null!");
return false;
}
return activator->extraList.GetCount();
}
int GetMerchandisePrice(RE::StaticFunctionTag*, RE::TESObjectREFR* activator) {
logger::info("Entered GetMerchandisePrice");
if (!activator) {
logger::error("GetMerchandisePrice activator is null!");
return false;
}
RE::ExtraCount * extra_quantity_price = activator->extraList.GetByType<RE::ExtraCount>();
int price = 0;
if (extra_quantity_price) {
price = extra_quantity_price->pad14;
} else {
logger::warn("GetMerchandisePrice ExtraCount not attached, returning price as 0");
}
return price;
}

View File

@ -13,7 +13,8 @@ bool ToggleMerchandise(
RE::BGSKeyword* activator_keyword,
RE::BGSKeyword* toggle_keyword,
RE::BGSKeyword* next_keyword,
RE::BGSKeyword* prev_keyword);
RE::BGSKeyword* prev_keyword
);
bool LoadNextMerchandise(
RE::StaticFunctionTag*,
RE::BSFixedString api_url,
@ -27,7 +28,8 @@ bool LoadNextMerchandise(
RE::BGSKeyword* activator_keyword,
RE::BGSKeyword* toggle_keyword,
RE::BGSKeyword* next_keyword,
RE::BGSKeyword* prev_keyword);
RE::BGSKeyword* prev_keyword
);
bool LoadPrevMerchandise(
RE::StaticFunctionTag*,
RE::BSFixedString api_url,
@ -41,7 +43,39 @@ bool LoadPrevMerchandise(
RE::BGSKeyword* activator_keyword,
RE::BGSKeyword* toggle_keyword,
RE::BGSKeyword* next_keyword,
RE::BGSKeyword* prev_keyword);
RE::BGSKeyword* prev_keyword
);
bool LoadMerchandiseByShopId(
RE::StaticFunctionTag*,
RE::BSFixedString api_url,
RE::BSFixedString api_key,
uint32_t shop_id,
RE::TESObjectREFR* merchant_shelf,
RE::TESForm* activator_static,
RE::BGSKeyword* shelf_keyword,
RE::BGSKeyword* chest_keyword,
RE::BGSKeyword* item_keyword,
RE::BGSKeyword* activator_keyword,
RE::BGSKeyword* toggle_keyword,
RE::BGSKeyword* next_keyword,
RE::BGSKeyword* prev_keyword
);
bool RefreshMerchandise(
RE::StaticFunctionTag*,
RE::BSFixedString api_url,
RE::BSFixedString api_key,
uint32_t shop_id,
RE::TESObjectREFR* merchant_shelf,
RE::TESForm* activator_static,
RE::BGSKeyword* shelf_keyword,
RE::BGSKeyword* chest_keyword,
RE::BGSKeyword* item_keyword,
RE::BGSKeyword* activator_keyword,
RE::BGSKeyword* toggle_keyword,
RE::BGSKeyword* next_keyword,
RE::BGSKeyword* prev_keyword
);
bool ReplaceMerch3D(RE::StaticFunctionTag*, RE::TESObjectREFR* merchant_shelf, RE::TESForm* activator_static, RE::BGSKeyword* shelf_keyword, RE::BGSKeyword* item_keyword);
RE::TESForm * BuyMerchandise(RE::StaticFunctionTag*, RE::TESObjectREFR * merchandise_activator);
bool CreateMerchandiseList(RE::StaticFunctionTag*, RE::BSFixedString api_url, RE::BSFixedString api_key, uint32_t shop_id, RE::TESObjectREFR* merchant_chest);
int GetMerchandiseQuantity(RE::StaticFunctionTag*, RE::TESObjectREFR* activator);
int GetMerchandisePrice(RE::StaticFunctionTag*, RE::TESObjectREFR* activator);

89
src/BRTransaction.cpp Normal file
View File

@ -0,0 +1,89 @@
#include "bindings.h"
void CreateTransactionImpl(
RE::BSFixedString api_url,
RE::BSFixedString api_key,
uint32_t shop_id,
bool is_sell,
uint32_t quantity,
uint32_t amount,
RE::BGSKeyword* item_keyword,
RE::TESObjectREFR* activator
) {
logger::info("Entered CreateTransactionImpl");
RE::TESDataHandler * data_handler = RE::TESDataHandler::GetSingleton();
if (!activator) {
logger::error("CreateTransactionImpl activator is null!");
return;
}
SKSE::RegistrationMap<int, int, int> successReg = SKSE::RegistrationMap<int, int, int>();
successReg.Register(activator, RE::BSFixedString("OnCreateTransactionSuccess"));
SKSE::RegistrationMap<RE::BSFixedString> failReg = SKSE::RegistrationMap<RE::BSFixedString>();
failReg.Register(activator, RE::BSFixedString("OnCreateTransactionFail"));
RE::TESObjectREFR * merch_ref = activator->GetLinkedRef(item_keyword);
RE::TESBoundObject * base = merch_ref->GetBaseObject();
if (!base) {
logger::error("CreateTransactionImpl merchandise item base is null!");
failReg.SendEvent(RE::BSFixedString("Could not find the merchandise for the activator"));
successReg.Unregister(activator);
failReg.Unregister(activator);
}
const char * name = base->GetName();
uint32_t form_type = (uint32_t)base->GetFormType();
RE::FormID form_id = base->GetFormID();
logger::info(FMT_STRING("CreateTransactionImpl base form_id: {:x}, name: {}, type: {:x}"), (uint32_t)form_id, name, (uint32_t)form_type);
RE::TESFile * file = base->GetFile(0);
const char * mod_name = file->fileName;
bool is_light = file->recordFlags.all(RE::TESFile::RecordFlag::kSmallFile);
uint32_t local_form_id = is_light ? form_id & 0xfff : form_id & 0xFFFFFF;
logger::info(FMT_STRING("CreateTransactionImpl base form file_name: {}, local_form_id: {:x}"), mod_name, local_form_id);
// TODO: implement is_food
bool is_food = false;
uint32_t price = 0;
RE::ExtraCount * extra_quantity_price = activator->extraList.GetByType<RE::ExtraCount>();
if (extra_quantity_price) {
price = extra_quantity_price->pad14;
}
RawTransaction input_transaction = { 0, shop_id, mod_name, local_form_id, name, form_type, is_food, price, is_sell, quantity, amount };
FFIResult<RawTransaction> result = create_transaction(api_url.c_str(), api_key.c_str(), input_transaction);
if (result.IsOk()) {
RawTransaction saved_transaction = result.AsOk();
logger::info(FMT_STRING("CreateTransaction success: {}"), saved_transaction.id);
successReg.SendEvent(saved_transaction.id, saved_transaction.quantity, saved_transaction.amount);
} else {
const char* error = result.AsErr();
logger::error(FMT_STRING("CreateTransaction failure: {}"), error);
failReg.SendEvent(RE::BSFixedString(error));
}
successReg.Unregister(activator);
failReg.Unregister(activator);
}
bool CreateTransaction(
RE::StaticFunctionTag*,
RE::BSFixedString api_url,
RE::BSFixedString api_key,
uint32_t shop_id,
bool is_sell,
uint32_t quantity,
uint32_t amount,
RE::BGSKeyword* item_keyword,
RE::TESObjectREFR* activator
) {
logger::info("Entered CreateTransaction");
if (!activator) {
logger::error("CreateTransaction activator is null!");
return false;
}
std::thread thread(CreateTransactionImpl, api_url, api_key, shop_id, is_sell, quantity, amount, item_keyword, activator);
thread.detach();
return true;
}

13
src/BRTransaction.h Normal file
View File

@ -0,0 +1,13 @@
#pragma once
bool CreateTransaction(
RE::StaticFunctionTag*,
RE::BSFixedString api_url,
RE::BSFixedString api_key,
uint32_t shop_id,
bool is_sell,
uint32_t quantity,
uint32_t amount,
RE::BGSKeyword* item_keyword,
RE::TESObjectREFR* activator
);

View File

@ -6,6 +6,7 @@
#include "BRShop.h"
#include "BRInteriorRefList.h"
#include "BRMerchandiseList.h"
#include "BRTransaction.h"
bool RegisterFuncs(RE::BSScript::IVirtualMachine* a_vm)
{
@ -25,9 +26,13 @@ bool RegisterFuncs(RE::BSScript::IVirtualMachine* a_vm)
a_vm->RegisterFunction("Toggle", "BRMerchandiseList", ToggleMerchandise);
a_vm->RegisterFunction("NextPage", "BRMerchandiseList", LoadNextMerchandise);
a_vm->RegisterFunction("PrevPage", "BRMerchandiseList", LoadPrevMerchandise);
a_vm->RegisterFunction("Buy", "BRMerchandiseList", BuyMerchandise);
a_vm->RegisterFunction("Load", "BRMerchandiseList", LoadMerchandiseByShopId);
a_vm->RegisterFunction("Refresh", "BRMerchandiseList", RefreshMerchandise);
a_vm->RegisterFunction("Replace3D", "BRMerchandiseList", ReplaceMerch3D);
a_vm->RegisterFunction("Create", "BRMerchandiseList", CreateMerchandiseList);
a_vm->RegisterFunction("GetQuantity", "BRMerchandiseList", GetMerchandiseQuantity);
a_vm->RegisterFunction("GetPrice", "BRMerchandiseList", GetMerchandisePrice);
a_vm->RegisterFunction("Create", "BRTransaction", CreateTransaction);
return true;
}