Add missing setFactionReaction instruction, use absolute storage instead of difference

Seems to be closer to how MW is storing it (it has the complete FACT record in the savegame, actually).

This (somewhat) breaks OMW savegame compatibility in that old changes are discarded, but I don't think the faction reactions are quest relevant anywhere.
pull/451/head
scrawl 10 years ago
parent 40c29abe20
commit 5104a5a023

@ -74,6 +74,8 @@ namespace MWBase
/// Changes faction1's opinion of faction2 by \a diff. /// Changes faction1's opinion of faction2 by \a diff.
virtual void modFactionReaction (const std::string& faction1, const std::string& faction2, int diff) = 0; virtual void modFactionReaction (const std::string& faction1, const std::string& faction2, int diff) = 0;
virtual void setFactionReaction (const std::string& faction1, const std::string& faction2, int absolute) = 0;
/// @return faction1's opinion of faction2 /// @return faction1's opinion of faction2
virtual int getFactionReaction (const std::string& faction1, const std::string& faction2) const = 0; virtual int getFactionReaction (const std::string& faction1, const std::string& faction2) const = 0;

@ -640,7 +640,7 @@ namespace MWDialogue
if (iter->second) if (iter->second)
state.mKnownTopics.push_back (iter->first); state.mKnownTopics.push_back (iter->first);
state.mModFactionReaction = mModFactionReaction; state.mChangedFactionReaction = mChangedFactionReaction;
writer.startRecord (ESM::REC_DIAS); writer.startRecord (ESM::REC_DIAS);
state.save (writer); state.save (writer);
@ -661,7 +661,7 @@ namespace MWDialogue
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; mChangedFactionReaction = state.mChangedFactionReaction;
} }
} }
@ -674,10 +674,23 @@ namespace MWDialogue
MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(fact1); MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(fact1);
MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(fact2); MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(fact2);
std::map<std::string, int>& map = mModFactionReaction[fact1]; int newValue = getFactionReaction(faction1, faction2) + diff;
if (map.find(fact2) == map.end())
map[fact2] = 0; std::map<std::string, int>& map = mChangedFactionReaction[fact1];
map[fact2] += diff; map[fact2] = newValue;
}
void DialogueManager::setFactionReaction(const std::string &faction1, const std::string &faction2, int absolute)
{
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 = mChangedFactionReaction[fact1];
map[fact2] = absolute;
} }
int DialogueManager::getFactionReaction(const std::string &faction1, const std::string &faction2) const int DialogueManager::getFactionReaction(const std::string &faction1, const std::string &faction2) const
@ -685,10 +698,9 @@ namespace MWDialogue
std::string fact1 = Misc::StringUtils::lowerCase(faction1); std::string fact1 = Misc::StringUtils::lowerCase(faction1);
std::string fact2 = Misc::StringUtils::lowerCase(faction2); std::string fact2 = Misc::StringUtils::lowerCase(faction2);
ModFactionReactionMap::const_iterator map = mModFactionReaction.find(fact1); ModFactionReactionMap::const_iterator map = mChangedFactionReaction.find(fact1);
int diff = 0; if (map != mChangedFactionReaction.end() && map->second.find(fact2) != map->second.end())
if (map != mModFactionReaction.end() && map->second.find(fact2) != map->second.end()) return map->second.at(fact2);
diff = map->second.at(fact2);
const ESM::Faction* faction = MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(fact1); const ESM::Faction* faction = MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(fact1);
@ -696,9 +708,9 @@ namespace MWDialogue
for (; it != faction->mReactions.end(); ++it) for (; it != faction->mReactions.end(); ++it)
{ {
if (Misc::StringUtils::ciEqual(it->first, fact2)) if (Misc::StringUtils::ciEqual(it->first, fact2))
return it->second + diff; return it->second;
} }
return diff; return 0;
} }
void DialogueManager::clearInfoActor(const MWWorld::Ptr &actor) const void DialogueManager::clearInfoActor(const MWWorld::Ptr &actor) const

@ -27,7 +27,7 @@ namespace MWDialogue
// Modified faction reactions. <Faction1, <Faction2, Difference> > // Modified faction reactions. <Faction1, <Faction2, Difference> >
typedef std::map<std::string, std::map<std::string, int> > ModFactionReactionMap; typedef std::map<std::string, std::map<std::string, int> > ModFactionReactionMap;
ModFactionReactionMap mModFactionReaction; ModFactionReactionMap mChangedFactionReaction;
std::list<std::string> mActorKnownTopics; std::list<std::string> mActorKnownTopics;
@ -97,6 +97,8 @@ namespace MWDialogue
/// Changes faction1's opinion of faction2 by \a diff. /// Changes faction1's opinion of faction2 by \a diff.
virtual void modFactionReaction (const std::string& faction1, const std::string& faction2, int diff); virtual void modFactionReaction (const std::string& faction1, const std::string& faction2, int diff);
virtual void setFactionReaction (const std::string& faction1, const std::string& faction2, int absolute);
/// @return faction1's opinion of faction2 /// @return faction1's opinion of faction2
virtual int getFactionReaction (const std::string& faction1, const std::string& faction2) const; virtual int getFactionReaction (const std::string& faction1, const std::string& faction2) const;

@ -236,6 +236,25 @@ namespace MWScript
} }
}; };
class OpSetFactionReaction : 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 newValue = runtime[0].mInteger;
runtime.pop();
MWBase::Environment::get().getDialogueManager()->setFactionReaction(faction1, faction2, newValue);
}
};
template <class R> template <class R>
class OpClearInfoActor : public Interpreter::Opcode0 class OpClearInfoActor : public Interpreter::Opcode0
{ {
@ -268,6 +287,7 @@ namespace MWScript
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); interpreter.installSegment5 (Compiler::Dialogue::opcodeModFactionReaction, new OpModFactionReaction);
interpreter.installSegment5 (Compiler::Dialogue::opcodeSetFactionReaction, new OpSetFactionReaction);
interpreter.installSegment5 (Compiler::Dialogue::opcodeGetFactionReaction, new OpGetFactionReaction); interpreter.installSegment5 (Compiler::Dialogue::opcodeGetFactionReaction, new OpGetFactionReaction);
interpreter.installSegment5 (Compiler::Dialogue::opcodeClearInfoActor, new OpClearInfoActor<ImplicitRef>); interpreter.installSegment5 (Compiler::Dialogue::opcodeClearInfoActor, new OpClearInfoActor<ImplicitRef>);
interpreter.installSegment5 (Compiler::Dialogue::opcodeClearInfoActorExplicit, new OpClearInfoActor<ExplicitRef>); interpreter.installSegment5 (Compiler::Dialogue::opcodeClearInfoActorExplicit, new OpClearInfoActor<ExplicitRef>);

@ -442,5 +442,6 @@ op 0x20002fb: AddToLevCreature
op 0x20002fc: RemoveFromLevCreature op 0x20002fc: RemoveFromLevCreature
op 0x20002fd: AddToLevItem op 0x20002fd: AddToLevItem
op 0x20002fe: RemoveFromLevItem op 0x20002fe: RemoveFromLevItem
op 0x20002ff: SetFactionReaction
opcodes 0x20002ff-0x3ffffff unused opcodes 0x2000300-0x3ffffff unused

@ -192,6 +192,7 @@ namespace Compiler
extensions.registerFunction("samefaction", 'l', "", opcodeSameFaction, extensions.registerFunction("samefaction", 'l', "", opcodeSameFaction,
opcodeSameFactionExplicit); opcodeSameFactionExplicit);
extensions.registerInstruction("modfactionreaction", "ccl", opcodeModFactionReaction); extensions.registerInstruction("modfactionreaction", "ccl", opcodeModFactionReaction);
extensions.registerInstruction("setfactionreaction", "ccl", opcodeSetFactionReaction);
extensions.registerFunction("getfactionreaction", 'l', "ccX", opcodeGetFactionReaction); extensions.registerFunction("getfactionreaction", 'l', "ccX", opcodeGetFactionReaction);
extensions.registerInstruction("clearinfoactor", "", opcodeClearInfoActor, opcodeClearInfoActorExplicit); extensions.registerInstruction("clearinfoactor", "", opcodeClearInfoActor, opcodeClearInfoActorExplicit);
} }

@ -167,6 +167,7 @@ namespace Compiler
const int opcodeSameFaction = 0x20001b5; const int opcodeSameFaction = 0x20001b5;
const int opcodeSameFactionExplicit = 0x20001b6; const int opcodeSameFactionExplicit = 0x20001b6;
const int opcodeModFactionReaction = 0x2000242; const int opcodeModFactionReaction = 0x2000242;
const int opcodeSetFactionReaction = 0x20002ff;
const int opcodeGetFactionReaction = 0x2000243; const int opcodeGetFactionReaction = 0x2000243;
const int opcodeClearInfoActor = 0x2000245; const int opcodeClearInfoActor = 0x2000245;
const int opcodeClearInfoActorExplicit = 0x2000246; const int opcodeClearInfoActorExplicit = 0x2000246;

@ -13,13 +13,20 @@ void ESM::DialogueState::load (ESMReader &esm)
{ {
std::string faction = esm.getHString(); std::string faction = esm.getHString();
while (esm.isNextSub ("REAC")) while (esm.isNextSub("REA2"))
{ {
std::string faction2 = esm.getHString(); std::string faction2 = esm.getHString();
int reaction; int reaction;
esm.getHNT(reaction, "INTV"); esm.getHNT(reaction, "INTV");
mChangedFactionReaction[faction][faction2] = reaction;
}
mModFactionReaction[faction][faction2] = reaction; // no longer used
while (esm.isNextSub ("REAC"))
{
esm.skipHSub();
esm.getSubHeader();
esm.skipHSub();
} }
} }
} }
@ -32,15 +39,15 @@ void ESM::DialogueState::save (ESMWriter &esm) const
esm.writeHNString ("TOPI", *iter); esm.writeHNString ("TOPI", *iter);
} }
for (std::map<std::string, std::map<std::string, int> >::const_iterator iter = mModFactionReaction.begin(); for (std::map<std::string, std::map<std::string, int> >::const_iterator iter = mChangedFactionReaction.begin();
iter != mModFactionReaction.end(); ++iter) iter != mChangedFactionReaction.end(); ++iter)
{ {
esm.writeHNString ("FACT", iter->first); esm.writeHNString ("FACT", iter->first);
for (std::map<std::string, int>::const_iterator reactIter = iter->second.begin(); for (std::map<std::string, int>::const_iterator reactIter = iter->second.begin();
reactIter != iter->second.end(); ++reactIter) reactIter != iter->second.end(); ++reactIter)
{ {
esm.writeHNString ("REAC", reactIter->first); esm.writeHNString ("REA2", reactIter->first);
esm.writeHNT ("INTV", reactIter->second); esm.writeHNT ("INTV", reactIter->second);
} }
} }

@ -16,7 +16,7 @@ namespace ESM
{ {
std::vector<std::string> mKnownTopics; std::vector<std::string> mKnownTopics;
std::map<std::string, std::map<std::string, int> > mModFactionReaction; std::map<std::string, std::map<std::string, int> > mChangedFactionReaction;
void load (ESMReader &esm); void load (ESMReader &esm);
void save (ESMWriter &esm) const; void save (ESMWriter &esm) const;

Loading…
Cancel
Save