Skip to content
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

Fixes for alchemy dude's quest #2352

Merged
merged 5 commits into from
Sep 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 2 additions & 59 deletions src/main/java/emu/grasscutter/game/quest/GameMainQuest.java
Original file line number Diff line number Diff line change
Expand Up @@ -169,23 +169,6 @@ public void finish() {
this.state = ParentQuestState.PARENT_QUEST_STATE_FINISHED;
}

/*
* We also need to check for unfinished childQuests in this MainQuest
* force them to complete and send a packet about this to the user,
* because at some points there are special "invisible" child quests that control
* some situations.
*
* For example, subQuest 35312 is responsible for the event of leaving the territory
* of the island with a statue and automatically returns the character back,
* quest 35311 completes the main quest line 353 and starts 35501 from
* new MainQuest 355 but if 35312 is not completed after the completion
* of the main quest 353 - the character will not be able to leave place
* (return again and again)
*/
// this.getChildQuests().values().stream()
// .filter(p -> p.state != QuestState.QUEST_STATE_FINISHED)
// .forEach(GameQuest::finish);

this.getOwner().getSession().send(new PacketFinishedParentQuestUpdateNotify(this));
this.getOwner().getSession().send(new PacketCodexDataUpdateNotify(this));

Expand Down Expand Up @@ -383,46 +366,6 @@ public void checkProgress() {
}
}

public void tryAcceptSubQuests(QuestCond condType, String paramStr, int... params) {
try {
List<GameQuest> subQuestsWithCond =
getChildQuests().values().stream()
.filter(
p ->
p.getState() == QuestState.QUEST_STATE_UNSTARTED
|| p.getState() == QuestState.UNFINISHED)
.filter(
p ->
p.getQuestData().getAcceptCond().stream()
.anyMatch(
q ->
condType == QuestCond.QUEST_COND_NONE || q.getType() == condType))
.toList();
var questSystem = owner.getServer().getQuestSystem();

for (GameQuest subQuestWithCond : subQuestsWithCond) {
var acceptCond = subQuestWithCond.getQuestData().getAcceptCond();
int[] accept = new int[acceptCond.size()];

for (int i = 0; i < subQuestWithCond.getQuestData().getAcceptCond().size(); i++) {
var condition = acceptCond.get(i);
boolean result =
questSystem.triggerCondition(
getOwner(), subQuestWithCond.getQuestData(), condition, paramStr, params);
accept[i] = result ? 1 : 0;
}

boolean shouldAccept =
LogicType.calculate(subQuestWithCond.getQuestData().getAcceptCondComb(), accept);

if (shouldAccept) subQuestWithCond.start();
}
this.save();
} catch (Exception e) {
Grasscutter.getLogger().error("An error occurred while trying to accept quest.", e);
}
}

public void tryFailSubQuests(QuestContent condType, String paramStr, int... params) {
try {
List<GameQuest> subQuestsWithCond =
Expand All @@ -437,15 +380,15 @@ public void tryFailSubQuests(QuestContent condType, String paramStr, int... para
for (GameQuest subQuestWithCond : subQuestsWithCond) {
val failCond = subQuestWithCond.getQuestData().getFailCond();

for (int i = 0; i < subQuestWithCond.getQuestData().getFailCond().size(); i++) {
for (int i = 0; i < failCond.size(); i++) {
val condition = failCond.get(i);
if (condition.getType() == condType) {
boolean result =
this.getOwner()
.getServer()
.getQuestSystem()
.triggerContent(subQuestWithCond, condition, paramStr, params);
subQuestWithCond.getFailProgressList()[i] = result ? 1 : 0;
subQuestWithCond.setFailProgress(i, result ? 1 : 0);
if (result) {
getOwner().getSession().send(new PacketQuestProgressUpdateNotify(subQuestWithCond));
}
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/emu/grasscutter/game/quest/GameQuest.java
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,10 @@ public void setFailProgress(int index, int value) {
public boolean clearProgress(boolean notifyDelete) {
// TODO improve
var oldState = state;
if (questData.getAcceptCond() != null && questData.getAcceptCond().size() != 0) {
this.getMainQuest().getQuestManager().getAcceptProgressLists().put(this.getSubQuestId(), new int[questData.getAcceptCond().size()]);
}

if (questData.getFinishCond() != null && questData.getFinishCond().size() != 0) {
for (var condition : questData.getFinishCond()) {
if (condition.getType() == QuestContent.QUEST_CONTENT_LUA_NOTIFY) {
Expand Down
22 changes: 12 additions & 10 deletions src/main/java/emu/grasscutter/game/quest/QuestManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public final class QuestManager extends BasePlayerManager {
@Getter private final Player player;

@Getter private final Int2ObjectMap<GameMainQuest> mainQuests;
@Getter private Int2ObjectMap<int[]> acceptProgressLists;
@Getter private final List<Integer> loggedQuests;

private long lastHourCheck = 0;
Expand All @@ -52,6 +53,7 @@ public QuestManager(Player player) {
this.player = player;
this.mainQuests = new Int2ObjectOpenHashMap<>();
this.loggedQuests = new ArrayList<>();
this.acceptProgressLists = new Int2ObjectOpenHashMap<>();

if (DEBUG) {
this.loggedQuests.addAll(
Expand Down Expand Up @@ -484,8 +486,6 @@ public void queueEvent(QuestCond condType, String paramStr, int... params) {
eventExecutor.submit(() -> triggerEvent(condType, paramStr, params));
}

// QUEST_EXEC are handled directly by each subQuest

public void triggerEvent(QuestCond condType, String paramStr, int... params) {
Grasscutter.getLogger().trace("Trigger Event {}, {}, {}", condType, paramStr, params);
var potentialQuests = GameData.getQuestDataByConditions(condType, params[0], paramStr);
Expand All @@ -502,15 +502,17 @@ public void triggerEvent(QuestCond condType, String paramStr, int... params) {
return;
}
val acceptCond = questData.getAcceptCond();
int[] accept = new int[acceptCond.size()];
acceptProgressLists.putIfAbsent(questData.getId(), new int[acceptCond.size()]);
for (int i = 0; i < acceptCond.size(); i++) {
val condition = acceptCond.get(i);
boolean result =
questSystem.triggerCondition(owner, questData, condition, paramStr, params);
accept[i] = result ? 1 : 0;
if (condition.getType() == condType) {
boolean result =
questSystem.triggerCondition(owner, questData, condition, paramStr, params);
acceptProgressLists.get(questData.getId())[i] = result ? 1 : 0;
}
}

boolean shouldAccept = LogicType.calculate(questData.getAcceptCondComb(), accept);
boolean shouldAccept = LogicType.calculate(questData.getAcceptCondComb(), acceptProgressLists.get(questData.getId()));
if (this.loggedQuests.contains(questData.getId())) {
Grasscutter.getLogger()
.debug(
Expand All @@ -522,7 +524,7 @@ public void triggerEvent(QuestCond condType, String paramStr, int... params) {
Arrays.stream(params)
.mapToObj(String::valueOf)
.collect(Collectors.joining(", ")));
for (var i = 0; i < accept.length; i++) {
for (var i = 0; i < acceptCond.size(); i++) {
var condition = acceptCond.get(i);
Grasscutter.getLogger()
.debug(
Expand All @@ -532,14 +534,14 @@ public void triggerEvent(QuestCond condType, String paramStr, int... params) {
.filter(value -> value > 0)
.mapToObj(String::valueOf)
.collect(Collectors.joining(", ")),
accept[i] == 1 ? "success" : "failure");
acceptProgressLists.get(questData.getId())[i] == 1 ? "success" : "failure");
}
}

if (shouldAccept) {
GameQuest quest = owner.getQuestManager().addQuest(questData);
Grasscutter.getLogger()
.debug("Added quest {} result {}", questData.getSubId(), quest != null);
.debug("Added quest {}", questData.getSubId());
}
});
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package emu.grasscutter.game.quest.conditions;

import emu.grasscutter.data.excels.quest.QuestData;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.quest.QuestValueCond;
import emu.grasscutter.game.quest.enums.QuestCond;

@QuestValueCond(QuestCond.QUEST_COND_ITEM_GIVING_FINISHED)
public class ConditionItemGivingFinished extends BaseCondition {

@Override
public boolean execute(
Player owner,
QuestData questData,
QuestData.QuestAcceptCondition condition,
String paramStr,
int... params) {
return condition.getParam()[0] == params[0] && (condition.getParam()[1] == 0 || condition.getParam()[1] == params[1]);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
import emu.grasscutter.game.quest.enums.QuestContent;

@QuestValueContent(QuestContent.QUEST_CONTENT_FINISH_ITEM_GIVING)
public final class ContentFinishGivingItem extends BaseContent {
public final class ContentFinishItemGiving extends BaseContent {
@Override
public boolean execute(
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
return condition.getParam()[0] == params[0] && condition.getParam()[1] == params[1];
return condition.getParam()[0] == params[0] && (condition.getParam()[1] == 0 || condition.getParam()[1] == params[1]);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public enum QuestCond implements QuestTrigger {
QUEST_COND_PLAYER_LEVEL_EQUAL_GREATER(17),
QUEST_COND_SCENE_AREA_UNLOCKED(18), // missing, only NPC groups/talks
QUEST_COND_ITEM_GIVING_ACTIVED(19), // missing
QUEST_COND_ITEM_GIVING_FINISHED(20), // missing
QUEST_COND_ITEM_GIVING_FINISHED(20),
QUEST_COND_IS_DAYTIME(21), // only NPC groups
QUEST_COND_CURRENT_AVATAR(22), // missing
QUEST_COND_CURRENT_AREA(23), // missing
Expand Down
8 changes: 7 additions & 1 deletion src/main/java/emu/grasscutter/game/world/Scene.java
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,13 @@ public void killEntity(GameEntity target, int attackerId) {
"Can not solve monster drop: drop_id = {}, drop_tag = {}. Falling back to legacy drop system.",
monster.getMetaMonster().drop_id,
monster.getMetaMonster().drop_tag);
getWorld().getServer().getDropSystemLegacy().callDrop(monster);
world.getServer().getDropSystemLegacy().callDrop(monster);
}
}

if (target instanceof EntityGadget gadget) {
if (gadget.getMetaGadget() != null) {
world.getServer().getDropSystem().handleChestDrop(gadget.getMetaGadget().drop_id, gadget.getMetaGadget().drop_count, gadget);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
public class SceneGadget extends SceneObject {
public int gadget_id;
public int chest_drop_id;
public int drop_id;
public int drop_count;
public String drop_tag;
boolean showcutscene;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.GameData;
import emu.grasscutter.game.quest.enums.QuestCond;
import emu.grasscutter.game.quest.enums.QuestContent;
import emu.grasscutter.net.packet.*;
import emu.grasscutter.net.proto.ItemGivingReqOuterClass.ItemGivingReq;
Expand Down Expand Up @@ -50,8 +51,9 @@ public void handle(GameSession session, byte[] header, byte[] payload) throws Ex
player.sendPacket(new PacketItemGivingRsp(giveId, Mode.EXACT_SUCCESS));
// Remove the action from the active givings.
questManager.removeGivingItemAction(giveId);
// Queue the content action.
// Queue the content and condition actions.
questManager.queueEvent(QuestContent.QUEST_CONTENT_FINISH_ITEM_GIVING, giveId, 0);
questManager.queueEvent(QuestCond.QUEST_COND_ITEM_GIVING_FINISHED, giveId, 0);
}
case GIVING_METHOD_VAGUE_GROUP -> {
var matchedGroups = new ArrayList<Integer>();
Expand Down Expand Up @@ -96,8 +98,9 @@ public void handle(GameSession session, byte[] header, byte[] payload) throws Ex
player.sendPacket(new PacketItemGivingRsp(matchedGroups.get(0), Mode.GROUP_SUCCESS));
// Mark the giving action as completed.
questManager.markCompleted(giveId);
// Queue the content action.
questManager.queueEvent(QuestContent.QUEST_CONTENT_FINISH_ITEM_GIVING, giveId, 0);
// Queue the content and condition actions.
questManager.queueEvent(QuestContent.QUEST_CONTENT_FINISH_ITEM_GIVING, giveId, matchedGroups.get(0));
questManager.queueEvent(QuestCond.QUEST_COND_ITEM_GIVING_FINISHED, giveId, matchedGroups.get(0));
}
}
}
Expand Down