You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

145 lines
5.0 KiB

#include "EventListener.h"
#include "Util.h"
auto EventListener::GetSingleton() -> EventListener*
{
static EventListener singleton{};
return std::addressof(singleton);
}
void EventListener::Install()
{
SKSE::GetModCallbackEventSource()->AddEventSink(EventListener::GetSingleton());
RE::ScriptEventSourceHolder::GetSingleton()->AddEventSink<RE::TESActivateEvent>(EventListener::GetSingleton());
RE::UI::GetSingleton()->AddEventSink<RE::MenuOpenCloseEvent>(EventListener::GetSingleton());
}
auto EventListener::ProcessEvent(
const SKSE::ModCallbackEvent* a_event,
RE::BSTEventSource<SKSE::ModCallbackEvent>* a_eventSource)
-> RE::BSEventNotifyControl
{
if (a_event->eventName == "Enderal_StartPortableLab") {
SKSE::GetTaskInterface()->AddTask([]() {
FetchSupplies(RE::TESForm::LookupByID(0xBAD0C)->As<RE::TESFurniture>()); // CraftingAlchemyWorkbench
});
} else if (a_event->eventName == "Enderal_StartSpectralizing") {
SKSE::GetTaskInterface()->AddTask([]() {
FetchSpectralizingSupplies();
});
} else if (a_event->eventName == "Enderal_FinishSpectralizing") {
SKSE::GetTaskInterface()->AddTask([]() {
ReturnSupplies();
});
}
return RE::BSEventNotifyControl::kContinue;
}
auto EventListener::ProcessEvent(
const RE::MenuOpenCloseEvent* a_event,
RE::BSTEventSource<RE::MenuOpenCloseEvent>* a_eventSource)
-> RE::BSEventNotifyControl
{
if (a_event->menuName != RE::CraftingMenu::MENU_NAME) {
return RE::BSEventNotifyControl::kContinue;
}
if (a_event->opening) {
RE::CraftingMenu* menu = static_cast<RE::CraftingMenu*>(RE::UI::GetSingleton()->GetMenu(RE::CraftingMenu::MENU_NAME).get());
if (!menu || !menu->GetCraftingSubMenu()) {
return RE::BSEventNotifyControl::kContinue;
}
const auto furn = menu->GetCraftingSubMenu()->furniture;
if (!furn || furn->workBenchData.benchType != RE::TESFurniture::WorkBenchData::BenchType::kCreateObject || furn->As<RE::BGSKeywordForm>()->HasKeywordString("CraftingSmelterDismantling")) {
return RE::BSEventNotifyControl::kContinue;
}
SKSE::GetTaskInterface()->AddTask([furn]() {
if (!FetchSupplies(furn)) {
return;
}
std::thread([]() {
std::this_thread::sleep_for(std::chrono::milliseconds(50));
SKSE::GetTaskInterface()->AddTask([]() {
// Trigger item list update, this trick works only with the kCreateObject workbenches
if (auto scriptFactory = RE::IFormFactory::GetConcreteFormFactoryByType<RE::Script>()) {
if (auto script = scriptFactory->Create()) {
script->SetCommand("player.additem 1FE82 1 1");
script->CompileAndRun(nullptr);
}
}
RE::PlayerCharacter::GetSingleton()->RemoveItem(RE::TESForm::LookupByID(0x1FE82)->As<RE::TESBoundObject>(), 99, RE::ITEM_REMOVE_REASON::kRemove, nullptr, nullptr, 0, 0);
});
}).detach();
});
} else {
SKSE::GetTaskInterface()->AddTask([]() {
ReturnSupplies();
});
}
return RE::BSEventNotifyControl::kContinue;
}
auto EventListener::ProcessEvent(
const RE::TESActivateEvent* a_event,
RE::BSTEventSource<RE::TESActivateEvent>* a_eventSource)
-> RE::BSEventNotifyControl
{
if (!a_event->actionRef || !a_event->actionRef->IsPlayerRef() || !a_event->objectActivated) {
return RE::BSEventNotifyControl::kContinue;
}
const auto refr = a_event->objectActivated.get();
if (!refr || !refr->GetBaseObject()->Is(RE::FormType::Furniture)) {
return RE::BSEventNotifyControl::kContinue;
}
auto* furn = refr->GetBaseObject()->As<RE::TESFurniture>();
if (furn->workBenchData.benchType == RE::TESFurniture::WorkBenchData::BenchType::kNone || furn->workBenchData.benchType == RE::TESFurniture::WorkBenchData::BenchType::kCreateObject) {
return RE::BSEventNotifyControl::kContinue;
}
if (RE::PlayerCharacter::GetSingleton()->GetRace()->As<RE::BGSKeywordForm>()->HasKeywordString("ActorTypeCreature")) {
// No crafting in the werewolf form
return RE::BSEventNotifyControl::kContinue;
}
std::thread([furn]() {
std::this_thread::sleep_for(std::chrono::milliseconds(300));
const auto playerRef = RE::PlayerCharacter::GetSingleton();
const auto sitState = playerRef->AsActorState()->GetSitSleepState();
if (sitState != RE::SIT_SLEEP_STATE::kWantToSit && sitState != RE::SIT_SLEEP_STATE::kWaitingForSitAnim) {
return;
}
SKSE::GetTaskInterface()->AddTask([furn]() {
if (!FetchSupplies(furn)) {
return;
}
std::thread([]() {
const auto playerRef = RE::PlayerCharacter::GetSingleton();
const auto sitState = playerRef->AsActorState()->GetSitSleepState();
while (sitState == RE::SIT_SLEEP_STATE::kWantToSit || sitState == RE::SIT_SLEEP_STATE::kWaitingForSitAnim) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
std::this_thread::sleep_for(std::chrono::milliseconds(500));
if (!RE::UI::GetSingleton()->IsMenuOpen(RE::CraftingMenu::MENU_NAME)) {
SKSE::GetTaskInterface()->AddTask([]() {
ReturnSupplies();
});
}
}).detach();
});
}).detach();
return RE::BSEventNotifyControl::kContinue;
}