mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-21 06:23:53 +00:00
Expose races to Lua
This commit is contained in:
parent
b9fc9f0827
commit
cd118ee263
6 changed files with 182 additions and 7 deletions
|
@ -64,7 +64,7 @@ add_openmw_dir (mwlua
|
||||||
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 debugbindings corebindings worldbindings worker magicbindings factionbindings
|
||||||
classbindings itemdata inputprocessor animationbindings birthsignbindings
|
classbindings itemdata inputprocessor animationbindings birthsignbindings racebindings
|
||||||
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
|
||||||
types/potion types/ingredient types/misc types/repair types/armor types/light types/static
|
types/potion types/ingredient types/misc types/repair types/armor types/light types/static
|
||||||
|
|
|
@ -21,6 +21,10 @@ namespace sol
|
||||||
struct is_automagical<MWWorld::Store<ESM::BirthSign>> : std::false_type
|
struct is_automagical<MWWorld::Store<ESM::BirthSign>> : std::false_type
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
template <>
|
||||||
|
struct is_automagical<ESM::SpellList> : std::false_type
|
||||||
|
{
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace MWLua
|
namespace MWLua
|
||||||
|
@ -43,12 +47,19 @@ namespace MWLua
|
||||||
signT["texture"] = sol::readonly_property([vfs](const ESM::BirthSign& rec) -> std::string {
|
signT["texture"] = sol::readonly_property([vfs](const ESM::BirthSign& rec) -> std::string {
|
||||||
return Misc::ResourceHelpers::correctTexturePath(rec.mTexture, vfs);
|
return Misc::ResourceHelpers::correctTexturePath(rec.mTexture, vfs);
|
||||||
});
|
});
|
||||||
signT["spells"] = sol::readonly_property([lua](const ESM::BirthSign& rec) -> sol::table {
|
signT["spells"]
|
||||||
sol::table res(lua, sol::create);
|
= sol::readonly_property([](const ESM::BirthSign& rec) -> const ESM::SpellList* { return &rec.mPowers; });
|
||||||
for (size_t i = 0; i < rec.mPowers.mList.size(); ++i)
|
|
||||||
res[i + 1] = rec.mPowers.mList[i].serializeText();
|
auto spellListT = lua.new_usertype<ESM::SpellList>("ESM3_SpellList");
|
||||||
return res;
|
spellListT[sol::meta_function::length] = [](const ESM::SpellList& list) { return list.mList.size(); };
|
||||||
});
|
spellListT[sol::meta_function::index]
|
||||||
|
= [](const ESM::SpellList& list, size_t index) -> sol::optional<std::string> {
|
||||||
|
if (index == 0 || index > list.mList.size())
|
||||||
|
return sol::nullopt;
|
||||||
|
return list.mList[index - 1].serializeText(); // Translate from Lua's 1-based indexing.
|
||||||
|
};
|
||||||
|
spellListT[sol::meta_function::pairs] = lua["ipairsForArray"].template get<sol::function>();
|
||||||
|
spellListT[sol::meta_function::ipairs] = lua["ipairsForArray"].template get<sol::function>();
|
||||||
|
|
||||||
return LuaUtil::makeReadOnly(birthSigns);
|
return LuaUtil::makeReadOnly(birthSigns);
|
||||||
}
|
}
|
||||||
|
|
120
apps/openmw/mwlua/racebindings.cpp
Normal file
120
apps/openmw/mwlua/racebindings.cpp
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
#include <components/esm/attr.hpp>
|
||||||
|
#include <components/esm3/loadrace.hpp>
|
||||||
|
#include <components/lua/luastate.hpp>
|
||||||
|
|
||||||
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwworld/class.hpp"
|
||||||
|
#include "../mwworld/esmstore.hpp"
|
||||||
|
|
||||||
|
#include "luamanagerimp.hpp"
|
||||||
|
#include "racebindings.hpp"
|
||||||
|
#include "types/types.hpp"
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
struct RaceAttributes
|
||||||
|
{
|
||||||
|
const ESM::Race& mRace;
|
||||||
|
const sol::state_view mLua;
|
||||||
|
|
||||||
|
sol::table getAttribute(ESM::RefId id) const
|
||||||
|
{
|
||||||
|
sol::table res(mLua, sol::create);
|
||||||
|
res["male"] = mRace.mData.getAttribute(id, true);
|
||||||
|
res["female"] = mRace.mData.getAttribute(id, false);
|
||||||
|
return LuaUtil::makeReadOnly(res);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace sol
|
||||||
|
{
|
||||||
|
template <>
|
||||||
|
struct is_automagical<ESM::Race> : std::false_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct is_automagical<MWWorld::Store<ESM::Race>> : std::false_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct is_automagical<RaceAttributes> : std::false_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace MWLua
|
||||||
|
{
|
||||||
|
sol::table initRaceRecordBindings(const Context& context)
|
||||||
|
{
|
||||||
|
sol::state_view& lua = context.mLua->sol();
|
||||||
|
sol::table races(context.mLua->sol(), sol::create);
|
||||||
|
addRecordFunctionBinding<ESM::Race>(races, context);
|
||||||
|
|
||||||
|
auto raceT = lua.new_usertype<ESM::Race>("ESM3_Race");
|
||||||
|
raceT[sol::meta_function::to_string]
|
||||||
|
= [](const ESM::Race& rec) -> std::string { return "ESM3_Race[" + rec.mId.toDebugString() + "]"; };
|
||||||
|
raceT["id"] = sol::readonly_property([](const ESM::Race& rec) { return rec.mId.serializeText(); });
|
||||||
|
raceT["name"] = sol::readonly_property([](const ESM::Race& rec) -> std::string_view { return rec.mName; });
|
||||||
|
raceT["description"]
|
||||||
|
= sol::readonly_property([](const ESM::Race& rec) -> std::string_view { return rec.mDescription; });
|
||||||
|
raceT["spells"]
|
||||||
|
= sol::readonly_property([lua](const ESM::Race& rec) -> const ESM::SpellList* { return &rec.mPowers; });
|
||||||
|
raceT["skills"] = sol::readonly_property([lua](const ESM::Race& rec) -> sol::table {
|
||||||
|
sol::table res(lua, sol::create);
|
||||||
|
for (const auto& skillBonus : rec.mData.mBonus)
|
||||||
|
{
|
||||||
|
ESM::RefId skill = ESM::Skill::indexToRefId(skillBonus.mSkill);
|
||||||
|
if (!skill.empty())
|
||||||
|
res[skill.serializeText()] = skillBonus.mBonus;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
});
|
||||||
|
raceT["isPlayable"] = sol::readonly_property(
|
||||||
|
[](const ESM::Race& rec) -> bool { return rec.mData.mFlags & ESM::Race::Playable; });
|
||||||
|
raceT["isBeast"]
|
||||||
|
= sol::readonly_property([](const ESM::Race& rec) -> bool { return rec.mData.mFlags & ESM::Race::Beast; });
|
||||||
|
raceT["height"] = sol::readonly_property([lua](const ESM::Race& rec) -> sol::table {
|
||||||
|
sol::table res(lua, sol::create);
|
||||||
|
res["male"] = rec.mData.mMaleHeight;
|
||||||
|
res["female"] = rec.mData.mFemaleHeight;
|
||||||
|
return LuaUtil::makeReadOnly(res);
|
||||||
|
});
|
||||||
|
raceT["weight"] = sol::readonly_property([lua](const ESM::Race& rec) -> sol::table {
|
||||||
|
sol::table res(lua, sol::create);
|
||||||
|
res["male"] = rec.mData.mMaleWeight;
|
||||||
|
res["female"] = rec.mData.mFemaleWeight;
|
||||||
|
return LuaUtil::makeReadOnly(res);
|
||||||
|
});
|
||||||
|
|
||||||
|
raceT["attributes"] = sol::readonly_property([lua](const ESM::Race& rec) -> RaceAttributes {
|
||||||
|
return { rec, lua };
|
||||||
|
});
|
||||||
|
|
||||||
|
auto attributesT = lua.new_usertype<RaceAttributes>("ESM3_RaceAttributes");
|
||||||
|
const auto& store = MWBase::Environment::get().getESMStore()->get<ESM::Attribute>();
|
||||||
|
attributesT[sol::meta_function::index]
|
||||||
|
= [&](const RaceAttributes& attributes, std::string_view stringId) -> sol::optional<sol::table> {
|
||||||
|
ESM::RefId id = ESM::RefId::deserializeText(stringId);
|
||||||
|
if (!store.search(id))
|
||||||
|
return sol::nullopt;
|
||||||
|
return attributes.getAttribute(id);
|
||||||
|
};
|
||||||
|
attributesT[sol::meta_function::pairs] = [&](sol::this_state ts, RaceAttributes& attributes) {
|
||||||
|
auto iterator = store.begin();
|
||||||
|
return sol::as_function(
|
||||||
|
[iterator, attributes,
|
||||||
|
&store]() mutable -> std::pair<sol::optional<std::string>, sol::optional<sol::table>> {
|
||||||
|
if (iterator != store.end())
|
||||||
|
{
|
||||||
|
ESM::RefId id = iterator->mId;
|
||||||
|
++iterator;
|
||||||
|
return { id.serializeText(), attributes.getAttribute(id) };
|
||||||
|
}
|
||||||
|
return { sol::nullopt, sol::nullopt };
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return LuaUtil::makeReadOnly(races);
|
||||||
|
}
|
||||||
|
}
|
13
apps/openmw/mwlua/racebindings.hpp
Normal file
13
apps/openmw/mwlua/racebindings.hpp
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#ifndef MWLUA_RACEBINDINGS_H
|
||||||
|
#define MWLUA_RACEBINDINGS_H
|
||||||
|
|
||||||
|
#include <sol/forward.hpp>
|
||||||
|
|
||||||
|
#include "context.hpp"
|
||||||
|
|
||||||
|
namespace MWLua
|
||||||
|
{
|
||||||
|
sol::table initRaceRecordBindings(const Context& context);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // MWLUA_RACEBINDINGS_H
|
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
#include "../classbindings.hpp"
|
#include "../classbindings.hpp"
|
||||||
#include "../localscripts.hpp"
|
#include "../localscripts.hpp"
|
||||||
|
#include "../racebindings.hpp"
|
||||||
#include "../stats.hpp"
|
#include "../stats.hpp"
|
||||||
|
|
||||||
namespace sol
|
namespace sol
|
||||||
|
@ -86,6 +87,7 @@ namespace MWLua
|
||||||
addActorServicesBindings<ESM::NPC>(record, context);
|
addActorServicesBindings<ESM::NPC>(record, context);
|
||||||
|
|
||||||
npc["classes"] = initClassRecordBindings(context);
|
npc["classes"] = initClassRecordBindings(context);
|
||||||
|
npc["races"] = initRaceRecordBindings(context);
|
||||||
|
|
||||||
// This function is game-specific, in future we should replace it with something more universal.
|
// This function is game-specific, in future we should replace it with something more universal.
|
||||||
npc["isWerewolf"] = [](const Object& o) {
|
npc["isWerewolf"] = [](const Object& o) {
|
||||||
|
|
|
@ -958,6 +958,35 @@
|
||||||
-- @param #any objectOrRecordId
|
-- @param #any objectOrRecordId
|
||||||
-- @return #NpcRecord
|
-- @return #NpcRecord
|
||||||
|
|
||||||
|
--- @{#Races}: Race data
|
||||||
|
-- @field [parent=#NPC] #Races races
|
||||||
|
|
||||||
|
---
|
||||||
|
-- A read-only list of all @{#RaceRecord}s in the world database.
|
||||||
|
-- @field [parent=#Races] #list<#RaceRecord> records
|
||||||
|
|
||||||
|
---
|
||||||
|
-- Returns a read-only @{#RaceRecord}
|
||||||
|
-- @function [parent=#Races] record
|
||||||
|
-- @param #string recordId
|
||||||
|
-- @return #RaceRecord
|
||||||
|
|
||||||
|
---
|
||||||
|
-- Race data record
|
||||||
|
-- @type RaceRecord
|
||||||
|
-- @field #string id Race id
|
||||||
|
-- @field #string name Race name
|
||||||
|
-- @field #string description Race description
|
||||||
|
-- @field #map<#string, #number> skills A map of bonus skill points by skill ID
|
||||||
|
-- @field #list<#string> spells A read-only list containing the ids of all spells inherent to the race
|
||||||
|
-- @field #bool isPlayable True if the player can pick this race in character generation
|
||||||
|
-- @field #bool isBeast True if this race is a beast race
|
||||||
|
-- @field #map<#string, #number> height A read-only table with male and female fields
|
||||||
|
-- @field #map<#string, #number> weight A read-only table with male and female fields
|
||||||
|
-- @field #map<#string, #map<#string, #number>> attributes A read-only table of attribute ID to male and female base values
|
||||||
|
-- @usage -- Get base strength for men
|
||||||
|
-- strength = types.NPC.races.records[1].attributes.strength.male
|
||||||
|
|
||||||
---
|
---
|
||||||
-- @type NpcRecord
|
-- @type NpcRecord
|
||||||
-- @field #string id The record ID of the NPC
|
-- @field #string id The record ID of the NPC
|
||||||
|
|
Loading…
Reference in a new issue