415 lines
13 KiB
C++
415 lines
13 KiB
C++
#include "PapyrusGameData.h"
|
|
|
|
#include "skse64/GameFormComponents.h"
|
|
#include "skse64/GameData.h"
|
|
#include "skse64/GameRTTI.h"
|
|
#include "skse64/GameForms.h"
|
|
#include "skse64/GameObjects.h"
|
|
#include "skse64/GameReferences.h"
|
|
|
|
#include "skse64/PapyrusArgs.h"
|
|
|
|
#include <set>
|
|
|
|
enum WeaponTypes
|
|
{
|
|
kFilterType_HandToHandMelee = (1 << 0),
|
|
kFilterType_OneHandSword = (1 << 1),
|
|
kFilterType_OneHandDagger = (1 << 2),
|
|
kFilterType_OneHandAxe = (1 << 3),
|
|
kFilterType_OneHandMace = (1 << 4),
|
|
kFilterType_TwoHandSword = (1 << 5),
|
|
kFilterType_TwoHandAxe = (1 << 6),
|
|
kFilterType_Bow = (1 << 7),
|
|
kFilterType_Staff = (1 << 8),
|
|
kFilterType_CrossBow = (1 << 9)
|
|
};
|
|
|
|
#define IS_TYPE(weaponTypes, weapon, t, h, s) ((weaponTypes & t) == t) && (weapon->gameData.type == h || weapon->gameData.type == s)
|
|
|
|
bool VerifyKeywords(TESForm * form, VMArray<BGSKeyword*> * keywords)
|
|
{
|
|
if (keywords->Length() > 0) {
|
|
BGSKeywordForm* pKeywords = DYNAMIC_CAST(form, TESForm, BGSKeywordForm);
|
|
if (pKeywords) {
|
|
bool failed = false;
|
|
BGSKeyword * keyword = NULL;
|
|
for (UInt32 k = 0; k < keywords->Length(); k++) {
|
|
keywords->Get(&keyword, k);
|
|
if (keyword && !pKeywords->HasKeyword(keyword)) {
|
|
failed = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (failed)
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
namespace papyrusGameData
|
|
{
|
|
VMResultArray<TESForm*> GetAllWeapons(StaticFunctionTag*, BSFixedString modName, VMArray<BGSKeyword*> keywords, bool playable, bool ignoreTemplates, bool ignoreEnchantments, bool onlyEnchanted, UInt32 weaponTypes)
|
|
{
|
|
VMResultArray<TESForm*> result;
|
|
|
|
DataHandler * dataHandler = DataHandler::GetSingleton();
|
|
const ModInfo * modInfo = dataHandler->LookupModByName(modName.data);
|
|
if (!modInfo || !modInfo->IsActive())
|
|
return result;
|
|
|
|
TESObjectWEAP * weapon = NULL;
|
|
for (UInt32 i = 0; i < dataHandler->weapons.count; i++)
|
|
{
|
|
dataHandler->weapons.GetNthItem(i, weapon);
|
|
|
|
if (!modInfo->IsFormInMod(weapon->formID))
|
|
continue;
|
|
if (playable != weapon->IsPlayable())
|
|
continue;
|
|
if (ignoreTemplates && weapon->templateForm)
|
|
continue;
|
|
if (ignoreEnchantments && weapon->enchantable.enchantment)
|
|
continue;
|
|
if (onlyEnchanted && !weapon->enchantable.enchantment)
|
|
continue;
|
|
|
|
if (!VerifyKeywords(weapon, &keywords))
|
|
continue;
|
|
|
|
bool accept = false;
|
|
if (IS_TYPE(weaponTypes, weapon, kFilterType_HandToHandMelee, TESObjectWEAP::GameData::kType_HandToHandMelee, TESObjectWEAP::GameData::kType_H2H))
|
|
accept = true;
|
|
if (IS_TYPE(weaponTypes, weapon, kFilterType_OneHandSword, TESObjectWEAP::GameData::kType_OneHandSword, TESObjectWEAP::GameData::kType_1HS))
|
|
accept = true;
|
|
if (IS_TYPE(weaponTypes, weapon, kFilterType_OneHandDagger, TESObjectWEAP::GameData::kType_OneHandDagger, TESObjectWEAP::GameData::kType_1HD))
|
|
accept = true;
|
|
if (IS_TYPE(weaponTypes, weapon, kFilterType_OneHandAxe, TESObjectWEAP::GameData::kType_OneHandAxe, TESObjectWEAP::GameData::kType_1HA))
|
|
accept = true;
|
|
if (IS_TYPE(weaponTypes, weapon, kFilterType_OneHandMace, TESObjectWEAP::GameData::kType_OneHandMace, TESObjectWEAP::GameData::kType_1HM))
|
|
accept = true;
|
|
if (IS_TYPE(weaponTypes, weapon, kFilterType_TwoHandSword, TESObjectWEAP::GameData::kType_TwoHandSword, TESObjectWEAP::GameData::kType_2HS))
|
|
accept = true;
|
|
if (IS_TYPE(weaponTypes, weapon, kFilterType_TwoHandAxe, TESObjectWEAP::GameData::kType_TwoHandAxe, TESObjectWEAP::GameData::kType_2HA))
|
|
accept = true;
|
|
if (IS_TYPE(weaponTypes, weapon, kFilterType_Bow, TESObjectWEAP::GameData::kType_Bow, TESObjectWEAP::GameData::kType_Bow2))
|
|
accept = true;
|
|
if (IS_TYPE(weaponTypes, weapon, kFilterType_Staff, TESObjectWEAP::GameData::kType_Staff, TESObjectWEAP::GameData::kType_Staff2))
|
|
accept = true;
|
|
if (IS_TYPE(weaponTypes, weapon, kFilterType_CrossBow, TESObjectWEAP::GameData::kType_CrossBow, TESObjectWEAP::GameData::kType_CBow))
|
|
accept = true;
|
|
if (!accept)
|
|
continue;
|
|
|
|
result.push_back(weapon);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
VMResultArray<TESForm*> GetAllArmor(StaticFunctionTag*, BSFixedString modName, VMArray<BGSKeyword*> keywords, bool playable, bool ignoreTemplates, bool ignoreEnchantments, bool onlyEnchanted, bool ignoreSkin)
|
|
{
|
|
VMResultArray<TESForm*> result;
|
|
|
|
DataHandler * dataHandler = DataHandler::GetSingleton();
|
|
|
|
const ModInfo * modInfo = dataHandler->LookupModByName(modName.data);
|
|
if (!modInfo || !modInfo->IsActive())
|
|
return result;
|
|
|
|
std::set<TESObjectARMO*> exclude;
|
|
if (ignoreSkin) {
|
|
TESRace * race = NULL;
|
|
for (UInt32 i = 0; i < dataHandler->races.count; i++)
|
|
{
|
|
dataHandler->races.GetNthItem(i, race);
|
|
if (race->skin.skin)
|
|
exclude.insert(race->skin.skin);
|
|
}
|
|
|
|
TESNPC * npc = NULL;
|
|
for (UInt32 i = 0; i < dataHandler->npcs.count; i++)
|
|
{
|
|
dataHandler->npcs.GetNthItem(i, npc);
|
|
if (npc->skinForm.skin)
|
|
exclude.insert(npc->skinForm.skin);
|
|
}
|
|
}
|
|
|
|
TESObjectARMO * armor = NULL;
|
|
for (UInt32 i = 0; i < dataHandler->armors.count; i++)
|
|
{
|
|
dataHandler->armors.GetNthItem(i, armor);
|
|
|
|
if (!modInfo->IsFormInMod(armor->formID))
|
|
continue;
|
|
if (ignoreSkin && exclude.find(armor) != exclude.end())
|
|
continue;
|
|
if (playable != armor->IsPlayable())
|
|
continue;
|
|
if (ignoreTemplates && armor->templateArmor)
|
|
continue;
|
|
if (ignoreEnchantments && armor->enchantable.enchantment)
|
|
continue;
|
|
if (onlyEnchanted && !armor->enchantable.enchantment)
|
|
continue;
|
|
if (!VerifyKeywords(armor, &keywords))
|
|
continue;
|
|
|
|
result.push_back(armor);
|
|
}
|
|
|
|
|
|
return result;
|
|
}
|
|
|
|
VMResultArray<TESForm*> GetAllAmmo(StaticFunctionTag*, BSFixedString modName, VMArray<BGSKeyword*> keywords, bool playable)
|
|
{
|
|
VMResultArray<TESForm*> result;
|
|
|
|
DataHandler * dataHandler = DataHandler::GetSingleton();
|
|
const ModInfo * modInfo = dataHandler->LookupModByName(modName.data);
|
|
if (!modInfo || !modInfo->IsActive())
|
|
return result;
|
|
|
|
|
|
TESAmmo * ammo = NULL;
|
|
for (UInt32 i = 0; i < dataHandler->ammo.count; i++)
|
|
{
|
|
dataHandler->ammo.GetNthItem(i, ammo);
|
|
|
|
if (!modInfo->IsFormInMod(ammo->formID))
|
|
continue;
|
|
if (playable != ammo->IsPlayable())
|
|
continue;
|
|
if (!VerifyKeywords(ammo, &keywords))
|
|
continue;
|
|
|
|
result.push_back(ammo);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
VMResultArray<TESForm*> GetAllBooks(StaticFunctionTag*, BSFixedString modName, VMArray<BGSKeyword*> keywords, bool regular, bool spellBook, bool skillBook)
|
|
{
|
|
VMResultArray<TESForm*> result;
|
|
|
|
DataHandler * dataHandler = DataHandler::GetSingleton();
|
|
const ModInfo * modInfo = dataHandler->LookupModByName(modName.data);
|
|
if (!modInfo || !modInfo->IsActive())
|
|
return result;
|
|
|
|
TESObjectBOOK * book = NULL;
|
|
for (UInt32 i = 0; i < dataHandler->books.count; i++)
|
|
{
|
|
dataHandler->books.GetNthItem(i, book);
|
|
|
|
if (!modInfo->IsFormInMod(book->formID))
|
|
continue;
|
|
|
|
if (!VerifyKeywords(book, &keywords))
|
|
continue;
|
|
|
|
bool isSkillBook = book->data.GetSanitizedType() == TESObjectBOOK::Data::kType_Skill;
|
|
bool isSpellBook = book->data.GetSanitizedType() == TESObjectBOOK::Data::kType_Spell;
|
|
|
|
bool accept = false;
|
|
if (regular && !isSkillBook && !isSpellBook)
|
|
accept = true;
|
|
if (spellBook && isSpellBook)
|
|
accept = true;
|
|
if (skillBook && isSkillBook)
|
|
accept = true;
|
|
if (!accept)
|
|
continue;
|
|
|
|
|
|
result.push_back(book);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
VMResultArray<TESForm*> GetAllPotions(StaticFunctionTag*, BSFixedString modName, VMArray<BGSKeyword*> keywords, bool potions, bool food, bool poison)
|
|
{
|
|
VMResultArray<TESForm*> result;
|
|
|
|
DataHandler * dataHandler = DataHandler::GetSingleton();
|
|
const ModInfo * modInfo = dataHandler->LookupModByName(modName.data);
|
|
if (!modInfo || !modInfo->IsActive())
|
|
return result;
|
|
|
|
AlchemyItem * potion = NULL;
|
|
for (UInt32 i = 0; i < dataHandler->potions.count; i++)
|
|
{
|
|
dataHandler->potions.GetNthItem(i, potion);
|
|
|
|
if (!modInfo->IsFormInMod(potion->formID))
|
|
continue;
|
|
|
|
if (!VerifyKeywords(potion, &keywords))
|
|
continue;
|
|
|
|
bool isFood = potion->IsFood();
|
|
bool isPoison = potion->IsPoison();
|
|
|
|
bool accept = false;
|
|
if (potions && !isFood && !isPoison)
|
|
accept = true;
|
|
if (food && isFood)
|
|
accept = true;
|
|
if (poison && isPoison)
|
|
accept = true;
|
|
if (!accept)
|
|
continue;
|
|
|
|
|
|
result.push_back(potion);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
VMResultArray<TESForm*> GetAllIngredients(StaticFunctionTag*, BSFixedString modName, VMArray<BGSKeyword*> keywords)
|
|
{
|
|
VMResultArray<TESForm*> result;
|
|
|
|
DataHandler * dataHandler = DataHandler::GetSingleton();
|
|
const ModInfo * modInfo = dataHandler->LookupModByName(modName.data);
|
|
if (!modInfo || !modInfo->IsActive())
|
|
return result;
|
|
|
|
IngredientItem * ingredient = NULL;
|
|
for (UInt32 i = 0; i < dataHandler->ingredients.count; i++)
|
|
{
|
|
dataHandler->ingredients.GetNthItem(i, ingredient);
|
|
|
|
if (!modInfo->IsFormInMod(ingredient->formID))
|
|
continue;
|
|
|
|
if (!VerifyKeywords(ingredient, &keywords))
|
|
continue;
|
|
|
|
result.push_back(ingredient);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
VMResultArray<TESForm*> GetAllScrolls(StaticFunctionTag*, BSFixedString modName, VMArray<BGSKeyword*> keywords)
|
|
{
|
|
VMResultArray<TESForm*> result;
|
|
|
|
DataHandler * dataHandler = DataHandler::GetSingleton();
|
|
const ModInfo * modInfo = dataHandler->LookupModByName(modName.data);
|
|
if (!modInfo || !modInfo->IsActive())
|
|
return result;
|
|
|
|
ScrollItem * scroll = NULL;
|
|
for (UInt32 i = 0; i < dataHandler->scrolls.count; i++)
|
|
{
|
|
dataHandler->scrolls.GetNthItem(i, scroll);
|
|
|
|
if (!modInfo->IsFormInMod(scroll->formID))
|
|
continue;
|
|
|
|
if (!VerifyKeywords(scroll, &keywords))
|
|
continue;
|
|
|
|
result.push_back(scroll);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
VMResultArray<TESForm*> GetAllKeys(StaticFunctionTag*, BSFixedString modName, VMArray<BGSKeyword*> keywords)
|
|
{
|
|
VMResultArray<TESForm*> result;
|
|
|
|
DataHandler * dataHandler = DataHandler::GetSingleton();
|
|
const ModInfo * modInfo = dataHandler->LookupModByName(modName.data);
|
|
if (!modInfo || !modInfo->IsActive())
|
|
return result;
|
|
|
|
|
|
TESKey * key = NULL;
|
|
for (UInt32 i = 0; i < dataHandler->keys.count; i++)
|
|
{
|
|
dataHandler->keys.GetNthItem(i, key);
|
|
|
|
if (!modInfo->IsFormInMod(key->formID))
|
|
continue;
|
|
|
|
if (!VerifyKeywords(key, &keywords))
|
|
continue;
|
|
|
|
result.push_back(key);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
VMResultArray<TESForm*> GetAllMiscItems(StaticFunctionTag*, BSFixedString modName, VMArray<BGSKeyword*> keywords)
|
|
{
|
|
VMResultArray<TESForm*> result;
|
|
|
|
DataHandler * dataHandler = DataHandler::GetSingleton();
|
|
const ModInfo * modInfo = dataHandler->LookupModByName(modName.data);
|
|
if (!modInfo || !modInfo->IsActive())
|
|
return result;
|
|
|
|
TESObjectMISC * misc = NULL;
|
|
for (UInt32 i = 0; i < dataHandler->miscObjects.count; i++)
|
|
{
|
|
dataHandler->miscObjects.GetNthItem(i, misc);
|
|
|
|
if (!modInfo->IsFormInMod(misc->formID))
|
|
continue;
|
|
|
|
if (!VerifyKeywords(misc, &keywords))
|
|
continue;
|
|
|
|
result.push_back(misc);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
}
|
|
|
|
#include "skse64/PapyrusVM.h"
|
|
#include "skse64/PapyrusNativeFunctions.h"
|
|
|
|
void papyrusGameData::RegisterFuncs(VMClassRegistry* registry)
|
|
{
|
|
registry->RegisterFunction(
|
|
new NativeFunction7<StaticFunctionTag, VMResultArray<TESForm*>, BSFixedString, VMArray<BGSKeyword*>, bool, bool, bool, bool, UInt32>("GetAllWeapons", "GameData", papyrusGameData::GetAllWeapons, registry));
|
|
|
|
registry->RegisterFunction(
|
|
new NativeFunction7<StaticFunctionTag, VMResultArray<TESForm*>, BSFixedString, VMArray<BGSKeyword*>, bool, bool, bool, bool, bool>("GetAllArmor", "GameData", papyrusGameData::GetAllArmor, registry));
|
|
|
|
registry->RegisterFunction(
|
|
new NativeFunction3<StaticFunctionTag, VMResultArray<TESForm*>, BSFixedString, VMArray<BGSKeyword*>, bool>("GetAllAmmo", "GameData", papyrusGameData::GetAllAmmo, registry));
|
|
|
|
registry->RegisterFunction(
|
|
new NativeFunction5<StaticFunctionTag, VMResultArray<TESForm*>, BSFixedString, VMArray<BGSKeyword*>, bool, bool, bool>("GetAllBooks", "GameData", papyrusGameData::GetAllBooks, registry));
|
|
|
|
registry->RegisterFunction(
|
|
new NativeFunction5<StaticFunctionTag, VMResultArray<TESForm*>, BSFixedString, VMArray<BGSKeyword*>, bool, bool, bool>("GetAllPotions", "GameData", papyrusGameData::GetAllPotions, registry));
|
|
|
|
registry->RegisterFunction(
|
|
new NativeFunction2<StaticFunctionTag, VMResultArray<TESForm*>, BSFixedString, VMArray<BGSKeyword*>>("GetAllIngredients", "GameData", papyrusGameData::GetAllIngredients, registry));
|
|
|
|
registry->RegisterFunction(
|
|
new NativeFunction2<StaticFunctionTag, VMResultArray<TESForm*>, BSFixedString, VMArray<BGSKeyword*>>("GetAllScrolls", "GameData", papyrusGameData::GetAllScrolls, registry));
|
|
|
|
registry->RegisterFunction(
|
|
new NativeFunction2<StaticFunctionTag, VMResultArray<TESForm*>, BSFixedString, VMArray<BGSKeyword*>>("GetAllKeys", "GameData", papyrusGameData::GetAllKeys, registry));
|
|
|
|
registry->RegisterFunction(
|
|
new NativeFunction2<StaticFunctionTag, VMResultArray<TESForm*>, BSFixedString, VMArray<BGSKeyword*>>("GetAllMiscItems", "GameData", papyrusGameData::GetAllMiscItems, registry));
|
|
}
|