Skip to content

Commit

Permalink
Merge pull request #84 from dann1/dev
Browse files Browse the repository at this point in the history
Keyword helpers
  • Loading branch information
powerof3 authored Aug 19, 2023
2 parents d1b0d8a + 43eb469 commit a98e90d
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 8 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# `CommonLibSSE`
[![C++20](https://img.shields.io/static/v1?label=standard&message=C%2B%2B20&color=blue&logo=c%2B%2B&&logoColor=white&style=flat)](https://en.cppreference.com/w/cpp/compiler_support)
[![Platform](https://img.shields.io/static/v1?label=platform&message=windows&color=dimgray&style=flat)](#)
[![Main CI](https://img.shields.io/github/workflow/status/Ryan-rsm-McKenzie/CommonLibSSE/Main%20CI?logo=github&logoColor=white)](https://github.com/Ryan-rsm-McKenzie/CommonLibSSE/actions/workflows/main_ci.yml)
[![Main CI](https://github.com/dann1/CommonLibSSE/actions/workflows/main_ci.yml/badge.svg?branch=dev)](https://github.com/dann1/CommonLibSSE/actions/workflows/main_ci.yml?branch=dev)


## Build Dependencies
* [Boost](https://www.boost.org/)
Expand Down
11 changes: 10 additions & 1 deletion include/RE/T/TESForm.h
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ namespace RE
[[nodiscard]] const char* GetName() const;
[[nodiscard]] float GetWeight() const;
[[nodiscard]] bool HasKeywordInArray(const std::vector<BGSKeyword*>& a_keywords, bool a_matchAll) const;
[[nodiscard]] bool HasAnyKeywordByEditorID(const std::vector<std::string>& editorIDs) const;
[[nodiscard]] bool HasKeywordInList(BGSListForm* a_keywordList, bool a_matchAll) const;
[[nodiscard]] bool HasVMAD() const;
[[nodiscard]] bool HasWorldModel() const noexcept;
Expand All @@ -326,7 +327,15 @@ namespace RE
[[nodiscard]] bool IsInitialized() const noexcept { return (GetFormFlags() & RecordFlags::kInitialized) != 0; }
[[nodiscard]] bool IsKey() const noexcept { return Is(FormType::KeyMaster); }
[[nodiscard]] bool IsLockpick() const noexcept { return GetFormID() == 0x0000000A; }

/**
* @brief Checks if the Form represents Skooma.
*
* Determines whether the FormID matches one of the known form IDs for Skooma.
*
* @return True if the FormID is either 0x00057A7A or 0x0201391D, indicating that it is Skooma or RedWater Skooma.
*
*/
[[nodiscard]] bool IsSkooma() const noexcept { return (GetFormID() == 0x00057A7A || GetFormID() == 0x0201391D); }
[[nodiscard]] bool IsNot(FormType a_type) const noexcept { return !Is(a_type); }

template <class... Args>
Expand Down
7 changes: 7 additions & 0 deletions include/RE/T/TESObjectREFR.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include "RE/B/BGSDefaultObjectManager.h"
#include "RE/B/BSFixedString.h"
#include "RE/B/BSHandleRefObject.h"
#include "RE/B/BSPointerHandle.h"
Expand Down Expand Up @@ -421,18 +422,23 @@ namespace RE
bool HasKeyword(const BGSKeyword* a_keyword) const;
bool HasKeywordInArray(const std::vector<BGSKeyword*>& a_keywords, bool a_matchAll) const;
bool HasKeywordInList(BGSListForm* a_keywordList, bool a_matchAll) const;
bool HasKeywordWithType(DEFAULT_OBJECT keywordType) const;
bool HasQuestObject() const;
void InitChildActivates(TESObjectREFR* a_actionRef);
bool InitInventoryIfRequired(bool a_ignoreContainerExtraData = false);
bool Is3DLoaded() const;
bool IsActivationBlocked() const;
bool IsAnimal() const;
bool IsAnOwner(const Actor* a_testOwner, bool a_useFaction, bool a_requiresOwner) const;
bool IsCrimeToActivate();
bool IsDisabled() const;
bool IsDragon() const;
bool IsEnchanted() const;
bool IsHorse() const;
bool IsHumanoid() const;
bool IsInitiallyDisabled() const;
bool IsInWater() const;
bool IsJewelry() const;
bool IsLocked() const;
bool IsMarkedForDeletion() const;
bool IsOffLimits();
Expand All @@ -442,6 +448,7 @@ namespace RE
void MoveTo(TESObjectREFR* a_target);
bool MoveToNode(TESObjectREFR* a_target, const BSFixedString& a_nodeName);
bool MoveToNode(TESObjectREFR* a_target, NiAVObject* a_node);
bool NameIncludes(std::string a_word);
NiPointer<TESObjectREFR> PlaceObjectAtMe(TESBoundObject* a_baseToPlace, bool a_forcePersist) const;
void PlayAnimation(stl::zstring a_from, stl::zstring a_to);
void PlayAnimation(NiControllerManager* a_manager, NiControllerSequence* a_toSeq, NiControllerSequence* a_fromSeq);
Expand Down
28 changes: 28 additions & 0 deletions src/RE/T/TESForm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,34 @@ namespace RE
}
}

bool TESForm::HasAnyKeywordByEditorID(const std::vector<std::string>& editorIDs) const
{
// Try to cast to a keyword form interface
const auto keywordForm = As<BGSKeywordForm>();
if (!keywordForm) {
return false;
}

// Iterate through the keywords
for (std::uint32_t i = 0; i < keywordForm->GetNumKeywords(); ++i) {
auto keywordOpt = keywordForm->GetKeywordAt(i);
if (keywordOpt) {
auto keyword = *keywordOpt;
if (keyword) {
const char* keywordEditorID = keyword->GetFormEditorID();
if (keywordEditorID) {
// Check if the keywordEditorID is in the given editorIDs vector
if (std::find(editorIDs.begin(), editorIDs.end(), keywordEditorID) != editorIDs.end()) {
return true;
}
}
}
}
}

return false;
}

bool TESForm::HasKeywordInArray(const std::vector<BGSKeyword*>& a_keywords, bool a_matchAll) const
{
const auto keywordForm = As<BGSKeywordForm>();
Expand Down
45 changes: 39 additions & 6 deletions src/RE/T/TESObjectREFR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,17 @@ namespace RE
return hasKeyword;
}

bool TESObjectREFR::HasKeywordWithType(DEFAULT_OBJECT keywordType) const
{
auto dobj = BGSDefaultObjectManager::GetSingleton();
if (!dobj) {
return false;
}

auto keyword = dobj->GetObject<BGSKeyword>(keywordType);
return keyword ? HasKeyword(keyword) : false;
}

bool TESObjectREFR::HasQuestObject() const
{
using func_t = decltype(&TESObjectREFR::HasQuestObject);
Expand Down Expand Up @@ -615,6 +626,11 @@ namespace RE
return xFlags && xFlags->IsActivationBlocked();
}

bool TESObjectREFR::IsAnimal() const
{
return HasKeywordWithType(DEFAULT_OBJECT::kKeywordAnimal);
}

bool TESObjectREFR::IsAnOwner(const Actor* a_testOwner, bool a_useFaction, bool a_requiresOwner) const
{
using func_t = decltype(&TESObjectREFR::IsAnOwner);
Expand All @@ -634,6 +650,11 @@ namespace RE
return (GetFormFlags() & RecordFlags::kInitiallyDisabled) != 0;
}

bool TESObjectREFR::IsDragon() const
{
return HasKeywordWithType(DEFAULT_OBJECT::kKeywordDragon);
}

bool TESObjectREFR::IsEnchanted() const
{
auto xEnch = extraList.GetByType<ExtraEnchantment>();
Expand All @@ -654,20 +675,24 @@ namespace RE

bool TESObjectREFR::IsHorse() const
{
auto dobj = BGSDefaultObjectManager::GetSingleton();
if (!dobj) {
return false;
}
return HasKeywordWithType(DEFAULT_OBJECT::kKeywordHorse);
}

auto keyword = dobj->GetObject<BGSKeyword>(DEFAULT_OBJECT::kKeywordHorse);
return keyword ? HasKeyword(keyword) : false;
bool TESObjectREFR::IsHumanoid() const
{
return HasKeywordWithType(DEFAULT_OBJECT::kKeywordNPC);
}

bool TESObjectREFR::IsInitiallyDisabled() const
{
return (GetFormFlags() & RecordFlags::kInitiallyDisabled) != 0;
}

bool TESObjectREFR::IsJewelry() const
{
return HasKeywordWithType(DEFAULT_OBJECT::kKeywordJewelry);
}

bool TESObjectREFR::IsInWater() const
{
return GetWaterHeight() > GetPositionZ();
Expand Down Expand Up @@ -750,6 +775,14 @@ namespace RE
return true;
}

bool TESObjectREFR::NameIncludes(std::string a_word)
{
auto obj = GetObjectReference();
std::string name = obj ? obj->GetName() : "";

return name.find(a_word) != std::string::npos;
}

NiPointer<TESObjectREFR> TESObjectREFR::PlaceObjectAtMe(TESBoundObject* a_baseToPlace, bool a_forcePersist) const
{
const auto handle = TESDataHandler::GetSingleton()->CreateReferenceAtLocation(a_baseToPlace, GetPosition(), GetAngle(), GetParentCell(), GetWorldspace(), nullptr, nullptr, ObjectRefHandle(), a_forcePersist, true);
Expand Down

0 comments on commit a98e90d

Please sign in to comment.