1 #include "levelupdialog.hpp" 2 3 #include <MyGUI_Button.h> 4 #include <MyGUI_ImageBox.h> 5 #include <MyGUI_EditBox.h> 6 7 #include <components/fallback/fallback.hpp> 8 9 #include "../mwbase/windowmanager.hpp" 10 #include "../mwbase/environment.hpp" 11 #include "../mwbase/world.hpp" 12 #include "../mwbase/soundmanager.hpp" 13 14 #include "../mwworld/class.hpp" 15 16 #include "../mwmechanics/creaturestats.hpp" 17 #include "../mwmechanics/npcstats.hpp" 18 #include "../mwmechanics/actorutil.hpp" 19 20 #include "class.hpp" 21 22 namespace MWGui 23 { 24 const unsigned int LevelupDialog::sMaxCoins = 3; LevelupDialog()25 LevelupDialog::LevelupDialog() 26 : WindowBase("openmw_levelup_dialog.layout"), 27 mCoinCount(sMaxCoins) 28 { 29 getWidget(mOkButton, "OkButton"); 30 getWidget(mClassImage, "ClassImage"); 31 getWidget(mLevelText, "LevelText"); 32 getWidget(mLevelDescription, "LevelDescription"); 33 getWidget(mCoinBox, "Coins"); 34 getWidget(mAssignWidget, "AssignWidget"); 35 36 mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &LevelupDialog::onOkButtonClicked); 37 38 for (int i=1; i<9; ++i) 39 { 40 MyGUI::TextBox* t; 41 getWidget(t, "AttribVal" + MyGUI::utility::toString(i)); 42 mAttributeValues.push_back(t); 43 44 MyGUI::Button* b; 45 getWidget(b, "Attrib" + MyGUI::utility::toString(i)); 46 b->setUserData (i-1); 47 b->eventMouseButtonClick += MyGUI::newDelegate(this, &LevelupDialog::onAttributeClicked); 48 mAttributes.push_back(b); 49 50 getWidget(t, "AttribMultiplier" + MyGUI::utility::toString(i)); 51 mAttributeMultipliers.push_back(t); 52 } 53 54 for (unsigned int i = 0; i < mCoinCount; ++i) 55 { 56 MyGUI::ImageBox* image = mCoinBox->createWidget<MyGUI::ImageBox>("ImageBox", MyGUI::IntCoord(0,0,16,16), MyGUI::Align::Default); 57 image->setImageTexture ("icons\\tx_goldicon.dds"); 58 mCoins.push_back(image); 59 } 60 61 center(); 62 } 63 setAttributeValues()64 void LevelupDialog::setAttributeValues() 65 { 66 MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr(); 67 MWMechanics::CreatureStats& creatureStats = player.getClass().getCreatureStats(player); 68 MWMechanics::NpcStats& pcStats = player.getClass().getNpcStats (player); 69 70 for (int i = 0; i < 8; ++i) 71 { 72 int val = creatureStats.getAttribute(i).getBase(); 73 if (std::find(mSpentAttributes.begin(), mSpentAttributes.end(), i) != mSpentAttributes.end()) 74 { 75 val += pcStats.getLevelupAttributeMultiplier(i); 76 } 77 78 if (val >= 100) 79 val = 100; 80 81 mAttributeValues[i]->setCaption(MyGUI::utility::toString(val)); 82 } 83 } 84 85 resetCoins()86 void LevelupDialog::resetCoins() 87 { 88 const int coinSpacing = 33; 89 int curX = mCoinBox->getWidth()/2 - (coinSpacing*(mCoinCount - 1) + 16*mCoinCount)/2; 90 for (unsigned int i=0; i<sMaxCoins; ++i) 91 { 92 MyGUI::ImageBox* image = mCoins[i]; 93 image->detachFromWidget(); 94 image->attachToWidget(mCoinBox); 95 if (i < mCoinCount) 96 { 97 mCoins[i]->setVisible(true); 98 image->setCoord(MyGUI::IntCoord(curX,0,16,16)); 99 curX += 16+coinSpacing; 100 } 101 else 102 mCoins[i]->setVisible(false); 103 } 104 } 105 assignCoins()106 void LevelupDialog::assignCoins() 107 { 108 resetCoins(); 109 for (unsigned int i=0; i<mSpentAttributes.size(); ++i) 110 { 111 MyGUI::ImageBox* image = mCoins[i]; 112 image->detachFromWidget(); 113 image->attachToWidget(mAssignWidget); 114 115 int attribute = mSpentAttributes[i]; 116 117 int xdiff = mAttributeMultipliers[attribute]->getCaption() == "" ? 0 : 20; 118 119 MyGUI::IntPoint pos = mAttributes[attribute]->getAbsolutePosition() - mAssignWidget->getAbsolutePosition() - MyGUI::IntPoint(22+xdiff,0); 120 pos.top += (mAttributes[attribute]->getHeight() - image->getHeight())/2; 121 image->setPosition(pos); 122 } 123 124 setAttributeValues(); 125 } 126 onOpen()127 void LevelupDialog::onOpen() 128 { 129 MWBase::World *world = MWBase::Environment::get().getWorld(); 130 MWWorld::Ptr player = world->getPlayerPtr(); 131 MWMechanics::CreatureStats& creatureStats = player.getClass().getCreatureStats(player); 132 MWMechanics::NpcStats& pcStats = player.getClass().getNpcStats(player); 133 134 setClassImage(mClassImage, getLevelupClassImage(pcStats.getSkillIncreasesForSpecialization(0), 135 pcStats.getSkillIncreasesForSpecialization(1), 136 pcStats.getSkillIncreasesForSpecialization(2))); 137 138 int level = creatureStats.getLevel ()+1; 139 mLevelText->setCaptionWithReplacing("#{sLevelUpMenu1} " + MyGUI::utility::toString(level)); 140 141 std::string levelupdescription; 142 levelupdescription = Fallback::Map::getString("Level_Up_Level"+MyGUI::utility::toString(level)); 143 144 if (levelupdescription == "") 145 levelupdescription = Fallback::Map::getString("Level_Up_Default"); 146 147 mLevelDescription->setCaption (levelupdescription); 148 149 unsigned int availableAttributes = 0; 150 for (int i = 0; i < 8; ++i) 151 { 152 MyGUI::TextBox* text = mAttributeMultipliers[i]; 153 if (pcStats.getAttribute(i).getBase() < 100) 154 { 155 mAttributes[i]->setEnabled(true); 156 mAttributeValues[i]->setEnabled(true); 157 availableAttributes++; 158 159 float mult = pcStats.getLevelupAttributeMultiplier (i); 160 mult = std::min(mult, 100-pcStats.getAttribute(i).getBase()); 161 text->setCaption(mult <= 1 ? "" : "x" + MyGUI::utility::toString(mult)); 162 } 163 else 164 { 165 mAttributes[i]->setEnabled(false); 166 mAttributeValues[i]->setEnabled(false); 167 168 text->setCaption(""); 169 } 170 } 171 172 mCoinCount = std::min(sMaxCoins, availableAttributes); 173 174 mSpentAttributes.clear(); 175 resetCoins(); 176 177 setAttributeValues(); 178 179 center(); 180 181 // Play LevelUp Music 182 MWBase::Environment::get().getSoundManager()->streamMusic("Special/MW_Triumph.mp3"); 183 } 184 onOkButtonClicked(MyGUI::Widget * sender)185 void LevelupDialog::onOkButtonClicked(MyGUI::Widget* sender) 186 { 187 MWWorld::Ptr player = MWMechanics::getPlayer(); 188 MWMechanics::NpcStats& pcStats = player.getClass().getNpcStats (player); 189 190 if (mSpentAttributes.size() < mCoinCount) 191 MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage36}"); 192 else 193 { 194 // increase attributes 195 for (unsigned int i = 0; i < mCoinCount; ++i) 196 { 197 MWMechanics::AttributeValue attribute = pcStats.getAttribute(mSpentAttributes[i]); 198 attribute.setBase(attribute.getBase() + pcStats.getLevelupAttributeMultiplier(mSpentAttributes[i])); 199 200 if (attribute.getBase() >= 100) 201 attribute.setBase(100); 202 pcStats.setAttribute(mSpentAttributes[i], attribute); 203 } 204 205 pcStats.levelUp(); 206 207 MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Levelup); 208 } 209 210 } 211 onAttributeClicked(MyGUI::Widget * sender)212 void LevelupDialog::onAttributeClicked(MyGUI::Widget *sender) 213 { 214 int attribute = *sender->getUserData<int>(); 215 216 std::vector<int>::iterator found = std::find(mSpentAttributes.begin(), mSpentAttributes.end(), attribute); 217 if (found != mSpentAttributes.end()) 218 mSpentAttributes.erase(found); 219 else 220 { 221 if (mSpentAttributes.size() == mCoinCount) 222 mSpentAttributes[mCoinCount - 1] = attribute; 223 else 224 mSpentAttributes.push_back(attribute); 225 } 226 assignCoins(); 227 } 228 getLevelupClassImage(const int combatIncreases,const int magicIncreases,const int stealthIncreases)229 std::string LevelupDialog::getLevelupClassImage(const int combatIncreases, const int magicIncreases, const int stealthIncreases) 230 { 231 std::string ret = "acrobat"; 232 233 int total = combatIncreases + magicIncreases + stealthIncreases; 234 if (total == 0) 235 return ret; 236 237 int combatFraction = static_cast<int>(static_cast<float>(combatIncreases) / total * 10.f); 238 int magicFraction = static_cast<int>(static_cast<float>(magicIncreases) / total * 10.f); 239 int stealthFraction = static_cast<int>(static_cast<float>(stealthIncreases) / total * 10.f); 240 241 if (combatFraction > 7) 242 ret = "warrior"; 243 else if (magicFraction > 7) 244 ret = "mage"; 245 else if (stealthFraction > 7) 246 ret = "thief"; 247 248 switch (combatFraction) 249 { 250 case 7: 251 ret = "warrior"; 252 break; 253 case 6: 254 if (stealthFraction == 1) 255 ret = "barbarian"; 256 else if (stealthFraction == 3) 257 ret = "crusader"; 258 else 259 ret = "knight"; 260 break; 261 case 5: 262 if (stealthFraction == 3) 263 ret = "scout"; 264 else 265 ret = "archer"; 266 break; 267 case 4: 268 ret = "rogue"; 269 break; 270 default: 271 break; 272 } 273 274 switch (magicFraction) 275 { 276 case 7: 277 ret = "mage"; 278 break; 279 case 6: 280 if (combatFraction == 2) 281 ret = "sorcerer"; 282 else if (combatIncreases == 3) 283 ret = "healer"; 284 else 285 ret = "battlemage"; 286 break; 287 case 5: 288 ret = "witchhunter"; 289 break; 290 case 4: 291 ret = "spellsword"; 292 // In vanilla there's also code for "nightblade", however it seems to be unreachable. 293 break; 294 default: 295 break; 296 } 297 298 switch (stealthFraction) 299 { 300 case 7: 301 ret = "thief"; 302 break; 303 case 6: 304 if (magicFraction == 1) 305 ret = "agent"; 306 else if (magicIncreases == 3) 307 ret = "assassin"; 308 else 309 ret = "acrobat"; 310 break; 311 case 5: 312 if (magicIncreases == 3) 313 ret = "monk"; 314 else 315 ret = "pilgrim"; 316 break; 317 case 3: 318 if (magicFraction == 3) 319 ret = "bard"; 320 break; 321 default: 322 break; 323 } 324 325 return ret; 326 } 327 } 328