1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-27 21:35:24 +00:00
OpenMW/apps/openmw/mwclass/activator.cpp
florent.teppe 65cdd489fb create a specific esm reader function for RefID to avoid allocation for string and then again for RefId
Fixed some types

removed useless header

applied clang format

fixed compile tests

fixed clang tidy, and closer to logic before this MR

Removed hardcoded refids

unless there is a returned value we don't use static RefIds
can use == between RefId and hardcoded string

Fix clang format

Fixed a few instances where std::string was used, when only const std::string& was needed

removed unused variable
2022-12-27 19:15:57 +01:00

219 lines
7.6 KiB
C++

#include "activator.hpp"
#include <MyGUI_TextIterator.h>
#include <components/esm3/loadacti.hpp>
#include <components/esm3/loadcrea.hpp>
#include <components/esm3/loadsndg.hpp>
#include <components/esm3/loadsoun.hpp>
#include <components/misc/rng.hpp>
#include <components/sceneutil/positionattitudetransform.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/world.hpp"
#include "../mwworld/action.hpp"
#include "../mwworld/cellstore.hpp"
#include "../mwworld/esmstore.hpp"
#include "../mwworld/failedaction.hpp"
#include "../mwworld/nullaction.hpp"
#include "../mwworld/ptr.hpp"
#include "../mwphysics/physicssystem.hpp"
#include "../mwrender/objects.hpp"
#include "../mwrender/renderinginterface.hpp"
#include "../mwrender/vismask.hpp"
#include "../mwgui/tooltips.hpp"
#include "../mwgui/ustring.hpp"
#include "../mwmechanics/npcstats.hpp"
#include "classmodel.hpp"
namespace MWClass
{
Activator::Activator()
: MWWorld::RegisteredClass<Activator>(ESM::Activator::sRecordId)
{
}
void Activator::insertObjectRendering(
const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const
{
if (!model.empty())
{
renderingInterface.getObjects().insertModel(ptr, model, true);
ptr.getRefData().getBaseNode()->setNodeMask(MWRender::Mask_Static);
}
}
void Activator::insertObject(const MWWorld::Ptr& ptr, const std::string& model, const osg::Quat& rotation,
MWPhysics::PhysicsSystem& physics) const
{
insertObjectPhysics(ptr, model, rotation, physics);
}
void Activator::insertObjectPhysics(const MWWorld::Ptr& ptr, const std::string& model, const osg::Quat& rotation,
MWPhysics::PhysicsSystem& physics) const
{
physics.addObject(ptr, model, rotation, MWPhysics::CollisionType_World);
}
std::string Activator::getModel(const MWWorld::ConstPtr& ptr) const
{
return getClassModel<ESM::Activator>(ptr);
}
bool Activator::isActivator() const
{
return true;
}
bool Activator::useAnim() const
{
return true;
}
std::string_view Activator::getName(const MWWorld::ConstPtr& ptr) const
{
const MWWorld::LiveCellRef<ESM::Activator>* ref = ptr.get<ESM::Activator>();
return ref->mBase->mName;
}
const ESM::RefId& Activator::getScript(const MWWorld::ConstPtr& ptr) const
{
const MWWorld::LiveCellRef<ESM::Activator>* ref = ptr.get<ESM::Activator>();
return ref->mBase->mScript;
}
bool Activator::hasToolTip(const MWWorld::ConstPtr& ptr) const
{
return !getName(ptr).empty();
}
MWGui::ToolTipInfo Activator::getToolTipInfo(const MWWorld::ConstPtr& ptr, int count) const
{
const MWWorld::LiveCellRef<ESM::Activator>* ref = ptr.get<ESM::Activator>();
MWGui::ToolTipInfo info;
std::string_view name = getName(ptr);
info.caption
= MyGUI::TextIterator::toTagsString(MWGui::toUString(name)) + MWGui::ToolTips::getCountString(count);
std::string text;
if (MWBase::Environment::get().getWindowManager()->getFullHelp())
{
text += MWGui::ToolTips::getCellRefString(ptr.getCellRef());
text += MWGui::ToolTips::getMiscString(ref->mBase->mScript.getRefIdString(), "Script");
}
info.text = text;
return info;
}
std::unique_ptr<MWWorld::Action> Activator::activate(const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const
{
if (actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf())
{
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
const ESM::Sound* sound = store.get<ESM::Sound>().searchRandom("WolfActivator", prng);
std::unique_ptr<MWWorld::Action> action = std::make_unique<MWWorld::FailedAction>("#{sWerewolfRefusal}");
if (sound)
action->setSound(sound->mId);
return action;
}
return std::make_unique<MWWorld::NullAction>();
}
MWWorld::Ptr Activator::copyToCellImpl(const MWWorld::ConstPtr& ptr, MWWorld::CellStore& cell) const
{
const MWWorld::LiveCellRef<ESM::Activator>* ref = ptr.get<ESM::Activator>();
return MWWorld::Ptr(cell.insert(ref), &cell);
}
const ESM::RefId& Activator::getSoundIdFromSndGen(const MWWorld::Ptr& ptr, std::string_view name) const
{
const std::string model
= getModel(ptr); // Assume it's not empty, since we wouldn't have gotten the soundgen otherwise
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
const ESM::RefId* creatureId = nullptr;
const VFS::Manager* const vfs = MWBase::Environment::get().getResourceSystem()->getVFS();
for (const ESM::Creature& iter : store.get<ESM::Creature>())
{
if (!iter.mModel.empty()
&& Misc::StringUtils::ciEqual(model, Misc::ResourceHelpers::correctMeshPath(iter.mModel, vfs)))
{
creatureId = !iter.mOriginal.empty() ? &iter.mOriginal : &iter.mId;
break;
}
}
int type = getSndGenTypeFromName(name);
std::vector<const ESM::SoundGenerator*> fallbacksounds;
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
if (creatureId && !creatureId->empty())
{
std::vector<const ESM::SoundGenerator*> sounds;
for (auto sound = store.get<ESM::SoundGenerator>().begin(); sound != store.get<ESM::SoundGenerator>().end();
++sound)
{
if (type == sound->mType && !sound->mCreature.empty() && (*creatureId == sound->mCreature))
sounds.push_back(&*sound);
if (type == sound->mType && sound->mCreature.empty())
fallbacksounds.push_back(&*sound);
}
if (!sounds.empty())
return sounds[Misc::Rng::rollDice(sounds.size(), prng)]->mSound;
if (!fallbacksounds.empty())
return fallbacksounds[Misc::Rng::rollDice(fallbacksounds.size(), prng)]->mSound;
}
else
{
// The activator doesn't have a corresponding creature ID, but we can try to use the defaults
for (auto sound = store.get<ESM::SoundGenerator>().begin(); sound != store.get<ESM::SoundGenerator>().end();
++sound)
if (type == sound->mType && sound->mCreature.empty())
fallbacksounds.push_back(&*sound);
if (!fallbacksounds.empty())
return fallbacksounds[Misc::Rng::rollDice(fallbacksounds.size(), prng)]->mSound;
}
return ESM::RefId::sEmpty;
}
int Activator::getSndGenTypeFromName(std::string_view name)
{
if (name == "left")
return ESM::SoundGenerator::LeftFoot;
if (name == "right")
return ESM::SoundGenerator::RightFoot;
if (name == "swimleft")
return ESM::SoundGenerator::SwimLeft;
if (name == "swimright")
return ESM::SoundGenerator::SwimRight;
if (name == "moan")
return ESM::SoundGenerator::Moan;
if (name == "roar")
return ESM::SoundGenerator::Roar;
if (name == "scream")
return ESM::SoundGenerator::Scream;
if (name == "land")
return ESM::SoundGenerator::Land;
throw std::runtime_error("Unexpected soundgen type: " + std::string(name));
}
}