diff --git a/README.md b/README.md index 8406df7..f67926b 100644 --- a/README.md +++ b/README.md @@ -175,6 +175,16 @@ scriptName MyScript extends Quest } ``` +## Multiple Targets in a single line + +```papyrus +; This will bind `MyScript` to the the player and three specified NPCs in Riverwood using some of the supported binding options +scriptName MyScript extends Actor +{ + !BIND SvenRef|$Player|0x1348A|HildeRef +} +``` + # Logs > ℹ ️ If you run into any problems, check the `SkyrimScripting.Bind.log` in your diff --git a/Scripts/BindMeToMultipleTargets.pex b/Scripts/BindMeToMultipleTargets.pex new file mode 100644 index 0000000..e9d577e Binary files /dev/null and b/Scripts/BindMeToMultipleTargets.pex differ diff --git a/Scripts/Bindings/BindExamples.sh b/Scripts/Bindings/BindExamples.sh index 790cd56..f8cfbc4 100644 --- a/Scripts/Bindings/BindExamples.sh +++ b/Scripts/Bindings/BindExamples.sh @@ -4,6 +4,7 @@ BindMeToPlayer $Player BindMeToHodByID 0x1348A BindMeToHodByEditorID HodRef +BindMeToMultipleTargets SvenRef|0x1348A|$Player|HildeRef BindMeToGeneratedQuest $Quest BindMeToGeneratedQuestWithName $Quest(MyCoolQuest) BindMeToGeneratedObject $Object diff --git a/Scripts/DocStringBindToMultipleTargets.pex b/Scripts/DocStringBindToMultipleTargets.pex new file mode 100644 index 0000000..c89cdf7 Binary files /dev/null and b/Scripts/DocStringBindToMultipleTargets.pex differ diff --git a/Scripts/Source/BindMeToMultipleTargets.psc b/Scripts/Source/BindMeToMultipleTargets.psc new file mode 100644 index 0000000..df951c5 --- /dev/null +++ b/Scripts/Source/BindMeToMultipleTargets.psc @@ -0,0 +1,6 @@ +scriptName BindMeToMultipleTargets extends Actor + +event OnInit() + string script = StringUtil.Substring(self, 1, StringUtil.Find(self, " ") - 1) + Debug.Trace("[BIND] Script " + script + " bound to " + self + " " + GetBaseObject().GetName()) +endEvent diff --git a/Scripts/Source/DocStringBindToMultipleTargets.psc b/Scripts/Source/DocStringBindToMultipleTargets.psc new file mode 100644 index 0000000..2ad1c58 --- /dev/null +++ b/Scripts/Source/DocStringBindToMultipleTargets.psc @@ -0,0 +1,9 @@ +scriptName DocStringBindToMultipleTargets extends Actor +{ + !BIND SvenRef|0x1348A|$Player|HildeRef +} + +event OnInit() + string script = StringUtil.Substring(self, 1, StringUtil.Find(self, " ") - 1) + Debug.Trace("[BIND] Script " + script + " bound to " + self + " " + GetBaseObject().GetName()) +endEvent diff --git a/plugin.cpp b/plugin.cpp index afaa983..7f74ef6 100644 --- a/plugin.cpp +++ b/plugin.cpp @@ -51,6 +51,13 @@ namespace SkyrimScripting::Bind { rtrim(s); ltrim(s); } + std::vector split(const std::string& text, char delim) { + std::string line; + std::vector vec; + std::stringstream ss(text); + while (std::getline(ss, line, delim)) vec.push_back(line); + return vec; + } RE::TESForm* LookupFormID(RE::FormID formID) { auto* form = RE::TESForm::LookupByID(formID); @@ -135,24 +142,15 @@ namespace SkyrimScripting::Bind { logger::info("BIND ERROR [{}:{}] ({}) No default BIND behavior available for script which `extends` {}", FilePath, LineNumber, ScriptName, parentName); } - void ProcessBindingLine(std::string line) { - if (line.empty()) return; - trim(line); - std::istringstream lineStream{line}; - lineStream >> ScriptName; - if (ScriptName.empty() || ScriptName.starts_with('#') || ScriptName.starts_with("//")) return; - if (!vm->TypeIsValid(ScriptName)) { - logger::info("BIND ERROR [{}:{}] Script '{}' does not exist", FilePath, LineNumber, ScriptName); - return; - } - logger::info("\"{}\"", line); - std::string bindTarget; - lineStream >> bindTarget; + void ProcessBindingTarget(std::string bindTarget) { + trim(bindTarget); LowerCase(bindTarget); if (bindTarget.empty()) { AutoBindBasedOnScriptExtends(); return; - } else if (bindTarget.starts_with("0x")) + } else if (bindTarget.contains('|')) + for (const auto& target : split(bindTarget, '|')) ProcessBindingTarget(target); + else if (bindTarget.starts_with("0x")) Bind_FormID(std::stoi(bindTarget, 0, 16)); else if (bindTarget == "$player") Bind_FormID(0x14); @@ -170,6 +168,22 @@ namespace SkyrimScripting::Bind { Bind_EditorID(bindTarget); } + void ProcessBindingLine(std::string line) { + if (line.empty()) return; + trim(line); + std::istringstream lineStream{line}; + lineStream >> ScriptName; + if (ScriptName.empty() || ScriptName.starts_with('#') || ScriptName.starts_with("//")) return; + if (!vm->TypeIsValid(ScriptName)) { + logger::info("BIND ERROR [{}:{}] Script '{}' does not exist", FilePath, LineNumber, ScriptName); + return; + } + logger::info("\"{}\"", line); + std::string bindTarget; + lineStream >> bindTarget; + ProcessBindingTarget(bindTarget); + } + void ProcessBindingFile() { logger::info("Reading Binding File: {}", FilePath); LineNumber = 1;