Skip to content

Commit ee97a2f

Browse files
committed
Add WornRestrictionsForWeapons
1 parent e7b0b91 commit ee97a2f

File tree

9 files changed

+145
-3
lines changed

9 files changed

+145
-3
lines changed

.github/workflows/main.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,4 @@ jobs:
2626
FOMOD_AE_MIN_GAME_VERSION: '1.6'
2727
FOMOD_REQUIRED_INSTALLATION_DIR: "Skyrim/Data"
2828
PUBLISH_ARCHIVE_TYPE: '7z'
29-
VCPKG_COMMIT_ID: 'ee1093857f3d16b007065542bbb2229369c70c2e'
29+
VCPKG_COMMIT_ID: '5c7d3a872dd861817fc812647176d5076085a7eb'

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
cmake_minimum_required(VERSION 3.20)
22
set(NAME "po3_Tweaks" CACHE STRING "")
3-
set(VERSION 1.10.2 CACHE STRING "")
3+
set(VERSION 1.11.0 CACHE STRING "")
44
set(AE_VERSION 1)
55
set(VR_VERSION 1)
66

cmake/sourcelist.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ set(sources ${sources}
2828
src/Fixes/UnderwaterCamera.cpp
2929
src/Fixes/UseFurnitureInCombat.cpp
3030
src/Fixes/ValidateScreenshotFolder.cpp
31+
src/Fixes/WornRestrictionsForWeapons.cpp
3132
src/PCH.cpp
3233
src/Papyrus.cpp
3334
src/Settings.cpp

src/Fixes.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,13 @@ void Fixes::PostLoad::Install()
6868
// broken on some setups
6969
//FirstPersonAlpha::Install();
7070
}
71+
if (fixes.wornRestrictionsForWeapons) {
72+
if (GetModuleHandle(L"AmmoEnchanting")) {
73+
logger::info("\t\tDetected AmmoEnchanting, skipping ExpandedWornRestrictions patch."sv);
74+
} else {
75+
WornRestrictionsForWeapons::Install();
76+
}
77+
}
7178
//UnderWaterCamera::Install(); tbd
7279
}
7380

src/Fixes.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,4 +136,9 @@ namespace Fixes
136136
{
137137
void Install();
138138
}
139+
140+
namespace WornRestrictionsForWeapons
141+
{
142+
void Install();
143+
}
139144
}
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
#include "Fixes.h"
2+
3+
//make weapon enchantments support worn restriction list
4+
//adapted from: https://github.com/Exit-9B/AmmoEnchanting/blob/main/src/Ext/EnchantConstructMenu.cpp
5+
6+
namespace Fixes::WornRestrictionsForWeapons
7+
{
8+
struct detail
9+
{
10+
static bool GetCompatibleRestrictions(
11+
RE::CraftingSubMenus::EnchantConstructMenu::ItemChangeEntry* a_item,
12+
RE::CraftingSubMenus::EnchantConstructMenu::EnchantmentEntry* a_effect)
13+
{
14+
if (!a_item || !a_item->data || !a_item->data->object || !a_effect || !a_effect->data) {
15+
return true;
16+
}
17+
18+
auto wornRestrictionList = a_effect->data->data.wornRestrictions;
19+
auto keywordForm = a_item->data->object->As<RE::BGSKeywordForm>();
20+
21+
if (!wornRestrictionList || !keywordForm) {
22+
return true;
23+
}
24+
25+
bool valid = false;
26+
27+
keywordForm->ForEachKeyword([&](auto* keyword) {
28+
if (wornRestrictionList->HasForm(keyword)) {
29+
valid = true;
30+
return RE::BSContainer::ForEachResult::kStop;
31+
}
32+
return RE::BSContainer::ForEachResult::kContinue;
33+
});
34+
35+
return valid;
36+
}
37+
};
38+
39+
struct CanSelectEnchantmentEntry
40+
{
41+
static bool func(RE::CraftingSubMenus::EnchantConstructMenu* a_this, std::uint32_t a_index, bool a_showNotification)
42+
{
43+
if (a_index >= a_this->listEntries.size()) {
44+
return false;
45+
}
46+
47+
using FilterFlag = RE::CraftingSubMenus::EnchantConstructMenu::FilterFlag;
48+
49+
bool compatibleRestrictions = true;
50+
auto& entry = a_this->listEntries[a_index];
51+
52+
switch (entry->filterFlag.get()) {
53+
case FilterFlag::EnchantArmor:
54+
case FilterFlag::EnchantWeapon:
55+
{
56+
for (auto& effect : a_this->selected.effects) {
57+
const auto item = static_cast<RE::CraftingSubMenus::EnchantConstructMenu::ItemChangeEntry*>(entry.get());
58+
compatibleRestrictions &= detail::GetCompatibleRestrictions(item, effect.get());
59+
}
60+
}
61+
break;
62+
case FilterFlag::EffectWeapon:
63+
case FilterFlag::EffectArmor:
64+
{
65+
const auto item = a_this->selected.item.get();
66+
const auto effect = static_cast<RE::CraftingSubMenus::EnchantConstructMenu::EnchantmentEntry*>(entry.get());
67+
compatibleRestrictions = detail::GetCompatibleRestrictions(item, effect);
68+
}
69+
break;
70+
}
71+
72+
if (!compatibleRestrictions) {
73+
if (a_showNotification) {
74+
static const auto setting = RE::GameSettingCollection::GetSingleton()->GetSetting("sEnchantArmorIncompatible");
75+
if (setting) {
76+
RE::DebugNotification(setting->GetString());
77+
}
78+
}
79+
return false;
80+
}
81+
82+
switch (entry->filterFlag.get()) {
83+
case FilterFlag::EnchantWeapon:
84+
{
85+
if (!a_this->selected.effects.empty()) {
86+
return a_this->selected.effects[0]->filterFlag == FilterFlag::EffectWeapon;
87+
}
88+
}
89+
break;
90+
case FilterFlag::EnchantArmor:
91+
{
92+
if (!a_this->selected.effects.empty()) {
93+
return a_this->selected.effects[0]->filterFlag == FilterFlag::EffectArmor;
94+
}
95+
}
96+
break;
97+
case FilterFlag::EffectWeapon:
98+
{
99+
if (a_this->selected.item) {
100+
return a_this->selected.item->filterFlag == FilterFlag::EnchantWeapon;
101+
}
102+
}
103+
break;
104+
case FilterFlag::EffectArmor:
105+
{
106+
if (a_this->selected.item) {
107+
return a_this->selected.item->filterFlag == FilterFlag::EnchantArmor;
108+
}
109+
}
110+
break;
111+
default:
112+
break;
113+
}
114+
115+
return true;
116+
}
117+
static inline constexpr std::size_t size{ OFFSET(0x27D, 0x1E9) };
118+
};
119+
120+
void Install()
121+
{
122+
REL::Relocation<std::uintptr_t> func{ REL_ID(50569, 51461) };
123+
stl::asm_replace<CanSelectEnchantmentEntry>(func.address());
124+
125+
logger::info("\t\tInstalled worn restrictions for weapons patch"sv);
126+
}
127+
}

src/Settings.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ void Settings::Fixes::Load(CSimpleIniA& a_ini)
7070
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");
7171
get_value(a_ini, loadEditorIDs, section, "Load EditorIDs", ";Loads editorIDs for skipped forms at runtime");
7272
get_value(a_ini, firstPersonAlpha, section, "First Person SetAlpha Fix", ";Fixes SetAlpha function making hands invisible for first person");
73+
get_value(a_ini, wornRestrictionsForWeapons, section, "Worn Restrictions For Weapons", ";Enable enchantment 'Worn Restrictions' feature on weapons");
7374
#ifdef SKYRIMVR
7475
get_value(a_ini, fixVRCrosshairRefEvent, section, "VR CrosshairRefEvent Fix", "; Trigger CrossHairRefEvent with hand selection (normally requires game controller to enable crosshair events)");
7576
#endif

src/Settings.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class Settings : public ISingleton<Settings>
2828
bool validateScreenshotFolder{ true };
2929
bool loadEditorIDs{ true };
3030
bool firstPersonAlpha{ true };
31+
bool wornRestrictionsForWeapons{ true };
3132
#ifdef SKYRIMVR
3233
bool fixVRCrosshairRefEvent{ true };
3334
#endif

vcpkg.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "po3tweaks",
3-
"version-string": "1.10.2",
3+
"version-string": "1.11.0",
44
"description": "Collection of bug fixes and tweaks for Skyrim SE/AE/VR",
55
"homepage": "https://github.com/powerof3/po3-Tweaks/",
66
"license": "MIT",

0 commit comments

Comments
 (0)