diff --git a/lib/VCMI_lib.cbp b/lib/VCMI_lib.cbp
index 98bf37af0..97d17da8d 100644
--- a/lib/VCMI_lib.cbp
+++ b/lib/VCMI_lib.cbp
@@ -182,6 +182,7 @@
+
diff --git a/scripting/lua/LuaStack.h b/scripting/lua/LuaStack.h
index e3b721537..e2c63ccf2 100644
--- a/scripting/lua/LuaStack.h
+++ b/scripting/lua/LuaStack.h
@@ -211,16 +211,38 @@ public:
bool tryGet(int position, double & value);
bool tryGet(int position, std::string & value);
- template::value, int>::type = 0>
- bool tryGet(int position, T * & value)
+ template::value && std::is_const::value, int>::type = 0>
+ STRONG_INLINE bool tryGet(int position, T * & value)
{
- return tryGetUData(position, value);
+ using NCValue = typename std::remove_const::type;
+
+ using UData = NCValue *;
+ using CUData = T *;
+
+ return tryGetCUData(position, value);
}
- template::value, int>::type = 0>
- bool tryGet(int position, std::shared_ptr & value)
+ template::value && !std::is_const::value, int>::type = 0>
+ STRONG_INLINE bool tryGet(int position, T * & value)
{
- return tryGetUData(position, value);
+ return tryGetUData(position, value);
+ }
+
+ template::value && std::is_const::value, int>::type = 0>
+ STRONG_INLINE bool tryGet(int position, std::shared_ptr & value)
+ {
+ using NCValue = typename std::remove_const::type;
+
+ using UData = std::shared_ptr;
+ using CUData = std::shared_ptr;
+
+ return tryGetCUData, UData, CUData>(position, value);
+ }
+
+ template::value && !std::is_const::value, int>::type = 0>
+ STRONG_INLINE bool tryGet(int position, std::shared_ptr & value)
+ {
+ return tryGetUData>(position, value);
}
template
@@ -228,13 +250,67 @@ public:
{
static auto KEY = api::TypeRegistry::get()->getKey();
- void * raw = luaL_checkudata(L, position, KEY);
+ void * raw = lua_touserdata(L, position);
if(!raw)
return false;
- value = *(static_cast(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(raw));
+ lua_pop(L, 2);
+ return true;
+ }
+
+ lua_pop(L, 2);
+ return false;
+ }
+
+ template
+ bool tryGetCUData(int position, T & value)
+ {
+ static auto KEY = api::TypeRegistry::get()->getKey();
+ static auto C_KEY = api::TypeRegistry::get()->getKey();
+
+ 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(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(raw));
+ lua_pop(L, 2);
+ return true;
+ }
+
+ lua_pop(L, 2);
+ return false;
}
bool tryGet(int position, JsonNode & value);
diff --git a/scripting/lua/LuaWrapper.h b/scripting/lua/LuaWrapper.h
index aa4794bff..f809d21ea 100644
--- a/scripting/lua/LuaWrapper.h
+++ b/scripting/lua/LuaWrapper.h
@@ -161,13 +161,16 @@ class OpaqueWrapper : public RegistarBase
{
public:
using ObjectType = typename std::remove_cv::type;
- using UDataType = T *;
+ using UDataType = ObjectType *;
+ using CUDataType = const ObjectType *;
+
using RegType = detail::RegType;
using CustomRegType = detail::CustomRegType;
void pushMetatable(lua_State * L) const override final
{
static auto KEY = api::TypeRegistry::get()->getKey();
+ static auto S_KEY = api::TypeRegistry::get()->getKey();
LuaStack S(L);
@@ -176,6 +179,11 @@ public:
S.balance();
+ if(luaL_newmetatable(L, S_KEY) != 0)
+ adjustMetatable(L);
+
+ S.balance();
+
detail::Dispatcher::pushStaticTable(L);
adjustStaticTable(L);
diff --git a/scripting/lua/api/Creature.cpp b/scripting/lua/api/Creature.cpp
index bc6f0a971..6adc4e4fb 100644
--- a/scripting/lua/api/Creature.cpp
+++ b/scripting/lua/api/Creature.cpp
@@ -26,8 +26,6 @@ VCMI_REGISTER_CORE_SCRIPT_API(CreatureProxy, "Creature");
const std::vector CreatureProxy::REGISTER =
{
- {"accessBonuses", LuaCallWrapper>::createFunctor(&EntityWithBonuses::accessBonuses)},
-
{"getCost", LuaCallWrapper::createFunctor(&Creature::getCost)},
{"isDoubleWide", LuaCallWrapper::createFunctor(&Creature::isDoubleWide)},
};
diff --git a/scripting/lua/api/ObjectInstance.h b/scripting/lua/api/ObjectInstance.h
index 0b6746c25..134f366cd 100644
--- a/scripting/lua/api/ObjectInstance.h
+++ b/scripting/lua/api/ObjectInstance.h
@@ -21,10 +21,10 @@ namespace scripting
namespace api
{
-class ObjectInstanceProxy : public OpaqueWrapper
+class ObjectInstanceProxy : public OpaqueWrapper
{
public:
- using Wrapper = OpaqueWrapper;
+ using Wrapper = OpaqueWrapper;
static const std::vector REGISTER;
static const std::vector REGISTER_CUSTOM;
};
diff --git a/scripting/lua/api/events/AdventureEvents.cpp b/scripting/lua/api/events/AdventureEvents.cpp
index bd86596bb..f6d36bf00 100644
--- a/scripting/lua/api/events/AdventureEvents.cpp
+++ b/scripting/lua/api/events/AdventureEvents.cpp
@@ -39,6 +39,21 @@ const std::vector ObjectVisitStartedProx
&SubscriptionRegistryProxy::subscribeAfter,
true
},
+ {
+ "getPlayer",
+ LuaMethodWrapper::invoke,
+ false
+ },
+ {
+ "getHero",
+ LuaMethodWrapper::invoke,
+ false
+ },
+ {
+ "getObject",
+ LuaMethodWrapper::invoke,
+ false
+ },
};
}
diff --git a/scripts/lib/erm.lua b/scripts/lib/erm.lua
index aa7140a1e..a09eb0777 100644
--- a/scripts/lib/erm.lua
+++ b/scripts/lib/erm.lua
@@ -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 = {}
diff --git a/scripts/lib/erm/MF_T.lua b/scripts/lib/erm/MF_T.lua
index 4f3fd343e..b427ea366 100644
--- a/scripts/lib/erm/MF_T.lua
+++ b/scripts/lib/erm/MF_T.lua
@@ -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
diff --git a/scripts/lib/erm/OB_T.lua b/scripts/lib/erm/OB_T.lua
new file mode 100644
index 000000000..df4c01659
--- /dev/null
+++ b/scripts/lib/erm/OB_T.lua
@@ -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
diff --git a/test/erm/ERM_OB_T.cpp b/test/erm/ERM_OB_T.cpp
index 05f52b826..f8767f667 100644
--- a/test/erm/ERM_OB_T.cpp
+++ b/test/erm/ERM_OB_T.cpp
@@ -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();
}
}