mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-10-31 20:26:43 +00:00 
			
		
		
		
	take2
This commit is contained in:
		
							parent
							
								
									ff16ee2d64
								
							
						
					
					
						commit
						83ebaf27cc
					
				
					 7 changed files with 153 additions and 82 deletions
				
			
		|  | @ -61,8 +61,8 @@ add_openmw_dir (mwscript | |||
| add_openmw_dir (mwlua | ||||
|     luamanagerimp object objectlists userdataserializer luaevents engineevents objectvariant | ||||
|     context globalscripts localscripts playerscripts luabindings objectbindings cellbindings mwscriptbindings | ||||
|     camerabindings vfsbindings uibindings soundbindings inputbindings nearbybindings postprocessingbindings stats debugbindings | ||||
|     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/potion types/ingredient types/misc types/repair types/armor types/light types/static types/clothing types/levelledlist types/terminal types/itemstats | ||||
|     camerabindings vfsbindings uibindings soundbindings inputbindings nearbybindings postprocessingbindings stats debugbindings itemdata | ||||
|     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/potion types/ingredient types/misc types/repair types/armor types/light types/static types/clothing types/levelledlist types/terminal | ||||
|     worker magicbindings factionbindings | ||||
|     ) | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										129
									
								
								apps/openmw/mwlua/itemdata.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								apps/openmw/mwlua/itemdata.cpp
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,129 @@ | |||
| #include "itemdata.hpp" | ||||
| 
 | ||||
| #include "context.hpp" | ||||
| 
 | ||||
| #include "luamanagerimp.hpp" | ||||
| 
 | ||||
| #include "../mwworld/class.hpp" | ||||
| 
 | ||||
| #include "objectvariant.hpp" | ||||
| 
 | ||||
| namespace | ||||
| { | ||||
|     using SelfObject = MWLua::SelfObject; | ||||
|     using Index = const SelfObject::CachedStat::Index&; | ||||
| 
 | ||||
|     constexpr std::array properties = { "condition", /*"enchantmentCharge", "soul", "owner", etc..*/ }; | ||||
| 
 | ||||
|     void invalidPropErr(std::string_view prop, const MWWorld::Ptr& ptr) | ||||
|     { | ||||
|         throw std::runtime_error(std::string(prop) + " does not exist for item " | ||||
|             + std::string(ptr.getClass().getName(ptr)) + "(" + std::string(ptr.getTypeDescription()) + ")"); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| namespace MWLua | ||||
| { | ||||
|     static void addStatUpdateAction(MWLua::LuaManager* manager, const SelfObject& obj) | ||||
|     { | ||||
|         if (!obj.mStatsCache.empty()) | ||||
|             return; // was already added before
 | ||||
|         manager->addAction( | ||||
|             [obj = Object(obj)] { | ||||
|                 LocalScripts* scripts = obj.ptr().getRefData().getLuaScripts(); | ||||
|                 if (scripts) | ||||
|                     scripts->applyStatsCache(); | ||||
|             }, | ||||
|             "StatUpdateAction"); | ||||
|     } | ||||
| 
 | ||||
|     class ItemData | ||||
|     { | ||||
|         ObjectVariant mObject; | ||||
| 
 | ||||
|     public: | ||||
|         ItemData(ObjectVariant object) | ||||
|             : mObject(object) | ||||
|         { | ||||
|         } | ||||
| 
 | ||||
|         sol::object get(const Context& context, std::string_view prop) const | ||||
|         { | ||||
|             if (mObject.isSelfObject()) | ||||
|             { | ||||
|                 SelfObject* self = mObject.asSelfObject(); | ||||
|                 auto it = self->mStatsCache.find({ &ItemData::setValue, std::monostate{}, prop }); | ||||
|                 if (it != self->mStatsCache.end()) | ||||
|                     return it->second; | ||||
|             } | ||||
|             return sol::make_object(context.mLua->sol(), getValue(context, prop)); | ||||
|         } | ||||
| 
 | ||||
|         void set(const Context& context, std::string_view prop, const sol::object& value) const | ||||
|         { | ||||
|             SelfObject* obj = mObject.asSelfObject(); | ||||
|             addStatUpdateAction(context.mLuaManager, *obj); | ||||
|             obj->mStatsCache[SelfObject::CachedStat{ &ItemData::setValue, std::monostate{}, prop }] = value; | ||||
|         } | ||||
| 
 | ||||
|         sol::object getValue(const Context& context, std::string_view prop) const | ||||
|         { | ||||
|             if (prop == "condition") | ||||
|             { | ||||
|                 MWWorld::Ptr o = mObject.ptr(); | ||||
|                 if (o.getClass().isLight(o)) | ||||
|                     return sol::make_object(context.mLua->sol(), o.getClass().getRemainingUsageTime(o)); | ||||
|                 else if (o.getClass().hasItemHealth(o)) | ||||
|                     return sol::make_object(context.mLua->sol(), o.getClass().getItemHealth(o)); | ||||
|             } | ||||
| 
 | ||||
|             return sol::lua_nil; | ||||
|         } | ||||
| 
 | ||||
|         static void setValue(Index i, std::string_view prop, const MWWorld::Ptr& ptr, const sol::object& value) | ||||
|         { | ||||
|             if (prop == "condition") | ||||
|             { | ||||
|                 double cond = value.as<double>(); | ||||
|                 if (ptr.getClass().isLight(ptr)) | ||||
|                     ptr.getClass().setRemainingUsageTime(ptr, cond); | ||||
|                 else if (ptr.getClass().hasItemHealth(ptr)) | ||||
|                     ptr.getCellRef().setCharge(std::max(0, static_cast<int>(cond))); | ||||
|                 else /*ignore or error?*/ | ||||
|                     invalidPropErr(prop, ptr); | ||||
|             } | ||||
|         } | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| namespace sol | ||||
| { | ||||
|     template <> | ||||
|     struct is_automagical<MWLua::ItemData> : std::false_type | ||||
|     { | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| namespace MWLua | ||||
| { | ||||
|     void addItemDataBindings(sol::table& item, const Context& context) | ||||
|     { | ||||
|         item["itemData"] = [](const sol::object& object) -> sol::optional<ItemData> { | ||||
|             ObjectVariant o(object); | ||||
|             if (o.ptr().getClass().isItem(o.ptr()) || o.ptr().mRef->getType() == ESM::REC_LIGH) | ||||
|                 return ItemData(std::move(o)); | ||||
|             return {}; | ||||
|         }; | ||||
| 
 | ||||
|         sol::usertype<ItemData> itemData = context.mLua->sol().new_usertype<ItemData>("ItemData"); | ||||
|         itemData[sol::meta_function::new_index] = [](const ItemData& stat, const sol::variadic_args args) { | ||||
|             throw std::runtime_error("Unknown ItemData property '" + args.get<std::string>() + "'"); | ||||
|         }; | ||||
| 
 | ||||
|         for (std::string_view prop : properties) | ||||
|         { | ||||
|             itemData[prop] = sol::property([context, prop](const ItemData& stat) { return stat.get(context, prop); }, | ||||
|                 [context, prop](const ItemData& stat, const sol::object& value) { stat.set(context, prop, value); }); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										13
									
								
								apps/openmw/mwlua/itemdata.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								apps/openmw/mwlua/itemdata.hpp
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,13 @@ | |||
| #ifndef MWLUA_ITEMDATA_H | ||||
| #define MWLUA_ITEMDATA_H | ||||
| 
 | ||||
| #include <sol/forward.hpp> | ||||
| 
 | ||||
| namespace MWLua | ||||
| { | ||||
|     struct Context; | ||||
| 
 | ||||
|     void addItemDataBindings(sol::table& item, const Context& context); | ||||
| 
 | ||||
| } | ||||
| #endif // MWLUA_ITEMDATA_H
 | ||||
|  | @ -22,7 +22,7 @@ namespace MWLua | |||
|         class CachedStat | ||||
|         { | ||||
|         public: | ||||
|             using Index = std::variant<int, ESM::RefId>; | ||||
|             using Index = std::variant<int, ESM::RefId, std::monostate>; | ||||
|             using Setter = void (*)(const Index&, std::string_view, const MWWorld::Ptr&, const sol::object&); | ||||
| 
 | ||||
|             CachedStat(Setter setter, Index index, std::string_view prop) | ||||
|  |  | |||
|  | @ -1,31 +1,22 @@ | |||
| #include "itemstats.hpp" | ||||
| #include <sol/sol.hpp> | ||||
| 
 | ||||
| namespace sol | ||||
| { | ||||
|     template <> | ||||
|     struct is_automagical<MWLua::ItemStat> : std::false_type | ||||
|     { | ||||
|     }; | ||||
| } | ||||
| #include "../../mwworld/class.hpp" | ||||
| 
 | ||||
| #include "../itemdata.hpp" | ||||
| 
 | ||||
| #include "types.hpp" | ||||
| 
 | ||||
| namespace MWLua | ||||
| { | ||||
| 
 | ||||
|     void addItemBindings(sol::table item, const Context& context) | ||||
|     { | ||||
|         sol::usertype<ItemStat> ItemStats = context.mLua->sol().new_usertype<ItemStat>("ItemStat"); | ||||
|         ItemStats[sol::meta_function::new_index] = [](const ItemStat& i, const sol::variadic_args args) { | ||||
|             throw std::runtime_error("Unknown itemStat property '" + args.get<std::string>() + "'"); | ||||
|         }; | ||||
|         ItemStats["condition"] = sol::property([](const ItemStat& i) { return i.getCondition(); }, | ||||
|             [](const ItemStat& i, float cond) { i.setCondition(cond); }); | ||||
| 
 | ||||
|         item["getEnchantmentCharge"] | ||||
|             = [](const Object& object) { return object.ptr().getCellRef().getEnchantmentCharge(); }; | ||||
|         item["setEnchantmentCharge"] | ||||
|             = [](const GObject& object, float charge) { object.ptr().getCellRef().setEnchantmentCharge(charge); }; | ||||
|         item["isRestocking"] | ||||
|             = [](const Object& object) -> bool { return object.ptr().getRefData().getCount(false) < 0; }; | ||||
|         item["itemStats"] = [](const sol::object& object) { return ItemStat(object); }; | ||||
| 
 | ||||
|         addItemDataBindings(item, context); | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -1,33 +0,0 @@ | |||
| #include "itemstats.hpp" | ||||
| 
 | ||||
| namespace MWLua | ||||
| { | ||||
|     ItemStat::ItemStat(const sol::object& object) | ||||
|         : mObject(ObjectVariant(object)) | ||||
|     { | ||||
|     } | ||||
|     sol::optional<double> ItemStat::getCondition() const | ||||
|     { | ||||
|         MWWorld::Ptr o = mObject.ptr(); | ||||
|         if (o.getClass().isLight(o)) | ||||
|             return o.getClass().getRemainingUsageTime(o); | ||||
|         else if (o.getClass().hasItemHealth(o)) | ||||
|             return o.getClass().getItemHealth(o); | ||||
|         else | ||||
|             return sol::nullopt; | ||||
|     } | ||||
|     void ItemStat::setCondition(float cond) const | ||||
|     { | ||||
|         if (!mObject.isGObject()) | ||||
|             throw std::runtime_error("This property can only be set in global scripts"); | ||||
| 
 | ||||
|         MWWorld::Ptr o = mObject.ptr(); | ||||
|         if (o.getClass().isLight(o)) | ||||
|             return o.getClass().setRemainingUsageTime(o, cond); | ||||
|         else if (o.getClass().hasItemHealth(o)) | ||||
|             o.getCellRef().setCharge(std::max(0, static_cast<int>(cond))); | ||||
|         else | ||||
|             throw std::runtime_error("'condition' property does not exist for " + std::string(o.getClass().getName(o)) | ||||
|                 + "(" + std::string(o.getTypeDescription()) + ")"); | ||||
|     }; | ||||
| } | ||||
|  | @ -1,29 +0,0 @@ | |||
| #ifndef MWLUA_ITEMSTATS_H | ||||
| #define MWLUA_ITEMSTATS_H | ||||
| 
 | ||||
| #include <sol/sol.hpp> | ||||
| 
 | ||||
| #include "../../mwworld/class.hpp" | ||||
| 
 | ||||
| #include "../objectvariant.hpp" | ||||
| #include "types.hpp" | ||||
| 
 | ||||
| namespace MWLua | ||||
| { | ||||
|     class ItemStat | ||||
|     { | ||||
|     public: | ||||
|         ItemStat(const sol::object& object); | ||||
| 
 | ||||
|         sol::optional<double> getCondition() const; | ||||
| 
 | ||||
|         void setCondition(float cond) const; | ||||
| 
 | ||||
|         /*
 | ||||
|          * set,get, enchantmentCharge, soul? etc.. | ||||
|          */ | ||||
| 
 | ||||
|         ObjectVariant mObject; | ||||
|     }; | ||||
| } | ||||
| #endif // MWLUA_ITEMSTATS_H
 | ||||
		Loading…
	
		Reference in a new issue