2021-04-17 11:50:20 +02:00
|
|
|
#include "luabindings.hpp"
|
|
|
|
|
2022-09-08 21:08:59 +02:00
|
|
|
#include <components/esm/records.hpp>
|
2021-04-17 11:50:20 +02:00
|
|
|
|
|
|
|
#include "../mwworld/cellstore.hpp"
|
2022-08-17 19:09:38 +02:00
|
|
|
|
2022-03-05 19:53:39 +01:00
|
|
|
#include "types/types.hpp"
|
2022-08-17 19:09:38 +02:00
|
|
|
#include "worldview.hpp"
|
2021-04-17 11:50:20 +02:00
|
|
|
|
2021-12-14 00:36:26 +01:00
|
|
|
namespace sol
|
|
|
|
{
|
|
|
|
template <>
|
|
|
|
struct is_automagical<MWLua::LCell> : std::false_type
|
|
|
|
{
|
|
|
|
};
|
|
|
|
template <>
|
|
|
|
struct is_automagical<MWLua::GCell> : std::false_type
|
|
|
|
{
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2021-04-17 11:50:20 +02:00
|
|
|
namespace MWLua
|
|
|
|
{
|
|
|
|
|
|
|
|
template <class CellT, class ObjectT>
|
|
|
|
static void initCellBindings(const std::string& prefix, const Context& context)
|
|
|
|
{
|
|
|
|
sol::usertype<CellT> cellT = context.mLua->sol().new_usertype<CellT>(prefix + "Cell");
|
|
|
|
|
|
|
|
cellT[sol::meta_function::equal_to] = [](const CellT& a, const CellT& b) { return a.mStore == b.mStore; };
|
|
|
|
cellT[sol::meta_function::to_string] = [](const CellT& c) {
|
|
|
|
const ESM::Cell* cell = c.mStore->getCell();
|
|
|
|
std::stringstream res;
|
|
|
|
if (cell->isExterior())
|
|
|
|
res << "exterior(" << cell->getGridX() << ", " << cell->getGridY() << ")";
|
|
|
|
else
|
|
|
|
res << "interior(" << cell->mName << ")";
|
|
|
|
return res.str();
|
|
|
|
};
|
|
|
|
|
2022-12-24 01:56:27 +01:00
|
|
|
cellT["name"]
|
|
|
|
= sol::readonly_property([](const CellT& c) { return c.mStore->getCell()->mName.getRefIdString(); });
|
|
|
|
cellT["region"]
|
|
|
|
= sol::readonly_property([](const CellT& c) { return c.mStore->getCell()->mRegion.getRefIdString(); });
|
2021-04-17 11:50:20 +02:00
|
|
|
cellT["gridX"] = sol::readonly_property([](const CellT& c) { return c.mStore->getCell()->getGridX(); });
|
|
|
|
cellT["gridY"] = sol::readonly_property([](const CellT& c) { return c.mStore->getCell()->getGridY(); });
|
|
|
|
cellT["hasWater"] = sol::readonly_property([](const CellT& c) { return c.mStore->getCell()->hasWater(); });
|
2022-06-23 20:21:06 +02:00
|
|
|
cellT["isExterior"] = sol::readonly_property([](const CellT& c) { return c.mStore->isExterior(); });
|
|
|
|
cellT["isQuasiExterior"] = sol::readonly_property(
|
2022-06-24 23:41:11 +00:00
|
|
|
[](const CellT& c) { return (c.mStore->getCell()->mData.mFlags & ESM::Cell::QuasiEx) != 0; });
|
2021-04-17 11:50:20 +02:00
|
|
|
|
|
|
|
cellT["isInSameSpace"] = [](const CellT& c, const ObjectT& obj) {
|
|
|
|
const MWWorld::Ptr& ptr = obj.ptr();
|
|
|
|
if (!ptr.isInCell())
|
|
|
|
return false;
|
|
|
|
MWWorld::CellStore* cell = ptr.getCell();
|
|
|
|
return cell == c.mStore || (cell->isExterior() && c.mStore->isExterior());
|
|
|
|
};
|
2022-09-22 21:26:05 +03:00
|
|
|
|
2021-04-17 11:50:20 +02:00
|
|
|
if constexpr (std::is_same_v<CellT, GCell>)
|
|
|
|
{ // only for global scripts
|
2022-12-23 19:57:12 +01:00
|
|
|
cellT["getAll"] = [ids = getPackageToTypeTable(context.mLua->sol())](
|
2022-03-05 19:53:39 +01:00
|
|
|
const CellT& cell, sol::optional<sol::table> type) {
|
|
|
|
ObjectIdList res = std::make_shared<std::vector<ObjectId>>();
|
|
|
|
auto visitor = [&](const MWWorld::Ptr& ptr) {
|
2022-12-23 19:57:12 +01:00
|
|
|
MWBase::Environment::get().getWorldModel()->registerPtr(ptr);
|
2022-07-05 00:53:15 +02:00
|
|
|
if (getLiveCellRefType(ptr.mRef) == ptr.getType())
|
2022-03-05 19:53:39 +01:00
|
|
|
res->push_back(getId(ptr));
|
|
|
|
return true;
|
|
|
|
};
|
|
|
|
|
|
|
|
bool ok = false;
|
|
|
|
sol::optional<uint32_t> typeId = sol::nullopt;
|
|
|
|
if (type.has_value())
|
|
|
|
typeId = ids[*type];
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ok = true;
|
|
|
|
cell.mStore->forEach(std::move(visitor));
|
|
|
|
}
|
|
|
|
if (typeId.has_value())
|
|
|
|
{
|
|
|
|
ok = true;
|
|
|
|
switch (*typeId)
|
|
|
|
{
|
|
|
|
case ESM::REC_INTERNAL_PLAYER:
|
|
|
|
{
|
|
|
|
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
|
|
|
if (player.getCell() == cell.mStore)
|
|
|
|
res->push_back(getId(player));
|
|
|
|
}
|
|
|
|
break;
|
2022-09-22 21:26:05 +03:00
|
|
|
|
2022-03-05 19:53:39 +01:00
|
|
|
case ESM::REC_CREA:
|
|
|
|
cell.mStore->template forEachType<ESM::Creature>(visitor);
|
|
|
|
break;
|
|
|
|
case ESM::REC_NPC_:
|
|
|
|
cell.mStore->template forEachType<ESM::NPC>(visitor);
|
|
|
|
break;
|
|
|
|
case ESM::REC_ACTI:
|
|
|
|
cell.mStore->template forEachType<ESM::Activator>(visitor);
|
|
|
|
break;
|
|
|
|
case ESM::REC_DOOR:
|
|
|
|
cell.mStore->template forEachType<ESM::Door>(visitor);
|
|
|
|
break;
|
|
|
|
case ESM::REC_CONT:
|
|
|
|
cell.mStore->template forEachType<ESM::Container>(visitor);
|
|
|
|
break;
|
2022-09-22 21:26:05 +03:00
|
|
|
|
2022-03-05 19:53:39 +01:00
|
|
|
case ESM::REC_ALCH:
|
|
|
|
cell.mStore->template forEachType<ESM::Potion>(visitor);
|
|
|
|
break;
|
|
|
|
case ESM::REC_ARMO:
|
|
|
|
cell.mStore->template forEachType<ESM::Armor>(visitor);
|
|
|
|
break;
|
|
|
|
case ESM::REC_BOOK:
|
|
|
|
cell.mStore->template forEachType<ESM::Book>(visitor);
|
|
|
|
break;
|
|
|
|
case ESM::REC_CLOT:
|
|
|
|
cell.mStore->template forEachType<ESM::Clothing>(visitor);
|
|
|
|
break;
|
|
|
|
case ESM::REC_INGR:
|
|
|
|
cell.mStore->template forEachType<ESM::Ingredient>(visitor);
|
|
|
|
break;
|
|
|
|
case ESM::REC_LIGH:
|
|
|
|
cell.mStore->template forEachType<ESM::Light>(visitor);
|
|
|
|
break;
|
|
|
|
case ESM::REC_MISC:
|
|
|
|
cell.mStore->template forEachType<ESM::Miscellaneous>(visitor);
|
|
|
|
break;
|
|
|
|
case ESM::REC_WEAP:
|
|
|
|
cell.mStore->template forEachType<ESM::Weapon>(visitor);
|
|
|
|
break;
|
|
|
|
case ESM::REC_APPA:
|
|
|
|
cell.mStore->template forEachType<ESM::Apparatus>(visitor);
|
|
|
|
break;
|
|
|
|
case ESM::REC_LOCK:
|
|
|
|
cell.mStore->template forEachType<ESM::Lockpick>(visitor);
|
|
|
|
break;
|
|
|
|
case ESM::REC_PROB:
|
|
|
|
cell.mStore->template forEachType<ESM::Probe>(visitor);
|
|
|
|
break;
|
|
|
|
case ESM::REC_REPA:
|
|
|
|
cell.mStore->template forEachType<ESM::Repair>(visitor);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ok = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!ok)
|
|
|
|
throw std::runtime_error(
|
|
|
|
std::string("Incorrect type argument in cell:getAll: " + LuaUtil::toString(*type)));
|
|
|
|
return GObjectList{ res };
|
2021-04-17 11:50:20 +02:00
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void initCellBindingsForLocalScripts(const Context& context)
|
|
|
|
{
|
|
|
|
initCellBindings<LCell, LObject>("L", context);
|
|
|
|
}
|
|
|
|
|
|
|
|
void initCellBindingsForGlobalScripts(const Context& context)
|
|
|
|
{
|
|
|
|
initCellBindings<GCell, GObject>("G", context);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|