-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathPapyrusScriptBindings.h
96 lines (86 loc) · 4.42 KB
/
PapyrusScriptBindings.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#pragma once
#pragma warning(push)
#include <SKSE/SKSE.h>
#include <RE/Skyrim.h>
#include <RE/T/TESForm.h>
#include <RE/T/TESObjectREFR.h>
#pragma warning(pop)
#include "BindingDefinition.h"
using namespace RE::BSScript;
using namespace RE::BSScript::Internal;
namespace ScriptsWithoutESP::PapyrusScriptBindings {
void BindToForm(const std::string& scriptName, RE::TESForm* form, bool addOnce = false) {
try {
auto* vm = VirtualMachine::GetSingleton();
auto* handlePolicy = vm->GetObjectHandlePolicy();
RE::VMHandle handle = handlePolicy->GetHandleForObject(form->GetFormType(), form);
if (handle) {
// If there is already a script with the same name attached to this object, don't bind a new one
RE::BSFixedString caseInsensitiveScriptName = scriptName;
if (addOnce) {
if (vm->attachedScripts.contains(handle)) {
for (auto& attachedScript : vm->attachedScripts.find(handle)->second) {
if (attachedScript->GetTypeInfo()->GetName() == caseInsensitiveScriptName) {
return; // Don't bind! Already bound!
}
}
}
}
RE::BSTSmartPointer<RE::BSScript::Object> objectPtr;
vm->CreateObject(scriptName, objectPtr);
auto* bindPolicy = vm->GetObjectBindPolicy();
bindPolicy->BindObject(objectPtr, handle);
RE::ConsoleLog::GetSingleton()->Print(std::format("[Bindings] Bound script '{}' to reference!", scriptName).c_str());
} else {
RE::ConsoleLog::GetSingleton()->Print(std::format("[Bindings] Error getting handle for script {} to reference", scriptName).c_str());
}
} catch (...) {
RE::ConsoleLog::GetSingleton()->Print(std::format("[Bindings] Error binding script {} to reference", scriptName).c_str());
}
}
void BindToEditorId(const std::string& scriptName, const std::string& editorId, bool addOnce = false) {
auto* form = RE::TESForm::LookupByEditorID(editorId);
if (form) {
BindToForm(scriptName, form, addOnce);
} else {
RE::ConsoleLog::GetSingleton()->Print(std::format("[Binding] Could not find Form via Editor ID: '{}' for script '{}'", editorId, scriptName).c_str());
}
}
void BindToFormId(const std::string& scriptName, int formId, const std::string optionalPluginFile = "", bool addOnce = false) {
if (optionalPluginFile.empty()) {
auto* form = RE::TESForm::LookupByID(formId);
if (form) {
BindToForm(scriptName, form, addOnce);
} else {
RE::ConsoleLog::GetSingleton()->Print(std::format("[Binding] Could not find Form via Form ID: '{}' for script '{}'", formId, scriptName).c_str());
}
} else {
auto* dataHandler = RE::TESDataHandler::GetSingleton();
if (dataHandler->GetModIndex(optionalPluginFile) != 255) {
auto* form = dataHandler->LookupForm(formId, optionalPluginFile);
if (form) {
BindToForm(scriptName, form, addOnce);
} else {
RE::ConsoleLog::GetSingleton()->Print(std::format("[Binding] Could not find Form via Form ID: '{}' in plugin '{}' for script '{}'", formId, optionalPluginFile, scriptName).c_str());
}
} else {
RE::ConsoleLog::GetSingleton()->Print(std::format("[Binding] Could not find plugin '{}' for script '{}'", optionalPluginFile, scriptName).c_str());
}
}
}
void Bind(const BindingDefinition& def) {
try {
if (def.Type == BindingDefinitionType::EditorID) {
BindToEditorId(def.ScriptName, def.EditorID, def.AddOnce);
} else if (def.Type == BindingDefinitionType::FormID) {
BindToFormId(def.ScriptName, def.FormID, def.Plugin, def.AddOnce);
}
} catch (...) {
if (def.Filename.empty()) {
RE::ConsoleLog::GetSingleton()->Print(std::format("[Bindings] Bind() error {} {}", def.EditorID, def.FormID).c_str());
} else {
RE::ConsoleLog::GetSingleton()->Print(std::format("[AutoBindings] Bind() error {}", def.Filename).c_str());
}
}
}
}