forked from teamnwah/openmw-tes3coop
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:
parent
40c29abe20
commit
5104a5a023
9 changed files with 66 additions and 20 deletions
|
@ -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…
Reference in a new issue