#pragma once #include "Util.h" #include "PersistentFormManager.h" #include "Patches/DialogueMenuPatch.h" namespace Papyrus::PapyrusFunctions { inline RE::AlchemyItem* CreatePotion(RE::StaticFunctionTag*, std::vector effects, std::vector magnitudes, std::vector areas, std::vector durations, uint32_t arraySize) { RE::AlchemyItem* result = NULL; if (effects.size() >= arraySize && magnitudes.size() >= arraySize && areas.size() >= arraySize && durations.size() >= arraySize) { RE::tArray effectItems; effectItems.Allocate(effects.size()); uint16_t count = 0; for (uint16_t i = 0; i < effects.size(); ++i) { if (effects[i]) { effectItems[i].baseEffect = effects[i]; effectItems[i].effectItem.duration = durations[i]; effectItems[i].effectItem.magnitude = magnitudes[i]; effectItems[i].effectItem.area = areas[i]; count++; } } effectItems.count = count; RE::PersistentFormManager::GetSingleton()->CreatePotion(&result, &effectItems); effectItems.Clear(); } else { logger::warn("Illegal arrays for creating a potion"); } return result; } inline uint8_t GetNewGameCount(RE::StaticFunctionTag*) { return NewGameCount(); } inline RE::TESObjectREFR* GetCurrentContainer(RE::StaticFunctionTag*) { const auto handle = RE::ContainerMenu::GetTargetRefHandle(); const auto refr = RE::TESObjectREFR::LookupByHandle(handle); return refr ? refr.get() : nullptr; } inline std::vector GetPlayerFollowers(RE::StaticFunctionTag*) { std::vector result; if (const auto processLists = RE::ProcessLists::GetSingleton(); processLists) { for (auto& actorHandle : processLists->highActorHandles) { if (auto actor = actorHandle.get(); actor && actor->IsPlayerTeammate() && !actor->IsDead() && !actor->IsDisabled()) { result.push_back(actor.get()); } } } return result; } // Copied from Named Quicksaves by Ryan McKenzie (MIT) RE::BSFixedString GetPlayerHash(RE::StaticFunctionTag*) { char buf[] = "DEADBEEF"; auto saveData = RE::BSWin32SaveDataSystemUtility::GetSingleton(); if (saveData->profileHash == static_cast(-1)) { std::snprintf(buf, sizeof(buf), "%08o", 0); } else { std::snprintf(buf, sizeof(buf), "%08X", saveData->profileHash); } return buf; } RE::BSFixedString StringToHex(RE::StaticFunctionTag*, RE::BSFixedString a_string) { std::string_view str(a_string); std::stringstream sstream; for (auto ch : str) { sstream << std::uppercase << std::hex << static_cast(ch); } return sstream.str(); } void DisableDialogueQuitting(RE::StaticFunctionTag*) { DialogueMenuPatch::BlockTab(); } void EnableDialogueQuitting(RE::StaticFunctionTag*) { DialogueMenuPatch::BlockTab(false); } float ComputeNeededExp(RE::StaticFunctionTag*, std::uint32_t CurrentLevel, float Slope, float Mult, float fExpAcc = 1.0f, float fExpAcc_Level20 = 1.2f, float fExpAcc_Level30 = 1.5f, float fExpAcc_Level40 = 2.0f) { return ComputeNeededExpPoints(CurrentLevel, Slope, Mult, fExpAcc, fExpAcc_Level20, fExpAcc_Level30, fExpAcc_Level40); } inline void Bind(VM& a_vm) { BIND(CreatePotion); logger::info("{}", "Registered CreatePotion"sv); BIND(GetNewGameCount); logger::info("{}", "Registered GetNewGameCount"sv); BIND(GetCurrentContainer); logger::info("{}", "Registered GetCurrentContainer"sv); BIND(GetPlayerFollowers); logger::info("{}", "Registered GetPlayerFollowers"sv); BIND(GetPlayerHash); logger::info("{}", "Registered GetPlayerHash"sv); BIND(StringToHex); logger::info("{}", "Registered StringToHex"sv); BIND(DisableDialogueQuitting); logger::info("{}", "Registered DisableDialogueQuitting"sv); BIND(ComputeNeededExp); logger::info("{}", "Registered ComputeNeededExp"sv); } }