1 #include "activator.hpp" 2 3 #include <components/esm/loadacti.hpp> 4 #include <components/misc/rng.hpp> 5 #include <components/sceneutil/positionattitudetransform.hpp> 6 7 #include "../mwbase/environment.hpp" 8 #include "../mwbase/windowmanager.hpp" 9 #include "../mwbase/world.hpp" 10 11 #include "../mwworld/cellstore.hpp" 12 #include "../mwworld/esmstore.hpp" 13 #include "../mwworld/ptr.hpp" 14 #include "../mwworld/action.hpp" 15 #include "../mwworld/failedaction.hpp" 16 #include "../mwworld/nullaction.hpp" 17 18 #include "../mwphysics/physicssystem.hpp" 19 20 #include "../mwrender/objects.hpp" 21 #include "../mwrender/renderinginterface.hpp" 22 #include "../mwrender/vismask.hpp" 23 24 #include "../mwgui/tooltips.hpp" 25 26 #include "../mwmechanics/npcstats.hpp" 27 28 29 namespace MWClass 30 { 31 insertObjectRendering(const MWWorld::Ptr & ptr,const std::string & model,MWRender::RenderingInterface & renderingInterface) const32 void Activator::insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const 33 { 34 if (!model.empty()) 35 { 36 renderingInterface.getObjects().insertModel(ptr, model, true); 37 ptr.getRefData().getBaseNode()->setNodeMask(MWRender::Mask_Static); 38 } 39 } 40 insertObject(const MWWorld::Ptr & ptr,const std::string & model,MWPhysics::PhysicsSystem & physics) const41 void Activator::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const 42 { 43 if(!model.empty()) 44 physics.addObject(ptr, model); 45 } 46 getModel(const MWWorld::ConstPtr & ptr) const47 std::string Activator::getModel(const MWWorld::ConstPtr &ptr) const 48 { 49 const MWWorld::LiveCellRef<ESM::Activator> *ref = ptr.get<ESM::Activator>(); 50 51 const std::string &model = ref->mBase->mModel; 52 if (!model.empty()) { 53 return "meshes\\" + model; 54 } 55 return ""; 56 } 57 isActivator() const58 bool Activator::isActivator() const 59 { 60 return true; 61 } 62 useAnim() const63 bool Activator::useAnim() const 64 { 65 return true; 66 } 67 getName(const MWWorld::ConstPtr & ptr) const68 std::string Activator::getName (const MWWorld::ConstPtr& ptr) const 69 { 70 const MWWorld::LiveCellRef<ESM::Activator> *ref = ptr.get<ESM::Activator>(); 71 72 return ref->mBase->mName; 73 } 74 getScript(const MWWorld::ConstPtr & ptr) const75 std::string Activator::getScript (const MWWorld::ConstPtr& ptr) const 76 { 77 const MWWorld::LiveCellRef<ESM::Activator> *ref = 78 ptr.get<ESM::Activator>(); 79 80 return ref->mBase->mScript; 81 } 82 registerSelf()83 void Activator::registerSelf() 84 { 85 std::shared_ptr<Class> instance (new Activator); 86 87 registerClass (typeid (ESM::Activator).name(), instance); 88 } 89 hasToolTip(const MWWorld::ConstPtr & ptr) const90 bool Activator::hasToolTip (const MWWorld::ConstPtr& ptr) const 91 { 92 return !getName(ptr).empty(); 93 } 94 allowTelekinesis(const MWWorld::ConstPtr & ptr) const95 bool Activator::allowTelekinesis(const MWWorld::ConstPtr &ptr) const { 96 return false; 97 } 98 getToolTipInfo(const MWWorld::ConstPtr & ptr,int count) const99 MWGui::ToolTipInfo Activator::getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const 100 { 101 const MWWorld::LiveCellRef<ESM::Activator> *ref = ptr.get<ESM::Activator>(); 102 103 MWGui::ToolTipInfo info; 104 info.caption = MyGUI::TextIterator::toTagsString(getName(ptr)) + MWGui::ToolTips::getCountString(count); 105 106 std::string text; 107 if (MWBase::Environment::get().getWindowManager()->getFullHelp()) 108 { 109 text += MWGui::ToolTips::getCellRefString(ptr.getCellRef()); 110 text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script"); 111 } 112 info.text = text; 113 114 return info; 115 } 116 activate(const MWWorld::Ptr & ptr,const MWWorld::Ptr & actor) const117 std::shared_ptr<MWWorld::Action> Activator::activate(const MWWorld::Ptr &ptr, const MWWorld::Ptr &actor) const 118 { 119 if(actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf()) 120 { 121 const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); 122 const ESM::Sound *sound = store.get<ESM::Sound>().searchRandom("WolfActivator"); 123 124 std::shared_ptr<MWWorld::Action> action(new MWWorld::FailedAction("#{sWerewolfRefusal}")); 125 if(sound) action->setSound(sound->mId); 126 127 return action; 128 } 129 return std::shared_ptr<MWWorld::Action>(new MWWorld::NullAction); 130 } 131 132 copyToCellImpl(const MWWorld::ConstPtr & ptr,MWWorld::CellStore & cell) const133 MWWorld::Ptr Activator::copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const 134 { 135 const MWWorld::LiveCellRef<ESM::Activator> *ref = ptr.get<ESM::Activator>(); 136 137 return MWWorld::Ptr(cell.insert(ref), &cell); 138 } 139 getSoundIdFromSndGen(const MWWorld::Ptr & ptr,const std::string & name) const140 std::string Activator::getSoundIdFromSndGen(const MWWorld::Ptr &ptr, const std::string &name) const 141 { 142 const std::string model = getModel(ptr); // Assume it's not empty, since we wouldn't have gotten the soundgen otherwise 143 const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); 144 std::string creatureId; 145 146 for (const ESM::Creature &iter : store.get<ESM::Creature>()) 147 { 148 if (!iter.mModel.empty() && Misc::StringUtils::ciEqual(model, "meshes\\" + iter.mModel)) 149 { 150 creatureId = !iter.mOriginal.empty() ? iter.mOriginal : iter.mId; 151 break; 152 } 153 } 154 155 int type = getSndGenTypeFromName(name); 156 157 std::vector<const ESM::SoundGenerator*> fallbacksounds; 158 if (!creatureId.empty()) 159 { 160 std::vector<const ESM::SoundGenerator*> sounds; 161 for (auto sound = store.get<ESM::SoundGenerator>().begin(); sound != store.get<ESM::SoundGenerator>().end(); ++sound) 162 { 163 if (type == sound->mType && !sound->mCreature.empty() && (Misc::StringUtils::ciEqual(creatureId, sound->mCreature))) 164 sounds.push_back(&*sound); 165 if (type == sound->mType && sound->mCreature.empty()) 166 fallbacksounds.push_back(&*sound); 167 } 168 169 if (!sounds.empty()) 170 return sounds[Misc::Rng::rollDice(sounds.size())]->mSound; 171 if (!fallbacksounds.empty()) 172 return fallbacksounds[Misc::Rng::rollDice(fallbacksounds.size())]->mSound; 173 } 174 else 175 { 176 // The activator doesn't have a corresponding creature ID, but we can try to use the defaults 177 for (auto sound = store.get<ESM::SoundGenerator>().begin(); sound != store.get<ESM::SoundGenerator>().end(); ++sound) 178 if (type == sound->mType && sound->mCreature.empty()) 179 fallbacksounds.push_back(&*sound); 180 181 if (!fallbacksounds.empty()) 182 return fallbacksounds[Misc::Rng::rollDice(fallbacksounds.size())]->mSound; 183 } 184 185 return std::string(); 186 } 187 getSndGenTypeFromName(const std::string & name)188 int Activator::getSndGenTypeFromName(const std::string &name) 189 { 190 if (name == "left") 191 return ESM::SoundGenerator::LeftFoot; 192 if (name == "right") 193 return ESM::SoundGenerator::RightFoot; 194 if (name == "swimleft") 195 return ESM::SoundGenerator::SwimLeft; 196 if (name == "swimright") 197 return ESM::SoundGenerator::SwimRight; 198 if (name == "moan") 199 return ESM::SoundGenerator::Moan; 200 if (name == "roar") 201 return ESM::SoundGenerator::Roar; 202 if (name == "scream") 203 return ESM::SoundGenerator::Scream; 204 if (name == "land") 205 return ESM::SoundGenerator::Land; 206 207 throw std::runtime_error(std::string("Unexpected soundgen type: ")+name); 208 } 209 } 210