1 #include "misc.hpp" 2 3 #include <components/esm/loadmisc.hpp> 4 #include <components/settings/settings.hpp> 5 6 #include "../mwbase/environment.hpp" 7 #include "../mwbase/world.hpp" 8 #include "../mwbase/windowmanager.hpp" 9 10 #include "../mwworld/cellstore.hpp" 11 #include "../mwworld/esmstore.hpp" 12 #include "../mwphysics/physicssystem.hpp" 13 #include "../mwworld/manualref.hpp" 14 #include "../mwworld/nullaction.hpp" 15 #include "../mwworld/actionsoulgem.hpp" 16 17 #include "../mwgui/tooltips.hpp" 18 19 #include "../mwrender/objects.hpp" 20 #include "../mwrender/renderinginterface.hpp" 21 22 namespace MWClass 23 { isGold(const MWWorld::ConstPtr & ptr) const24 bool Miscellaneous::isGold (const MWWorld::ConstPtr& ptr) const 25 { 26 return Misc::StringUtils::ciEqual(ptr.getCellRef().getRefId(), "gold_001") 27 || Misc::StringUtils::ciEqual(ptr.getCellRef().getRefId(), "gold_005") 28 || Misc::StringUtils::ciEqual(ptr.getCellRef().getRefId(), "gold_010") 29 || Misc::StringUtils::ciEqual(ptr.getCellRef().getRefId(), "gold_025") 30 || Misc::StringUtils::ciEqual(ptr.getCellRef().getRefId(), "gold_100"); 31 } 32 insertObjectRendering(const MWWorld::Ptr & ptr,const std::string & model,MWRender::RenderingInterface & renderingInterface) const33 void Miscellaneous::insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const 34 { 35 if (!model.empty()) { 36 renderingInterface.getObjects().insertModel(ptr, model); 37 } 38 } 39 insertObject(const MWWorld::Ptr & ptr,const std::string & model,MWPhysics::PhysicsSystem & physics) const40 void Miscellaneous::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const 41 { 42 // TODO: add option somewhere to enable collision for placeable objects 43 } 44 getModel(const MWWorld::ConstPtr & ptr) const45 std::string Miscellaneous::getModel(const MWWorld::ConstPtr &ptr) const 46 { 47 const MWWorld::LiveCellRef<ESM::Miscellaneous> *ref = ptr.get<ESM::Miscellaneous>(); 48 49 const std::string &model = ref->mBase->mModel; 50 if (!model.empty()) { 51 return "meshes\\" + model; 52 } 53 return ""; 54 } 55 getName(const MWWorld::ConstPtr & ptr) const56 std::string Miscellaneous::getName (const MWWorld::ConstPtr& ptr) const 57 { 58 const MWWorld::LiveCellRef<ESM::Miscellaneous> *ref = ptr.get<ESM::Miscellaneous>(); 59 const std::string& name = ref->mBase->mName; 60 61 return !name.empty() ? name : ref->mBase->mId; 62 } 63 activate(const MWWorld::Ptr & ptr,const MWWorld::Ptr & actor) const64 std::shared_ptr<MWWorld::Action> Miscellaneous::activate (const MWWorld::Ptr& ptr, 65 const MWWorld::Ptr& actor) const 66 { 67 return defaultItemActivate(ptr, actor); 68 } 69 getScript(const MWWorld::ConstPtr & ptr) const70 std::string Miscellaneous::getScript (const MWWorld::ConstPtr& ptr) const 71 { 72 const MWWorld::LiveCellRef<ESM::Miscellaneous> *ref = ptr.get<ESM::Miscellaneous>(); 73 74 return ref->mBase->mScript; 75 } 76 getValue(const MWWorld::ConstPtr & ptr) const77 int Miscellaneous::getValue (const MWWorld::ConstPtr& ptr) const 78 { 79 const MWWorld::LiveCellRef<ESM::Miscellaneous> *ref = ptr.get<ESM::Miscellaneous>(); 80 81 int value = ref->mBase->mData.mValue; 82 if (ptr.getCellRef().getGoldValue() > 1 && ptr.getRefData().getCount() == 1) 83 value = ptr.getCellRef().getGoldValue(); 84 85 if (ptr.getCellRef().getSoul() != "") 86 { 87 const ESM::Creature *creature = MWBase::Environment::get().getWorld()->getStore().get<ESM::Creature>().search(ref->mRef.getSoul()); 88 if (creature) 89 { 90 int soul = creature->mData.mSoul; 91 if (Settings::Manager::getBool("rebalance soul gem values", "Game")) 92 { 93 // use the 'soul gem value rebalance' formula from the Morrowind Code Patch 94 float soulValue = 0.0001 * pow(soul, 3) + 2 * soul; 95 96 // for Azura's star add the unfilled value 97 if (Misc::StringUtils::ciEqual(ptr.getCellRef().getRefId(), "Misc_SoulGem_Azura")) 98 value += soulValue; 99 else 100 value = soulValue; 101 } 102 else 103 value *= soul; 104 } 105 } 106 107 return value; 108 } 109 registerSelf()110 void Miscellaneous::registerSelf() 111 { 112 std::shared_ptr<Class> instance (new Miscellaneous); 113 114 registerClass (typeid (ESM::Miscellaneous).name(), instance); 115 } 116 getUpSoundId(const MWWorld::ConstPtr & ptr) const117 std::string Miscellaneous::getUpSoundId (const MWWorld::ConstPtr& ptr) const 118 { 119 if (isGold(ptr)) 120 return std::string("Item Gold Up"); 121 return std::string("Item Misc Up"); 122 } 123 getDownSoundId(const MWWorld::ConstPtr & ptr) const124 std::string Miscellaneous::getDownSoundId (const MWWorld::ConstPtr& ptr) const 125 { 126 if (isGold(ptr)) 127 return std::string("Item Gold Down"); 128 return std::string("Item Misc Down"); 129 } 130 getInventoryIcon(const MWWorld::ConstPtr & ptr) const131 std::string Miscellaneous::getInventoryIcon (const MWWorld::ConstPtr& ptr) const 132 { 133 const MWWorld::LiveCellRef<ESM::Miscellaneous> *ref = ptr.get<ESM::Miscellaneous>(); 134 135 return ref->mBase->mIcon; 136 } 137 getToolTipInfo(const MWWorld::ConstPtr & ptr,int count) const138 MWGui::ToolTipInfo Miscellaneous::getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const 139 { 140 const MWWorld::LiveCellRef<ESM::Miscellaneous> *ref = ptr.get<ESM::Miscellaneous>(); 141 142 MWGui::ToolTipInfo info; 143 144 bool gold = isGold(ptr); 145 if (gold) 146 count *= getValue(ptr); 147 148 std::string countString; 149 if (!gold) 150 countString = MWGui::ToolTips::getCountString(count); 151 else // gold displays its count also if it's 1. 152 countString = " (" + std::to_string(count) + ")"; 153 154 info.caption = MyGUI::TextIterator::toTagsString(getName(ptr)) + countString + MWGui::ToolTips::getSoulString(ptr.getCellRef()); 155 info.icon = ref->mBase->mIcon; 156 157 std::string text; 158 159 text += MWGui::ToolTips::getWeightString(ref->mBase->mData.mWeight, "#{sWeight}"); 160 if (!gold && !ref->mBase->mData.mIsKey) 161 text += MWGui::ToolTips::getValueString(getValue(ptr), "#{sValue}"); 162 163 if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { 164 text += MWGui::ToolTips::getCellRefString(ptr.getCellRef()); 165 text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script"); 166 } 167 168 info.text = text; 169 170 return info; 171 } 172 copyToCell(const MWWorld::ConstPtr & ptr,MWWorld::CellStore & cell,int count) const173 MWWorld::Ptr Miscellaneous::copyToCell(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell, int count) const 174 { 175 MWWorld::Ptr newPtr; 176 177 const MWWorld::ESMStore &store = 178 MWBase::Environment::get().getWorld()->getStore(); 179 180 if (isGold(ptr)) { 181 int goldAmount = getValue(ptr) * count; 182 183 std::string base = "Gold_001"; 184 if (goldAmount >= 100) 185 base = "Gold_100"; 186 else if (goldAmount >= 25) 187 base = "Gold_025"; 188 else if (goldAmount >= 10) 189 base = "Gold_010"; 190 else if (goldAmount >= 5) 191 base = "Gold_005"; 192 193 // Really, I have no idea why moving ref out of conditional 194 // scope causes list::push_back throwing std::bad_alloc 195 MWWorld::ManualRef newRef(store, base); 196 const MWWorld::LiveCellRef<ESM::Miscellaneous> *ref = 197 newRef.getPtr().get<ESM::Miscellaneous>(); 198 199 newPtr = MWWorld::Ptr(cell.insert(ref), &cell); 200 newPtr.getCellRef().setGoldValue(goldAmount); 201 newPtr.getRefData().setCount(1); 202 } else { 203 const MWWorld::LiveCellRef<ESM::Miscellaneous> *ref = 204 ptr.get<ESM::Miscellaneous>(); 205 newPtr = MWWorld::Ptr(cell.insert(ref), &cell); 206 newPtr.getRefData().setCount(count); 207 } 208 newPtr.getCellRef().unsetRefNum(); 209 210 return newPtr; 211 } 212 use(const MWWorld::Ptr & ptr,bool force) const213 std::shared_ptr<MWWorld::Action> Miscellaneous::use (const MWWorld::Ptr& ptr, bool force) const 214 { 215 if (ptr.getCellRef().getSoul().empty() || !MWBase::Environment::get().getWorld()->getStore().get<ESM::Creature>().search(ptr.getCellRef().getSoul())) 216 return std::shared_ptr<MWWorld::Action>(new MWWorld::NullAction()); 217 else 218 return std::shared_ptr<MWWorld::Action>(new MWWorld::ActionSoulgem(ptr)); 219 } 220 canSell(const MWWorld::ConstPtr & item,int npcServices) const221 bool Miscellaneous::canSell (const MWWorld::ConstPtr& item, int npcServices) const 222 { 223 const MWWorld::LiveCellRef<ESM::Miscellaneous> *ref = item.get<ESM::Miscellaneous>(); 224 225 return !ref->mBase->mData.mIsKey && (npcServices & ESM::NPC::Misc) && !isGold(item); 226 } 227 getWeight(const MWWorld::ConstPtr & ptr) const228 float Miscellaneous::getWeight(const MWWorld::ConstPtr &ptr) const 229 { 230 const MWWorld::LiveCellRef<ESM::Miscellaneous> *ref = ptr.get<ESM::Miscellaneous>(); 231 return ref->mBase->mData.mWeight; 232 } 233 isKey(const MWWorld::ConstPtr & ptr) const234 bool Miscellaneous::isKey(const MWWorld::ConstPtr &ptr) const 235 { 236 const MWWorld::LiveCellRef<ESM::Miscellaneous> *ref = ptr.get<ESM::Miscellaneous>(); 237 return ref->mBase->mData.mIsKey != 0; 238 } 239 240 } 241