Lua: Standardize record stores

fix-osga-rotate-wildly
Zackhasacat 9 months ago committed by psi29a
parent 38eb741bfd
commit 6d529835ae

@ -63,7 +63,7 @@ add_openmw_dir (mwlua
luamanagerimp object objectlists userdataserializer luaevents engineevents objectvariant luamanagerimp object objectlists userdataserializer luaevents engineevents objectvariant
context menuscripts globalscripts localscripts playerscripts luabindings objectbindings cellbindings context menuscripts globalscripts localscripts playerscripts luabindings objectbindings cellbindings
mwscriptbindings camerabindings vfsbindings uibindings soundbindings inputbindings nearbybindings mwscriptbindings camerabindings vfsbindings uibindings soundbindings inputbindings nearbybindings
postprocessingbindings stats debugbindings corebindings worldbindings worker magicbindings factionbindings postprocessingbindings stats recordstore debugbindings corebindings worldbindings worker magicbindings factionbindings
classbindings itemdata inputprocessor animationbindings birthsignbindings racebindings markupbindings classbindings itemdata inputprocessor animationbindings birthsignbindings racebindings markupbindings
types/types types/door types/item types/actor types/container types/lockable types/weapon types/npc types/types types/door types/item types/actor types/container types/lockable types/weapon types/npc
types/creature types/player types/activator types/book types/lockpick types/probe types/apparatus types/creature types/player types/activator types/book types/lockpick types/probe types/apparatus

@ -97,8 +97,7 @@ namespace MWLua
api["magic"] = initCoreMagicBindings(context); api["magic"] = initCoreMagicBindings(context);
api["stats"] = initCoreStatsBindings(context); api["stats"] = initCoreStatsBindings(context);
initCoreFactionBindings(context); api["factions"] = initCoreFactionBindings(context);
api["factions"] = &MWBase::Environment::get().getESMStore()->get<ESM::Faction>();
api["l10n"] = LuaUtil::initL10nLoader(lua->sol(), MWBase::Environment::get().getL10nManager()); api["l10n"] = LuaUtil::initL10nLoader(lua->sol(), MWBase::Environment::get().getL10nManager());
const MWWorld::Store<ESM::GameSetting>* gmstStore const MWWorld::Store<ESM::GameSetting>* gmstStore

@ -1,4 +1,5 @@
#include "factionbindings.hpp" #include "factionbindings.hpp"
#include "recordstore.hpp"
#include <components/esm3/loadfact.hpp> #include <components/esm3/loadfact.hpp>
#include <components/lua/luastate.hpp> #include <components/lua/luastate.hpp>
@ -32,10 +33,6 @@ namespace sol
{ {
}; };
template <> template <>
struct is_automagical<MWWorld::Store<ESM::Faction>> : std::false_type
{
};
template <>
struct is_automagical<MWWorld::Store<FactionRank>> : std::false_type struct is_automagical<MWWorld::Store<FactionRank>> : std::false_type
{ {
}; };
@ -43,27 +40,11 @@ namespace sol
namespace MWLua namespace MWLua
{ {
using FactionStore = MWWorld::Store<ESM::Faction>; sol::table initCoreFactionBindings(const Context& context)
void initCoreFactionBindings(const Context& context)
{ {
sol::state_view& lua = context.mLua->sol(); sol::state_view& lua = context.mLua->sol();
sol::usertype<FactionStore> factionStoreT = lua.new_usertype<FactionStore>("ESM3_FactionStore"); sol::table factions(lua, sol::create);
factionStoreT[sol::meta_function::to_string] = [](const FactionStore& store) { addRecordFunctionBinding<ESM::Faction>(factions, context);
return "ESM3_FactionStore{" + std::to_string(store.getSize()) + " factions}";
};
factionStoreT[sol::meta_function::length] = [](const FactionStore& store) { return store.getSize(); };
factionStoreT[sol::meta_function::index] = sol::overload(
[](const FactionStore& store, size_t index) -> const ESM::Faction* {
if (index == 0 || index > store.getSize())
return nullptr;
return store.at(index - 1);
},
[](const FactionStore& store, std::string_view factionId) -> const ESM::Faction* {
return store.search(ESM::RefId::deserializeText(factionId));
});
factionStoreT[sol::meta_function::pairs] = lua["ipairsForArray"].template get<sol::function>();
factionStoreT[sol::meta_function::ipairs] = lua["ipairsForArray"].template get<sol::function>();
// Faction record // Faction record
auto factionT = lua.new_usertype<ESM::Faction>("ESM3_Faction"); auto factionT = lua.new_usertype<ESM::Faction>("ESM3_Faction");
factionT[sol::meta_function::to_string] factionT[sol::meta_function::to_string]
@ -113,5 +94,6 @@ namespace MWLua
res.add(rec.mAttribute2); res.add(rec.mAttribute2);
return res; return res;
}); });
return LuaUtil::makeReadOnly(factions);
} }
} }

@ -7,7 +7,7 @@
namespace MWLua namespace MWLua
{ {
void initCoreFactionBindings(const Context& context); sol::table initCoreFactionBindings(const Context& context);
} }
#endif // MWLUA_FACTIONBINDINGS_H #endif // MWLUA_FACTIONBINDINGS_H

@ -31,6 +31,7 @@
#include "luamanagerimp.hpp" #include "luamanagerimp.hpp"
#include "object.hpp" #include "object.hpp"
#include "objectvariant.hpp" #include "objectvariant.hpp"
#include "recordstore.hpp"
namespace MWLua namespace MWLua
{ {
@ -135,10 +136,6 @@ namespace MWLua
namespace sol namespace sol
{ {
template <typename T>
struct is_automagical<typename MWWorld::Store<T>> : std::false_type
{
};
template <> template <>
struct is_automagical<ESM::Spell> : std::false_type struct is_automagical<ESM::Spell> : std::false_type
{ {
@ -228,50 +225,18 @@ namespace MWLua
} }
// Spell store // Spell store
using SpellStore = MWWorld::Store<ESM::Spell>; sol::table spells(lua, sol::create);
const SpellStore* spellStore = &MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>(); addRecordFunctionBinding<ESM::Spell>(spells, context);
sol::usertype<SpellStore> spellStoreT = lua.new_usertype<SpellStore>("ESM3_SpellStore"); magicApi["spells"] = LuaUtil::makeReadOnly(spells);
spellStoreT[sol::meta_function::to_string]
= [](const SpellStore& store) { return "ESM3_SpellStore{" + std::to_string(store.getSize()) + " spells}"; };
spellStoreT[sol::meta_function::length] = [](const SpellStore& store) { return store.getSize(); };
spellStoreT[sol::meta_function::index] = sol::overload(
[](const SpellStore& store, size_t index) -> const ESM::Spell* {
if (index == 0 || index > store.getSize())
return nullptr;
return store.at(index - 1);
},
[](const SpellStore& store, std::string_view spellId) -> const ESM::Spell* {
return store.search(ESM::RefId::deserializeText(spellId));
});
spellStoreT[sol::meta_function::pairs] = lua["ipairsForArray"].template get<sol::function>();
spellStoreT[sol::meta_function::ipairs] = lua["ipairsForArray"].template get<sol::function>();
magicApi["spells"] = spellStore;
// Enchantment store // Enchantment store
using EnchantmentStore = MWWorld::Store<ESM::Enchantment>; sol::table enchantments(lua, sol::create);
const EnchantmentStore* enchantmentStore addRecordFunctionBinding<ESM::Enchantment>(enchantments, context);
= &MWBase::Environment::get().getWorld()->getStore().get<ESM::Enchantment>(); magicApi["enchantments"] = LuaUtil::makeReadOnly(enchantments);
sol::usertype<EnchantmentStore> enchantmentStoreT = lua.new_usertype<EnchantmentStore>("ESM3_EnchantmentStore");
enchantmentStoreT[sol::meta_function::to_string] = [](const EnchantmentStore& store) {
return "ESM3_EnchantmentStore{" + std::to_string(store.getSize()) + " enchantments}";
};
enchantmentStoreT[sol::meta_function::length] = [](const EnchantmentStore& store) { return store.getSize(); };
enchantmentStoreT[sol::meta_function::index] = sol::overload(
[](const EnchantmentStore& store, size_t index) -> const ESM::Enchantment* {
if (index == 0 || index > store.getSize())
return nullptr;
return store.at(index - 1);
},
[](const EnchantmentStore& store, std::string_view enchantmentId) -> const ESM::Enchantment* {
return store.search(ESM::RefId::deserializeText(enchantmentId));
});
enchantmentStoreT[sol::meta_function::pairs] = lua["ipairsForArray"].template get<sol::function>();
enchantmentStoreT[sol::meta_function::ipairs] = lua["ipairsForArray"].template get<sol::function>();
magicApi["enchantments"] = enchantmentStore;
// MagicEffect store // MagicEffect store
sol::table magicEffects(lua, sol::create);
magicApi["effects"] = LuaUtil::makeReadOnly(magicEffects);
using MagicEffectStore = MWWorld::Store<ESM::MagicEffect>; using MagicEffectStore = MWWorld::Store<ESM::MagicEffect>;
const MagicEffectStore* magicEffectStore const MagicEffectStore* magicEffectStore
= &MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>(); = &MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>();
@ -303,8 +268,10 @@ namespace MWLua
}; };
magicEffectStoreT[sol::meta_function::pairs] magicEffectStoreT[sol::meta_function::pairs]
= [iter = sol::make_object(lua, magicEffectsIter)] { return iter; }; = [iter = sol::make_object(lua, magicEffectsIter)] { return iter; };
magicEffectStoreT[sol::meta_function::ipairs]
= [iter = sol::make_object(lua, magicEffectsIter)] { return iter; };
magicApi["effects"] = magicEffectStore; magicEffects["records"] = magicEffectStore;
// Spell record // Spell record
auto spellT = lua.new_usertype<ESM::Spell>("ESM3_Spell"); auto spellT = lua.new_usertype<ESM::Spell>("ESM3_Spell");

@ -0,0 +1,63 @@
#ifndef MWLUA_RECORDSTORE_H
#define MWLUA_RECORDSTORE_H
#include <sol/sol.hpp>
#include <components/esm/defs.hpp>
#include <components/lua/luastate.hpp>
#include "apps/openmw/mwbase/environment.hpp"
#include "apps/openmw/mwbase/world.hpp"
#include "apps/openmw/mwworld/esmstore.hpp"
#include "apps/openmw/mwworld/store.hpp"
#include "context.hpp"
#include "object.hpp"
namespace sol
{
// Ensure sol does not try to create the automatic Container or usertype bindings for Store.
// They include write operations and we want the store to be read-only.
template <typename T>
struct is_automagical<typename MWWorld::Store<T>> : std::false_type
{
};
}
namespace MWLua
{
template <class T>
void addRecordFunctionBinding(
sol::table& table, const Context& context, const std::string& recordName = std::string(T::getRecordType()))
{
const MWWorld::Store<T>& store = MWBase::Environment::get().getESMStore()->get<T>();
table["record"] = sol::overload([](const Object& obj) -> const T* { return obj.ptr().get<T>()->mBase; },
[&store](std::string_view id) -> const T* { return store.search(ESM::RefId::deserializeText(id)); });
// Define a custom user type for the store.
// Provide the interface of a read-only array.
using StoreT = MWWorld::Store<T>;
sol::state_view& lua = context.mLua->sol();
sol::usertype<StoreT> storeT = lua.new_usertype<StoreT>(recordName + "WorldStore");
storeT[sol::meta_function::to_string] = [recordName](const StoreT& store) {
return "{" + std::to_string(store.getSize()) + " " + recordName + " records}";
};
storeT[sol::meta_function::length] = [](const StoreT& store) { return store.getSize(); };
storeT[sol::meta_function::index] = sol::overload(
[](const StoreT& store, size_t index) -> const T* {
if (index == 0 || index > store.getSize())
return nullptr;
return store.at(index - 1); // Translate from Lua's 1-based indexing.
},
[](const StoreT& store, std::string_view id) -> const T* {
return store.search(ESM::RefId::deserializeText(id));
});
storeT[sol::meta_function::ipairs] = lua["ipairsForArray"].template get<sol::function>();
storeT[sol::meta_function::pairs] = lua["ipairsForArray"].template get<sol::function>();
// Provide access to the store.
table["records"] = &store;
}
}
#endif // MWLUA_RECORDSTORE_H

@ -1,4 +1,5 @@
#include "soundbindings.hpp" #include "soundbindings.hpp"
#include "recordstore.hpp"
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/soundmanager.hpp" #include "../mwbase/soundmanager.hpp"
@ -196,24 +197,7 @@ namespace MWLua
}, },
[]() { return MWBase::Environment::get().getSoundManager()->sayActive(MWWorld::ConstPtr()); }); []() { return MWBase::Environment::get().getSoundManager()->sayActive(MWWorld::ConstPtr()); });
using SoundStore = MWWorld::Store<ESM::Sound>; addRecordFunctionBinding<ESM::Sound>(api, context);
sol::usertype<SoundStore> soundStoreT = lua.new_usertype<SoundStore>("ESM3_SoundStore");
soundStoreT[sol::meta_function::to_string]
= [](const SoundStore& store) { return "ESM3_SoundStore{" + std::to_string(store.getSize()) + " sounds}"; };
soundStoreT[sol::meta_function::length] = [](const SoundStore& store) { return store.getSize(); };
soundStoreT[sol::meta_function::index] = sol::overload(
[](const SoundStore& store, size_t index) -> const ESM::Sound* {
if (index == 0 || index > store.getSize())
return nullptr;
return store.at(index - 1);
},
[](const SoundStore& store, std::string_view soundId) -> const ESM::Sound* {
return store.search(ESM::RefId::deserializeText(soundId));
});
soundStoreT[sol::meta_function::pairs] = lua["ipairsForArray"].template get<sol::function>();
soundStoreT[sol::meta_function::ipairs] = lua["ipairsForArray"].template get<sol::function>();
api["sounds"] = &MWBase::Environment::get().getWorld()->getStore().get<ESM::Sound>();
// Sound record // Sound record
auto soundT = lua.new_usertype<ESM::Sound>("ESM3_Sound"); auto soundT = lua.new_usertype<ESM::Sound>("ESM3_Sound");

@ -22,7 +22,7 @@
#include "../mwworld/esmstore.hpp" #include "../mwworld/esmstore.hpp"
#include "objectvariant.hpp" #include "objectvariant.hpp"
#include "types/types.hpp" #include "recordstore.hpp"
namespace namespace
{ {

@ -6,22 +6,8 @@
#include <components/esm/defs.hpp> #include <components/esm/defs.hpp>
#include <components/lua/luastate.hpp> #include <components/lua/luastate.hpp>
#include "apps/openmw/mwbase/environment.hpp"
#include "apps/openmw/mwworld/esmstore.hpp"
#include "apps/openmw/mwworld/store.hpp"
#include "../context.hpp" #include "../context.hpp"
#include "../object.hpp" #include "../recordstore.hpp"
namespace sol
{
// Ensure sol does not try to create the automatic Container or usertype bindings for Store.
// They include write operations and we want the store to be read-only.
template <typename T>
struct is_automagical<typename MWWorld::Store<T>> : std::false_type
{
};
}
namespace MWLua namespace MWLua
{ {
@ -68,36 +54,6 @@ namespace MWLua
void addESM4DoorBindings(sol::table door, const Context& context); void addESM4DoorBindings(sol::table door, const Context& context);
void addESM4TerminalBindings(sol::table term, const Context& context); void addESM4TerminalBindings(sol::table term, const Context& context);
template <class T>
void addRecordFunctionBinding(
sol::table& table, const Context& context, const std::string& recordName = std::string(T::getRecordType()))
{
const MWWorld::Store<T>& store = MWBase::Environment::get().getESMStore()->get<T>();
table["record"] = sol::overload([](const Object& obj) -> const T* { return obj.ptr().get<T>()->mBase; },
[&store](std::string_view id) -> const T* { return store.search(ESM::RefId::deserializeText(id)); });
// Define a custom user type for the store.
// Provide the interface of a read-only array.
using StoreT = MWWorld::Store<T>;
sol::state_view& lua = context.mLua->sol();
sol::usertype<StoreT> storeT = lua.new_usertype<StoreT>(recordName + "WorldStore");
storeT[sol::meta_function::to_string] = [recordName](const StoreT& store) {
return "{" + std::to_string(store.getSize()) + " " + recordName + " records}";
};
storeT[sol::meta_function::length] = [](const StoreT& store) { return store.getSize(); };
storeT[sol::meta_function::index] = [](const StoreT& store, size_t index) -> const T* {
if (index == 0 || index > store.getSize())
return nullptr;
return store.at(index - 1); // Translate from Lua's 1-based indexing.
};
storeT[sol::meta_function::pairs] = lua["ipairsForArray"].template get<sol::function>();
storeT[sol::meta_function::ipairs] = lua["ipairsForArray"].template get<sol::function>();
// Provide access to the store.
table["records"] = &store;
}
} }
#endif // MWLUA_TYPES_H #endif // MWLUA_TYPES_H

@ -10,10 +10,6 @@
-- The revision of OpenMW Lua API. It is an integer that is incremented every time the API is changed. See the actual value at the top of the page. -- The revision of OpenMW Lua API. It is an integer that is incremented every time the API is changed. See the actual value at the top of the page.
-- @field [parent=#core] #number API_REVISION -- @field [parent=#core] #number API_REVISION
---
-- A read-only list of all @{#FactionRecord}s in the world database.
-- @field [parent=#core] #list<#FactionRecord> factions
--- ---
-- Terminates the game and quits to the OS. Should be used only for testing purposes. -- Terminates the game and quits to the OS. Should be used only for testing purposes.
-- @function [parent=#core] quit -- @function [parent=#core] quit
@ -622,41 +618,52 @@
-- @field #number Curse Curse -- @field #number Curse Curse
-- @field #number Power Power, can be used once a day -- @field #number Power Power, can be used once a day
--- @{#Spells}: Spells
-- @field [parent=#Magic] #Spells spells
--- List of all @{#Spell}s. --- List of all @{#Spell}s.
-- @field [parent=#Magic] #list<#Spell> spells -- @field [parent=#Spells] #list<#Spell> records A read-only list of all @{#Spell} records in the world database, may be indexed by recordId.
-- @usage local spell = core.magic.spells['thunder fist'] -- get by id -- Implements [iterables#List](iterables.html#List) of #Spell.
-- @usage local spell = core.magic.spells[1] -- get by index -- @usage local spell = core.magic.spells.records['thunder fist'] -- get by id
-- @usage local spell = core.magic.spells.records[1] -- get by index
-- @usage -- Print all powers -- @usage -- Print all powers
-- for _, spell in pairs(core.magic.spells) do -- for _, spell in pairs(core.magic.spells.records) do
-- if spell.types == core.magic.SPELL_TYPE.Power then -- if spell.types == core.magic.SPELL_TYPE.Power then
-- print(spell.name) -- print(spell.name)
-- end -- end
-- end -- end
--- @{#Effects}: Magic Effects
-- @field [parent=#Magic] #Effects effects
--- Map from @{#MagicEffectId} to @{#MagicEffect} --- Map from @{#MagicEffectId} to @{#MagicEffect}
-- @field [parent=#Magic] #map<#number, #MagicEffect> effects -- @field [parent=#Effects] #map<#number, #MagicEffect> records
-- @usage -- Print all harmful effects -- @usage -- Print all harmful effects
-- for _, effect in pairs(core.magic.effects) do -- for _, effect in pairs(core.magic.effects.records) do
-- if effect.harmful then -- if effect.harmful then
-- print(effect.name) -- print(effect.name)
-- end -- end
-- end -- end
-- @usage -- Look up the record of a specific effect and print its icon -- @usage -- Look up the record of a specific effect and print its icon
-- local mgef = core.magic.effects[core.magic.EFFECT_TYPE.Reflect] -- local mgef = core.magic.effects.records[core.magic.EFFECT_TYPE.Reflect]
-- print('Reflect Icon: '..tostring(mgef.icon)) -- print('Reflect Icon: '..tostring(mgef.icon))
--- List of all @{#Enchantment}s. --- @{#Enchantments}: Enchantments
-- @field [parent=#Magic] #list<#Enchantment> enchantments -- @field [parent=#Magic] #Enchantments enchantments
-- @usage local enchantment = core.magic.enchantments['marara's boon'] -- get by id
-- @usage local enchantment = core.magic.enchantments[1] -- get by index --- A read-only list of all @{#Enchantment} records in the world database, may be indexed by recordId.
-- Implements [iterables#List](iterables.html#List) and [iterables#Map](iterables.html#map-iterable) of #Enchantment.
-- @field [parent=#Enchantments] #list<#Enchantment> records
-- @usage local enchantment = core.magic.enchantments.records['marara's boon'] -- get by id
-- @usage local enchantment = core.magic.enchantments.records[1] -- get by index
-- @usage -- Print all enchantments with constant effect -- @usage -- Print all enchantments with constant effect
-- for _, ench in pairs(core.magic.enchantments) do -- for _, ench in pairs(core.magic.enchantments.records) do
-- if ench.type == core.magic.ENCHANTMENT_TYPE.ConstantEffect then -- if ench.type == core.magic.ENCHANTMENT_TYPE.ConstantEffect then
-- print(ench.id) -- print(ench.id)
-- end -- end
-- end -- end
--- ---
-- @type Spell -- @type Spell
-- @field #string id Spell id -- @field #string id Spell id
@ -827,11 +834,12 @@
-- @field #number maxRange Raw maximal range value, from 0 to 255 -- @field #number maxRange Raw maximal range value, from 0 to 255
--- List of all @{#SoundRecord}s. --- List of all @{#SoundRecord}s.
-- @field [parent=#Sound] #list<#SoundRecord> sounds -- @field [parent=#Sound] #list<#SoundRecord> records A read-only list of all @{#SoundRecord}s in the world database, may be indexed by recordId.
-- @usage local sound = core.sound.sounds['Ashstorm'] -- get by id -- Implements [iterables#List](iterables.html#List) of #SoundRecord.
-- @usage local sound = core.sound.sounds[1] -- get by index -- @usage local sound = core.sound.records['Ashstorm'] -- get by id
-- @usage local sound = core.sound.records[1] -- get by index
-- @usage -- Print all sound files paths -- @usage -- Print all sound files paths
-- for _, sound in pairs(core.sound.sounds) do -- for _, sound in pairs(core.sound.records) do
-- print(sound.fileName) -- print(sound.fileName)
-- end -- end
@ -844,7 +852,10 @@
--- `core.stats.Attribute` --- `core.stats.Attribute`
-- @type Attribute -- @type Attribute
-- @field #list<#AttributeRecord> records A read-only list of all @{#AttributeRecord}s in the world database. -- @field #list<#AttributeRecord> records A read-only list of all @{#AttributeRecord}s in the world database, may be indexed by recordId.
-- Implements [iterables#List](iterables.html#List) of #AttributeRecord.
-- @usage local record = core.stats.Attribute.records['example_recordid']
-- @usage local record = core.stats.Attribute.records[1]
--- ---
-- Returns a read-only @{#AttributeRecord} -- Returns a read-only @{#AttributeRecord}
@ -857,7 +868,10 @@
--- `core.stats.Skill` --- `core.stats.Skill`
-- @type Skill -- @type Skill
-- @field #list<#SkillRecord> records A read-only list of all @{#SkillRecord}s in the world database. -- @field #list<#SkillRecord> records A read-only list of all @{#SkillRecord}s in the world database, may be indexed by recordId.
-- Implements [iterables#List](iterables.html#List) of #SkillRecord.
-- @usage local record = core.stats.Skill.records['example_recordid']
-- @usage local record = core.stats.Skill.records[1]
--- ---
-- Returns a read-only @{#SkillRecord} -- Returns a read-only @{#SkillRecord}
@ -892,6 +906,15 @@
-- @field #string failureSound VFS path to the failure sound -- @field #string failureSound VFS path to the failure sound
-- @field #string hitSound VFS path to the hit sound -- @field #string hitSound VFS path to the hit sound
--- @{#Factions}: Factions
-- @field [parent=#core] #Factions factions
---
-- A read-only list of all @{#FactionRecord}s in the world database.
-- @field [parent=#Factions] #list<#FactionRecord> records
-- @usage local record = core.factions.records['example_recordid']
-- @usage local record = core.factions.records[1]
--- ---
-- Faction data record -- Faction data record
-- @type FactionRecord -- @type FactionRecord

@ -718,7 +718,13 @@
-- @type Creature -- @type Creature
-- @extends #Actor -- @extends #Actor
-- @field #Actor baseType @{#Actor} -- @field #Actor baseType @{#Actor}
-- @field #list<#CreatureRecord> records A read-only list of all @{#CreatureRecord}s in the world database.
---
-- A read-only list of all @{#CreatureRecord}s in the world database, may be indexed by recordId.
-- Implements [iterables#List](iterables.html#List) of #CreatureRecord.
-- @field [parent=#Creature] #list<#CreatureRecord> records
-- @usage local record = types.NPC.classes['example_recordid']
-- @usage local record = types.NPC.classes[1]
--- ---
-- Whether the object is a creature. -- Whether the object is a creature.
@ -772,7 +778,13 @@
-- @extends #Actor -- @extends #Actor
-- @field #Actor baseType @{#Actor} -- @field #Actor baseType @{#Actor}
-- @field [parent=#NPC] #NpcStats stats -- @field [parent=#NPC] #NpcStats stats
-- @field #list<#NpcRecord> records A read-only list of all @{#NpcRecord}s in the world database.
---
-- A read-only list of all @{#NpcRecord}s in the world database, may be indexed by recordId.
-- Implements [iterables#List](iterables.html#List) of #NpcRecord.
-- @field [parent=#NPC] #map<#NpcRecord> records
-- @usage local record = types.NPC.classes['example_recordid']
-- @usage local record = types.NPC.classes[1]
--- ---
-- Whether the object is an NPC or a Player. -- Whether the object is an NPC or a Player.
@ -925,8 +937,11 @@
-- @field [parent=#NPC] #Classes classes -- @field [parent=#NPC] #Classes classes
--- ---
-- A read-only list of all @{#ClassRecord}s in the world database. -- A read-only list of all @{#ClassRecord}s in the world database, may be indexed by recordId.
-- Implements [iterables#List](iterables.html#List) of #ClassRecord.
-- @field [parent=#Classes] #list<#ClassRecord> records -- @field [parent=#Classes] #list<#ClassRecord> records
-- @usage local record = types.NPC.classes['example_recordid']
-- @usage local record = types.NPC.classes[1]
--- ---
-- Returns a read-only @{#ClassRecord} -- Returns a read-only @{#ClassRecord}
@ -963,7 +978,10 @@
--- ---
-- A read-only list of all @{#RaceRecord}s in the world database. -- A read-only list of all @{#RaceRecord}s in the world database.
-- Implements [iterables#List](iterables.html#List) of #RaceRecord.
-- @field [parent=#Races] #list<#RaceRecord> records -- @field [parent=#Races] #list<#RaceRecord> records
-- @usage local record = types.NPC.classes['example_recordid']
-- @usage local record = types.NPC.classes[1]
--- ---
-- Returns a read-only @{#RaceRecord} -- Returns a read-only @{#RaceRecord}
@ -1120,7 +1138,10 @@
--- ---
-- A read-only list of all @{#BirthSignRecord}s in the world database. -- A read-only list of all @{#BirthSignRecord}s in the world database.
-- Implements [iterables#List](iterables.html#List) of #BirthSignRecord.
-- @field [parent=#BirthSigns] #list<#BirthSignRecord> records -- @field [parent=#BirthSigns] #list<#BirthSignRecord> records
-- @usage local record = types.NPC.classes['example_recordid']
-- @usage local record = types.NPC.classes[1]
--- ---
-- Returns a read-only @{#BirthSignRecord} -- Returns a read-only @{#BirthSignRecord}
@ -1152,7 +1173,6 @@
-- @type Armor -- @type Armor
-- @extends #Item -- @extends #Item
-- @field #Item baseType @{#Item} -- @field #Item baseType @{#Item}
-- @field #list<#ArmorRecord> records A read-only list of all @{#ArmorRecord}s in the world database.
--- ---
-- Whether the object is an Armor. -- Whether the object is an Armor.
@ -1174,6 +1194,13 @@
-- @field #number LBracer -- @field #number LBracer
-- @field #number RBracer -- @field #number RBracer
---
-- A read-only list of all @{#ArmorRecord}s in the world database.
-- Implements [iterables#List](iterables.html#List) of #ArmorRecord.
-- @field [parent=#Armor] #list<#ArmorRecord> records
-- @usage local record = types.Armor.records['example_recordid']
-- @usage local record = types.Armor.records[1]
--- @{#ArmorTYPE} --- @{#ArmorTYPE}
-- @field [parent=#Armor] #ArmorTYPE TYPE -- @field [parent=#Armor] #ArmorTYPE TYPE
@ -1219,7 +1246,13 @@
-- @type Book -- @type Book
-- @extends #Item -- @extends #Item
-- @field #Item baseType @{#Item} -- @field #Item baseType @{#Item}
-- @field #list<#BookRecord> records A read-only list of all @{#BookRecord}s in the world database.
---
-- A read-only list of all @{#BookRecord}s in the world database.
-- Implements [iterables#List](iterables.html#List) of #BookRecord.
-- @field [parent=#Book] #list<#BookRecord> records
-- @usage local record = types.Book.records['example_recordid']
-- @usage local record = types.Book.records[1]
--- ---
-- Whether the object is a Book. -- Whether the object is a Book.
@ -1295,7 +1328,13 @@
-- @type Clothing -- @type Clothing
-- @extends #Item -- @extends #Item
-- @field #Item baseType @{#Item} -- @field #Item baseType @{#Item}
-- @field #list<#ClothingRecord> records A read-only list of all @{#ClothingRecord}s in the world database.
---
-- A read-only list of all @{#ClothingRecord}s in the world database.
-- Implements [iterables#List](iterables.html#List) of #ClothingRecord.
-- @field [parent=#Clothing] #list<#ClothingRecord> records
-- @usage local record = types.Clothing.records['example_recordid']
-- @usage local record = types.Clothing.records[1]
--- ---
-- Whether the object is a Clothing. -- Whether the object is a Clothing.
@ -1361,7 +1400,13 @@
-- @type Ingredient -- @type Ingredient
-- @extends #Item -- @extends #Item
-- @field #Item baseType @{#Item} -- @field #Item baseType @{#Item}
-- @field #list<#IngredientRecord> records A read-only list of all @{#IngredientRecord}s in the world database.
---
-- A read-only list of all @{#IngredientRecord}s in the world database.
-- Implements [iterables#List](iterables.html#List) of #IngredientRecord.
-- @field [parent=#Ingredient] #list<#IngredientRecord> records
-- @usage local record = types.Ingredient.records['example_recordid']
-- @usage local record = types.Ingredient.records[1]
--- ---
-- Whether the object is an Ingredient. -- Whether the object is an Ingredient.
@ -1448,7 +1493,13 @@
-- @type Light -- @type Light
-- @extends #Item -- @extends #Item
-- @field #Item baseType @{#Item} -- @field #Item baseType @{#Item}
-- @field #list<#LightRecord> records A read-only list of all @{#LightRecord}s in the world database.
---
-- A read-only list of all @{#LightRecord}s in the world database.
-- Implements [iterables#List](iterables.html#List) of #LightRecord.
-- @field [parent=#Light] #list<#LightRecord> records
-- @usage local record = types.Light.records['example_recordid']
-- @usage local record = types.Light.records[1]
--- ---
-- Whether the object is a Light. -- Whether the object is a Light.
@ -1486,7 +1537,13 @@
-- @type Miscellaneous -- @type Miscellaneous
-- @extends #Item -- @extends #Item
-- @field #Item baseType @{#Item} -- @field #Item baseType @{#Item}
-- @field #list<#MiscellaneousRecord> records A read-only list of all @{#MiscellaneousRecord}s in the world database.
---
-- A read-only list of all @{#MiscellaneousRecord}s in the world database.
-- Implements [iterables#List](iterables.html#List) of #MiscellaneousRecord.
-- @field [parent=#Miscellaneous] #list<#MiscellaneousRecord> records
-- @usage local record = types.Miscellaneous.records['example_recordid']
-- @usage local record = types.Miscellaneous.records[1]
--- ---
-- Whether the object is a Miscellaneous. -- Whether the object is a Miscellaneous.
@ -1537,7 +1594,13 @@
-- @type Potion -- @type Potion
-- @extends #Item -- @extends #Item
-- @field #Item baseType @{#Item} -- @field #Item baseType @{#Item}
-- @field #list<#PotionRecord> records A read-only list of all @{#PotionRecord}s in the world database.
---
-- A read-only list of all @{#PotionRecord}s in the world database.
-- Implements [iterables#List](iterables.html#List) of #PotionRecord.
-- @field [parent=#Potion] #list<#PotionRecord> records
-- @usage local record = types.Potion.records['example_recordid']
-- @usage local record = types.Potion.records[1]
--- ---
-- Whether the object is a Potion. -- Whether the object is a Potion.
@ -1578,7 +1641,13 @@
-- @type Weapon -- @type Weapon
-- @extends #Item -- @extends #Item
-- @field #Item baseType @{#Item} -- @field #Item baseType @{#Item}
-- @field #list<#WeaponRecord> records A read-only list of all @{#WeaponRecord}s in the world database.
---
-- A read-only list of all @{#WeaponRecord}s in the world database.
-- Implements [iterables#List](iterables.html#List) of #WeaponRecord.
-- @field [parent=#Weapon] #list<#WeaponRecord> records
-- @usage local record = types.Weapon.records['example_recordid']
-- @usage local record = types.Weapon.records[1]
--- ---
-- Whether the object is a Weapon. -- Whether the object is a Weapon.
@ -1650,7 +1719,14 @@
-- @type Apparatus -- @type Apparatus
-- @extends #Item -- @extends #Item
-- @field #Item baseType @{#Item} -- @field #Item baseType @{#Item}
-- @field #list<#ApparatusRecord> records A read-only list of all @{#ApparatusRecord}s in the world database.
---
-- A read-only list of all @{#ApparatusRecord}s in the world database.
-- Implements [iterables#List](iterables.html#List) of #ApparatusRecord.
-- @field [parent=#Apparatus] #list<#ApparatusRecord> records
-- @usage local record = types.Apparatus.records['example_recordid']
-- @usage local record = types.Apparatus.records[1]
--- ---
-- Whether the object is an Apparatus. -- Whether the object is an Apparatus.
@ -1693,7 +1769,13 @@
-- @type Lockpick -- @type Lockpick
-- @extends #Item -- @extends #Item
-- @field #Item baseType @{#Item} -- @field #Item baseType @{#Item}
-- @field #list<#LockpickRecord> records A read-only list of all @{#LockpickRecord}s in the world database.
---
-- A read-only list of all @{#LockpickRecord}s in the world database.
-- Implements [iterables#List](iterables.html#List) of #LockpickRecord.
-- @field [parent=#Lockpick] #list<#LockpickRecord> records
-- @usage local record = types.Lockpick.records['example_recordid']
-- @usage local record = types.Lockpick.records[1]
--- ---
-- Whether the object is a Lockpick. -- Whether the object is a Lockpick.
@ -1726,7 +1808,13 @@
-- @type Probe -- @type Probe
-- @extends #Item -- @extends #Item
-- @field #Item baseType @{#Item} -- @field #Item baseType @{#Item}
-- @field #list<#ProbeRecord> records A read-only list of all @{#ProbeRecord}s in the world database.
---
-- A read-only list of all @{#ProbeRecord}s in the world database.
-- Implements [iterables#List](iterables.html#List) of #ProbeRecord.
-- @field [parent=#Probe] #list<#ProbeRecord> records
-- @usage local record = types.Probe.records['example_recordid']
-- @usage local record = types.Probe.records[1]
--- ---
-- Whether the object is a Probe. -- Whether the object is a Probe.
@ -1759,7 +1847,13 @@
-- @type Repair -- @type Repair
-- @extends #Item -- @extends #Item
-- @field #Item baseType @{#Item} -- @field #Item baseType @{#Item}
-- @field #list<#RepairRecord> records A read-only list of all @{#RepairRecord}s in the world database.
---
-- A read-only list of all @{#RepairRecord}s in the world database.
-- Implements [iterables#List](iterables.html#List) of #RepairRecord.
-- @field [parent=#Repair] #list<#RepairRecord> records
-- @usage local record = types.Repair.records['example_recordid']
-- @usage local record = types.Repair.records[1]
--- ---
-- Whether the object is a Repair. -- Whether the object is a Repair.
@ -1790,7 +1884,13 @@
--- ---
-- @type Activator -- @type Activator
-- @field #list<#ActivatorRecord> records A read-only list of all @{#ActivatorRecord}s in the world database.
---
-- A read-only list of all @{#ActivatorRecord}s in the world database.
-- Implements [iterables#List](iterables.html#List) of #ActivatorRecord.
-- @field [parent=#Activator] #list<#ActivatorRecord> records
-- @usage local record = types.Activator.records['example_recordid']
-- @usage local record = types.Activator.records[1]
--- ---
-- Whether the object is an Activator. -- Whether the object is an Activator.
@ -1827,7 +1927,13 @@
-- @type Container -- @type Container
-- @extends #Lockable -- @extends #Lockable
-- @field #Lockable baseType @{#Lockable} -- @field #Lockable baseType @{#Lockable}
-- @field #list<#ContainerRecord> records A read-only list of all @{#ContainerRecord}s in the world database.
---
-- A read-only list of all @{#ContainerRecord}s in the world database.
-- Implements [iterables#List](iterables.html#List) of #ContainerRecord.
-- @field [parent=#Container] #list<#ContainerRecord> records
-- @usage local record = types.Container.records['example_recordid']
-- @usage local record = types.Container.records[1]
--- ---
-- Container content. -- Container content.
@ -1882,7 +1988,13 @@
-- @type Door -- @type Door
-- @extends #Lockable -- @extends #Lockable
-- @field #Lockable baseType @{#Lockable} -- @field #Lockable baseType @{#Lockable}
-- @field #list<#DoorRecord> records A read-only list of all @{#DoorRecord}s in the world database.
---
-- A read-only list of all @{#DoorRecord}s in the world database.
-- Implements [iterables#List](iterables.html#List) of #DoorRecord.
-- @field [parent=#Door] #list<#DoorRecord> records
-- @usage local record = types.Door.records['example_recordid']
-- @usage local record = types.Door.records[1]
--- ---
-- Whether the object is a Door. -- Whether the object is a Door.
@ -1936,7 +2048,13 @@
--- ---
-- @type Static -- @type Static
-- @field #list<#StaticRecord> records A read-only list of all @{#StaticRecord}s in the world database.
---
-- A read-only list of all @{#StaticRecord}s in the world database.
-- Implements [iterables#List](iterables.html#List) of #StaticRecord.
-- @field [parent=#Static] #list<#StaticRecord> records
-- @usage local record = types.Static.records['example_recordid']
-- @usage local record = types.Static.records[1]
--- ---
-- Whether the object is a Static. -- Whether the object is a Static.
@ -1961,7 +2079,13 @@
--- ---
-- @type CreatureLevelledList -- @type CreatureLevelledList
-- @field #list<#CreatureLevelledListRecord> records A read-only list of all @{#CreatureLevelledListRecord}s in the world database.
---
-- A read-only list of all @{#CreatureLevelledListRecord}s in the world database.
-- Implements [iterables#List](iterables.html#List) of #CreatureLevelledListRecord.
-- @field [parent=#CreatureLevelledList] #list<#CreatureLevelledListRecord> records
-- @usage local record = types.CreatureLevelledList.records['example_recordid']
-- @usage local record = types.CreatureLevelledList.records[1]
--- ---
-- Whether the object is a CreatureLevelledList. -- Whether the object is a CreatureLevelledList.
@ -2045,7 +2169,13 @@
--- ---
-- @type ESM4Terminal -- @type ESM4Terminal
-- @field #list<#ESM4TerminalRecord> records A read-only list of all @{#ESM4TerminalRecord}s in the world database.
---
-- A read-only list of all @{#ESM4TerminalRecord}s in the world database.
-- Implements [iterables#List](iterables.html#List) of #ESM4TerminalRecord.
-- @field [parent=#ESM4Terminal] #list<#ESM4TerminalRecord> records
-- @usage local record = types.ESM4Terminal.records['example_recordid']
-- @usage local record = types.ESM4Terminal.records[1]
--- ---
-- Whether the object is a ESM4Terminal. -- Whether the object is a ESM4Terminal.
@ -2110,9 +2240,11 @@
-- @return #ESM4DoorRecord -- @return #ESM4DoorRecord
--- ---
-- Returns a read-only list of all @{#ESM4DoorRecord}s in the world database. -- A read-only list of all @{#ESM4DoorRecord}s in the world database.
-- @function [parent=#ESM4Door] records -- Implements [iterables#List](iterables.html#List) of #ESM4DoorRecord.
-- @return #list<#ESM4DoorRecord> -- @field [parent=#ESM4Door] #list<#ESM4DoorRecord> records
-- @usage local record = types.ESM4Door.records['example_recordid']
-- @usage local record = types.ESM4Door.records[1]
--- ---
-- @type ESM4DoorRecord -- @type ESM4DoorRecord

@ -2,6 +2,7 @@ local testing = require('testing_util')
local core = require('openmw.core') local core = require('openmw.core')
local async = require('openmw.async') local async = require('openmw.async')
local util = require('openmw.util') local util = require('openmw.util')
local types = require('openmw.types')
local world = require('openmw.world') local world = require('openmw.world')
local function testTimers() local function testTimers()
@ -87,6 +88,45 @@ local function testMWScript()
testing.expectEqual(variableStoreCount, indexCheck) testing.expectEqual(variableStoreCount, indexCheck)
end end
local function testRecordStore(store,storeName,skipPairs)
testing.expect(store.records)
local firstRecord = store.records[1]
if not firstRecord then return end
testing.expectEqual(firstRecord.id,store.records[firstRecord.id].id)
local status, _ = pcall(function()
for index, value in ipairs(store.records) do
if value.id == firstRecord.id then
testing.expectEqual(index,1,storeName)
break
end
end
end)
testing.expectEqual(status,true,storeName)
end
local function testRecordStores()
for key, type in pairs(types) do
if type.records then
testRecordStore(type,key)
end
end
testRecordStore(core.magic.enchantments,"enchantments")
testRecordStore(core.magic.effects,"effects",true)
testRecordStore(core.magic.spells,"spells")
testRecordStore(core.stats.Attribute,"Attribute")
testRecordStore(core.stats.Skill,"Skill")
testRecordStore(core.sound,"sound")
testRecordStore(core.factions,"factions")
testRecordStore(types.NPC.classes,"classes")
testRecordStore(types.NPC.races,"races")
testRecordStore(types.Player.birthSigns,"birthSigns")
end
local function initPlayer() local function initPlayer()
player:teleport('', util.vector3(4096, 4096, 867.237), util.transform.identity) player:teleport('', util.vector3(4096, 4096, 867.237), util.transform.identity)
coroutine.yield() coroutine.yield()
@ -124,6 +164,7 @@ tests = {
end}, end},
{'teleport', testTeleport}, {'teleport', testTeleport},
{'getGMST', testGetGMST}, {'getGMST', testGetGMST},
{'recordStores', testRecordStores},
{'mwscript', testMWScript}, {'mwscript', testMWScript},
} }

Loading…
Cancel
Save