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.
openmw-35
scrawl 10 years ago
parent 40c29abe20
commit 5104a5a023

@ -74,6 +74,8 @@ namespace MWBase
/// 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 setFactionReaction (const std::string& faction1, const std::string& faction2, int absolute) = 0;
/// @return faction1's opinion of faction2
virtual int getFactionReaction (const std::string& faction1, const std::string& faction2) const = 0;

@ -640,7 +640,7 @@ namespace MWDialogue
if (iter->second)
state.mKnownTopics.push_back (iter->first);
state.mModFactionReaction = mModFactionReaction;
state.mChangedFactionReaction = mChangedFactionReaction;
writer.startRecord (ESM::REC_DIAS);
state.save (writer);
@ -661,7 +661,7 @@ namespace MWDialogue
if (store.get<ESM::Dialogue>().search (*iter))
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(fact2);
std::map<std::string, int>& map = mModFactionReaction[fact1];
if (map.find(fact2) == map.end())
map[fact2] = 0;
map[fact2] += diff;
int newValue = getFactionReaction(faction1, faction2) + diff;
std::map<std::string, int>& map = mChangedFactionReaction[fact1];
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
@ -685,10 +698,9 @@ namespace MWDialogue
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);
ModFactionReactionMap::const_iterator map = mChangedFactionReaction.find(fact1);
if (map != mChangedFactionReaction.end() && map->second.find(fact2) != map->second.end())
return map->second.at(fact2);
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)
{
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

@ -27,7 +27,7 @@ namespace MWDialogue
// Modified faction reactions. <Faction1, <Faction2, Difference> >
typedef std::map<std::string, std::map<std::string, int> > ModFactionReactionMap;
ModFactionReactionMap mModFactionReaction;
ModFactionReactionMap mChangedFactionReaction;
std::list<std::string> mActorKnownTopics;
@ -97,6 +97,8 @@ namespace MWDialogue
/// Changes faction1's opinion of faction2 by \a 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
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>
class OpClearInfoActor : public Interpreter::Opcode0
{
@ -268,6 +287,7 @@ namespace MWScript
interpreter.installSegment5 (Compiler::Dialogue::opcodeSameFaction, new OpSameFaction<ImplicitRef>);
interpreter.installSegment5 (Compiler::Dialogue::opcodeSameFactionExplicit, new OpSameFaction<ExplicitRef>);
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::opcodeClearInfoActor, new OpClearInfoActor<ImplicitRef>);
interpreter.installSegment5 (Compiler::Dialogue::opcodeClearInfoActorExplicit, new OpClearInfoActor<ExplicitRef>);

@ -442,5 +442,6 @@ op 0x20002fb: AddToLevCreature
op 0x20002fc: RemoveFromLevCreature
op 0x20002fd: AddToLevItem
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,
opcodeSameFactionExplicit);
extensions.registerInstruction("modfactionreaction", "ccl", opcodeModFactionReaction);
extensions.registerInstruction("setfactionreaction", "ccl", opcodeSetFactionReaction);
extensions.registerFunction("getfactionreaction", 'l', "ccX", opcodeGetFactionReaction);
extensions.registerInstruction("clearinfoactor", "", opcodeClearInfoActor, opcodeClearInfoActorExplicit);
}

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

@ -13,13 +13,20 @@ void ESM::DialogueState::load (ESMReader &esm)
{
std::string faction = esm.getHString();
while (esm.isNextSub ("REAC"))
while (esm.isNextSub("REA2"))
{
std::string faction2 = esm.getHString();
int reaction;
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);
}
for (std::map<std::string, std::map<std::string, int> >::const_iterator iter = mModFactionReaction.begin();
iter != mModFactionReaction.end(); ++iter)
for (std::map<std::string, std::map<std::string, int> >::const_iterator iter = mChangedFactionReaction.begin();
iter != mChangedFactionReaction.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.writeHNString ("REA2", reactIter->first);
esm.writeHNT ("INTV", reactIter->second);
}
}

@ -16,7 +16,7 @@ namespace ESM
{
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 save (ESMWriter &esm) const;

Loading…
Cancel
Save