diff --git a/Source/items.cpp b/Source/items.cpp index af3ef5612..b1970b6ba 100644 --- a/Source/items.cpp +++ b/Source/items.cpp @@ -2309,8 +2309,12 @@ void InitItems() if (sgGameInitInfo.bCowQuest != 0 && currlevel == 19) SpawnQuestItem(IDI_GREYSUIT, { 25, 25 }, 3, 1, false); // In multiplayer items spawn during level generation to avoid desyncs - if (gbIsMultiplayer && Quests[Q_MUSHROOM].IsAvailable()) - SpawnQuestItem(IDI_FUNGALTM, { 0, 0 }, 5, 1, false); + if (gbIsMultiplayer) { + if (Quests[Q_MUSHROOM].IsAvailable()) + SpawnQuestItem(IDI_FUNGALTM, { 0, 0 }, 5, 1, false); + if (currlevel == Quests[Q_VEIL]._qlevel + 1 && Quests[Q_VEIL]._qactive != QUEST_NOTAVAIL) + SpawnQuestItem(IDI_GLDNELIX, { 0, 0 }, 5, 1, false); + } if (currlevel > 0 && currlevel < 16) AddInitItems(); if (currlevel >= 21 && currlevel <= 23) diff --git a/Source/monster.cpp b/Source/monster.cpp index 597e422c6..f68d31c3c 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -1449,10 +1449,7 @@ void MonsterTalk(Monster &monster) if (monster.talkMsg == TEXT_VEIL9) { Quests[Q_VEIL]._qactive = QUEST_ACTIVE; Quests[Q_VEIL]._qlog = true; - } - if (monster.talkMsg == TEXT_VEIL11 && (monster.flags & MFLAG_QUEST_COMPLETE) == 0) { - SpawnUnique(UITEM_STEELVEIL, monster.position.tile + Direction::South); - monster.flags |= MFLAG_QUEST_COMPLETE; + NetSendCmdQuest(true, Quests[Q_VEIL]); } } if (monster.uniqueType == UniqueMonsterType::WarlordOfBlood) { @@ -2879,6 +2876,8 @@ void LachdananAi(Monster &monster) if (monster.talkMsg == TEXT_VEIL9 && !IsTileVisible(monster.position.tile) && monster.goal == MonsterGoal::Talking) { monster.talkMsg = TEXT_VEIL10; monster.goal = MonsterGoal::Inquiring; + Quests[Q_VEIL]._qvar2 = QS_VEIL_EARLY_RETURN; + NetSendCmdQuest(true, Quests[Q_VEIL]); } if (IsTileVisible(monster.position.tile)) { @@ -2887,6 +2886,7 @@ void LachdananAi(Monster &monster) monster.talkMsg = TEXT_NONE; Quests[Q_VEIL]._qactive = QUEST_DONE; MonsterDeath(monster, monster.direction, true); + NetSendCmdQuest(true, Quests[Q_VEIL]); } } } @@ -4506,9 +4506,15 @@ void TalktoMonster(Player &player, Monster &monster) } } if (Quests[Q_VEIL].IsAvailable() && monster.talkMsg >= TEXT_VEIL9) { - if (RemoveInventoryItemById(player, IDI_GLDNELIX)) { + if (RemoveInventoryItemById(player, IDI_GLDNELIX) && (monster.flags & MFLAG_QUEST_COMPLETE) == 0) { monster.talkMsg = TEXT_VEIL11; monster.goal = MonsterGoal::Inquiring; + monster.flags |= MFLAG_QUEST_COMPLETE; + if (MyPlayer == &player) { + SpawnUnique(UITEM_STEELVEIL, monster.position.tile + Direction::South); + Quests[Q_VEIL]._qvar2 = QS_VEIL_ITEM_SPAWNED; + NetSendCmdQuest(true, Quests[Q_VEIL]); + } } } } diff --git a/Source/quests.cpp b/Source/quests.cpp index 79b2a4166..ad193015b 100644 --- a/Source/quests.cpp +++ b/Source/quests.cpp @@ -680,9 +680,10 @@ void ResyncQuests() } } } - if (currlevel == Quests[Q_VEIL]._qlevel + 1 && Quests[Q_VEIL]._qactive == QUEST_ACTIVE && Quests[Q_VEIL]._qvar1 == 0) { + if (currlevel == Quests[Q_VEIL]._qlevel + 1 && Quests[Q_VEIL]._qactive == QUEST_ACTIVE && Quests[Q_VEIL]._qvar1 == 0 && !gbIsMultiplayer) { Quests[Q_VEIL]._qvar1 = 1; - SpawnQuestItem(IDI_GLDNELIX, { 0, 0 }, 5, 1, false); + SpawnQuestItem(IDI_GLDNELIX, { 0, 0 }, 5, 1, true); + NetSendCmdQuest(true, Quests[Q_VEIL]); } if (setlevel && setlvlnum == SL_VILEBETRAYER) { if (Quests[Q_BETRAYER]._qvar1 >= 4) @@ -783,6 +784,24 @@ void ResyncQuests() warlord->goal = MonsterGoal::Normal; } } + if (Quests[Q_VEIL].IsAvailable() && gbIsMultiplayer) { + Monster *lachdan = FindUniqueMonster(UniqueMonsterType::Lachdan); + if (lachdan != nullptr) { + switch (Quests[Q_VEIL]._qvar2) { + case QS_VEIL_EARLY_RETURN: + lachdan->talkMsg = TEXT_VEIL10; + lachdan->goal = MonsterGoal::Inquiring; + break; + case QS_VEIL_ITEM_SPAWNED: + if (lachdan->talkMsg == TEXT_VEIL11) + break; + lachdan->talkMsg = TEXT_VEIL11; + lachdan->flags |= MFLAG_QUEST_COMPLETE; + lachdan->goal = MonsterGoal::Inquiring; + break; + } + } + } } void DrawQuestLog(const Surface &out) diff --git a/Source/quests.h b/Source/quests.h index 5666e99c8..b715e7267 100644 --- a/Source/quests.h +++ b/Source/quests.h @@ -60,6 +60,13 @@ enum { QS_WARLORD_ATTACKING, }; +/** @brief States of Lachdanan quest for multiplayer sync */ +enum { + QS_VEIL_INIT, + QS_VEIL_EARLY_RETURN, + QS_VEIL_ITEM_SPAWNED, +}; + enum quest_state : uint8_t { QUEST_NOTAVAIL, // quest did not spawn this game QUEST_INIT, // quest has spawned, waiting to trigger