Merge branch 'awildmoonappeared' into 'master'

Expose levelled creatures to Lua

See merge request OpenMW/openmw!3127
revert-6246b479
Petr Mikheev 2 years ago
commit e35bf97603

@ -62,7 +62,7 @@ add_openmw_dir (mwlua
luamanagerimp object worldview userdataserializer luaevents engineevents objectvariant luamanagerimp object worldview userdataserializer luaevents engineevents objectvariant
context globalscripts localscripts playerscripts luabindings objectbindings cellbindings context globalscripts localscripts playerscripts luabindings objectbindings cellbindings
camerabindings uibindings inputbindings nearbybindings postprocessingbindings stats debugbindings camerabindings uibindings inputbindings nearbybindings postprocessingbindings stats debugbindings
types/types types/door types/actor types/container types/weapon types/npc 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/clothing types/types types/door types/actor types/container types/weapon types/npc 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/clothing types/levelledlist
worker magicbindings worker magicbindings
) )

@ -0,0 +1,59 @@
#include "types.hpp"
#include <components/esm3/loadlevlist.hpp>
#include "../../mwbase/environment.hpp"
#include "../../mwbase/world.hpp"
#include "../../mwmechanics/levelledlist.hpp"
namespace sol
{
template <>
struct is_automagical<ESM::CreatureLevList> : std::false_type
{
};
template <>
struct is_automagical<ESM::LevelledListBase::LevelItem> : std::false_type
{
};
}
namespace MWLua
{
void addLevelledCreatureBindings(sol::table list, const Context& context)
{
auto& state = context.mLua->sol();
auto item = state.new_usertype<ESM::LevelledListBase::LevelItem>("ESM3_LevelledListItem");
item["id"] = sol::readonly_property(
[](const ESM::LevelledListBase::LevelItem& rec) -> std::string { return rec.mId.serializeText(); });
item["level"]
= sol::readonly_property([](const ESM::LevelledListBase::LevelItem& rec) -> int { return rec.mLevel; });
item[sol::meta_function::to_string] = [](const ESM::LevelledListBase::LevelItem& rec) -> std::string {
return "ESM3_LevelledListItem[" + rec.mId.toDebugString() + ", " + std::to_string(rec.mLevel) + "]";
};
addRecordFunctionBinding<ESM::CreatureLevList>(list, context);
auto record = state.new_usertype<ESM::CreatureLevList>("ESM3_CreatureLevelledList");
record[sol::meta_function::to_string] = [](const ESM::CreatureLevList& rec) -> std::string {
return "ESM3_CreatureLevelledList[" + rec.mId.toDebugString() + "]";
};
record["id"] = sol::readonly_property(
[](const ESM::CreatureLevList& rec) -> std::string { return rec.mId.serializeText(); });
record["chanceNone"] = sol::readonly_property(
[](const ESM::CreatureLevList& rec) -> float { return std::clamp(rec.mChanceNone / 100.f, 0.f, 1.f); });
record["creatures"] = sol::readonly_property([&](const ESM::CreatureLevList& rec) -> sol::table {
sol::table res(state, sol::create);
for (size_t i = 0; i < rec.mList.size(); ++i)
res[i + 1] = rec.mList[i];
return res;
});
record["calculateFromAllLevels"] = sol::readonly_property(
[](const ESM::CreatureLevList& rec) -> bool { return rec.mFlags & ESM::CreatureLevList::AllLevels; });
record["getRandomId"] = [](const ESM::CreatureLevList& rec, int level) -> std::string {
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
return MWMechanics::getLevelledItem(&rec, true, prng, level).serializeText();
};
}
}

@ -20,6 +20,7 @@ namespace MWLua
constexpr std::string_view Creature = "Creature"; constexpr std::string_view Creature = "Creature";
constexpr std::string_view Door = "Door"; constexpr std::string_view Door = "Door";
constexpr std::string_view Ingredient = "Ingredient"; constexpr std::string_view Ingredient = "Ingredient";
constexpr std::string_view LevelledCreature = "LevelledCreature";
constexpr std::string_view Light = "Light"; constexpr std::string_view Light = "Light";
constexpr std::string_view MiscItem = "Miscellaneous"; constexpr std::string_view MiscItem = "Miscellaneous";
constexpr std::string_view NPC = "NPC"; constexpr std::string_view NPC = "NPC";
@ -63,6 +64,7 @@ namespace MWLua
{ ESM::REC_CREA, ObjectTypeName::Creature }, { ESM::REC_CREA, ObjectTypeName::Creature },
{ ESM::REC_DOOR, ObjectTypeName::Door }, { ESM::REC_DOOR, ObjectTypeName::Door },
{ ESM::REC_INGR, ObjectTypeName::Ingredient }, { ESM::REC_INGR, ObjectTypeName::Ingredient },
{ ESM::REC_LEVC, ObjectTypeName::LevelledCreature },
{ ESM::REC_LIGH, ObjectTypeName::Light }, { ESM::REC_LIGH, ObjectTypeName::Light },
{ ESM::REC_MISC, ObjectTypeName::MiscItem }, { ESM::REC_MISC, ObjectTypeName::MiscItem },
{ ESM::REC_NPC_, ObjectTypeName::NPC }, { ESM::REC_NPC_, ObjectTypeName::NPC },
@ -189,6 +191,8 @@ namespace MWLua
addType(ObjectTypeName::NPC, { ESM::REC_INTERNAL_PLAYER, ESM::REC_NPC_ }, ObjectTypeName::Actor), context); addType(ObjectTypeName::NPC, { ESM::REC_INTERNAL_PLAYER, ESM::REC_NPC_ }, ObjectTypeName::Actor), context);
addPlayerBindings(addType(ObjectTypeName::Player, { ESM::REC_INTERNAL_PLAYER }, ObjectTypeName::NPC), context); addPlayerBindings(addType(ObjectTypeName::Player, { ESM::REC_INTERNAL_PLAYER }, ObjectTypeName::NPC), context);
addLevelledCreatureBindings(addType(ObjectTypeName::LevelledCreature, { ESM::REC_LEVC }), context);
addArmorBindings(addType(ObjectTypeName::Armor, { ESM::REC_ARMO }, ObjectTypeName::Item), context); addArmorBindings(addType(ObjectTypeName::Armor, { ESM::REC_ARMO }, ObjectTypeName::Item), context);
addClothingBindings(addType(ObjectTypeName::Clothing, { ESM::REC_CLOT }, ObjectTypeName::Item), context); addClothingBindings(addType(ObjectTypeName::Clothing, { ESM::REC_CLOT }, ObjectTypeName::Item), context);
addIngredientBindings(addType(ObjectTypeName::Ingredient, { ESM::REC_INGR }, ObjectTypeName::Item), context); addIngredientBindings(addType(ObjectTypeName::Ingredient, { ESM::REC_INGR }, ObjectTypeName::Item), context);

@ -63,6 +63,7 @@ namespace MWLua
void addClothingBindings(sol::table clothing, const Context& context); void addClothingBindings(sol::table clothing, const Context& context);
void addStaticBindings(sol::table stat, const Context& context); void addStaticBindings(sol::table stat, const Context& context);
void addLightBindings(sol::table light, const Context& context); void addLightBindings(sol::table light, const Context& context);
void addLevelledCreatureBindings(sol::table list, const Context& context);
void addESM4DoorBindings(sol::table door, const Context& context); void addESM4DoorBindings(sol::table door, const Context& context);

@ -15,12 +15,20 @@
namespace MWMechanics namespace MWMechanics
{ {
ESM::RefId getLevelledItem(const ESM::LevelledListBase* levItem, bool creature, Misc::Rng::Generator& prng) ESM::RefId getLevelledItem(
const ESM::LevelledListBase* levItem, bool creature, Misc::Rng::Generator& prng, std::optional<int> level)
{ {
const std::vector<ESM::LevelledListBase::LevelItem>& items = levItem->mList; const std::vector<ESM::LevelledListBase::LevelItem>& items = levItem->mList;
const MWWorld::Ptr& player = getPlayer(); int playerLevel;
int playerLevel = player.getClass().getCreatureStats(player).getLevel(); if (level.has_value())
playerLevel = *level;
else
{
const MWWorld::Ptr& player = getPlayer();
playerLevel = player.getClass().getCreatureStats(player).getLevel();
level = playerLevel;
}
if (Misc::Rng::roll0to99(prng) < levItem->mChanceNone) if (Misc::Rng::roll0to99(prng) < levItem->mChanceNone)
return ESM::RefId(); return ESM::RefId();
@ -65,9 +73,9 @@ namespace MWMechanics
else else
{ {
if (ref.getPtr().getType() == ESM::ItemLevList::sRecordId) if (ref.getPtr().getType() == ESM::ItemLevList::sRecordId)
return getLevelledItem(ref.getPtr().get<ESM::ItemLevList>()->mBase, false, prng); return getLevelledItem(ref.getPtr().get<ESM::ItemLevList>()->mBase, false, prng, level);
else else
return getLevelledItem(ref.getPtr().get<ESM::CreatureLevList>()->mBase, true, prng); return getLevelledItem(ref.getPtr().get<ESM::CreatureLevList>()->mBase, true, prng, level);
} }
} }
} }

@ -3,6 +3,8 @@
#include <components/misc/rng.hpp> #include <components/misc/rng.hpp>
#include <optional>
namespace ESM namespace ESM
{ {
struct LevelledListBase; struct LevelledListBase;
@ -13,7 +15,8 @@ namespace MWMechanics
{ {
/// @return ID of resulting item, or empty if none /// @return ID of resulting item, or empty if none
ESM::RefId getLevelledItem(const ESM::LevelledListBase* levItem, bool creature, Misc::Rng::Generator& prng); ESM::RefId getLevelledItem(
const ESM::LevelledListBase* levItem, bool creature, Misc::Rng::Generator& prng, std::optional<int> level = {});
} }

@ -1382,6 +1382,46 @@
-- @field #string id Record id -- @field #string id Record id
-- @field #string model VFS path to the model -- @field #string model VFS path to the model
--- @{#CreatureLevelledList} functions
-- @field [parent=#types] #CreatureLevelledList CreatureLevelledList
---
-- @type CreatureLevelledList
-- @field #list<#CreatureLevelledListRecord> records A read-only list of all @{#CreatureLevelledListRecord}s in the world database.
---
-- Whether the object is a CreatureLevelledList.
-- @function [parent=#CreatureLevelledList] objectIsInstance
-- @param openmw.core#GameObject object
-- @return #boolean
---
-- Returns the read-only @{#CreatureLevelledListRecord} of a levelled creature
-- @function [parent=#CreatureLevelledList] record
-- @param #any objectOrRecordId
-- @return #CreatureLevelledListRecord
---
-- @type CreatureLevelledListRecord
-- @field #string id Record id
-- @field #number chanceNone Chance this list won't spawn anything [0-1]
-- @field #boolean calculateFromAllLevels Calculate from all levels <= player level, not just the closest below player
-- @field #list<#LevelledListItem> creatures
---
-- Picks a random id from the levelled list.
-- @function [parent=#CreatureLevelledListRecord] getRandomId
-- @param openmw.core#CreatureLevelledListRecord The list
-- @param #number The maximum level to select entries for
-- @return #string An id
---
-- @type LevelledListItem
-- @field #string id Item id
-- @field #number level The minimum player level at which this item can occur
--- Functions for @{#ESM4Activator} objects --- Functions for @{#ESM4Activator} objects
-- @field [parent=#types] #ESM4Activator ESM4Activator -- @field [parent=#types] #ESM4Activator ESM4Activator

Loading…
Cancel
Save