165 lines
5.6 KiB
C++
165 lines
5.6 KiB
C++
#include "EventListener.h"
|
|
#include "ArtifactTracker.h"
|
|
#include "Util.h"
|
|
|
|
auto EventListener::GetSingleton() -> EventListener*
|
|
{
|
|
static EventListener singleton{};
|
|
return std::addressof(singleton);
|
|
}
|
|
|
|
void EventListener::Install()
|
|
{
|
|
RE::PlayerCharacter::GetSingleton()->AsBGSActorCellEventSource()->AddEventSink<RE::BGSActorCellEvent>(EventListener::GetSingleton());
|
|
RE::ScriptEventSourceHolder::GetSingleton()->AddEventSink<RE::TESContainerChangedEvent>(EventListener::GetSingleton());
|
|
RE::ScriptEventSourceHolder::GetSingleton()->AddEventSink<RE::TESActorLocationChangeEvent>(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 == "KID_KeywordDistributionDone") {
|
|
ArtifactTracker::Init(true);
|
|
}
|
|
|
|
return RE::BSEventNotifyControl::kContinue;
|
|
}
|
|
|
|
auto EventListener::ProcessEvent(
|
|
const RE::TESContainerChangedEvent* a_event,
|
|
RE::BSTEventSource<RE::TESContainerChangedEvent>* a_eventSource)
|
|
-> RE::BSEventNotifyControl
|
|
{
|
|
const auto form = ArtifactTracker::GetArtifactByID(a_event->baseObj);
|
|
if (form) {
|
|
ArtifactTracker::OnContainerChanged(a_event, form);
|
|
}
|
|
|
|
return RE::BSEventNotifyControl::kContinue;
|
|
}
|
|
|
|
auto EventListener::ProcessEvent(
|
|
const RE::BGSActorCellEvent* a_event,
|
|
RE::BSTEventSource<RE::BGSActorCellEvent>* a_eventSource)
|
|
-> RE::BSEventNotifyControl
|
|
{
|
|
// Fires on every cell change, loaded or not.
|
|
// If it's new and not loaded, we can't add a new cell storage.
|
|
// In this case, it registers TESCellFullyLoadedEvent, which ensures a new ref can be added.
|
|
if (a_event->flags == RE::BGSActorCellEvent::CellFlag::kEnter) {
|
|
#ifdef _DEBUG
|
|
SKSE::log::info("BGSActorCellEvent");
|
|
#endif
|
|
|
|
ArtifactTracker::OnCellEnter(a_event->cellID);
|
|
}
|
|
|
|
return RE::BSEventNotifyControl::kContinue;
|
|
}
|
|
|
|
auto EventListener::ProcessEvent(
|
|
const RE::TESCellFullyLoadedEvent* a_event,
|
|
RE::BSTEventSource<RE::TESCellFullyLoadedEvent>* a_eventSource)
|
|
-> RE::BSEventNotifyControl
|
|
{
|
|
if (a_event->cell) {
|
|
#ifdef _DEBUG
|
|
SKSE::log::info("TESCellFullyLoadedEvent");
|
|
#endif
|
|
ArtifactTracker::OnCellEnter(a_event->cell->GetLocation(), a_event->cell);
|
|
}
|
|
|
|
return RE::BSEventNotifyControl::kContinue;
|
|
}
|
|
|
|
auto EventListener::ProcessEvent(
|
|
const RE::MenuOpenCloseEvent* a_event,
|
|
RE::BSTEventSource<RE::MenuOpenCloseEvent>* a_eventSource)
|
|
-> RE::BSEventNotifyControl
|
|
{
|
|
if (a_event->menuName == "ContainerMenu") {
|
|
#ifdef _DEBUG
|
|
SKSE::log::info("MenuOpenCloseEvent");
|
|
#endif
|
|
|
|
bool bOpening = a_event->opening;
|
|
|
|
SKSE::GetTaskInterface()->AddTask([bOpening]() {
|
|
if (bOpening) {
|
|
RE::BSInputDeviceManager::GetSingleton()->AddEventSink(EventListener::GetSingleton());
|
|
} else {
|
|
RE::BSInputDeviceManager::GetSingleton()->RemoveEventSink(EventListener::GetSingleton());
|
|
if (ArtifactTracker::g_bTakeAll && ArtifactTracker::g_bNotifyNewArtifact && ArtifactTracker::g_bTakeAllCount > 0) {
|
|
//RE::DebugNotification(fmt::format("{} new artifact(s) acquired", ArtifactTracker::g_bTakeAllCount).c_str());
|
|
RE::BSTSmartPointer<RE::BSScript::IStackCallbackFunctor> stackCallback;
|
|
RE::BSScript::Internal::VirtualMachine::GetSingleton()->DispatchStaticCall("ETR_NewArtifactsCombinedNotification", "Show", RE::MakeFunctionArguments<std::uint32_t>(std::move(ArtifactTracker::g_bTakeAllCount)), stackCallback);
|
|
}
|
|
ArtifactTracker::g_bTakeAll = false;
|
|
ArtifactTracker::g_bTakeAllCount = 0;
|
|
}
|
|
|
|
if (ArtifactTracker::IsHome()) {
|
|
ArtifactTracker::SetContainerMode(bOpening);
|
|
}
|
|
});
|
|
}
|
|
|
|
return RE::BSEventNotifyControl::kContinue;
|
|
}
|
|
|
|
auto EventListener::ProcessEvent(
|
|
const RE::TESActivateEvent* a_event,
|
|
RE::BSTEventSource<RE::TESActivateEvent>* a_eventSource)
|
|
-> RE::BSEventNotifyControl
|
|
{
|
|
// This listener is expected to be unregistered outside of home.
|
|
if (ArtifactTracker::IsHome() && a_event->actionRef->IsPlayerRef() && a_event->objectActivated) {
|
|
const auto ref = a_event->objectActivated.get();
|
|
if (ref && ArtifactTracker::g_artifactAllFormTypes.contains(ref->GetBaseObject()->GetFormType())) {
|
|
std::thread([]() {
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
|
ArtifactTracker::SyncCellStorage();
|
|
}).detach();
|
|
}
|
|
}
|
|
|
|
return RE::BSEventNotifyControl::kContinue;
|
|
}
|
|
|
|
auto EventListener::ProcessEvent(
|
|
const RE::TESActorLocationChangeEvent* a_event,
|
|
RE::BSTEventSource<RE::TESActorLocationChangeEvent>* a_eventSource)
|
|
-> RE::BSEventNotifyControl
|
|
{
|
|
if (a_event->actor->IsPlayerRef() || (a_event->actor->As<RE::Actor>() && a_event->actor->As<RE::Actor>()->IsPlayerTeammate())) {
|
|
ArtifactTracker::OnLocationChange();
|
|
}
|
|
|
|
return RE::BSEventNotifyControl::kContinue;
|
|
}
|
|
|
|
RE::BSEventNotifyControl EventListener::ProcessEvent(
|
|
RE::InputEvent* const* a_event,
|
|
RE::BSTEventSource<RE::InputEvent*>* a_eventSource)
|
|
{
|
|
auto inputEvent = a_event ? *a_event : nullptr;
|
|
auto buttonEvent = inputEvent ? inputEvent->AsButtonEvent() : nullptr;
|
|
|
|
if (!buttonEvent || !buttonEvent->IsPressed()) {
|
|
return RE::BSEventNotifyControl::kContinue;
|
|
}
|
|
|
|
if (RE::UI::GetSingleton()->GameIsPaused() && RE::UI::GetSingleton()->IsItemMenuOpen() && RE::UI::GetSingleton()->IsMenuOpen("ContainerMenu")) {
|
|
const auto takeAllKey = RE::ControlMap::GetSingleton()->GetMappedKey(RE::UserEvents::GetSingleton()->readyWeapon, buttonEvent->GetDevice(), RE::UserEvents::INPUT_CONTEXT_ID::kGameplay);
|
|
if (takeAllKey == buttonEvent->GetIDCode()) {
|
|
ArtifactTracker::g_bTakeAll = true;
|
|
ArtifactTracker::g_bTakeAllCount = 0;
|
|
}
|
|
}
|
|
|
|
return RE::BSEventNotifyControl::kContinue;
|
|
}
|