mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	!?OB WIP
This commit is contained in:
		| @@ -182,6 +182,7 @@ | ||||
| 		<Unit filename="../scripts/lib/erm/MA.lua" /> | ||||
| 		<Unit filename="../scripts/lib/erm/MF.lua" /> | ||||
| 		<Unit filename="../scripts/lib/erm/MF_T.lua" /> | ||||
| 		<Unit filename="../scripts/lib/erm/OB_T.lua" /> | ||||
| 		<Unit filename="../scripts/lib/erm/OW.lua" /> | ||||
| 		<Unit filename="../scripts/lib/erm/PI_T.lua" /> | ||||
| 		<Unit filename="../scripts/lib/erm/ReceiverBase.lua" /> | ||||
|   | ||||
| @@ -211,16 +211,38 @@ public: | ||||
| 	bool tryGet(int position, double & value); | ||||
| 	bool tryGet(int position, std::string & value); | ||||
|  | ||||
| 	template<typename T, typename std::enable_if<detail::IsRegularClass<T>::value, int>::type = 0> | ||||
| 	bool tryGet(int position, T * & value) | ||||
| 	template<typename T, typename std::enable_if<detail::IsRegularClass<T>::value && std::is_const<T>::value, int>::type = 0> | ||||
| 	STRONG_INLINE bool tryGet(int position, T * & value) | ||||
| 	{ | ||||
| 		return tryGetUData(position, value); | ||||
| 		using NCValue = typename std::remove_const<T>::type; | ||||
|  | ||||
| 		using UData = NCValue *; | ||||
| 		using CUData = T *; | ||||
|  | ||||
| 		return tryGetCUData<T *, UData, CUData>(position, value); | ||||
| 	} | ||||
|  | ||||
| 	template<typename T, typename std::enable_if<detail::IsRegularClass<T>::value, int>::type = 0> | ||||
| 	bool tryGet(int position, std::shared_ptr<T> & value) | ||||
| 	template<typename T, typename std::enable_if<detail::IsRegularClass<T>::value && !std::is_const<T>::value, int>::type = 0> | ||||
| 	STRONG_INLINE bool tryGet(int position, T * & value) | ||||
| 	{ | ||||
| 		return tryGetUData(position, value); | ||||
| 		return tryGetUData<T *>(position, value); | ||||
| 	} | ||||
|  | ||||
| 	template<typename T, typename std::enable_if<detail::IsRegularClass<T>::value && std::is_const<T>::value, int>::type = 0> | ||||
| 	STRONG_INLINE bool tryGet(int position, std::shared_ptr<T> & value) | ||||
| 	{ | ||||
| 		using NCValue = typename std::remove_const<T>::type; | ||||
|  | ||||
| 		using UData = std::shared_ptr<NCValue>; | ||||
| 		using CUData = std::shared_ptr<T>; | ||||
|  | ||||
| 		return tryGetCUData<std::shared_ptr<T>, UData, CUData>(position, value); | ||||
| 	} | ||||
|  | ||||
| 	template<typename T, typename std::enable_if<detail::IsRegularClass<T>::value && !std::is_const<T>::value, int>::type = 0> | ||||
| 	STRONG_INLINE bool tryGet(int position, std::shared_ptr<T> & value) | ||||
| 	{ | ||||
| 		return tryGetUData<std::shared_ptr<T>>(position, value); | ||||
| 	} | ||||
|  | ||||
| 	template<typename U> | ||||
| @@ -228,13 +250,67 @@ public: | ||||
| 	{ | ||||
| 		static auto KEY = api::TypeRegistry::get()->getKey<U>(); | ||||
|  | ||||
| 		void * raw = luaL_checkudata(L, position, KEY); | ||||
| 		void * raw = lua_touserdata(L, position); | ||||
|  | ||||
| 		if(!raw) | ||||
| 			return false; | ||||
|  | ||||
| 		value = *(static_cast<U *>(raw)); | ||||
| 		return true; | ||||
| 		if(lua_getmetatable(L, position) == 0) | ||||
| 			return false; | ||||
|  | ||||
| 		lua_getfield(L, LUA_REGISTRYINDEX, KEY); | ||||
|  | ||||
| 		if(lua_rawequal(L, -1, -2) == 1) | ||||
| 		{ | ||||
| 			value = *(static_cast<U *>(raw)); | ||||
| 			lua_pop(L, 2); | ||||
| 			return true; | ||||
| 		} | ||||
|  | ||||
| 		lua_pop(L, 2); | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	template<typename T, typename U, typename CU> | ||||
| 	bool tryGetCUData(int position, T & value) | ||||
| 	{ | ||||
| 		static auto KEY = api::TypeRegistry::get()->getKey<U>(); | ||||
| 		static auto C_KEY = api::TypeRegistry::get()->getKey<CU>(); | ||||
|  | ||||
| 		void * raw = lua_touserdata(L, position); | ||||
|  | ||||
| 		if(!raw) | ||||
| 			return false; | ||||
|  | ||||
| 		if(lua_getmetatable(L, position) == 0) | ||||
| 			return false; | ||||
|  | ||||
| 		//top is metatable | ||||
|  | ||||
| 		lua_getfield(L, LUA_REGISTRYINDEX, KEY); | ||||
|  | ||||
| 		if(lua_rawequal(L, -1, -2) == 1) | ||||
| 		{ | ||||
| 			value = *(static_cast<U *>(raw)); | ||||
| 			lua_pop(L, 2); | ||||
| 			return true; | ||||
| 		} | ||||
|  | ||||
| 		lua_pop(L, 1); | ||||
|  | ||||
| 		//top is metatable | ||||
|  | ||||
| 		lua_getfield(L, LUA_REGISTRYINDEX, C_KEY); | ||||
|  | ||||
| 		if(lua_rawequal(L, -1, -2) == 1) | ||||
| 		{ | ||||
| 			value = *(static_cast<CU *>(raw)); | ||||
| 			lua_pop(L, 2); | ||||
| 			return true; | ||||
| 		} | ||||
|  | ||||
| 		lua_pop(L, 2); | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	bool tryGet(int position, JsonNode & value); | ||||
|   | ||||
| @@ -161,13 +161,16 @@ class OpaqueWrapper : public RegistarBase | ||||
| { | ||||
| public: | ||||
| 	using ObjectType = typename std::remove_cv<T>::type; | ||||
| 	using UDataType = T *; | ||||
| 	using UDataType = ObjectType *; | ||||
| 	using CUDataType = const ObjectType *; | ||||
|  | ||||
| 	using RegType = detail::RegType<UDataType>; | ||||
| 	using CustomRegType = detail::CustomRegType; | ||||
|  | ||||
| 	void pushMetatable(lua_State * L) const override final | ||||
| 	{ | ||||
| 		static auto KEY = api::TypeRegistry::get()->getKey<UDataType>(); | ||||
| 		static auto S_KEY = api::TypeRegistry::get()->getKey<CUDataType>(); | ||||
|  | ||||
| 		LuaStack S(L); | ||||
|  | ||||
| @@ -176,6 +179,11 @@ public: | ||||
|  | ||||
| 		S.balance(); | ||||
|  | ||||
| 		if(luaL_newmetatable(L, S_KEY) != 0) | ||||
| 			adjustMetatable(L); | ||||
|  | ||||
| 		S.balance(); | ||||
|  | ||||
| 		detail::Dispatcher<Proxy, UDataType>::pushStaticTable(L); | ||||
|  | ||||
| 		adjustStaticTable(L); | ||||
|   | ||||
| @@ -26,8 +26,6 @@ VCMI_REGISTER_CORE_SCRIPT_API(CreatureProxy, "Creature"); | ||||
|  | ||||
| const std::vector<CreatureProxy::RegType> CreatureProxy::REGISTER = | ||||
| { | ||||
| 	{"accessBonuses", LuaCallWrapper<const EntityWithBonuses<CreatureID>>::createFunctor(&EntityWithBonuses<CreatureID>::accessBonuses)}, | ||||
|  | ||||
| 	{"getCost", LuaCallWrapper<const Creature>::createFunctor(&Creature::getCost)}, | ||||
| 	{"isDoubleWide", LuaCallWrapper<const Creature>::createFunctor(&Creature::isDoubleWide)}, | ||||
| }; | ||||
|   | ||||
| @@ -21,10 +21,10 @@ namespace scripting | ||||
| namespace api | ||||
| { | ||||
|  | ||||
| class ObjectInstanceProxy : public OpaqueWrapper<const IObjectInterface, ObjectInstanceProxy> | ||||
| class ObjectInstanceProxy : public OpaqueWrapper<const CGObjectInstance, ObjectInstanceProxy> | ||||
| { | ||||
| public: | ||||
| 	using Wrapper = OpaqueWrapper<const IObjectInterface, ObjectInstanceProxy>; | ||||
| 	using Wrapper = OpaqueWrapper<const CGObjectInstance, ObjectInstanceProxy>; | ||||
| 	static const std::vector<typename Wrapper::RegType> REGISTER; | ||||
| 	static const std::vector<typename Wrapper::CustomRegType> REGISTER_CUSTOM; | ||||
| }; | ||||
|   | ||||
| @@ -39,6 +39,21 @@ const std::vector<ObjectVisitStartedProxy::CustomRegType> ObjectVisitStartedProx | ||||
| 		&SubscriptionRegistryProxy<ObjectVisitStartedProxy>::subscribeAfter, | ||||
| 		true | ||||
| 	}, | ||||
| 	{ | ||||
| 		"getPlayer", | ||||
| 		LuaMethodWrapper<ObjectVisitStarted, PlayerColor(ObjectVisitStarted:: *)()const, &ObjectVisitStarted::getPlayer>::invoke, | ||||
| 		false | ||||
| 	}, | ||||
| 	{ | ||||
| 		"getHero", | ||||
| 		LuaMethodWrapper<ObjectVisitStarted, ObjectInstanceID(ObjectVisitStarted:: *)()const, &ObjectVisitStarted::getHero>::invoke, | ||||
| 		false | ||||
| 	}, | ||||
| 	{ | ||||
| 		"getObject", | ||||
| 		LuaMethodWrapper<ObjectVisitStarted, ObjectInstanceID(ObjectVisitStarted:: *)()const, &ObjectVisitStarted::getObject>::invoke, | ||||
| 		false | ||||
| 	}, | ||||
| }; | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -200,7 +200,7 @@ end | ||||
| !?TL client only? depends on time limit feature | ||||
| ]] | ||||
|  | ||||
| local supportedTriggers = {"PI", "FU", "GM", "MF", "TM"} | ||||
| local supportedTriggers = {"PI", "FU", "GM", "MF", "OB", "TM"} | ||||
|  | ||||
| local TriggerLoaders = {} | ||||
|  | ||||
|   | ||||
| @@ -6,7 +6,7 @@ local trigger = TriggerBase:new() | ||||
|  | ||||
| function trigger:new(o) | ||||
| 	o = TriggerBase.new(self, o) | ||||
| 	o.sub = ApplyDamage.subscribeBefore(EVENT_BUS, function(event) | ||||
| 	o.sub = ApplyDamage.subscribeBefore(eventBus, function(event) | ||||
| 		o:call(event) | ||||
| 	end) | ||||
| 	return o | ||||
|   | ||||
							
								
								
									
										27
									
								
								scripts/lib/erm/OB_T.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								scripts/lib/erm/OB_T.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| local TriggerBase = require("core:erm.TriggerBase") | ||||
| local ObjectVisitStarted = require("events.ObjectVisitStarted") | ||||
| local eventBus = EVENT_BUS | ||||
| local game = GAME | ||||
|  | ||||
| local trigger = TriggerBase:new() | ||||
|  | ||||
| function trigger:new(o) | ||||
| 	o = TriggerBase.new(self, o) | ||||
|  | ||||
| 	local id1 = tonumber(o.id[1]) | ||||
|  | ||||
| 	o.sub = ObjectVisitStarted.subscribeBefore(eventBus, | ||||
| 	function(event) | ||||
| 		local objIndex = event:getObject() | ||||
|  | ||||
| 		local obj = game:getObj(objIndex, false) | ||||
|  | ||||
| 		if obj:getObjGroupIndex() == id1 then | ||||
| 			o:call(event) | ||||
| 		end | ||||
| 	end) | ||||
|  | ||||
| 	return o | ||||
| end | ||||
|  | ||||
| return trigger | ||||
| @@ -42,23 +42,26 @@ protected: | ||||
|  | ||||
| TEST_F(ERM_OB_T, ByTypeIndex) | ||||
| { | ||||
| 	EXPECT_CALL(infoMock, getObj(Eq(ObjectInstanceID(234)), _)).WillRepeatedly(Return(&objectMock)); | ||||
| 	EXPECT_CALL(objectMock, getObjGroupIndex()).WillRepeatedly(Return(420)); | ||||
| 	EXPECT_CALL(infoMock, getObj(Eq(ObjectInstanceID(234)), _)).Times(AtLeast(1)).WillRepeatedly(Return(&objectMock)); | ||||
| 	EXPECT_CALL(objectMock, getObjGroupIndex()).Times(AtLeast(1)).WillRepeatedly(Return(420)); | ||||
|  | ||||
| 	loadScript(VLC->scriptHandler->erm, | ||||
| 		"VERM\n" | ||||
| 		"!?OB420;\n" | ||||
| 		"!!VRv42:S4;\n" | ||||
| 		"!?OB421;\n" | ||||
| 		"!!VRv43:S5;\n" | ||||
| 	); | ||||
|  | ||||
| 	SCOPED_TRACE("\n" + subject->code); | ||||
| 	runClientServer(); | ||||
|  | ||||
| 	events::ObjectVisitStarted::defaultExecute(&eventBus, nullptr, PlayerColor(2), ObjectInstanceID(234), ObjectInstanceID(235)); | ||||
| 	events::ObjectVisitStarted::defaultExecute(&eventBus, nullptr, PlayerColor(2), ObjectInstanceID(235), ObjectInstanceID(234)); | ||||
|  | ||||
| 	const JsonNode actualState = context->saveState(); | ||||
|  | ||||
| 	EXPECT_EQ(actualState["ERM"]["v"]["42"], JsonUtils::floatNode(4)) << actualState.toJson(); | ||||
| 	EXPECT_TRUE(actualState["ERM"]["v"]["43"].isNull()) << actualState.toJson(); | ||||
| } | ||||
|  | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user