Skip to content

Commit

Permalink
Add WornRestrictionsForWeapons
Browse files Browse the repository at this point in the history
  • Loading branch information
powerof3 committed Jul 31, 2024
1 parent e7b0b91 commit ee97a2f
Show file tree
Hide file tree
Showing 9 changed files with 145 additions and 3 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ jobs:
FOMOD_AE_MIN_GAME_VERSION: '1.6'
FOMOD_REQUIRED_INSTALLATION_DIR: "Skyrim/Data"
PUBLISH_ARCHIVE_TYPE: '7z'
VCPKG_COMMIT_ID: 'ee1093857f3d16b007065542bbb2229369c70c2e'
VCPKG_COMMIT_ID: '5c7d3a872dd861817fc812647176d5076085a7eb'
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.20)
set(NAME "po3_Tweaks" CACHE STRING "")
set(VERSION 1.10.2 CACHE STRING "")
set(VERSION 1.11.0 CACHE STRING "")
set(AE_VERSION 1)
set(VR_VERSION 1)

Expand Down
1 change: 1 addition & 0 deletions cmake/sourcelist.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ set(sources ${sources}
src/Fixes/UnderwaterCamera.cpp
src/Fixes/UseFurnitureInCombat.cpp
src/Fixes/ValidateScreenshotFolder.cpp
src/Fixes/WornRestrictionsForWeapons.cpp
src/PCH.cpp
src/Papyrus.cpp
src/Settings.cpp
Expand Down
7 changes: 7 additions & 0 deletions src/Fixes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,13 @@ void Fixes::PostLoad::Install()
// broken on some setups
//FirstPersonAlpha::Install();
}
if (fixes.wornRestrictionsForWeapons) {
if (GetModuleHandle(L"AmmoEnchanting")) {
logger::info("\t\tDetected AmmoEnchanting, skipping ExpandedWornRestrictions patch."sv);
} else {
WornRestrictionsForWeapons::Install();
}
}
//UnderWaterCamera::Install(); tbd
}

Expand Down
5 changes: 5 additions & 0 deletions src/Fixes.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,4 +136,9 @@ namespace Fixes
{
void Install();
}

namespace WornRestrictionsForWeapons
{
void Install();
}
}
127 changes: 127 additions & 0 deletions src/Fixes/WornRestrictionsForWeapons.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
#include "Fixes.h"

//make weapon enchantments support worn restriction list
//adapted from: https://github.com/Exit-9B/AmmoEnchanting/blob/main/src/Ext/EnchantConstructMenu.cpp

namespace Fixes::WornRestrictionsForWeapons
{
struct detail
{
static bool GetCompatibleRestrictions(
RE::CraftingSubMenus::EnchantConstructMenu::ItemChangeEntry* a_item,
RE::CraftingSubMenus::EnchantConstructMenu::EnchantmentEntry* a_effect)
{
if (!a_item || !a_item->data || !a_item->data->object || !a_effect || !a_effect->data) {
return true;
}

auto wornRestrictionList = a_effect->data->data.wornRestrictions;
auto keywordForm = a_item->data->object->As<RE::BGSKeywordForm>();

if (!wornRestrictionList || !keywordForm) {
return true;
}

bool valid = false;

keywordForm->ForEachKeyword([&](auto* keyword) {
if (wornRestrictionList->HasForm(keyword)) {
valid = true;
return RE::BSContainer::ForEachResult::kStop;
}
return RE::BSContainer::ForEachResult::kContinue;
});

return valid;
}
};

struct CanSelectEnchantmentEntry
{
static bool func(RE::CraftingSubMenus::EnchantConstructMenu* a_this, std::uint32_t a_index, bool a_showNotification)
{
if (a_index >= a_this->listEntries.size()) {
return false;
}

using FilterFlag = RE::CraftingSubMenus::EnchantConstructMenu::FilterFlag;

bool compatibleRestrictions = true;
auto& entry = a_this->listEntries[a_index];

switch (entry->filterFlag.get()) {
case FilterFlag::EnchantArmor:
case FilterFlag::EnchantWeapon:
{
for (auto& effect : a_this->selected.effects) {
const auto item = static_cast<RE::CraftingSubMenus::EnchantConstructMenu::ItemChangeEntry*>(entry.get());
compatibleRestrictions &= detail::GetCompatibleRestrictions(item, effect.get());
}
}
break;
case FilterFlag::EffectWeapon:
case FilterFlag::EffectArmor:
{
const auto item = a_this->selected.item.get();
const auto effect = static_cast<RE::CraftingSubMenus::EnchantConstructMenu::EnchantmentEntry*>(entry.get());
compatibleRestrictions = detail::GetCompatibleRestrictions(item, effect);
}
break;
}

if (!compatibleRestrictions) {
if (a_showNotification) {
static const auto setting = RE::GameSettingCollection::GetSingleton()->GetSetting("sEnchantArmorIncompatible");
if (setting) {
RE::DebugNotification(setting->GetString());
}
}
return false;
}

switch (entry->filterFlag.get()) {
case FilterFlag::EnchantWeapon:
{
if (!a_this->selected.effects.empty()) {
return a_this->selected.effects[0]->filterFlag == FilterFlag::EffectWeapon;
}
}
break;
case FilterFlag::EnchantArmor:
{
if (!a_this->selected.effects.empty()) {
return a_this->selected.effects[0]->filterFlag == FilterFlag::EffectArmor;
}
}
break;
case FilterFlag::EffectWeapon:
{
if (a_this->selected.item) {
return a_this->selected.item->filterFlag == FilterFlag::EnchantWeapon;
}
}
break;
case FilterFlag::EffectArmor:
{
if (a_this->selected.item) {
return a_this->selected.item->filterFlag == FilterFlag::EnchantArmor;
}
}
break;
default:
break;
}

return true;
}
static inline constexpr std::size_t size{ OFFSET(0x27D, 0x1E9) };
};

void Install()
{
REL::Relocation<std::uintptr_t> func{ REL_ID(50569, 51461) };
stl::asm_replace<CanSelectEnchantmentEntry>(func.address());

logger::info("\t\tInstalled worn restrictions for weapons patch"sv);
}
}
1 change: 1 addition & 0 deletions src/Settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ void Settings::Fixes::Load(CSimpleIniA& a_ini)
get_value(a_ini, validateScreenshotFolder, section, "Validate Screenshot Location", ";Validates game screenshot location.\n;Defaults to Skyrim root directory if sScreenshotBaseName ini setting is empty or folder path does not exist");
get_value(a_ini, loadEditorIDs, section, "Load EditorIDs", ";Loads editorIDs for skipped forms at runtime");
get_value(a_ini, firstPersonAlpha, section, "First Person SetAlpha Fix", ";Fixes SetAlpha function making hands invisible for first person");
get_value(a_ini, wornRestrictionsForWeapons, section, "Worn Restrictions For Weapons", ";Enable enchantment 'Worn Restrictions' feature on weapons");
#ifdef SKYRIMVR
get_value(a_ini, fixVRCrosshairRefEvent, section, "VR CrosshairRefEvent Fix", "; Trigger CrossHairRefEvent with hand selection (normally requires game controller to enable crosshair events)");
#endif
Expand Down
1 change: 1 addition & 0 deletions src/Settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class Settings : public ISingleton<Settings>
bool validateScreenshotFolder{ true };
bool loadEditorIDs{ true };
bool firstPersonAlpha{ true };
bool wornRestrictionsForWeapons{ true };
#ifdef SKYRIMVR
bool fixVRCrosshairRefEvent{ true };
#endif
Expand Down
2 changes: 1 addition & 1 deletion vcpkg.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "po3tweaks",
"version-string": "1.10.2",
"version-string": "1.11.0",
"description": "Collection of bug fixes and tweaks for Skyrim SE/AE/VR",
"homepage": "https://github.com/powerof3/po3-Tweaks/",
"license": "MIT",
Expand Down

0 comments on commit ee97a2f

Please sign in to comment.