Merge branch 'FillJournalConsoleCommand' into 'master'

Implement FillJournal script instruction

Closes #8509

See merge request OpenMW/openmw!4676
This commit is contained in:
psi29a 2025-07-17 14:22:53 +00:00
commit 0006cb22e2
5 changed files with 83 additions and 22 deletions

View File

@ -82,6 +82,39 @@ namespace MWScript
}
};
class OpFillJournal : public Interpreter::Opcode0
{
public:
void execute(Interpreter::Runtime& runtime) override
{
const MWWorld::Store<ESM::Dialogue>& dialogues
= MWBase::Environment::get().getESMStore()->get<ESM::Dialogue>();
MWWorld::Ptr playerPtr = MWBase::Environment::get().getWorld()->getPlayerPtr();
MWBase::Journal* journal = MWBase::Environment::get().getJournal();
MWBase::DialogueManager* dialogueManager = MWBase::Environment::get().getDialogueManager();
for (const auto& dialogue : dialogues)
{
if (dialogue.mType == ESM::Dialogue::Type::Journal)
{
for (const auto& journalInfo : dialogue.mInfoOrder.getOrderedInfo())
{
if (journalInfo.mQuestStatus != ESM::DialInfo::QS_Name)
journal->addEntry(dialogue.mId, journalInfo.mData.mJournalIndex, playerPtr);
}
}
else if (dialogue.mType == ESM::Dialogue::Type::Topic)
{
for (const auto& topicInfo : dialogue.mInfoOrder.getOrderedInfo())
{
journal->addTopic(dialogue.mId, topicInfo.mId, playerPtr);
}
dialogueManager->addTopic(dialogue.mId);
}
}
}
};
class OpAddTopic : public Interpreter::Opcode0
{
public:
@ -288,6 +321,7 @@ namespace MWScript
interpreter.installSegment5<OpJournal<ExplicitRef>>(Compiler::Dialogue::opcodeJournalExplicit);
interpreter.installSegment5<OpSetJournalIndex>(Compiler::Dialogue::opcodeSetJournalIndex);
interpreter.installSegment5<OpGetJournalIndex>(Compiler::Dialogue::opcodeGetJournalIndex);
interpreter.installSegment5<OpFillJournal>(Compiler::Dialogue::opcodeFillJournal);
interpreter.installSegment5<OpAddTopic>(Compiler::Dialogue::opcodeAddTopic);
interpreter.installSegment3<OpChoice>(Compiler::Dialogue::opcodeChoice);
interpreter.installSegment5<OpForceGreeting<ImplicitRef>>(Compiler::Dialogue::opcodeForceGreeting);

View File

@ -485,5 +485,6 @@ op 0x2000322: GetPCVisionBonus
op 0x2000323: SetPCVisionBonus
op 0x2000324: ModPCVisionBonus
op 0x2000325: TestModels, T3D
op 0x2000326: FillJournal
opcodes 0x2000326-0x3ffffff unused
opcodes 0x2000327-0x3ffffff unused

View File

@ -4,6 +4,7 @@
#include <sstream>
#include <components/compiler/locals.hpp>
#include <components/debug/debuglog.hpp>
#include <components/esm/records.hpp>
#include "../mwworld/esmstore.hpp"
@ -300,26 +301,43 @@ namespace MWScript
std::string_view InterpreterContext::getNPCFaction() const
{
const ESM::NPC* npc = getReferenceImp().get<ESM::NPC>()->mBase;
const ESM::Faction* faction = MWBase::Environment::get().getESMStore()->get<ESM::Faction>().find(npc->mFaction);
const MWWorld::Ptr& ptr = getReferenceImp();
const ESM::RefId& factionId = ptr.getClass().getPrimaryFaction(ptr);
if (factionId.empty())
{
Log(Debug::Warning) << "getNPCFaction(): NPC " << ptr.getCellRef().getRefId() << " has no primary faction";
return "%";
}
MWBase::World* world = MWBase::Environment::get().getWorld();
const MWWorld::ESMStore& store = world->getStore();
const ESM::Faction* faction = store.get<ESM::Faction>().find(factionId);
return faction->mName;
}
std::string_view InterpreterContext::getNPCRank() const
{
const MWWorld::Ptr& ptr = getReferenceImp();
const ESM::RefId& faction = ptr.getClass().getPrimaryFaction(ptr);
if (faction.empty())
throw std::runtime_error("getNPCRank(): NPC is not in a faction");
int rank = ptr.getClass().getPrimaryFactionRank(ptr);
if (rank < 0 || rank > 9)
throw std::runtime_error("getNPCRank(): invalid rank");
const MWWorld::Class& ptrClass = ptr.getClass();
const ESM::RefId& factionId = ptrClass.getPrimaryFaction(ptr);
if (factionId.empty())
{
Log(Debug::Warning) << "getNPCRank(): NPC " << ptr.getCellRef().getRefId() << " has no primary faction";
return "%";
}
MWBase::World* world = MWBase::Environment::get().getWorld();
const MWWorld::ESMStore& store = world->getStore();
const ESM::Faction* fact = store.get<ESM::Faction>().find(faction);
return fact->mRanks[rank];
const ESM::Faction* faction = store.get<ESM::Faction>().find(factionId);
int rank = ptrClass.getPrimaryFactionRank(ptr);
if (rank < 0 || rank > 9)
{
Log(Debug::Warning) << "getNPCRank(): NPC " << ptr.getCellRef().getRefId() << " has invalid rank " << rank
<< " in faction " << factionId;
return "%";
}
return faction->mRanks[rank];
}
std::string_view InterpreterContext::getPCName() const
@ -344,13 +362,16 @@ namespace MWScript
std::string_view InterpreterContext::getPCRank() const
{
const MWWorld::Ptr& ptr = getReferenceImp();
const ESM::RefId& factionId = ptr.getClass().getPrimaryFaction(ptr);
if (factionId.empty())
{
Log(Debug::Warning) << "getPCRank(): NPC " << ptr.getCellRef().getRefId() << " has no primary faction";
return "%";
}
MWBase::World* world = MWBase::Environment::get().getWorld();
MWWorld::Ptr player = world->getPlayerPtr();
const ESM::RefId& factionId = getReferenceImp().getClass().getPrimaryFaction(getReferenceImp());
if (factionId.empty())
throw std::runtime_error("getPCRank(): NPC is not in a faction");
const auto& ranks = player.getClass().getNpcStats(player).getFactionRanks();
auto it = ranks.find(factionId);
int rank = -1;
@ -373,13 +394,16 @@ namespace MWScript
std::string_view InterpreterContext::getPCNextRank() const
{
const MWWorld::Ptr& ptr = getReferenceImp();
const ESM::RefId& factionId = ptr.getClass().getPrimaryFaction(ptr);
if (factionId.empty())
{
Log(Debug::Warning) << "getPCNextRank(): NPC " << ptr.getCellRef().getRefId() << " has no primary faction";
return "%";
}
MWBase::World* world = MWBase::Environment::get().getWorld();
MWWorld::Ptr player = world->getPlayerPtr();
const ESM::RefId& factionId = getReferenceImp().getClass().getPrimaryFaction(getReferenceImp());
if (factionId.empty())
throw std::runtime_error("getPCNextRank(): NPC is not in a faction");
const auto& ranks = player.getClass().getNpcStats(player).getFactionRanks();
auto it = ranks.find(factionId);
int rank = -1;

View File

@ -163,6 +163,7 @@ namespace Compiler
extensions.registerInstruction("journal", "cl", opcodeJournal, opcodeJournalExplicit);
extensions.registerInstruction("setjournalindex", "cl", opcodeSetJournalIndex);
extensions.registerFunction("getjournalindex", 'l', "c", opcodeGetJournalIndex);
extensions.registerInstruction("filljournal", "", opcodeFillJournal);
extensions.registerInstruction("addtopic", "S", opcodeAddTopic);
extensions.registerInstruction(
"choice", "j/SlSlSlSlSlSlSlSlSlSlSlSlSlSlSlSlSlSlSlSlSlSlSlSl", opcodeChoice);

View File

@ -155,6 +155,7 @@ namespace Compiler
const int opcodeJournalExplicit = 0x200030b;
const int opcodeSetJournalIndex = 0x2000134;
const int opcodeGetJournalIndex = 0x2000135;
const int opcodeFillJournal = 0x2000326;
const int opcodeAddTopic = 0x200013a;
const int opcodeChoice = 0x2000a;
const int opcodeForceGreeting = 0x200014f;