diff --git a/apps/openmw/mwgui/stats_window.cpp b/apps/openmw/mwgui/stats_window.cpp index 38a06940f..70ceed857 100644 --- a/apps/openmw/mwgui/stats_window.cpp +++ b/apps/openmw/mwgui/stats_window.cpp @@ -252,6 +252,7 @@ void StatsWindow::onFrame () } setFactions(PCstats.getFactionRanks()); + setExpelled(PCstats.getExpelled ()); const std::string &signId = MWBase::Environment::get().getWorld()->getPlayer().getBirthSign(); @@ -273,6 +274,15 @@ void StatsWindow::setFactions (const FactionList& factions) } } +void StatsWindow::setExpelled (const std::set& expelled) +{ + if (mExpelled != expelled) + { + mExpelled = expelled; + mChanged = true; + } +} + void StatsWindow::setBirthSign (const std::string& signId) { if (signId != mBirthSignId) @@ -462,6 +472,10 @@ void StatsWindow::updateSkillArea() if (!mSkillWidgets.empty()) addSeparator(coord1, coord2); + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + MWMechanics::NpcStats PCstats = MWWorld::Class::get(player).getNpcStats(player); + std::set& expelled = PCstats.getExpelled (); + addGroup(mWindowManager.getGameSettingString("sFaction", "Faction"), coord1, coord2); FactionList::const_iterator end = mFactions.end(); for (FactionList::const_iterator it = mFactions.begin(); it != end; ++it) @@ -473,36 +487,42 @@ void StatsWindow::updateSkillArea() std::string text; text += std::string("#DDC79E") + faction->mName; - text += std::string("\n#BF9959") + faction->mRanks[it->second]; - if (it->second < 9) + if (expelled.find(it->first) != expelled.end()) + text += "\n#{sExpelled}"; + else { - // player doesn't have max rank yet - text += std::string("\n\n#DDC79E#{sNextRank} ") + faction->mRanks[it->second+1]; - - ESM::RankData rankData = faction->mData.mRankData[it->second+1]; - const ESM::Attribute* attr1 = store.get().find(faction->mData.mAttribute1); - const ESM::Attribute* attr2 = store.get().find(faction->mData.mAttribute2); - assert(attr1 && attr2); + text += std::string("\n#BF9959") + faction->mRanks[it->second]; - text += "\n#BF9959#{" + attr1->mName + "}: " + boost::lexical_cast(rankData.mAttribute1) - + ", #{" + attr2->mName + "}: " + boost::lexical_cast(rankData.mAttribute2); - - text += "\n\n#DDC79E#{sFavoriteSkills}"; - text += "\n#BF9959"; - for (int i=0; i<6; ++i) + if (it->second < 9) { - text += "#{"+ESM::Skill::sSkillNameIds[faction->mData.mSkillID[i]]+"}"; - if (i<5) - text += ", "; + // player doesn't have max rank yet + text += std::string("\n\n#DDC79E#{sNextRank} ") + faction->mRanks[it->second+1]; + + ESM::RankData rankData = faction->mData.mRankData[it->second+1]; + const ESM::Attribute* attr1 = store.get().find(faction->mData.mAttribute1); + const ESM::Attribute* attr2 = store.get().find(faction->mData.mAttribute2); + assert(attr1 && attr2); + + text += "\n#BF9959#{" + attr1->mName + "}: " + boost::lexical_cast(rankData.mAttribute1) + + ", #{" + attr2->mName + "}: " + boost::lexical_cast(rankData.mAttribute2); + + text += "\n\n#DDC79E#{sFavoriteSkills}"; + text += "\n#BF9959"; + for (int i=0; i<6; ++i) + { + text += "#{"+ESM::Skill::sSkillNameIds[faction->mData.mSkillID[i]]+"}"; + if (i<5) + text += ", "; + } + + text += "\n"; + + if (rankData.mSkill1 > 0) + text += "\n#{sNeedOneSkill} " + boost::lexical_cast(rankData.mSkill1); + if (rankData.mSkill2 > 0) + text += "\n#{sNeedTwoSkills} " + boost::lexical_cast(rankData.mSkill2); } - - text += "\n"; - - if (rankData.mSkill1 > 0) - text += "\n#{sNeedOneSkill} " + boost::lexical_cast(rankData.mSkill1); - if (rankData.mSkill2 > 0) - text += "\n#{sNeedTwoSkills} " + boost::lexical_cast(rankData.mSkill2); } w->setUserString("ToolTipType", "Layout"); diff --git a/apps/openmw/mwgui/stats_window.hpp b/apps/openmw/mwgui/stats_window.hpp index f43682c96..6619680fa 100644 --- a/apps/openmw/mwgui/stats_window.hpp +++ b/apps/openmw/mwgui/stats_window.hpp @@ -50,6 +50,7 @@ namespace MWGui MyGUI::Widget* addItem(const std::string& text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); void setFactions (const FactionList& factions); + void setExpelled (const std::set& expelled); void setBirthSign (const std::string &signId); void onWindowResize(MyGUI::Window* window); @@ -71,6 +72,7 @@ namespace MWGui std::string mBirthSignId; int mReputation, mBounty; std::vector mSkillWidgets; //< Skills and other information + std::set mExpelled; bool mChanged; diff --git a/apps/openmw/mwmechanics/npcstats.cpp b/apps/openmw/mwmechanics/npcstats.cpp index 20a0360e7..ca58f4825 100644 --- a/apps/openmw/mwmechanics/npcstats.cpp +++ b/apps/openmw/mwmechanics/npcstats.cpp @@ -350,4 +350,4 @@ void MWMechanics::NpcStats::setWerewolf (bool set) int MWMechanics::NpcStats::getWerewolfKills() const { return mWerewolfKills; -} \ No newline at end of file +} diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index b4bc713db..835a3e3ff 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -37,7 +37,13 @@ op 0x20014: SetPCFacRep op 0x20015: SetPCFacRep, explicit reference op 0x20016: ModPCFacRep op 0x20017: ModPCFacRep, explicit reference -op s 0x20018-0x3ffff unused +op 0x20018: PcExpelled +op 0x20019: PcExpelled, explicit +op 0x2001a: PcExpell +op 0x2001b: PcExpell, explicit +op 0x2001c: PcClearExpelled +op 0x2001d: PcClearExpelled, explicit +op s 0x2001e-0x3ffff unused Segment 4: (not implemented yet) @@ -281,7 +287,12 @@ op 0x20001e4: ModScale, explicit op 0x20001e5: SetDelete op 0x20001e6: SetDelete, explicit op 0x20001e7: GetSquareRoot -opcodes 0x20001e3-0x3ffffff unused +op 0x20001e8: RaiseRank +op 0x20001e9: RaiseRank, explicit +op 0x20001ea: LowerRank +op 0x20001eb: LowerRank, explicit + +opcodes 0x20001ec-0x3ffffff unused diff --git a/apps/openmw/mwscript/statsextensions.cpp b/apps/openmw/mwscript/statsextensions.cpp index 9fa315e2f..69ac7d5fe 100644 --- a/apps/openmw/mwscript/statsextensions.cpp +++ b/apps/openmw/mwscript/statsextensions.cpp @@ -812,6 +812,179 @@ namespace MWScript } }; + template + class OpPcExpelled : public Interpreter::Opcode1 + { + public: + + virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + { + MWWorld::Ptr ptr = R()(runtime); + + std::string factionID = ""; + if(arg0 >0 ) + { + factionID = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + } + else + { + if(MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks().empty()) + { + factionID = ""; + } + else + { + factionID = MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks().begin()->first; + } + } + boost::algorithm::to_lower(factionID); + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + if(factionID!="") + { + std::set& expelled = MWWorld::Class::get(player).getNpcStats(player).getExpelled (); + if (expelled.find (factionID) != expelled.end()) + { + runtime.push(1); + } + else + { + runtime.push(0); + } + } + else + { + runtime.push(0); + } + } + }; + + template + class OpPcExpell : public Interpreter::Opcode1 + { + public: + + virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + { + MWWorld::Ptr ptr = R()(runtime); + + std::string factionID = ""; + if(arg0 >0 ) + { + factionID = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + } + else + { + if(MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks().empty()) + { + factionID = ""; + } + else + { + factionID = MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks().begin()->first; + } + } + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + if(factionID!="") + { + std::set& expelled = MWWorld::Class::get(player).getNpcStats(player).getExpelled (); + boost::algorithm::to_lower(factionID); + expelled.insert(factionID); + } + } + }; + + template + class OpPcClearExpelled : public Interpreter::Opcode1 + { + public: + + virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + { + MWWorld::Ptr ptr = R()(runtime); + + std::string factionID = ""; + if(arg0 >0 ) + { + factionID = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + } + else + { + if(MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks().empty()) + { + factionID = ""; + } + else + { + factionID = MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks().begin()->first; + } + } + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + if(factionID!="") + { + std::set& expelled = MWWorld::Class::get(player).getNpcStats(player).getExpelled (); + boost::algorithm::to_lower(factionID); + expelled.erase (factionID); + } + } + }; + + template + class OpRaiseRank : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + + std::string factionID = ""; + if(MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks().empty()) + return; + else + { + factionID = MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks().begin()->first; + } + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + + // no-op when executed on the player + if (ptr == player) + return; + + std::map& ranks = MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks (); + ranks[factionID] = ranks[factionID]+1; + } + }; + + template + class OpLowerRank : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + + std::string factionID = ""; + if(MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks().empty()) + return; + else + { + factionID = MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks().begin()->first; + } + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + + // no-op when executed on the player + if (ptr == player) + return; + + std::map& ranks = MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks (); + ranks[factionID] = ranks[factionID]-1; + } + }; + const int numberOfAttributes = 8; const int opcodeGetAttribute = 0x2000027; @@ -886,6 +1059,17 @@ namespace MWScript const int opcodeGetWerewolfKills = 0x20001e2; + const int opcodePcExpelled = 0x20018; + const int opcodePcExpelledExplicit = 0x20019; + const int opcodePcExpell = 0x2001a; + const int opcodePcExpellExplicit = 0x2001b; + const int opcodePcClearExpelled = 0x2001c; + const int opcodePcClearExpelledExplicit = 0x2001d; + const int opcodeRaiseRank = 0x20001e8; + const int opcodeRaiseRankExplicit = 0x20001e9; + const int opcodeLowerRank = 0x20001ea; + const int opcodeLowerRankExplicit = 0x20001eb; + void registerExtensions (Compiler::Extensions& extensions) { static const char *attributes[numberOfAttributes] = @@ -990,6 +1174,11 @@ namespace MWScript extensions.registerFunction ("getrace", 'l', "c", opcodeGetRace, opcodeGetRaceExplicit); extensions.registerFunction ("getwerewolfkills", 'f', "", opcodeGetWerewolfKills); + extensions.registerFunction ("pcexpelled", 'l', "/S", opcodePcExpelled, opcodePcExpelledExplicit); + extensions.registerInstruction ("pcexpell", "/S", opcodePcExpell, opcodePcExpellExplicit); + extensions.registerInstruction ("pcclearexpelled", "/S", opcodePcClearExpelled, opcodePcClearExpelledExplicit); + extensions.registerInstruction ("raiserank", "", opcodeRaiseRank, opcodeRaiseRankExplicit); + extensions.registerInstruction ("lowerrank", "", opcodeLowerRank, opcodeLowerRankExplicit); } void installOpcodes (Interpreter::Interpreter& interpreter) @@ -1089,6 +1278,17 @@ namespace MWScript interpreter.installSegment5 (opcodeGetRace, new OpGetRace); interpreter.installSegment5 (opcodeGetRaceExplicit, new OpGetRace); interpreter.installSegment5 (opcodeGetWerewolfKills, new OpGetWerewolfKills); + + interpreter.installSegment3 (opcodePcExpelled, new OpPcExpelled); + interpreter.installSegment3 (opcodePcExpelledExplicit, new OpPcExpelled); + interpreter.installSegment3 (opcodePcExpell, new OpPcExpell); + interpreter.installSegment3 (opcodePcExpellExplicit, new OpPcExpell); + interpreter.installSegment3 (opcodePcClearExpelled, new OpPcClearExpelled); + interpreter.installSegment3 (opcodePcClearExpelledExplicit, new OpPcClearExpelled); + interpreter.installSegment5 (opcodeRaiseRank, new OpRaiseRank); + interpreter.installSegment5 (opcodeRaiseRankExplicit, new OpRaiseRank); + interpreter.installSegment5 (opcodeLowerRank, new OpLowerRank); + interpreter.installSegment5 (opcodeLowerRankExplicit, new OpLowerRank); } } }