mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-19 15:39:49 +00:00
Implement onNewExterior to spawn fish in generated exteriors
This commit is contained in:
parent
e35bf97603
commit
f02dd0ef03
9 changed files with 102 additions and 8 deletions
|
@ -11,6 +11,7 @@
|
|||
|
||||
namespace MWWorld
|
||||
{
|
||||
class CellStore;
|
||||
class Ptr;
|
||||
}
|
||||
|
||||
|
@ -47,6 +48,7 @@ namespace MWBase
|
|||
virtual void objectRemovedFromScene(const MWWorld::Ptr& ptr) = 0;
|
||||
virtual void itemConsumed(const MWWorld::Ptr& consumable, const MWWorld::Ptr& actor) = 0;
|
||||
virtual void objectActivated(const MWWorld::Ptr& object, const MWWorld::Ptr& actor) = 0;
|
||||
virtual void exteriorCreated(MWWorld::CellStore& cell) = 0;
|
||||
// TODO: notify LuaManager about other events
|
||||
// virtual void objectOnHit(const MWWorld::Ptr &ptr, float damage, bool ishealth, const MWWorld::Ptr &object,
|
||||
// const MWWorld::Ptr &attacker, const osg::Vec3f &hitPosition, bool successful) = 0;
|
||||
|
|
|
@ -71,6 +71,8 @@ namespace MWLua
|
|||
scripts->onConsume(LObject(consumable));
|
||||
}
|
||||
|
||||
void operator()(const OnNewExterior& event) const { mGlobalScripts.onNewExterior(GCell{ &event.mCell }); }
|
||||
|
||||
private:
|
||||
MWWorld::Ptr getPtr(const ESM::RefNum& id) const
|
||||
{
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
#include <components/esm3/cellref.hpp> // defines RefNum that is used as a unique id
|
||||
|
||||
#include "../mwworld/cellstore.hpp"
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
class GlobalScripts;
|
||||
|
@ -38,7 +40,11 @@ namespace MWLua
|
|||
ESM::RefNum mActor;
|
||||
ESM::RefNum mConsumable;
|
||||
};
|
||||
using Event = std::variant<OnNewGame, OnActive, OnInactive, OnConsume, OnActivate>;
|
||||
struct OnNewExterior
|
||||
{
|
||||
MWWorld::CellStore& mCell;
|
||||
};
|
||||
using Event = std::variant<OnNewGame, OnActive, OnInactive, OnConsume, OnActivate, OnNewExterior>;
|
||||
|
||||
void clear() { mQueue.clear(); }
|
||||
void addToQueue(Event e) { mQueue.push_back(std::move(e)); }
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace MWLua
|
|||
: LuaUtil::ScriptsContainer(lua, "Global")
|
||||
{
|
||||
registerEngineHandlers({ &mObjectActiveHandlers, &mActorActiveHandlers, &mItemActiveHandlers,
|
||||
&mNewGameHandlers, &mPlayerAddedHandlers, &mOnActivateHandlers });
|
||||
&mNewGameHandlers, &mPlayerAddedHandlers, &mOnActivateHandlers, &mOnNewExteriorHandlers });
|
||||
}
|
||||
|
||||
void newGameStarted() { callEngineHandlers(mNewGameHandlers); }
|
||||
|
@ -32,6 +32,7 @@ namespace MWLua
|
|||
{
|
||||
callEngineHandlers(mOnActivateHandlers, obj, actor);
|
||||
}
|
||||
void onNewExterior(const GCell& cell) { callEngineHandlers(mOnNewExteriorHandlers, cell); }
|
||||
|
||||
private:
|
||||
EngineHandlerList mObjectActiveHandlers{ "onObjectActive" };
|
||||
|
@ -40,6 +41,7 @@ namespace MWLua
|
|||
EngineHandlerList mNewGameHandlers{ "onNewGame" };
|
||||
EngineHandlerList mPlayerAddedHandlers{ "onPlayerAdded" };
|
||||
EngineHandlerList mOnActivateHandlers{ "onActivate" };
|
||||
EngineHandlerList mOnNewExteriorHandlers{ "onNewExterior" };
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -71,6 +71,10 @@ namespace MWLua
|
|||
{
|
||||
mEngineEvents.addToQueue(EngineEvents::OnActivate{ getId(actor), getId(object) });
|
||||
}
|
||||
void exteriorCreated(MWWorld::CellStore& cell) override
|
||||
{
|
||||
mEngineEvents.addToQueue(EngineEvents::OnNewExterior{ cell });
|
||||
}
|
||||
|
||||
MWBase::LuaManager::ActorControls* getActorControls(const MWWorld::Ptr&) const override;
|
||||
|
||||
|
|
|
@ -19,6 +19,9 @@
|
|||
#include "cellstore.hpp"
|
||||
#include "esmstore.hpp"
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/luamanager.hpp"
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
namespace
|
||||
|
@ -55,7 +58,7 @@ namespace MWWorld
|
|||
return store.insert(record);
|
||||
}
|
||||
|
||||
Cell createExteriorCell(ESM::ExteriorCellLocation location, ESMStore& store)
|
||||
std::tuple<Cell, bool> createExteriorCell(ESM::ExteriorCellLocation location, ESMStore& store)
|
||||
{
|
||||
if (ESM::isEsm4Ext(location.mWorldspace))
|
||||
{
|
||||
|
@ -63,17 +66,19 @@ namespace MWWorld
|
|||
throw std::runtime_error(
|
||||
"Exterior ESM4 world is not found: " + location.mWorldspace.toDebugString());
|
||||
const ESM4::Cell* cell = store.get<ESM4::Cell>().searchExterior(location);
|
||||
if (cell == nullptr)
|
||||
bool created = cell == nullptr;
|
||||
if (created)
|
||||
cell = createEsm4Cell(location, store);
|
||||
assert(cell != nullptr);
|
||||
return MWWorld::Cell(*cell);
|
||||
return { MWWorld::Cell(*cell), created };
|
||||
}
|
||||
|
||||
const ESM::Cell* cell = store.get<ESM::Cell>().search(location.mX, location.mY);
|
||||
if (cell == nullptr)
|
||||
bool created = cell == nullptr;
|
||||
if (created)
|
||||
cell = createEsmCell(location, store);
|
||||
assert(cell != nullptr);
|
||||
return Cell(*cell);
|
||||
return { Cell(*cell), created };
|
||||
}
|
||||
|
||||
std::optional<Cell> createCell(ESM::RefId id, const ESMStore& store)
|
||||
|
@ -165,10 +170,12 @@ namespace MWWorld
|
|||
|
||||
if (it == mExteriors.end())
|
||||
{
|
||||
Cell cell = createExteriorCell(location, mStore);
|
||||
auto [cell, created] = createExteriorCell(location, mStore);
|
||||
const ESM::RefId id = cell.getId();
|
||||
cellStore = &emplaceCellStore(id, std::move(cell), mStore, mReaders, mCells);
|
||||
mExteriors.emplace(location, cellStore);
|
||||
if (created)
|
||||
MWBase::Environment::get().getLuaManager()->exteriorCreated(*cellStore);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -65,6 +65,7 @@ set(BUILTIN_DATA_FILES
|
|||
|
||||
scripts/omw/activationhandlers.lua
|
||||
scripts/omw/ai.lua
|
||||
scripts/omw/cellhandlers.lua
|
||||
scripts/omw/camera/camera.lua
|
||||
scripts/omw/camera/head_bobbing.lua
|
||||
scripts/omw/camera/third_person.lua
|
||||
|
|
|
@ -7,6 +7,7 @@ PLAYER: scripts/omw/settings/player.lua
|
|||
|
||||
# Mechanics
|
||||
GLOBAL: scripts/omw/activationhandlers.lua
|
||||
GLOBAL: scripts/omw/cellhandlers.lua
|
||||
PLAYER: scripts/omw/mechanics/playercontroller.lua
|
||||
PLAYER: scripts/omw/playercontrols.lua
|
||||
PLAYER: scripts/omw/camera/camera.lua
|
||||
|
|
69
files/data/scripts/omw/cellhandlers.lua
Normal file
69
files/data/scripts/omw/cellhandlers.lua
Normal file
|
@ -0,0 +1,69 @@
|
|||
local types = require('openmw.types')
|
||||
local util = require('openmw.util')
|
||||
local world = require('openmw.world')
|
||||
|
||||
local CELL_SIZE = 8192
|
||||
|
||||
local function getRandomPosition(cellX, cellY)
|
||||
local x = math.random(7892)
|
||||
local y = math.random(7892)
|
||||
local z = -math.random(1748)
|
||||
return util.vector3(cellX + x, cellY + y, z)
|
||||
end
|
||||
|
||||
local function getRandomOffset()
|
||||
local x = math.random(1000)
|
||||
local y = math.random(1000)
|
||||
local z = math.random(1000)
|
||||
local v = util.vector3(x, y, z)
|
||||
return v:normalize() * 100
|
||||
end
|
||||
|
||||
local function getPlayerLevel()
|
||||
for i, actor in pairs(world.activeActors) do
|
||||
if (types.Player.objectIsInstance(actor)) then
|
||||
return types.Player.stats.level(actor).current
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function spawnFish(cell)
|
||||
if (cell.worldSpaceId ~= 'sys::default') then
|
||||
return
|
||||
end
|
||||
local spawnCount = math.random(0, 10)
|
||||
if (spawnCount < 1) then
|
||||
return
|
||||
end
|
||||
local list = types.LevelledCreature.record('h2o_all_lev-2')
|
||||
if (list == nil) then
|
||||
return
|
||||
end
|
||||
local cellX = cell.gridX * CELL_SIZE
|
||||
local cellY = cell.gridY * CELL_SIZE
|
||||
local level = getPlayerLevel()
|
||||
if (spawnCount <= 5) then -- spawn a number of random creatures selected from the list
|
||||
while(spawnCount > 0) do
|
||||
local id = list:getRandomId(level)
|
||||
if (id ~= '') then
|
||||
local ref = world.createObject(id)
|
||||
ref:teleport(cell, getRandomPosition(cellX, cellY))
|
||||
end
|
||||
spawnCount = spawnCount - 1
|
||||
end
|
||||
else -- spawn a horde of a single creature selected from the list
|
||||
local id = list:getRandomId(level)
|
||||
if (id ~= '') then
|
||||
local basePos = getRandomPosition(cellX, cellY)
|
||||
while(spawnCount > 0) do
|
||||
local ref = world.createObject(id)
|
||||
ref:teleport(cell, basePos + getRandomOffset())
|
||||
spawnCount = spawnCount - 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return {
|
||||
engineHandlers = { onNewExterior = spawnFish }
|
||||
}
|
Loading…
Reference in a new issue