forked from teamnwah/openmw-tes3coop
Implement modFactionReaction instruction (Closes #1347)
This commit is contained in:
parent
578adb4ef6
commit
e266c39c5d
13 changed files with 138 additions and 42 deletions
|
@ -68,6 +68,12 @@ namespace MWBase
|
||||||
virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress) const = 0;
|
virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress) const = 0;
|
||||||
|
|
||||||
virtual void readRecord (ESM::ESMReader& reader, int32_t type) = 0;
|
virtual void readRecord (ESM::ESMReader& reader, int32_t type) = 0;
|
||||||
|
|
||||||
|
/// Changes faction1's opinion of faction2 by \a diff.
|
||||||
|
virtual void modFactionReaction (const std::string& faction1, const std::string& faction2, int diff) = 0;
|
||||||
|
|
||||||
|
/// @return faction1's opinion of faction2
|
||||||
|
virtual int getFactionReaction (const std::string& faction1, const std::string& faction2) const = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -642,6 +642,8 @@ namespace MWDialogue
|
||||||
if (iter->second)
|
if (iter->second)
|
||||||
state.mKnownTopics.push_back (iter->first);
|
state.mKnownTopics.push_back (iter->first);
|
||||||
|
|
||||||
|
state.mModFactionReaction = mModFactionReaction;
|
||||||
|
|
||||||
writer.startRecord (ESM::REC_DIAS);
|
writer.startRecord (ESM::REC_DIAS);
|
||||||
state.save (writer);
|
state.save (writer);
|
||||||
writer.endRecord (ESM::REC_DIAS);
|
writer.endRecord (ESM::REC_DIAS);
|
||||||
|
@ -661,9 +663,44 @@ namespace MWDialogue
|
||||||
iter!=state.mKnownTopics.end(); ++iter)
|
iter!=state.mKnownTopics.end(); ++iter)
|
||||||
if (store.get<ESM::Dialogue>().search (*iter))
|
if (store.get<ESM::Dialogue>().search (*iter))
|
||||||
mKnownTopics.insert (std::make_pair (*iter, true));
|
mKnownTopics.insert (std::make_pair (*iter, true));
|
||||||
|
|
||||||
|
mModFactionReaction = state.mModFactionReaction;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DialogueManager::modFactionReaction(const std::string &faction1, const std::string &faction2, int diff)
|
||||||
|
{
|
||||||
|
std::string fact1 = Misc::StringUtils::lowerCase(faction1);
|
||||||
|
std::string fact2 = Misc::StringUtils::lowerCase(faction2);
|
||||||
|
|
||||||
|
// Make sure the factions exist
|
||||||
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(fact1);
|
||||||
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(fact2);
|
||||||
|
|
||||||
|
std::map<std::string, int>& map = mModFactionReaction[fact1];
|
||||||
|
if (map.find(fact2) == map.end())
|
||||||
|
map[fact2] = 0;
|
||||||
|
map[fact2] += diff;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DialogueManager::getFactionReaction(const std::string &faction1, const std::string &faction2) const
|
||||||
|
{
|
||||||
|
std::string fact1 = Misc::StringUtils::lowerCase(faction1);
|
||||||
|
std::string fact2 = Misc::StringUtils::lowerCase(faction2);
|
||||||
|
|
||||||
|
ModFactionReactionMap::const_iterator map = mModFactionReaction.find(fact1);
|
||||||
|
int diff = 0;
|
||||||
|
if (map != mModFactionReaction.end() && map->second.find(fact2) != map->second.end())
|
||||||
|
diff = map->second.at(fact2);
|
||||||
|
|
||||||
|
const ESM::Faction* faction = MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(fact1);
|
||||||
|
|
||||||
|
std::map<std::string, int>::const_iterator it = faction->mReactions.find(fact2);
|
||||||
|
if (it == faction->mReactions.end())
|
||||||
|
return diff;
|
||||||
|
else
|
||||||
|
return it->second + diff;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<HyperTextToken> ParseHyperText(const std::string& text)
|
std::vector<HyperTextToken> ParseHyperText(const std::string& text)
|
||||||
{
|
{
|
||||||
|
|
|
@ -24,6 +24,11 @@ namespace MWDialogue
|
||||||
{
|
{
|
||||||
std::map<std::string, ESM::Dialogue> mDialogueMap;
|
std::map<std::string, ESM::Dialogue> mDialogueMap;
|
||||||
std::map<std::string, bool> mKnownTopics;// Those are the topics the player knows.
|
std::map<std::string, bool> mKnownTopics;// Those are the topics the player knows.
|
||||||
|
|
||||||
|
// Modified faction reactions. <Faction1, <Faction2, Difference> >
|
||||||
|
typedef std::map<std::string, std::map<std::string, int> > ModFactionReactionMap;
|
||||||
|
ModFactionReactionMap mModFactionReaction;
|
||||||
|
|
||||||
std::list<std::string> mActorKnownTopics;
|
std::list<std::string> mActorKnownTopics;
|
||||||
|
|
||||||
Translation::Storage& mTranslationDataStorage;
|
Translation::Storage& mTranslationDataStorage;
|
||||||
|
@ -86,6 +91,12 @@ namespace MWDialogue
|
||||||
virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress) const;
|
virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress) const;
|
||||||
|
|
||||||
virtual void readRecord (ESM::ESMReader& reader, int32_t type);
|
virtual void readRecord (ESM::ESMReader& reader, int32_t type);
|
||||||
|
|
||||||
|
/// Changes faction1's opinion of faction2 by \a diff.
|
||||||
|
virtual void modFactionReaction (const std::string& faction1, const std::string& faction2, int diff);
|
||||||
|
|
||||||
|
/// @return faction1's opinion of faction2
|
||||||
|
virtual int getFactionReaction (const std::string& faction1, const std::string& faction2) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -396,16 +396,15 @@ int MWDialogue::Filter::getSelectStructInteger (const SelectWrapper& select) con
|
||||||
|
|
||||||
int value = 0;
|
int value = 0;
|
||||||
|
|
||||||
const ESM::Faction& faction =
|
|
||||||
*MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find (factionId);
|
|
||||||
|
|
||||||
MWMechanics::NpcStats& playerStats = player.getClass().getNpcStats (player);
|
MWMechanics::NpcStats& playerStats = player.getClass().getNpcStats (player);
|
||||||
|
|
||||||
for (std::vector<ESM::Faction::Reaction>::const_iterator iter (faction.mReactions.begin());
|
std::map<std::string, int>::const_iterator playerFactionIt = playerStats.getFactionRanks().begin();
|
||||||
iter!=faction.mReactions.end(); ++iter)
|
for (; playerFactionIt != playerStats.getFactionRanks().end(); ++playerFactionIt)
|
||||||
if (playerStats.getFactionRanks().find (iter->mFaction)!=playerStats.getFactionRanks().end())
|
{
|
||||||
if (low ? iter->mReaction<value : iter->mReaction>value)
|
int reaction = MWBase::Environment::get().getDialogueManager()->getFactionReaction(factionId, playerFactionIt->first);
|
||||||
value = iter->mReaction;
|
if (low ? reaction < value : reaction > value)
|
||||||
|
value = reaction;
|
||||||
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
|
@ -498,27 +498,24 @@ namespace MWMechanics
|
||||||
|
|
||||||
if (playerStats.getFactionRanks().find(npcFaction) != playerStats.getFactionRanks().end())
|
if (playerStats.getFactionRanks().find(npcFaction) != playerStats.getFactionRanks().end())
|
||||||
{
|
{
|
||||||
for(std::vector<ESM::Faction::Reaction>::const_iterator it = MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(npcFaction)->mReactions.begin();
|
if (!playerStats.getExpelled(npcFaction))
|
||||||
it != MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(npcFaction)->mReactions.end(); ++it)
|
|
||||||
{
|
{
|
||||||
if(Misc::StringUtils::ciEqual(it->mFaction, npcFaction)
|
reaction = playerStats.getFactionReputation(npcFaction);
|
||||||
&& !playerStats.getExpelled(it->mFaction))
|
|
||||||
reaction = it->mReaction;
|
rank = playerStats.getFactionRanks().find(npcFaction)->second;
|
||||||
}
|
}
|
||||||
rank = playerStats.getFactionRanks().find(npcFaction)->second;
|
|
||||||
}
|
}
|
||||||
else if (npcFaction != "")
|
else if (!npcFaction.empty())
|
||||||
{
|
{
|
||||||
for(std::vector<ESM::Faction::Reaction>::const_iterator it = MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(npcFaction)->mReactions.begin();
|
std::map<std::string, int>::const_iterator playerFactionIt = playerStats.getFactionRanks().begin();
|
||||||
it != MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(npcFaction)->mReactions.end();++it)
|
for (; playerFactionIt != playerStats.getFactionRanks().end(); ++playerFactionIt)
|
||||||
{
|
{
|
||||||
if(playerStats.getFactionRanks().find(Misc::StringUtils::lowerCase(it->mFaction)) != playerStats.getFactionRanks().end() )
|
std::string itFaction = playerFactionIt->first;
|
||||||
{
|
|
||||||
if(it->mReaction < reaction)
|
int itReaction = MWBase::Environment::get().getDialogueManager()->getFactionReaction(npcFaction, itFaction);
|
||||||
reaction = it->mReaction;
|
if (playerFactionIt == playerStats.getFactionRanks().begin() || itReaction < reaction)
|
||||||
}
|
reaction = itReaction;
|
||||||
}
|
}
|
||||||
rank = 0;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -196,6 +196,24 @@ namespace MWScript
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class OpModFactionReaction : public Interpreter::Opcode0
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
|
{
|
||||||
|
std::string faction1 = runtime.getStringLiteral (runtime[0].mInteger);
|
||||||
|
runtime.pop();
|
||||||
|
|
||||||
|
std::string faction2 = runtime.getStringLiteral (runtime[0].mInteger);
|
||||||
|
runtime.pop();
|
||||||
|
|
||||||
|
int modReaction = runtime[0].mInteger;
|
||||||
|
runtime.pop();
|
||||||
|
|
||||||
|
MWBase::Environment::get().getDialogueManager()->modFactionReaction(faction1, faction2, modReaction);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void installOpcodes (Interpreter::Interpreter& interpreter)
|
void installOpcodes (Interpreter::Interpreter& interpreter)
|
||||||
{
|
{
|
||||||
|
@ -215,6 +233,7 @@ namespace MWScript
|
||||||
interpreter.installSegment5 (Compiler::Dialogue::opcodeGetReputationExplicit, new OpGetReputation<ExplicitRef>);
|
interpreter.installSegment5 (Compiler::Dialogue::opcodeGetReputationExplicit, new OpGetReputation<ExplicitRef>);
|
||||||
interpreter.installSegment5 (Compiler::Dialogue::opcodeSameFaction, new OpSameFaction<ImplicitRef>);
|
interpreter.installSegment5 (Compiler::Dialogue::opcodeSameFaction, new OpSameFaction<ImplicitRef>);
|
||||||
interpreter.installSegment5 (Compiler::Dialogue::opcodeSameFactionExplicit, new OpSameFaction<ExplicitRef>);
|
interpreter.installSegment5 (Compiler::Dialogue::opcodeSameFactionExplicit, new OpSameFaction<ExplicitRef>);
|
||||||
|
interpreter.installSegment5 (Compiler::Dialogue::opcodeModFactionReaction, new OpModFactionReaction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -390,5 +390,6 @@ op 0x200023e: GetPcInJail
|
||||||
op 0x200023f: GetPcTraveling
|
op 0x200023f: GetPcTraveling
|
||||||
op 0x2000240: onKnockout
|
op 0x2000240: onKnockout
|
||||||
op 0x2000241: onKnockoutExplicit
|
op 0x2000241: onKnockoutExplicit
|
||||||
|
op 0x2000242: ModFactionReaction
|
||||||
|
|
||||||
opcodes 0x2000242-0x3ffffff unused
|
opcodes 0x2000243-0x3ffffff unused
|
||||||
|
|
|
@ -179,6 +179,7 @@ namespace Compiler
|
||||||
opcodeGetReputationExplicit);
|
opcodeGetReputationExplicit);
|
||||||
extensions.registerFunction("samefaction", 'l', "", opcodeSameFaction,
|
extensions.registerFunction("samefaction", 'l', "", opcodeSameFaction,
|
||||||
opcodeSameFactionExplicit);
|
opcodeSameFactionExplicit);
|
||||||
|
extensions.registerInstruction("modfactionreaction", "ccl", opcodeModFactionReaction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -152,6 +152,7 @@ namespace Compiler
|
||||||
const int opcodeGetReputationExplicit = 0x20001b2;
|
const int opcodeGetReputationExplicit = 0x20001b2;
|
||||||
const int opcodeSameFaction = 0x20001b5;
|
const int opcodeSameFaction = 0x20001b5;
|
||||||
const int opcodeSameFactionExplicit = 0x20001b6;
|
const int opcodeSameFactionExplicit = 0x20001b6;
|
||||||
|
const int opcodeModFactionReaction = 0x2000242;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Gui
|
namespace Gui
|
||||||
|
|
|
@ -8,6 +8,20 @@ void ESM::DialogueState::load (ESMReader &esm)
|
||||||
{
|
{
|
||||||
while (esm.isNextSub ("TOPI"))
|
while (esm.isNextSub ("TOPI"))
|
||||||
mKnownTopics.push_back (esm.getHString());
|
mKnownTopics.push_back (esm.getHString());
|
||||||
|
|
||||||
|
while (esm.isNextSub ("FACT"))
|
||||||
|
{
|
||||||
|
std::string faction = esm.getHString();
|
||||||
|
|
||||||
|
while (esm.isNextSub ("REAC"))
|
||||||
|
{
|
||||||
|
std::string faction2 = esm.getHString();
|
||||||
|
int reaction;
|
||||||
|
esm.getHNT(reaction, "INTV");
|
||||||
|
|
||||||
|
mModFactionReaction[faction][faction2] = reaction;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESM::DialogueState::save (ESMWriter &esm) const
|
void ESM::DialogueState::save (ESMWriter &esm) const
|
||||||
|
@ -16,6 +30,18 @@ void ESM::DialogueState::save (ESMWriter &esm) const
|
||||||
iter!=mKnownTopics.end(); ++iter)
|
iter!=mKnownTopics.end(); ++iter)
|
||||||
{
|
{
|
||||||
esm.writeHNString ("TOPI", *iter);
|
esm.writeHNString ("TOPI", *iter);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
for (std::map<std::string, std::map<std::string, int> >::const_iterator iter = mModFactionReaction.begin();
|
||||||
|
iter != mModFactionReaction.end(); ++iter)
|
||||||
|
{
|
||||||
|
esm.writeHNString ("FACT", iter->first);
|
||||||
|
|
||||||
|
for (std::map<std::string, int>::const_iterator reactIter = iter->second.begin();
|
||||||
|
reactIter != iter->second.end(); ++reactIter)
|
||||||
|
{
|
||||||
|
esm.writeHNString ("REAC", reactIter->first);
|
||||||
|
esm.writeHNT ("INTV", reactIter->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
|
@ -15,9 +16,11 @@ namespace ESM
|
||||||
{
|
{
|
||||||
std::vector<std::string> mKnownTopics;
|
std::vector<std::string> mKnownTopics;
|
||||||
|
|
||||||
|
std::map<std::string, std::map<std::string, int> > mModFactionReaction;
|
||||||
|
|
||||||
void load (ESMReader &esm);
|
void load (ESMReader &esm);
|
||||||
void save (ESMWriter &esm) const;
|
void save (ESMWriter &esm) const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -44,10 +44,10 @@ void Faction::load(ESMReader &esm)
|
||||||
// Read faction response values
|
// Read faction response values
|
||||||
while (esm.hasMoreSubs())
|
while (esm.hasMoreSubs())
|
||||||
{
|
{
|
||||||
Reaction r;
|
std::string faction = esm.getHNString("ANAM");
|
||||||
r.mFaction = esm.getHNString("ANAM");
|
int reaction;
|
||||||
esm.getHNT(r.mReaction, "INTV");
|
esm.getHNT(reaction, "INTV");
|
||||||
mReactions.push_back(r);
|
mReactions[faction] = reaction;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void Faction::save(ESMWriter &esm) const
|
void Faction::save(ESMWriter &esm) const
|
||||||
|
@ -64,10 +64,10 @@ void Faction::save(ESMWriter &esm) const
|
||||||
|
|
||||||
esm.writeHNT("FADT", mData, 240);
|
esm.writeHNT("FADT", mData, 240);
|
||||||
|
|
||||||
for (std::vector<Reaction>::const_iterator it = mReactions.begin(); it != mReactions.end(); ++it)
|
for (std::map<std::string, int>::const_iterator it = mReactions.begin(); it != mReactions.end(); ++it)
|
||||||
{
|
{
|
||||||
esm.writeHNString("ANAM", it->mFaction);
|
esm.writeHNString("ANAM", it->first);
|
||||||
esm.writeHNT("INTV", it->mReaction);
|
esm.writeHNT("INTV", it->second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#define OPENMW_ESM_FACT_H
|
#define OPENMW_ESM_FACT_H
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <map>
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
|
@ -53,13 +53,8 @@ struct Faction
|
||||||
|
|
||||||
FADTstruct mData;
|
FADTstruct mData;
|
||||||
|
|
||||||
struct Reaction
|
// <Faction ID, Reaction>
|
||||||
{
|
std::map<std::string, int> mReactions;
|
||||||
std::string mFaction;
|
|
||||||
int mReaction;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<Reaction> mReactions;
|
|
||||||
|
|
||||||
// Name of faction ranks (may be empty for NPC factions)
|
// Name of faction ranks (may be empty for NPC factions)
|
||||||
std::string mRanks[10];
|
std::string mRanks[10];
|
||||||
|
|
Loading…
Reference in a new issue