enderalse/source/fs.dll/skse64/skse64/PapyrusGameData.cpp

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));
}