mirror of
https://github.com/OpenMW/openmw.git
synced 2025-04-29 02:06:51 +00:00
move enchant charge and soul to itemdata
This commit is contained in:
parent
ef0bb02def
commit
045e6d8c4f
4 changed files with 101 additions and 29 deletions
|
@ -1,22 +1,28 @@
|
||||||
#include "itemdata.hpp"
|
#include "itemdata.hpp"
|
||||||
|
|
||||||
|
#include <components/esm3/loadcrea.hpp>
|
||||||
|
#include <components/esm3/loadench.hpp>
|
||||||
|
|
||||||
#include "context.hpp"
|
#include "context.hpp"
|
||||||
#include "luamanagerimp.hpp"
|
#include "luamanagerimp.hpp"
|
||||||
#include "objectvariant.hpp"
|
#include "objectvariant.hpp"
|
||||||
|
|
||||||
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwmechanics/spellutil.hpp"
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
#include "../mwworld/esmstore.hpp"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
using SelfObject = MWLua::SelfObject;
|
using SelfObject = MWLua::SelfObject;
|
||||||
using Index = const SelfObject::CachedStat::Index&;
|
using Index = const SelfObject::CachedStat::Index&;
|
||||||
|
|
||||||
constexpr std::array properties = { "condition", /*"enchantmentCharge", "soul", "owner", etc..*/ };
|
constexpr std::array properties = { "condition", "enchantmentCharge", "soul" };
|
||||||
|
|
||||||
void invalidPropErr(std::string_view prop, const MWWorld::Ptr& ptr)
|
void valueErr(std::string_view prop, std::string type)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("'" + std::string(prop) + "'" + " property does not exist for item "
|
throw std::logic_error("'" + std::string(prop) + "'" + " received invalid value type (" + type + ")");
|
||||||
+ std::string(ptr.getClass().getName(ptr)) + "(" + std::string(ptr.getTypeDescription()) + ")");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,26 +60,56 @@ namespace MWLua
|
||||||
if (it != self->mStatsCache.end())
|
if (it != self->mStatsCache.end())
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
return sol::make_object(context.mLua->sol(), getValue(context, prop));
|
return sol::make_object(context.mLua->sol(), getValue(context, prop, mObject.ptr()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void set(const Context& context, std::string_view prop, const sol::object& value) const
|
void set(const Context& context, std::string_view prop, const sol::object& value) const
|
||||||
|
{
|
||||||
|
if (mObject.isGObject())
|
||||||
|
setValue({}, prop, mObject.ptr(), value);
|
||||||
|
else if (mObject.isSelfObject())
|
||||||
{
|
{
|
||||||
SelfObject* obj = mObject.asSelfObject();
|
SelfObject* obj = mObject.asSelfObject();
|
||||||
addStatUpdateAction(context.mLuaManager, *obj);
|
addStatUpdateAction(context.mLuaManager, *obj);
|
||||||
obj->mStatsCache[SelfObject::CachedStat{ &ItemData::setValue, std::monostate{}, prop }] = value;
|
obj->mStatsCache[SelfObject::CachedStat{ &ItemData::setValue, std::monostate{}, prop }] = value;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
throw std::runtime_error("Only global or self scripts can set the value");
|
||||||
|
}
|
||||||
|
|
||||||
sol::object getValue(const Context& context, std::string_view prop) const
|
static sol::object getValue(const Context& context, std::string_view prop, const MWWorld::Ptr& ptr)
|
||||||
{
|
{
|
||||||
if (prop == "condition")
|
if (prop == "condition")
|
||||||
{
|
{
|
||||||
MWWorld::Ptr o = mObject.ptr();
|
if (ptr.mRef->getType() == ESM::REC_LIGH)
|
||||||
if (o.mRef->getType() == ESM::REC_LIGH)
|
return sol::make_object(context.mLua->sol(), ptr.getClass().getRemainingUsageTime(ptr));
|
||||||
return sol::make_object(context.mLua->sol(), o.getClass().getRemainingUsageTime(o));
|
else if (ptr.getClass().hasItemHealth(ptr))
|
||||||
else if (o.getClass().hasItemHealth(o))
|
return sol::make_object(context.mLua->sol(),
|
||||||
return sol::make_object(
|
ptr.getClass().getItemHealth(ptr) + ptr.getCellRef().getChargeIntRemainder());
|
||||||
context.mLua->sol(), o.getClass().getItemHealth(o) + o.getCellRef().getChargeIntRemainder());
|
}
|
||||||
|
else if (prop == "enchantmentCharge")
|
||||||
|
{
|
||||||
|
const ESM::RefId& enchantmentName = ptr.getClass().getEnchantment(ptr);
|
||||||
|
|
||||||
|
if (enchantmentName.empty())
|
||||||
|
return sol::lua_nil;
|
||||||
|
|
||||||
|
float charge = ptr.getCellRef().getEnchantmentCharge();
|
||||||
|
const auto& store = MWBase::Environment::get().getESMStore();
|
||||||
|
const auto* enchantment = store->get<ESM::Enchantment>().find(enchantmentName);
|
||||||
|
|
||||||
|
if (charge == -1) // return the full charge
|
||||||
|
return sol::make_object(context.mLua->sol(), MWMechanics::getEnchantmentCharge(*enchantment));
|
||||||
|
|
||||||
|
return sol::make_object(context.mLua->sol(), charge);
|
||||||
|
}
|
||||||
|
else if (prop == "soul")
|
||||||
|
{
|
||||||
|
ESM::RefId soul = ptr.getCellRef().getSoul();
|
||||||
|
if (soul.empty())
|
||||||
|
return sol::lua_nil;
|
||||||
|
|
||||||
|
return sol::make_object(context.mLua->sol(), soul.serializeText());
|
||||||
}
|
}
|
||||||
|
|
||||||
return sol::lua_nil;
|
return sol::lua_nil;
|
||||||
|
@ -82,6 +118,8 @@ namespace MWLua
|
||||||
static void setValue(Index i, std::string_view prop, const MWWorld::Ptr& ptr, const sol::object& value)
|
static void setValue(Index i, std::string_view prop, const MWWorld::Ptr& ptr, const sol::object& value)
|
||||||
{
|
{
|
||||||
if (prop == "condition")
|
if (prop == "condition")
|
||||||
|
{
|
||||||
|
if (value.get_type() == sol::type::number)
|
||||||
{
|
{
|
||||||
float cond = LuaUtil::cast<float>(value);
|
float cond = LuaUtil::cast<float>(value);
|
||||||
if (ptr.mRef->getType() == ESM::REC_LIGH)
|
if (ptr.mRef->getType() == ESM::REC_LIGH)
|
||||||
|
@ -92,8 +130,37 @@ namespace MWLua
|
||||||
ptr.getCellRef().setChargeIntRemainder(std::max(0.f, std::modf(cond, &cond)));
|
ptr.getCellRef().setChargeIntRemainder(std::max(0.f, std::modf(cond, &cond)));
|
||||||
ptr.getCellRef().setCharge(std::max(0.f, cond));
|
ptr.getCellRef().setCharge(std::max(0.f, cond));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
invalidPropErr(prop, ptr);
|
valueErr(prop, sol::type_name(value.lua_state(), value.get_type()));
|
||||||
|
}
|
||||||
|
else if (prop == "enchantmentCharge")
|
||||||
|
{
|
||||||
|
if (value.get_type() == sol::type::lua_nil)
|
||||||
|
ptr.getCellRef().setEnchantmentCharge(-1);
|
||||||
|
else if (value.get_type() == sol::type::number)
|
||||||
|
ptr.getCellRef().setEnchantmentCharge(std::max(0.0f, LuaUtil::cast<float>(value)));
|
||||||
|
else
|
||||||
|
valueErr(prop, sol::type_name(value.lua_state(), value.get_type()));
|
||||||
|
}
|
||||||
|
else if (prop == "soul")
|
||||||
|
{
|
||||||
|
if (value.get_type() == sol::type::lua_nil)
|
||||||
|
ptr.getCellRef().setSoul(ESM::RefId{});
|
||||||
|
else if (value.get_type() == sol::type::string)
|
||||||
|
{
|
||||||
|
std::string_view souldId = LuaUtil::cast<std::string_view>(value);
|
||||||
|
ESM::RefId creature = ESM::RefId::deserializeText(souldId);
|
||||||
|
const auto& store = *MWBase::Environment::get().getESMStore();
|
||||||
|
|
||||||
|
// TODO: Add Support for NPC Souls
|
||||||
|
if (store.get<ESM::Creature>().search(creature))
|
||||||
|
ptr.getCellRef().setSoul(creature);
|
||||||
|
else
|
||||||
|
throw std::runtime_error("Cannot use non-existent creature as a soul: " + std::string(souldId));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
valueErr(prop, sol::type_name(value.lua_state(), value.get_type()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,6 +11,7 @@ namespace MWLua
|
||||||
{
|
{
|
||||||
void addItemBindings(sol::table item, const Context& context)
|
void addItemBindings(sol::table item, const Context& context)
|
||||||
{
|
{
|
||||||
|
// Deprecated. Moved to itemData; should be removed later
|
||||||
item["getEnchantmentCharge"] = [](const Object& object) -> sol::optional<float> {
|
item["getEnchantmentCharge"] = [](const Object& object) -> sol::optional<float> {
|
||||||
float charge = object.ptr().getCellRef().getEnchantmentCharge();
|
float charge = object.ptr().getCellRef().getEnchantmentCharge();
|
||||||
if (charge == -1)
|
if (charge == -1)
|
||||||
|
|
|
@ -55,6 +55,7 @@ namespace MWLua
|
||||||
addRecordFunctionBinding<ESM::Miscellaneous>(miscellaneous, context);
|
addRecordFunctionBinding<ESM::Miscellaneous>(miscellaneous, context);
|
||||||
miscellaneous["createRecordDraft"] = tableToMisc;
|
miscellaneous["createRecordDraft"] = tableToMisc;
|
||||||
|
|
||||||
|
// Deprecated. Moved to itemData; should be removed later
|
||||||
miscellaneous["setSoul"] = [](const GObject& object, std::string_view soulId) {
|
miscellaneous["setSoul"] = [](const GObject& object, std::string_view soulId) {
|
||||||
ESM::RefId creature = ESM::RefId::deserializeText(soulId);
|
ESM::RefId creature = ESM::RefId::deserializeText(soulId);
|
||||||
const MWWorld::ESMStore& store = *MWBase::Environment::get().getESMStore();
|
const MWWorld::ESMStore& store = *MWBase::Environment::get().getESMStore();
|
||||||
|
@ -75,6 +76,7 @@ namespace MWLua
|
||||||
return soul.serializeText();
|
return soul.serializeText();
|
||||||
};
|
};
|
||||||
miscellaneous["soul"] = miscellaneous["getSoul"]; // for compatibility; should be removed later
|
miscellaneous["soul"] = miscellaneous["getSoul"]; // for compatibility; should be removed later
|
||||||
|
|
||||||
sol::usertype<ESM::Miscellaneous> record
|
sol::usertype<ESM::Miscellaneous> record
|
||||||
= context.mLua->sol().new_usertype<ESM::Miscellaneous>("ESM3_Miscellaneous");
|
= context.mLua->sol().new_usertype<ESM::Miscellaneous>("ESM3_Miscellaneous");
|
||||||
record[sol::meta_function::to_string]
|
record[sol::meta_function::to_string]
|
||||||
|
|
|
@ -750,7 +750,7 @@
|
||||||
-- @return #boolean
|
-- @return #boolean
|
||||||
|
|
||||||
---
|
---
|
||||||
-- Get this item's current enchantment charge.
|
-- (DEPRECATED, use itemData(item).enchantmentCharge) Get this item's current enchantment charge.
|
||||||
-- @function [parent=#Item] getEnchantmentCharge
|
-- @function [parent=#Item] getEnchantmentCharge
|
||||||
-- @param openmw.core#GameObject item
|
-- @param openmw.core#GameObject item
|
||||||
-- @return #number The charge remaining. `nil` if the enchantment has never been used, implying the charge is full. Unenchanted items will always return a value of `nil`.
|
-- @return #number The charge remaining. `nil` if the enchantment has never been used, implying the charge is full. Unenchanted items will always return a value of `nil`.
|
||||||
|
@ -763,7 +763,7 @@
|
||||||
-- @return #boolean
|
-- @return #boolean
|
||||||
|
|
||||||
---
|
---
|
||||||
-- Set this item's enchantment charge.
|
-- (DEPRECATED, use itemData(item).enchantmentCharge) Set this item's enchantment charge.
|
||||||
-- @function [parent=#Item] setEnchantmentCharge
|
-- @function [parent=#Item] setEnchantmentCharge
|
||||||
-- @param openmw.core#GameObject item
|
-- @param openmw.core#GameObject item
|
||||||
-- @param #number charge Can be `nil` to reset the unused state / full
|
-- @param #number charge Can be `nil` to reset the unused state / full
|
||||||
|
@ -777,14 +777,16 @@
|
||||||
-- @return #boolean
|
-- @return #boolean
|
||||||
|
|
||||||
---
|
---
|
||||||
-- Set of properties that differentiates one item from another of the same record type.
|
-- Set of properties that differentiates one item from another of the same record type; can be used by any script, but only global and self scripts can change values.
|
||||||
-- @function [parent=#Item] itemData
|
-- @function [parent=#Item] itemData
|
||||||
-- @param openmw.core#GameObject item
|
-- @param openmw.core#GameObject item
|
||||||
-- @return #ItemData
|
-- @return #ItemData
|
||||||
|
|
||||||
---
|
---
|
||||||
-- @type ItemData
|
-- @type ItemData
|
||||||
-- @field #number condition The item's current condition. Time remaining for lights. Uses left for lockpicks and probes. Current health for weapons and armor.
|
-- @field #number condition The item's current condition. Time remaining for lights. Uses left for repairs, lockpicks and probes. Current health for weapons and armor.
|
||||||
|
-- @field #number enchantmentCharge The item's current enchantment charge. Unenchanted items will always return a value of `nil`. Setting this to `nil` will reset the charge of the item.
|
||||||
|
-- @field #string soul The recordId of the item's current soul. Items without soul will always return a value of `nil`. Setting this to `nil` will remove the soul from the item.
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
-- @{#Creature} functions
|
-- @{#Creature} functions
|
||||||
|
@ -1689,7 +1691,7 @@
|
||||||
-- @return #MiscellaneousRecord
|
-- @return #MiscellaneousRecord
|
||||||
|
|
||||||
---
|
---
|
||||||
-- Returns the read-only soul of a miscellaneous item
|
-- (DEPRECATED, use itemData(item).soul) Returns the read-only soul of a miscellaneous item
|
||||||
-- @function [parent=#Miscellaneous] getSoul
|
-- @function [parent=#Miscellaneous] getSoul
|
||||||
-- @param openmw.core#GameObject object
|
-- @param openmw.core#GameObject object
|
||||||
-- @return #string
|
-- @return #string
|
||||||
|
@ -1702,7 +1704,7 @@
|
||||||
-- @return #MiscellaneousRecord A strongly typed Miscellaneous record.
|
-- @return #MiscellaneousRecord A strongly typed Miscellaneous record.
|
||||||
|
|
||||||
---
|
---
|
||||||
-- Sets the soul of a miscellaneous item, intended for soul gem objects; Must be used in a global script.
|
-- (DEPRECATED, use itemData(item).soul) Sets the soul of a miscellaneous item, intended for soul gem objects; Must be used in a global script.
|
||||||
-- @function [parent=#Miscellaneous] setSoul
|
-- @function [parent=#Miscellaneous] setSoul
|
||||||
-- @param openmw.core#GameObject object
|
-- @param openmw.core#GameObject object
|
||||||
-- @param #string soulId Record ID for the soul of the creature to use
|
-- @param #string soulId Record ID for the soul of the creature to use
|
||||||
|
|
Loading…
Reference in a new issue