#pragma once #include #include "VersionDb.h" #include "World.h" #define POINTER_SKYRIMSE(className, variableName, ...) static VersionDbPtr variableName(__VA_ARGS__) #define POINTER_SKYRIMSE_LEGACY(className, variableName, ...) static AutoPtr variableName(__VA_ARGS__) // TODO: should this be debug only? I removed the check since debug is broken, can only use releasedbg #define TP_ASSERT(Expr, Msg, ...) \ if (!(Expr)) \ { \ Utils::Assert(#Expr, fmt::format(Msg, __VA_ARGS__).c_str()); \ } struct TESForm; namespace Utils { static void Assert(const char* apExpression, const char* apMessage) { spdlog::critical("Assertion failed ({}): {}", apExpression, apMessage); if (IsDebuggerPresent()) __debugbreak(); } std::optional GetServerId(entt::entity aEntity) noexcept; template T* GetByServerId(const uint32_t acServerId) noexcept { auto view = World::Get().view(); for (entt::entity entity : view) { std::optional serverIdRes = GetServerId(entity); if (!serverIdRes.has_value()) continue; uint32_t serverId = serverIdRes.value(); if (serverId == acServerId) { const auto& formIdComponent = view.get(entity); TESForm* pForm = TESForm::GetById(formIdComponent.Id); if (pForm != nullptr) { return Cast(pForm); } } } spdlog::debug("{}: form not found for server id {:X}", __FUNCTION__, acServerId); return nullptr; } void ShowHudMessage(const TiltedPhoques::String& acMessage); } // namespace Utils namespace TiltedPhoques { template constexpr decltype(auto) ThisCall(TFunc* aFunction, VersionDbPtr& aThis, TArgs&&... args) noexcept { return ThisCall(aFunction, aThis.Get(), args...); } template constexpr decltype(auto) ThisCall(VersionDbPtr& aFunction, VersionDbPtr& aThis, TArgs&&... args) noexcept { return ThisCall(aFunction.Get(), aThis.Get(), args...); } template constexpr decltype(auto) ThisCall(VersionDbPtr& aFunction, TThis* apThis, TArgs&&... args) noexcept { return ThisCall(aFunction.Get(), apThis, args...); } } // namespace TiltedPhoques