Merge branch 'lua_lock_trap' into 'master'

Allow Lua to access lock and trap data for doors and containers

See merge request OpenMW/openmw!2985
revert-6246b479
psi29a 2 years ago
commit 825d862f52

@ -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/levelledlist types/types types/door 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/potion types/ingredient types/misc types/repair types/armor types/light types/static types/clothing types/levelledlist
worker magicbindings worker magicbindings
) )

@ -0,0 +1,87 @@
#include "types.hpp"
#include <components/esm3/loadmisc.hpp>
#include <components/esm3/loadspel.hpp>
#include <components/misc/resourcehelpers.hpp>
#include <components/resource/resourcesystem.hpp>
#include <apps/openmw/mwworld/esmstore.hpp>
#include "../luabindings.hpp"
#include "../worldview.hpp"
namespace MWLua
{
void addLockableBindings(sol::table lockable)
{
lockable["getLockLevel"]
= [](const Object& object) { return std::abs(object.ptr().getCellRef().getLockLevel()); };
lockable["isLocked"] = [](const Object& object) { return object.ptr().getCellRef().isLocked(); };
lockable["getKeyRecord"] = [](const Object& object) -> sol::optional<const ESM::Miscellaneous*> {
ESM::RefId key = object.ptr().getCellRef().getKey();
if (key.empty())
return sol::nullopt;
return MWBase::Environment::get().getESMStore()->get<ESM::Miscellaneous>().find(key);
};
lockable["lock"] = [](const GObject& object, sol::optional<int> lockLevel) {
object.ptr().getCellRef().setLocked(true);
int level = 1;
if (lockLevel)
level = lockLevel.value();
else if (object.ptr().getCellRef().getLockLevel() < 0)
level = -object.ptr().getCellRef().getLockLevel();
else if (object.ptr().getCellRef().getLockLevel() > 0)
level = object.ptr().getCellRef().getLockLevel();
object.ptr().getCellRef().setLockLevel(level);
};
lockable["unlock"] = [](const GObject& object) {
if (!object.ptr().getCellRef().isLocked())
return;
object.ptr().getCellRef().setLocked(false);
object.ptr().getCellRef().setLockLevel(-object.ptr().getCellRef().getLockLevel());
};
lockable["setTrapSpell"] = [](const GObject& object, const sol::object& spellOrId) {
if (spellOrId == sol::nil)
{
object.ptr().getCellRef().setTrap(ESM::RefId()); // remove the trap value
return;
}
if (spellOrId.is<ESM::Spell>())
object.ptr().getCellRef().setTrap(spellOrId.as<const ESM::Spell*>()->mId);
else
{
ESM::RefId spellId = ESM::RefId::deserializeText(LuaUtil::cast<std::string_view>(spellOrId));
const auto& spellStore = MWBase::Environment::get().getESMStore()->get<ESM::Spell>();
const ESM::Spell* spell = spellStore.find(spellId);
object.ptr().getCellRef().setTrap(spell->mId);
}
};
lockable["setKeyRecord"] = [](const GObject& object, const sol::object& itemOrRecordId) {
if (itemOrRecordId == sol::nil)
{
object.ptr().getCellRef().setKey(ESM::RefId()); // remove the trap value
return;
}
if (itemOrRecordId.is<ESM::Miscellaneous>())
object.ptr().getCellRef().setKey(itemOrRecordId.as<const ESM::Miscellaneous*>()->mId);
else
{
ESM::RefId miscId = ESM::RefId::deserializeText(LuaUtil::cast<std::string_view>(itemOrRecordId));
const auto& keyStore = MWBase::Environment::get().getESMStore()->get<ESM::Miscellaneous>();
const ESM::Miscellaneous* key = keyStore.find(miscId);
object.ptr().getCellRef().setKey(key->mId);
}
};
lockable["getTrapSpell"] = [](sol::this_state lua, const Object& o) -> sol::optional<const ESM::Spell*> {
ESM::RefId trap = o.ptr().getCellRef().getTrap();
if (trap.empty())
return sol::nullopt;
return MWBase::Environment::get().getESMStore()->get<ESM::Spell>().find(trap);
};
}
}

@ -11,6 +11,7 @@ namespace MWLua
// These names are part of OpenMW Lua API. // These names are part of OpenMW Lua API.
constexpr std::string_view Actor = "Actor"; // base type for NPC, Creature, Player constexpr std::string_view Actor = "Actor"; // base type for NPC, Creature, Player
constexpr std::string_view Item = "Item"; // base type for all items constexpr std::string_view Item = "Item"; // base type for all items
constexpr std::string_view Lockable = "Lockable"; // base type for doors and containers
constexpr std::string_view Activator = "Activator"; constexpr std::string_view Activator = "Activator";
constexpr std::string_view Armor = "Armor"; constexpr std::string_view Armor = "Armor";
@ -185,6 +186,8 @@ namespace MWLua
addType(ObjectTypeName::Item, addType(ObjectTypeName::Item,
{ ESM::REC_ARMO, ESM::REC_BOOK, ESM::REC_CLOT, ESM::REC_INGR, ESM::REC_LIGH, ESM::REC_MISC, ESM::REC_ALCH, { ESM::REC_ARMO, ESM::REC_BOOK, ESM::REC_CLOT, ESM::REC_INGR, ESM::REC_LIGH, ESM::REC_MISC, ESM::REC_ALCH,
ESM::REC_WEAP, ESM::REC_APPA, ESM::REC_LOCK, ESM::REC_PROB, ESM::REC_REPA }); ESM::REC_WEAP, ESM::REC_APPA, ESM::REC_LOCK, ESM::REC_PROB, ESM::REC_REPA });
addLockableBindings(
addType(ObjectTypeName::Lockable, { ESM::REC_CONT, ESM::REC_DOOR, ESM::REC_CONT4, ESM::REC_DOOR4 }));
addCreatureBindings(addType(ObjectTypeName::Creature, { ESM::REC_CREA }, ObjectTypeName::Actor), context); addCreatureBindings(addType(ObjectTypeName::Creature, { ESM::REC_CREA }, ObjectTypeName::Actor), context);
addNpcBindings( addNpcBindings(
@ -207,8 +210,8 @@ namespace MWLua
addRepairBindings(addType(ObjectTypeName::Repair, { ESM::REC_REPA }, ObjectTypeName::Item), context); addRepairBindings(addType(ObjectTypeName::Repair, { ESM::REC_REPA }, ObjectTypeName::Item), context);
addActivatorBindings(addType(ObjectTypeName::Activator, { ESM::REC_ACTI }), context); addActivatorBindings(addType(ObjectTypeName::Activator, { ESM::REC_ACTI }), context);
addContainerBindings(addType(ObjectTypeName::Container, { ESM::REC_CONT }), context); addContainerBindings(addType(ObjectTypeName::Container, { ESM::REC_CONT }, ObjectTypeName::Lockable), context);
addDoorBindings(addType(ObjectTypeName::Door, { ESM::REC_DOOR }), context); addDoorBindings(addType(ObjectTypeName::Door, { ESM::REC_DOOR }, ObjectTypeName::Lockable), context);
addStaticBindings(addType(ObjectTypeName::Static, { ESM::REC_STAT }), context); addStaticBindings(addType(ObjectTypeName::Static, { ESM::REC_STAT }), context);
addType(ObjectTypeName::ESM4Activator, { ESM::REC_ACTI4 }); addType(ObjectTypeName::ESM4Activator, { ESM::REC_ACTI4 });
@ -217,7 +220,7 @@ namespace MWLua
addType(ObjectTypeName::ESM4Book, { ESM::REC_BOOK4 }); addType(ObjectTypeName::ESM4Book, { ESM::REC_BOOK4 });
addType(ObjectTypeName::ESM4Clothing, { ESM::REC_CLOT4 }); addType(ObjectTypeName::ESM4Clothing, { ESM::REC_CLOT4 });
addType(ObjectTypeName::ESM4Container, { ESM::REC_CONT4 }); addType(ObjectTypeName::ESM4Container, { ESM::REC_CONT4 });
addESM4DoorBindings(addType(ObjectTypeName::ESM4Door, { ESM::REC_DOOR4 }), context); addESM4DoorBindings(addType(ObjectTypeName::ESM4Door, { ESM::REC_DOOR4 }, ObjectTypeName::Lockable), context);
addType(ObjectTypeName::ESM4Furniture, { ESM::REC_FURN4 }); addType(ObjectTypeName::ESM4Furniture, { ESM::REC_FURN4 });
addType(ObjectTypeName::ESM4Ingredient, { ESM::REC_INGR4 }); addType(ObjectTypeName::ESM4Ingredient, { ESM::REC_INGR4 });
addType(ObjectTypeName::ESM4Light, { ESM::REC_LIGH4 }); addType(ObjectTypeName::ESM4Light, { ESM::REC_LIGH4 });

@ -60,6 +60,7 @@ namespace MWLua
void addPotionBindings(sol::table potion, const Context& context); void addPotionBindings(sol::table potion, const Context& context);
void addIngredientBindings(sol::table Ingredient, const Context& context); void addIngredientBindings(sol::table Ingredient, const Context& context);
void addArmorBindings(sol::table armor, const Context& context); void addArmorBindings(sol::table armor, const Context& context);
void addLockableBindings(sol::table lockable);
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);

@ -316,6 +316,19 @@ namespace MWWorld
} }
} }
void CellRef::setKey(const ESM::RefId& key)
{
if (key != getKey())
{
mChanged = true;
std::visit(ESM::VisitOverload{
[&](ESM4::Reference& /*ref*/) {},
[&](ESM::CellRef& ref) { ref.mKey = key; },
},
mCellRef.mVariant);
}
}
void CellRef::setGoldValue(int value) void CellRef::setGoldValue(int value)
{ {
if (value != getGoldValue()) if (value != getGoldValue())

@ -184,7 +184,7 @@ namespace MWWorld
{ {
return std::visit([](auto&& ref) -> const ESM::RefId& { return ref.mKey; }, mCellRef.mVariant); return std::visit([](auto&& ref) -> const ESM::RefId& { return ref.mKey; }, mCellRef.mVariant);
} }
void setKey(const ESM::RefId& key);
ESM::RefId getTrap() const ESM::RefId getTrap() const
{ {
struct Visitor struct Visitor

@ -893,6 +893,59 @@
-- @field #number value -- @field #number value
--- @{#Lockable} functions
-- @field [parent=#types] #Lockable Lockable
---
-- Returns the key record of a lockable object(door, container)
-- @function [parent=#Lockable] getKeyRecord
-- @param openmw.core#GameObject object
-- @return #MiscellaneousRecord
---
-- Sets the key of a lockable object(door, container); removes it if empty string is provided. Must be used in a global script.
-- @function [parent=#Lockable] setKeyRecord
-- @param openmw.core#GameObject object
-- @param #any miscOrId @{#MiscellaneousRecord} or string misc item id Record ID of the key to use.
---
-- Returns the trap spell of a lockable object(door, container)
-- @function [parent=#Lockable] getTrapSpell
-- @param openmw.core#GameObject object
-- @return openmw.core#Spell
---
-- Sets the trap spell of a lockable object(door, container); removes it if empty string is provided. Must be used in a global script.
-- @function [parent=#Lockable] setTrapSpell
-- @param openmw.core#GameObject object
-- @param #any spellOrId @{openmw.core#Spell} or string spell id Record ID for the trap to use
---
-- Returns the lock level of a lockable object(door, container). Does not determine if an object is locked or not, if an object is locked while this is set above 0, this value will be used if no other value is specified.
-- @function [parent=#Lockable] getLockLevel
-- @param openmw.core#GameObject object
-- @return #number
---
-- Returns true if the lockable object is locked, and false if it is not.
-- @function [parent=#Lockable] isLocked
-- @param openmw.core#GameObject object
-- @return #boolean
---
-- Sets the lock level level of a lockable object(door, container);Locks if not already locked; Must be used in a global script.
-- @function [parent=#Lockable] lock
-- @param openmw.core#GameObject object
-- @param #number lockLevel Level to lock the object at. Optional, if not specified, then 1 will be used, or the previous level if it was locked before.
---
-- Unlocks the lockable object. Does not change the lock level, it can be kept for future use.
-- @function [parent=#Lockable] unlock
-- @param openmw.core#GameObject object
--- @{#Light} functions --- @{#Light} functions
-- @field [parent=#types] #Light Light -- @field [parent=#types] #Light Light
@ -1275,6 +1328,8 @@
--- ---
-- @type Container -- @type Container
-- @extends #Lockable
-- @field #Lockable baseType @{#Lockable}
-- @field #list<#ContainerRecord> records A read-only list of all @{#ContainerRecord}s in the world database. -- @field #list<#ContainerRecord> records A read-only list of all @{#ContainerRecord}s in the world database.
--- ---
@ -1320,6 +1375,8 @@
--- ---
-- @type Door -- @type Door
-- @extends #Lockable
-- @field #Lockable baseType @{#Lockable}
-- @field #list<#DoorRecord> records A read-only list of all @{#DoorRecord}s in the world database. -- @field #list<#DoorRecord> records A read-only list of all @{#DoorRecord}s in the world database.
--- ---
@ -1471,6 +1528,8 @@
--- ---
-- @type ESM4Door -- @type ESM4Door
-- @extends #Lockable
-- @field #Lockable baseType @{#Lockable}
--- ---
-- Whether the object is a ESM4Door. -- Whether the object is a ESM4Door.

Loading…
Cancel
Save