1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-30 09:15:38 +00:00

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.
This commit is contained in:
scrawl 2015-01-19 23:55:17 +01:00
parent 40c29abe20
commit 5104a5a023
9 changed files with 66 additions and 20 deletions

View file

@ -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;

View file

@ -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

View file

@ -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;

View file

@ -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>);

View file

@ -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

View file

@ -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);
}

View file

@ -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;

View file

@ -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);
}
}

View file

@ -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;