-
Notifications
You must be signed in to change notification settings - Fork 328
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix for QuestListsManager.GetQuest #2646
Fix for QuestListsManager.GetQuest #2646
Conversation
QuestListsManager.GetQuest() will check mods for quests as well.
Can you give an example of a use case that doesn't work as expected without this change? |
Easy. RLQ or QP1 by @JayH2971 :) |
The top condition |
I suppose you mean that QP1 wants to use "startquest" to start quests that are not part of a QuestList, and that it works if QP1 is loose files, but does not work if it's a dfmod. The impact seems fine. QuestLIstsManager.GetQuest is used by console commands, those RunQuest/StartQuest quest commands, and some daedra summoning procedure. I don't think this would impact cases where failure to resolve a dfmod quest is intended, so should be good |
RunQuest/StartQuest console commands also doesn't work, if the quest is not in the quest list. The quest action "start quest" also doesn't work, if the quest is not in the quest list. I mean it does, if the quest file is just a loose file, but if the quest file is in the dfmod, then all that jazz doesn't work |
So I've been dredging my memory for whether there was any good reason for me to have done it this way, in case it's a good reason, because it was definitely intentional. I can't remember anything and my conclusion is just that I was thinking of quest lists as fixed lists of all quests in a mod and very different from quest packed loose files. I can be very rigid in my thinking, I like definitive on/off definitions. Anyway I think this is all good, thanks for waiting for me to search my memory. |
I have a bit of concerns with the approach of this change, but I don't think it's unfixable. The main problem is that I think it tries to fetch the mod asset too early, preventing I'm posting my pseudocode notes for what's involved
Note that So in terms of GetQuest. Before:
After:
I fear in the latter case, all the checks for My suggested approach: add the load from mods at the end. Give the registered quests a chance to resolve first, and then pick an unregistered file at the end. I don't like how DFU always picks mod assets by name without care for the relative folder they're in, but ideally we should only do the "pick unregistered file" from the Quests folder, like we do for loose files. I don't expect it from this PR, as I know it's not a thing DFU does well. Worth investigating for later. |
this part is actually have more to that, if the loose file exist, and we are asking to LoadQuest(questName), all mods will be checked if the replacement exist. But if there's no loose file, then mod replacements will be ignored. What about this variant? public Quest GetQuest(string questName, int factionId = 0)
{
string questFileName = questName + QExt;
// Check each registered init quest & containing folder.
foreach (QuestData questData in init)
{
if (questData.name == questName)
return LoadQuest(questData, factionId);
string questFile = Path.Combine(questData.path, questFileName);
Quest initQuest = LoadQuest(questFile, questData.path, factionId);
if (initQuest != null)
return initQuest;
}
// Check guild quests.
foreach (FactionFile.GuildGroups guildGroup in guilds.Keys)
foreach (QuestData questData in guilds[guildGroup])
if (questData.name == questName)
return LoadQuest(questData, factionId);
// Check social quests.
foreach (FactionFile.SocialGroups socialGroup in social.Keys)
foreach (QuestData questData in social[socialGroup])
if (questData.name == questName)
return LoadQuest(questData, factionId);
// Check QuestSourceFolder containing classic quests and mods.
Quest quest = LoadQuest(questName, QuestMachine.QuestSourceFolder, factionId);
return quest;
} |
I think you should still keep the loose file check at the top, as that should have priority over registered mod quests. It's not a great feature, but no reason to make this inconsistent with how loose files generally work. |
Firstly thanks for spotting that unintended consequence KAB. I'm keen for the classic quests to get handled before looking in mods or questlists etc. I think by loose files you mean classic quests since they're all loose. People could put new quests in there but I created the quest packs folder to keep them separate. Packs have to have quest lists that are auto-registered so they also don't allow loading. The aim of this PR is (I think) to allow mod quest scripts to get loaded using the same mechanism that loads classic (loose) quests by creating a temporary QuestData object with the name and the classic quests asset folder path. This does check mods too for that quest filename but that was only intended for when a registered quest (from a list) is being sought. Hence why the file check was done first before doing the call to LoadQuest. As you probably know from discord my preferred solution is that mods register lists of all their quests, and for those that shouldn't be offered should be set as requiring 101 rep, which should not happen since 100 is max. This seems like a lot of effort to avoid adding a single line to a file by mod authors but maybe I am missing the point like I missed what KAB caught? |
Am I right, that there are no paths inside of dfmod? Even the code that is parsing QuestList from the mods, don't pass path in, because it can't. // Seek from mods using pattern: QuestList-<packName>.txt
TextAsset questListAsset;
string fileName = QuestListPrefix + questList + QExt;
if (ModManager.Instance != null && ModManager.Instance.TryGetAsset(fileName, false, out questListAsset))
{
try {
List<string> lines = ModManager.GetTextAssetLines(questListAsset);
Table table = new Table(lines.ToArray());
ParseQuestList(table);
} catch (Exception ex) {
Debug.LogErrorFormat("QuestListsManager unable to parse quest list table {0} with exception message {1}", questListAsset.name, ex.Message);
}
} and inside the So it will all come down to this evetually, that assets from the dfmod could be loaded only by the filename? |
Yeah sorry, scratch the "path" part. Too complicated for no reason. When auto-registering quest lists, just store a list of quest names that are in the same folder as one of the quest lists. Then, when loading that quest name with |
Sounds like a good middle ground to me KAB. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I finally got around to running this. Seems good. I'll probably send a test build to JayH before release to make sure we don't have one last thing to fix before quest mods can properly migrate to dfmods
QuestListsManager.GetQuest() will check mods for quests as well.
I removed
if (File.Exists(questFile))
check, becauseLoadQuest()
function also checks for that, and more importantly, checking mods for quest files included.Then, if we didn't find any, we proceed as usual.