Copy some files from Grasscutter-Quests

NOT completely finished, nor is it completely done. Protocol issues remain! (including lack of packet IDs)
This commit is contained in:
KingRainbow44
2023-04-01 18:06:30 -04:00
parent 262ee38ded
commit daa51e53b7
381 changed files with 10285 additions and 9150 deletions

View File

@@ -1,443 +1,490 @@
package emu.grasscutter.game.quest;
import dev.morphia.annotations.Entity;
import dev.morphia.annotations.Id;
import dev.morphia.annotations.Indexed;
import dev.morphia.annotations.Transient;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.binout.MainQuestData;
import emu.grasscutter.data.binout.MainQuestData.SubQuestData;
import emu.grasscutter.data.binout.MainQuestData.TalkData;
import emu.grasscutter.data.binout.ScriptSceneData;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.data.excels.RewardData;
import emu.grasscutter.database.DatabaseHelper;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.ActionReason;
import emu.grasscutter.game.quest.enums.LogicType;
import emu.grasscutter.game.quest.enums.ParentQuestState;
import emu.grasscutter.game.quest.enums.QuestState;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.net.proto.ChildQuestOuterClass.ChildQuest;
import emu.grasscutter.net.proto.ParentQuestOuterClass.ParentQuest;
import emu.grasscutter.scripts.ScriptLoader;
import emu.grasscutter.server.packet.send.PacketCodexDataUpdateNotify;
import emu.grasscutter.server.packet.send.PacketFinishedParentQuestUpdateNotify;
import emu.grasscutter.server.packet.send.PacketQuestProgressUpdateNotify;
import emu.grasscutter.utils.Position;
import java.util.*;
import javax.script.Bindings;
import javax.script.CompiledScript;
import javax.script.ScriptException;
import lombok.Getter;
import org.bson.types.ObjectId;
@Entity(value = "quests", useDiscriminator = false)
public class GameMainQuest {
@Getter List<QuestGroupSuite> questGroupSuites;
@Getter int[] suggestTrackMainQuestList;
@Id private ObjectId id;
@Indexed @Getter private int ownerUid;
@Transient @Getter private Player owner;
@Transient @Getter private QuestManager questManager;
@Getter private Map<Integer, GameQuest> childQuests;
@Getter private int parentQuestId;
@Getter private int[] questVars;
// QuestUpdateQuestVarReq is sent in two stages...
@Getter private List<Integer> questVarsUpdate;
@Getter private ParentQuestState state;
@Getter private boolean isFinished;
@Getter private Map<Integer, TalkData> talks;
// key is subId
private Map<Integer, Position> rewindPositions;
private Map<Integer, Position> rewindRotations;
@Deprecated // Morphia only. Do not use.
public GameMainQuest() {}
public GameMainQuest(Player player, int parentQuestId) {
this.owner = player;
this.ownerUid = player.getUid();
this.questManager = player.getQuestManager();
this.parentQuestId = parentQuestId;
this.childQuests = new HashMap<>();
this.talks = new HashMap<>();
// official server always has a list of 5 questVars, with default value 0
this.questVars = new int[] {0, 0, 0, 0, 0};
this.state = ParentQuestState.PARENT_QUEST_STATE_NONE;
this.questGroupSuites = new ArrayList<>();
this.rewindPositions = new HashMap<>();
this.rewindRotations = new HashMap<>();
addAllChildQuests();
addRewindPoints();
}
private void addAllChildQuests() {
List<Integer> subQuestIds =
Arrays.stream(GameData.getMainQuestDataMap().get(this.parentQuestId).getSubQuests())
.map(SubQuestData::getSubId)
.toList();
for (Integer subQuestId : subQuestIds) {
QuestData questConfig = GameData.getQuestDataMap().get(subQuestId);
this.childQuests.put(subQuestId, new GameQuest(this, questConfig));
}
}
public void setOwner(Player player) {
if (player.getUid() != this.getOwnerUid()) return;
this.owner = player;
}
public int getQuestVar(int i) {
return questVars[i];
}
public void setQuestVar(int i, int value) {
int previousValue = this.questVars[i];
this.questVars[i] = value;
Grasscutter.getLogger()
.debug("questVar {} value changed from {} to {}", i, previousValue, value);
}
public void incQuestVar(int i, int inc) {
int previousValue = this.questVars[i];
this.questVars[i] += inc;
Grasscutter.getLogger()
.debug(
"questVar {} value incremented from {} to {}", i, previousValue, previousValue + inc);
}
public void decQuestVar(int i, int dec) {
int previousValue = this.questVars[i];
this.questVars[i] -= dec;
Grasscutter.getLogger()
.debug(
"questVar {} value decremented from {} to {}", i, previousValue, previousValue - dec);
}
public GameQuest getChildQuestById(int id) {
return this.getChildQuests().get(id);
}
public GameQuest getChildQuestByOrder(int order) {
return this.getChildQuests().values().stream()
.filter(p -> p.getQuestData().getOrder() == order)
.toList()
.get(0);
}
public void finish() {
this.isFinished = true;
this.state = ParentQuestState.PARENT_QUEST_STATE_FINISHED;
this.getOwner().getSession().send(new PacketFinishedParentQuestUpdateNotify(this));
this.getOwner().getSession().send(new PacketCodexDataUpdateNotify(this));
this.save();
// Add rewards
MainQuestData mainQuestData = GameData.getMainQuestDataMap().get(this.getParentQuestId());
if (mainQuestData != null && mainQuestData.getRewardIdList() != null) {
for (int rewardId : mainQuestData.getRewardIdList()) {
RewardData rewardData = GameData.getRewardDataMap().get(rewardId);
if (rewardData == null) {
continue;
}
getOwner()
.getInventory()
.addItemParamDatas(rewardData.getRewardItemList(), ActionReason.QuestReward);
}
}
// handoff main quest
if (mainQuestData.getSuggestTrackMainQuestList() != null) {
Arrays.stream(mainQuestData.getSuggestTrackMainQuestList())
.forEach(getQuestManager()::startMainQuest);
}
}
// TODO
public void fail() {}
public void cancel() {}
// Rewinds to the last finished/unfinished rewind quest, and returns the avatar rewind position
// (if it exists)
public List<Position> rewind() {
if (this.questManager == null) {
this.questManager = getOwner().getQuestManager();
}
List<GameQuest> sortedByOrder =
new ArrayList<>(
getChildQuests().values().stream().filter(q -> q.getQuestData().isRewind()).toList());
sortedByOrder.sort(
(a, b) -> {
if (a == b) {
return 0;
}
return a.getQuestData().getOrder() > b.getQuestData().getOrder() ? 1 : -1;
});
boolean didRewind = false;
for (GameQuest quest : sortedByOrder) {
int i = sortedByOrder.indexOf(quest);
if ((i + 1) >= sortedByOrder.size()) {
didRewind = quest.rewind(null);
} else {
didRewind = quest.rewind(sortedByOrder.get(i + 1));
}
if (didRewind) {
break;
}
}
List<GameQuest> rewindQuests =
getChildQuests().values().stream()
.filter(
p ->
(p.getState() == QuestState.QUEST_STATE_UNFINISHED
|| p.getState() == QuestState.QUEST_STATE_FINISHED)
&& p.getQuestData().isRewind())
.toList();
for (GameQuest quest : rewindQuests) {
if (rewindPositions.containsKey(quest.getSubQuestId())) {
List<Position> posAndRot = new ArrayList<>();
posAndRot.add(0, rewindPositions.get(quest.getSubQuestId()));
posAndRot.add(1, rewindRotations.get(quest.getSubQuestId()));
return posAndRot;
}
}
return null;
}
public void addRewindPoints() {
Bindings bindings = ScriptLoader.getEngine().createBindings();
String script = "Quest/Share/Q" + getParentQuestId() + "ShareConfig.lua";
CompiledScript cs = ScriptLoader.getScript(script);
// mainQuest 303 doesn't have a ShareConfig
if (cs == null) {
Grasscutter.getLogger().debug("Couldn't find " + script);
return;
}
// Eval script
try {
cs.eval(bindings);
var rewindDataMap =
ScriptLoader.getSerializer().toMap(RewindData.class, bindings.get("rewind_data"));
for (String subId : rewindDataMap.keySet()) {
RewindData questRewind = rewindDataMap.get(subId);
if (questRewind != null) {
RewindData.AvatarData avatarData = questRewind.getAvatar();
if (avatarData != null) {
String avatarPos = avatarData.getPos();
QuestData.Guide guide =
GameData.getQuestDataMap().get(Integer.valueOf(subId)).getGuide();
if (guide != null) {
int sceneId = guide.getGuideScene();
ScriptSceneData fullGlobals =
GameData.getScriptSceneDataMap().get("flat.luas.scenes.full_globals.lua.json");
if (fullGlobals != null) {
ScriptSceneData.ScriptObject dummyPointScript =
fullGlobals
.getScriptObjectList()
.get(sceneId + "/scene" + sceneId + "_dummy_points.lua");
if (dummyPointScript != null) {
Map<String, List<Float>> dummyPointMap = dummyPointScript.getDummyPoints();
if (dummyPointMap != null) {
List<Float> avatarPosPos = dummyPointMap.get(avatarPos + ".pos");
if (avatarPosPos != null) {
Position pos =
new Position(
avatarPosPos.get(0), avatarPosPos.get(1), avatarPosPos.get(2));
List<Float> avatarPosRot = dummyPointMap.get(avatarPos + ".rot");
Position rot =
new Position(
avatarPosRot.get(0), avatarPosRot.get(1), avatarPosRot.get(2));
rewindPositions.put(Integer.valueOf(subId), pos);
rewindRotations.put(Integer.valueOf(subId), rot);
Grasscutter.getLogger()
.debug("Succesfully loaded rewind position for subQuest {}", subId);
}
}
}
}
}
}
}
}
} catch (ScriptException e) {
Grasscutter.getLogger().error("An error occurred while loading rewind positions");
}
}
public void tryAcceptSubQuests(QuestTrigger condType, String paramStr, int... params) {
try {
List<GameQuest> subQuestsWithCond =
getChildQuests().values().stream()
.filter(p -> p.getState() == QuestState.QUEST_STATE_UNSTARTED)
.filter(
p ->
p.getQuestData().getAcceptCond().stream()
.anyMatch(q -> q.getType() == condType))
.toList();
for (GameQuest subQuestWithCond : subQuestsWithCond) {
List<QuestData.QuestCondition> acceptCond = subQuestWithCond.getQuestData().getAcceptCond();
int[] accept = new int[acceptCond.size()];
for (int i = 0; i < subQuestWithCond.getQuestData().getAcceptCond().size(); i++) {
QuestData.QuestCondition condition = acceptCond.get(i);
boolean result =
this.getOwner()
.getServer()
.getQuestSystem()
.triggerCondition(subQuestWithCond, condition, paramStr, params);
accept[i] = result ? 1 : 0;
}
boolean shouldAccept =
LogicType.calculate(subQuestWithCond.getQuestData().getAcceptCondComb(), accept);
if (shouldAccept) {
subQuestWithCond.start();
getQuestManager().getAddToQuestListUpdateNotify().add(subQuestWithCond);
}
}
this.save();
} catch (Exception e) {
Grasscutter.getLogger().error("An error occurred while trying to accept quest.", e);
}
}
public void tryFailSubQuests(QuestTrigger condType, String paramStr, int... params) {
try {
List<GameQuest> subQuestsWithCond =
getChildQuests().values().stream()
.filter(p -> p.getState() == QuestState.QUEST_STATE_UNFINISHED)
.filter(
p ->
p.getQuestData().getFailCond().stream()
.anyMatch(q -> q.getType() == condType))
.toList();
for (GameQuest subQuestWithCond : subQuestsWithCond) {
List<QuestData.QuestCondition> failCond = subQuestWithCond.getQuestData().getFailCond();
for (int i = 0; i < subQuestWithCond.getQuestData().getFailCond().size(); i++) {
QuestData.QuestCondition 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;
if (result) {
getOwner().getSession().send(new PacketQuestProgressUpdateNotify(subQuestWithCond));
}
}
}
boolean shouldFail =
LogicType.calculate(
subQuestWithCond.getQuestData().getFailCondComb(),
subQuestWithCond.getFailProgressList());
if (shouldFail) {
subQuestWithCond.fail();
getQuestManager().getAddToQuestListUpdateNotify().add(subQuestWithCond);
}
}
} catch (Exception e) {
Grasscutter.getLogger().error("An error occurred while trying to fail quest.", e);
}
}
public void tryFinishSubQuests(QuestTrigger condType, String paramStr, int... params) {
try {
List<GameQuest> subQuestsWithCond =
getChildQuests().values().stream()
// There are subQuests with no acceptCond, but can be finished (example: 35104)
.filter(
p ->
p.getState() == QuestState.QUEST_STATE_UNFINISHED
&& p.getQuestData().getAcceptCond() != null)
.filter(
p ->
p.getQuestData().getFinishCond().stream()
.anyMatch(q -> q.getType() == condType))
.toList();
for (GameQuest subQuestWithCond : subQuestsWithCond) {
List<QuestData.QuestCondition> finishCond = subQuestWithCond.getQuestData().getFinishCond();
for (int i = 0; i < finishCond.size(); i++) {
QuestData.QuestCondition condition = finishCond.get(i);
if (condition.getType() == condType) {
boolean result =
this.getOwner()
.getServer()
.getQuestSystem()
.triggerContent(subQuestWithCond, condition, paramStr, params);
subQuestWithCond.getFinishProgressList()[i] = result ? 1 : 0;
if (result) {
getOwner().getSession().send(new PacketQuestProgressUpdateNotify(subQuestWithCond));
}
}
}
boolean shouldFinish =
LogicType.calculate(
subQuestWithCond.getQuestData().getFinishCondComb(),
subQuestWithCond.getFinishProgressList());
if (shouldFinish) {
subQuestWithCond.finish();
getQuestManager().getAddToQuestListUpdateNotify().add(subQuestWithCond);
}
}
} catch (Exception e) {
Grasscutter.getLogger().debug("An error occurred while trying to finish quest.", e);
}
}
public void save() {
DatabaseHelper.saveQuest(this);
}
public void delete() {
DatabaseHelper.deleteQuest(this);
}
public ParentQuest toProto() {
ParentQuest.Builder proto =
ParentQuest.newBuilder().setParentQuestId(getParentQuestId()).setIsFinished(isFinished());
proto
.setParentQuestState(getState().getValue())
.setVideoKey(QuestManager.getQuestKey(parentQuestId));
for (GameQuest quest : this.getChildQuests().values()) {
if (quest.getState() != QuestState.QUEST_STATE_UNSTARTED) {
ChildQuest childQuest =
ChildQuest.newBuilder()
.setQuestId(quest.getSubQuestId())
.setState(quest.getState().getValue())
.build();
proto.addChildQuestList(childQuest);
}
}
for (int i : getQuestVars()) {
proto.addQuestVar(i);
}
return proto.build();
}
}
package emu.grasscutter.game.quest;
import dev.morphia.annotations.Entity;
import dev.morphia.annotations.Id;
import dev.morphia.annotations.Indexed;
import dev.morphia.annotations.Transient;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.binout.MainQuestData;
import emu.grasscutter.data.binout.MainQuestData.SubQuestData;
import emu.grasscutter.data.binout.MainQuestData.TalkData;
import emu.grasscutter.data.binout.ScriptSceneData;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.data.excels.RewardData;
import emu.grasscutter.database.DatabaseHelper;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.ActionReason;
import emu.grasscutter.game.quest.enums.*;
import emu.grasscutter.game.world.World;
import emu.grasscutter.net.proto.ChildQuestOuterClass.ChildQuest;
import emu.grasscutter.net.proto.ParentQuestOuterClass.ParentQuest;
import emu.grasscutter.server.packet.send.PacketCodexDataUpdateNotify;
import emu.grasscutter.server.packet.send.PacketFinishedParentQuestUpdateNotify;
import emu.grasscutter.server.packet.send.PacketQuestProgressUpdateNotify;
import emu.grasscutter.utils.ConversionUtils;
import emu.grasscutter.utils.Position;
import lombok.Getter;
import lombok.val;
import org.bson.types.ObjectId;
import java.util.*;
@Entity(value = "quests", useDiscriminator = false)
public class GameMainQuest {
@Id private ObjectId id;
@Indexed @Getter private int ownerUid;
@Transient @Getter private Player owner;
@Transient @Getter private QuestManager questManager;
@Getter private Map<Integer, GameQuest> childQuests;
@Getter private int parentQuestId;
@Getter private int[] questVars;
@Getter private long[] timeVar;
//QuestUpdateQuestVarReq is sent in two stages...
@Getter private List<Integer> questVarsUpdate;
@Getter private ParentQuestState state;
@Getter private boolean isFinished;
@Getter List<QuestGroupSuite> questGroupSuites;
@Getter int[] suggestTrackMainQuestList;
@Getter private Map<Integer,TalkData> talks;
@Deprecated // Morphia only. Do not use.
public GameMainQuest() {}
public GameMainQuest(Player player, int parentQuestId) {
this.owner = player;
this.ownerUid = player.getUid();
this.questManager = player.getQuestManager();
this.parentQuestId = parentQuestId;
this.childQuests = new HashMap<>();
this.talks = new HashMap<>();
//official server always has a list of 5 questVars, with default value 0
this.questVars = new int[] {0,0,0,0,0};
this.timeVar = new long[] {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}; // theoretically max is 10 here
this.state = ParentQuestState.PARENT_QUEST_STATE_NONE;
this.questGroupSuites = new ArrayList<>();
addAllChildQuests();
}
private void addAllChildQuests() {
List<Integer> subQuestIds = Arrays.stream(GameData.getMainQuestDataMap().get(this.parentQuestId).getSubQuests()).map(SubQuestData::getSubId).toList();
for (Integer subQuestId : subQuestIds) {
QuestData questConfig = GameData.getQuestDataMap().get(subQuestId);
this.childQuests.put(subQuestId, new GameQuest(this, questConfig));
}
}
public Collection<GameQuest> getActiveQuests(){
return childQuests.values().stream()
.filter(q->q.getState().getValue() == QuestState.QUEST_STATE_UNFINISHED.getValue())
.toList();
}
public void setOwner(Player player) {
if (player.getUid() != this.getOwnerUid()) return;
this.owner = player;
}
public int getQuestVar(int i) {
return questVars[i];
}
public void setQuestVar(int i, int value) {
int previousValue = this.questVars[i];
this.questVars[i] = value;
Grasscutter.getLogger().debug("questVar {} value changed from {} to {}", i, previousValue, value);
}
public void incQuestVar(int i, int inc) {
int previousValue = this.questVars[i];
this.questVars[i] += inc;
Grasscutter.getLogger().debug("questVar {} value incremented from {} to {}", i, previousValue, previousValue + inc);
}
public void decQuestVar(int i, int dec) {
int previousValue = this.questVars[i];
this.questVars[i] -= dec;
Grasscutter.getLogger().debug("questVar {} value decremented from {} to {}", i, previousValue, previousValue - dec);
}
public GameQuest getChildQuestById(int id) {
return this.getChildQuests().get(id);
}
public GameQuest getChildQuestByOrder(int order) {
return this.getChildQuests().values().stream().filter(p -> p.getQuestData().getOrder() == order).toList().get(0);
}
public void finish() {
// Avoid recursion from child finish() in GameQuest
// when auto finishing all child quests with QUEST_STATE_UNFINISHED (below)
if (this.isFinished) {
Grasscutter.getLogger().debug("Skip main quest finishing because it's already finished");
return;
}
this.isFinished = true;
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));
this.save();
// Add rewards
MainQuestData mainQuestData = GameData.getMainQuestDataMap().get(this.getParentQuestId());
if(mainQuestData.getRewardIdList()!=null) {
for (int rewardId : mainQuestData.getRewardIdList()) {
RewardData rewardData = GameData.getRewardDataMap().get(rewardId);
if (rewardData == null) {
continue;
}
getOwner().getInventory().addItemParamDatas(rewardData.getRewardItemList(), ActionReason.QuestReward);
}
}
// handoff main quest
if (mainQuestData.getSuggestTrackMainQuestList() != null) {
Arrays.stream(mainQuestData.getSuggestTrackMainQuestList())
.forEach(getQuestManager()::startMainQuest);
}
}
//TODO
public void fail() {}
public void cancel() {}
public List<Position> rewindTo(GameQuest targetQuest, boolean notifyDelete){
if(targetQuest == null || !targetQuest.rewind(notifyDelete)){
return null;
}
/*if(rewindPositions.isEmpty()){
addRewindPoints();
}*/
List<Position> posAndRot = new ArrayList<>();
if(hasRewindPosition(targetQuest.getSubQuestId(), posAndRot)){
return posAndRot;
}
List<GameQuest> rewindQuests = getChildQuests().values().stream()
.filter(p -> (p.getState() == QuestState.QUEST_STATE_UNFINISHED || p.getState() == QuestState.QUEST_STATE_FINISHED) &&
p.getQuestData() != null && p.getQuestData().isRewind()).toList();
for (GameQuest quest : rewindQuests) {
if (hasRewindPosition(quest.getSubQuestId(), posAndRot)) {
return posAndRot;
}
}
return null;
}
// Rewinds to the last finished/unfinished rewind quest, and returns the avatar rewind position (if it exists)
public List<Position> rewind() {
if (this.questManager == null) {
this.questManager = getOwner().getQuestManager();
}
var activeQuests = getActiveQuests();
var highestActiveQuest = activeQuests.stream()
.filter(q -> q.getQuestData() != null)
.max(Comparator.comparing(q -> q.getQuestData().getOrder()))
.orElse(null);
if (highestActiveQuest == null) {
var firstUnstarted = getChildQuests().values().stream()
.filter(q -> q.getQuestData() != null && q.getState().getValue() != QuestState.FINISHED.getValue())
.min(Comparator.comparingInt(a -> a.getQuestData().getOrder()));
if(firstUnstarted.isEmpty()){
// all quests are probably finished, do don't rewind and maybe also set the mainquest to finished?
return null;
}
highestActiveQuest = firstUnstarted.get();
//todo maybe try to accept quests if there is no active quest and no rewind target?
//tryAcceptSubQuests(QuestTrigger.QUEST_COND_NONE, "", 0);
}
var highestOrder = highestActiveQuest.getQuestData().getOrder();
var rewindTarget = getChildQuests().values().stream()
.filter(q -> q.getQuestData() != null)
.filter(q -> q.getQuestData().isRewind() && q.getQuestData().getOrder() <= highestOrder)
.max(Comparator.comparingInt(a -> a.getQuestData().getOrder()))
.orElse(null);
return rewindTo(rewindTarget!=null? rewindTarget : highestActiveQuest, false);
}
public boolean hasRewindPosition(int subId, List<Position> posAndRot){
RewindData questRewind = GameData.getRewindDataMap().get(subId);
if (questRewind == null) return false;
RewindData.AvatarData avatarData = questRewind.getAvatar();
if (avatarData == null) return false;
String avatarPos = avatarData.getPos();
QuestData.Guide guide = GameData.getQuestDataMap().get(subId).getGuide();
if (guide == null) return false;
int sceneId = guide.getGuideScene();
ScriptSceneData fullGlobals = GameData.getScriptSceneDataMap().get("flat.luas.scenes.full_globals.lua.json");
if (fullGlobals == null) return false;
ScriptSceneData.ScriptObject dummyPointScript = fullGlobals.getScriptObjectList().get(sceneId + "/scene" + sceneId + "_dummy_points.lua");
if (dummyPointScript == null) return false;
Map<String, List<Float>> dummyPointMap = dummyPointScript.getDummyPoints();
if (dummyPointMap == null) return false;
List<Float> avatarPosPos = dummyPointMap.get(avatarPos + ".pos");
List<Float> avatarPosRot = dummyPointMap.get(avatarPos + ".rot");
if (avatarPosPos == null) return false;
posAndRot.add(0, new Position(avatarPosPos.get(0),avatarPosPos.get(1),avatarPosPos.get(2))); // position
posAndRot.add(1, new Position(avatarPosRot.get(0),avatarPosRot.get(1),avatarPosRot.get(2))); //rotation
Grasscutter.getLogger().info("Succesfully loaded rewind data for subQuest {}", subId);
return true;
}
public boolean hasTeleportPostion(int subId, List<Position> posAndRot){
TeleportData questTransmit = GameData.getTeleportDataMap().get(subId);
if (questTransmit == null) return false;
TeleportData.TransmitPoint transmitPoint = questTransmit.getTransmit_points().size() > 0 ? questTransmit.getTransmit_points().get(0) : null;
if (transmitPoint == null) return false;
String transmitPos = transmitPoint.getPos();
int sceneId = transmitPoint.getScene_id();
ScriptSceneData fullGlobals = GameData.getScriptSceneDataMap().get("flat.luas.scenes.full_globals.lua.json");
if (fullGlobals == null) return false;
ScriptSceneData.ScriptObject dummyPointScript = fullGlobals.getScriptObjectList().get(sceneId + "/scene" + sceneId + "_dummy_points.lua");
if (dummyPointScript == null) return false;
Map<String, List<Float>> dummyPointMap = dummyPointScript.getDummyPoints();
if (dummyPointMap == null) return false;
List<Float> transmitPosPos = dummyPointMap.get(transmitPos + ".pos");
List<Float> transmitPosRot = dummyPointMap.get(transmitPos + ".rot");
if (transmitPosPos == null) return false;
posAndRot.add(0, new Position(transmitPosPos.get(0), transmitPosPos.get(1), transmitPosPos.get(2))); // position
posAndRot.add(1, new Position(transmitPosRot.get(0), transmitPosRot.get(1), transmitPosRot.get(2))); // rotation
Grasscutter.getLogger().info("Succesfully loaded teleport data for subQuest {}", subId);
return true;
}
public void checkProgress(){
for (var quest : getChildQuests().values()){
if(quest.getState() == QuestState.QUEST_STATE_UNFINISHED) {
questManager.checkQuestAlreadyFullfilled(quest);
}
}
}
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 = getChildQuests().values().stream()
.filter(p -> p.getState() == QuestState.QUEST_STATE_UNFINISHED)
.filter(p -> p.getQuestData().getFailCond().stream().anyMatch(q -> q.getType() == condType))
.toList();
for (GameQuest subQuestWithCond : subQuestsWithCond) {
val failCond = subQuestWithCond.getQuestData().getFailCond();
for (int i = 0; i < subQuestWithCond.getQuestData().getFailCond().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;
if (result) {
getOwner().getSession().send(new PacketQuestProgressUpdateNotify(subQuestWithCond));
}
}
}
boolean shouldFail = LogicType.calculate(subQuestWithCond.getQuestData().getFailCondComb(), subQuestWithCond.getFailProgressList());
if (shouldFail)
subQuestWithCond.fail();
}
} catch (Exception e) {
Grasscutter.getLogger().error("An error occurred while trying to fail quest.", e);
}
}
public void tryFinishSubQuests(QuestContent condType, String paramStr, int... params) {
try {
List<GameQuest> subQuestsWithCond = getChildQuests().values().stream()
//There are subQuests with no acceptCond, but can be finished (example: 35104)
.filter(p -> p.getState() == QuestState.QUEST_STATE_UNFINISHED && p.getQuestData().getAcceptCond() != null)
.filter(p -> p.getQuestData().getFinishCond().stream().anyMatch(q -> q.getType() == condType))
.toList();
for (GameQuest subQuestWithCond : subQuestsWithCond) {
val finishCond = subQuestWithCond.getQuestData().getFinishCond();
for (int i = 0; i < finishCond.size(); i++) {
val condition = finishCond.get(i);
if (condition.getType() == condType) {
boolean result = this.getOwner().getServer().getQuestSystem().triggerContent(subQuestWithCond, condition, paramStr, params);
subQuestWithCond.getFinishProgressList()[i] = result ? 1 : 0;
if (result) {
getOwner().getSession().send(new PacketQuestProgressUpdateNotify(subQuestWithCond));
}
}
}
boolean shouldFinish = LogicType.calculate(subQuestWithCond.getQuestData().getFinishCondComb(), subQuestWithCond.getFinishProgressList());
if (shouldFinish)
subQuestWithCond.finish();
}
} catch (Exception e) {
Grasscutter.getLogger().debug("An error occurred while trying to finish quest.", e);
}
}
public void save() {
DatabaseHelper.saveQuest(this);
}
public void delete() {
DatabaseHelper.deleteQuest(this);
}
public ParentQuest toProto(boolean withChildQuests) {
var proto = ParentQuest.newBuilder()
.setParentQuestId(getParentQuestId())
.setIsFinished(isFinished())
.setParentQuestState(getState().getValue())
.setVideoKey(QuestManager.getQuestKey(parentQuestId));
if (withChildQuests) {
for (var quest : this.getChildQuests().values()) {
if (quest.getState() != QuestState.QUEST_STATE_UNSTARTED) {
var childQuest = ChildQuest.newBuilder()
.setQuestId(quest.getSubQuestId())
.setState(quest.getState().getValue())
.build();
proto.addChildQuestList(childQuest);
}
}
}
for (int i : getQuestVars()) {
proto.addQuestVar(i);
}
return proto.build();
}
// TimeVar handling TODO check if ingame or irl time
public boolean initTimeVar(int index){
if(index >= this.timeVar.length){
Grasscutter.getLogger().error("Trying to init out of bounds time var {} for quest {}", index, this.parentQuestId);
return false;
}
this.timeVar[index] = owner.getWorld().getTotalGameTimeMinutes();
owner.getActiveQuestTimers().add(this.parentQuestId);
return true;
}
public boolean clearTimeVar(int index){
if(index >= this.timeVar.length){
Grasscutter.getLogger().error("Trying to clear out of bounds time var {} for quest {}", index, this.parentQuestId);
return false;
}
this.timeVar[index] = -1;
if(!checkActiveTimers()){
owner.getActiveQuestTimers().remove(this.parentQuestId);
}
return true;
}
public boolean checkActiveTimers(){
return Arrays.stream(timeVar).anyMatch(value -> value!=-1);
}
public long getDaysSinceTimeVar(int index){
if(index >= this.timeVar.length){
Grasscutter.getLogger().error("Trying to get days for out of bounds time var {} for quest {}", index, this.parentQuestId);
return -1;
}
val varTime = timeVar[index];
if(varTime == -1){
return 0;
}
return owner.getWorld().getTotalGameTimeDays() - ConversionUtils.gameTimeToDays(varTime);
}
public long getHoursSinceTimeVar(int index){
if(index >= this.timeVar.length){
Grasscutter.getLogger().error("Trying to get hours for out of bounds time var {} for quest {}", index, this.parentQuestId);
return -1;
}
val varTime = timeVar[index];
if(varTime == -1){
return 0;
}
return owner.getWorld().getTotalGameTimeDays() - ConversionUtils.gameTimeToDays(varTime);
}
}

View File

@@ -7,20 +7,25 @@ import emu.grasscutter.data.GameData;
import emu.grasscutter.data.excels.ChapterData;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.data.excels.TriggerExcelConfigData;
import emu.grasscutter.game.dungeons.enums.DungeonPassConditionType;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.ActionReason;
import emu.grasscutter.game.quest.enums.QuestCond;
import emu.grasscutter.game.quest.enums.QuestContent;
import emu.grasscutter.game.quest.enums.QuestState;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.net.proto.ChapterStateOuterClass;
import emu.grasscutter.net.proto.QuestOuterClass.Quest;
import emu.grasscutter.scripts.data.SceneGroup;
import emu.grasscutter.server.packet.send.PacketChapterStateNotify;
import emu.grasscutter.server.packet.send.PacketDelQuestNotify;
import emu.grasscutter.server.packet.send.PacketQuestListUpdateNotify;
import emu.grasscutter.utils.Utils;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.script.Bindings;
import lombok.Getter;
import lombok.Setter;
import lombok.val;
@Entity
public class GameQuest {
@@ -29,12 +34,14 @@ public class GameQuest {
@Getter private int subQuestId;
@Getter private int mainQuestId;
@Getter @Setter private QuestState state;
@Getter @Setter public QuestState state;
@Getter @Setter private int startTime;
@Getter @Setter private int acceptTime;
@Getter @Setter private int finishTime;
@Getter @Setter private long startGameDay;
@Getter private int[] finishProgressList;
@Getter private int[] failProgressList;
@Transient @Getter private Map<String, TriggerExcelConfigData> triggerData;
@@ -55,15 +62,17 @@ public class GameQuest {
}
public void start() {
clearProgress(false);
this.acceptTime = Utils.getCurrentSeconds();
this.startTime = this.acceptTime;
this.startGameDay = getOwner().getWorld().getTotalGameTimeDays();
this.state = QuestState.QUEST_STATE_UNFINISHED;
List<QuestData.QuestCondition> triggerCond =
val triggerCond =
questData.getFinishCond().stream()
.filter(p -> p.getType() == QuestTrigger.QUEST_CONTENT_TRIGGER_FIRE)
.filter(p -> p.getType() == QuestContent.QUEST_CONTENT_TRIGGER_FIRE)
.toList();
if (triggerCond.size() > 0) {
for (QuestData.QuestCondition cond : triggerCond) {
for (val cond : triggerCond) {
TriggerExcelConfigData newTrigger =
GameData.getTriggerExcelConfigDataMap().get(cond.getParam()[0]);
if (newTrigger != null) {
@@ -81,21 +90,10 @@ public class GameQuest {
}
}
if (questData.getFinishCond() != null && questData.getFinishCond().size() != 0) {
this.finishProgressList = new int[questData.getFinishCond().size()];
}
if (questData.getFailCond() != null && questData.getFailCond().size() != 0) {
this.failProgressList = new int[questData.getFailCond().size()];
}
getQuestData()
.getBeginExec()
.forEach(e -> getOwner().getServer().getQuestSystem().triggerExec(this, e, e.getParam()));
getOwner().sendPacket(new PacketQuestListUpdateNotify(this));
if (ChapterData.beginQuestChapterMap.containsKey(subQuestId)) {
mainQuest
.getOwner()
getOwner()
.sendPacket(
new PacketChapterStateNotify(
ChapterData.beginQuestChapterMap.get(subQuestId).getId(),
@@ -104,24 +102,24 @@ public class GameQuest {
// Some subQuests and talks become active when some other subQuests are unfinished (even from
// different MainQuests)
this.getOwner()
getOwner()
.getQuestManager()
.triggerEvent(
QuestTrigger.QUEST_CONTENT_QUEST_STATE_EQUAL,
this.getSubQuestId(),
this.getState().getValue(),
.queueEvent(
QuestContent.QUEST_CONTENT_QUEST_STATE_EQUAL,
getSubQuestId(),
getState().getValue(),
0,
0,
0);
this.getOwner()
getOwner()
.getQuestManager()
.triggerEvent(
QuestTrigger.QUEST_COND_STATE_EQUAL,
this.getSubQuestId(),
this.getState().getValue(),
0,
0,
0);
.queueEvent(
QuestCond.QUEST_COND_STATE_EQUAL, getSubQuestId(), getState().getValue(), 0, 0, 0);
getQuestData()
.getBeginExec()
.forEach(e -> getOwner().getServer().getQuestSystem().triggerExec(this, e, e.getParam()));
getOwner().getQuestManager().checkQuestAlreadyFullfilled(this);
Grasscutter.getLogger().debug("Quest {} is started", subQuestId);
}
@@ -141,7 +139,7 @@ public class GameQuest {
}
public void setConfig(QuestData config) {
if (getSubQuestId() != config.getId()) return;
if (config == null || getSubQuestId() != config.getId()) return;
this.questData = config;
}
@@ -153,11 +151,37 @@ public class GameQuest {
failProgressList[index] = value;
}
public boolean clearProgress(boolean notifyDelete) {
// TODO improve
var oldState = state;
if (questData.getFinishCond() != null && questData.getFinishCond().size() != 0) {
this.finishProgressList = new int[questData.getFinishCond().size()];
}
if (questData.getFailCond() != null && questData.getFailCond().size() != 0) {
this.failProgressList = new int[questData.getFailCond().size()];
}
setState(QuestState.QUEST_STATE_UNSTARTED);
finishTime = 0;
acceptTime = 0;
startTime = 0;
if (oldState == QuestState.QUEST_STATE_UNSTARTED) {
return false;
}
if (notifyDelete) {
getOwner().sendPacket(new PacketDelQuestNotify(getSubQuestId()));
}
save();
return true;
}
public void finish() {
this.state = QuestState.QUEST_STATE_FINISHED;
this.finishTime = Utils.getCurrentSeconds();
if (getQuestData().finishParent()) {
getOwner().sendPacket(new PacketQuestListUpdateNotify(this));
if (getQuestData().isFinishParent()) {
// This quest finishes the questline - the main quest will also save the quest to db, so we
// don't have to call save() here
getMainQuest().finish();
@@ -169,8 +193,8 @@ public class GameQuest {
// Some subQuests have conditions that subQuests are finished (even from different MainQuests)
getOwner()
.getQuestManager()
.triggerEvent(
QuestTrigger.QUEST_CONTENT_QUEST_STATE_EQUAL,
.queueEvent(
QuestContent.QUEST_CONTENT_QUEST_STATE_EQUAL,
this.subQuestId,
this.state.getValue(),
0,
@@ -178,8 +202,16 @@ public class GameQuest {
0);
getOwner()
.getQuestManager()
.triggerEvent(
QuestTrigger.QUEST_COND_STATE_EQUAL, this.subQuestId, this.state.getValue(), 0, 0, 0);
.queueEvent(QuestContent.QUEST_CONTENT_FINISH_PLOT, this.subQuestId, 0);
getOwner()
.getQuestManager()
.queueEvent(
QuestCond.QUEST_COND_STATE_EQUAL, this.subQuestId, this.state.getValue(), 0, 0, 0);
getOwner()
.getScene()
.triggerDungeonEvent(DungeonPassConditionType.DUNGEON_COND_FINISH_QUEST, getSubQuestId());
getOwner().getProgressManager().tryUnlockOpenStates();
if (ChapterData.endQuestChapterMap.containsKey(subQuestId)) {
mainQuest
@@ -190,6 +222,10 @@ public class GameQuest {
ChapterStateOuterClass.ChapterState.CHAPTER_STATE_END));
}
// hard coding to give amber
if (getQuestData().getSubId() == 35402) {
getOwner().getInventory().addItem(1021, 1, ActionReason.QuestItem); // amber item id
}
Grasscutter.getLogger().debug("Quest {} is finished", subQuestId);
}
@@ -198,43 +234,47 @@ public class GameQuest {
this.state = QuestState.QUEST_STATE_FAILED;
this.finishTime = Utils.getCurrentSeconds();
getQuestData()
.getFailExec()
.forEach(e -> getOwner().getServer().getQuestSystem().triggerExec(this, e, e.getParam()));
this.getOwner().sendPacket(new PacketQuestListUpdateNotify(this));
// Some subQuests have conditions that subQuests fail (even from different MainQuests)
getOwner()
this.getOwner()
.getQuestManager()
.triggerEvent(
QuestTrigger.QUEST_CONTENT_QUEST_STATE_EQUAL,
.queueEvent(
QuestContent.QUEST_CONTENT_QUEST_STATE_EQUAL,
this.subQuestId,
this.state.getValue(),
0,
0,
0);
getOwner()
this.getOwner()
.getQuestManager()
.triggerEvent(
QuestTrigger.QUEST_COND_STATE_EQUAL, this.subQuestId, this.state.getValue(), 0, 0, 0);
.queueEvent(
QuestCond.QUEST_COND_STATE_EQUAL, this.subQuestId, this.state.getValue(), 0, 0, 0);
this.getQuestData()
.getFailExec()
.forEach(e -> getOwner().getServer().getQuestSystem().triggerExec(this, e, e.getParam()));
if (this.getQuestData().getTrialAvatarList() != null) {
this.getQuestData()
.getTrialAvatarList()
.forEach(t -> this.getOwner().getTeamManager().removeTrialAvatar(t));
}
Grasscutter.getLogger().debug("Quest {} is failed", subQuestId);
}
// Return true if ParentQuest should rewind to this childQuest
public boolean rewind(GameQuest nextRewind) {
if (questData.isRewind()) {
if (nextRewind == null) {
return true;
}
// if the next isRewind subQuest is none or unstarted, reset all subQuests with order higher
// than this one, and restart this quest
if (nextRewind.getState() == QuestState.QUEST_STATE_NONE
|| nextRewind.getState() == QuestState.QUEST_STATE_UNSTARTED) {
getMainQuest().getChildQuests().values().stream()
.filter(p -> p.getQuestData().getOrder() > this.getQuestData().getOrder())
.forEach(q -> q.setState(QuestState.QUEST_STATE_UNSTARTED));
this.start();
return true;
}
}
return false;
// Return true if it did the rewind
public boolean rewind(boolean notifyDelete) {
getMainQuest().getChildQuests().values().stream()
.filter(p -> p.getQuestData().getOrder() > this.getQuestData().getOrder())
.forEach(
q -> {
q.clearProgress(notifyDelete);
});
clearProgress(notifyDelete);
this.start();
return true;
}
public void save() {

View File

@@ -1,12 +1,12 @@
package emu.grasscutter.game.quest;
import lombok.AccessLevel;
import lombok.Data;
import lombok.experimental.FieldDefaults;
@Data
@FieldDefaults(level = AccessLevel.PRIVATE)
public class QuestEncryptionKey {
int mainQuestId;
long encryptionKey;
}
package emu.grasscutter.game.quest;
import lombok.AccessLevel;
import lombok.Data;
import lombok.experimental.FieldDefaults;
@Data
@FieldDefaults(level = AccessLevel.PRIVATE)
public class QuestEncryptionKey {
int mainQuestId;
long encryptionKey;
}

View File

@@ -1,17 +1,17 @@
package emu.grasscutter.game.quest;
import dev.morphia.annotations.Entity;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Data;
import lombok.experimental.FieldDefaults;
@Entity
@Data
@Builder(builderMethodName = "of")
@FieldDefaults(level = AccessLevel.PRIVATE)
public class QuestGroupSuite {
int scene;
int group;
int suite;
}
package emu.grasscutter.game.quest;
import dev.morphia.annotations.Entity;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Data;
import lombok.experimental.FieldDefaults;
@Entity
@Data
@Builder(builderMethodName = "of")
@FieldDefaults(level = AccessLevel.PRIVATE)
public class QuestGroupSuite {
int scene;
int group;
int suite;
}

View File

@@ -8,34 +8,47 @@ import emu.grasscutter.database.DatabaseHelper;
import emu.grasscutter.game.player.BasePlayerManager;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.quest.enums.ParentQuestState;
import emu.grasscutter.game.quest.enums.QuestCond;
import emu.grasscutter.game.quest.enums.QuestContent;
import emu.grasscutter.game.quest.enums.QuestState;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.server.packet.send.PacketFinishedParentQuestUpdateNotify;
import emu.grasscutter.server.packet.send.PacketQuestListUpdateNotify;
import emu.grasscutter.utils.Position;
import io.netty.util.concurrent.FastThreadLocalThread;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import lombok.Getter;
import lombok.val;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
public class QuestManager extends BasePlayerManager {
private static final Set<Integer> newPlayerMainQuests = Set.of(303, 318, 348, 349, 350, 351, 416, 500,
501, 502, 503, 504, 505, 506, 507, 508, 509, 20000, 20507, 20509, 21004, 21005, 21010, 21011, 21016, 21017,
21020, 21021, 21025, 40063, 70121, 70124, 70511, 71010, 71012, 71013, 71015, 71016, 71017, 71555);
@Getter
private final Player player;
@Getter
private final Int2ObjectMap<GameMainQuest> mainQuests;
@Getter private final Player player;
@Getter private final Int2ObjectMap<GameMainQuest> mainQuests;
private long lastHourCheck = 0;
private long lastDayCheck = 0;
public static final ExecutorService eventExecutor;
static {
eventExecutor = new ThreadPoolExecutor(4, 4,
60, TimeUnit.SECONDS, new LinkedBlockingDeque<>(1000),
FastThreadLocalThread::new, new ThreadPoolExecutor.AbortPolicy());
}
/*
On SetPlayerBornDataReq, the server sends FinishedParentQuestNotify, with this exact
parentQuestList. Captured on Game version 2.7
Note: quest 40063 is already set to finished, with childQuest 4006406's state set to 3
*/
@Getter
private final List<GameQuest> addToQuestListUpdateNotify;
private static Set<Integer> newPlayerMainQuests = Set.of(303,318,348,349,350,351,416,500,
501,502,503,504,505,506,507,508,509,20000,20507,20509,21004,21005,21010,21011,21016,21017,
21020,21021,21025,40063,70121,70124,70511,71010,71012,71013,71015,71016,71017,71555);
/*
On SetPlayerBornDataReq, the server sends ServerCondMeetQuestListUpdateNotify, with this exact
@@ -62,74 +75,119 @@ public class QuestManager extends BasePlayerManager {
*/
public static long getQuestKey(int mainQuestId) {
QuestEncryptionKey questEncryptionKey = GameData.getMainQuestEncryptionMap().get(mainQuestId);
return questEncryptionKey != null ? questEncryptionKey.getEncryptionKey() : 0L;
}
public QuestManager(Player player) {
super(player);
this.player = player;
this.mainQuests = new Int2ObjectOpenHashMap<>();
this.addToQuestListUpdateNotify = new ArrayList<>();
}
public static long getQuestKey(int mainQuestId) {
QuestEncryptionKey questEncryptionKey = GameData.getMainQuestEncryptionMap().get(mainQuestId);
return questEncryptionKey != null ? questEncryptionKey.getEncryptionKey() : 0L;
}
public void onNewPlayerCreate() {
public void onPlayerBorn() {
// TODO scan the quest and start the quest with acceptCond fulfilled
// The off send 3 request in that order: 1. FinishedParentQuestNotify, 2. QuestListNotify, 3. ServerCondMeetQuestListUpdateNotify
List<GameMainQuest> newQuests = this.addMultMainQuests(newPlayerMainQuests);
//getPlayer().sendPacket(new PacketServerCondMeetQuestListUpdateNotify(newPlayerServerCondMeetQuestListUpdateNotify));
for (GameMainQuest mainQuest : newQuests) {
startMainQuest(mainQuest.getParentQuestId());
}
//getPlayer().sendPacket(new PacketFinishedParentQuestUpdateNotify(newQuests));
//getPlayer().sendPacket(new PacketQuestListNotify(subQuests));
//getPlayer().sendPacket(new PacketServerCondMeetQuestListUpdateNotify(newPlayerServerCondMeetQuestListUpdateNotify));
}
public void onLogin() {
List<GameMainQuest> activeQuests = getActiveMainQuests();
List<GameQuest> activeSubs = new ArrayList<>(activeQuests.size());
for (GameMainQuest quest : activeQuests) {
List<Position> rewindPos = quest.rewind(); // <pos, rotation>
var activeQuest = quest.getActiveQuests();
if (rewindPos != null) {
getPlayer().getPosition().set(rewindPos.get(0));
getPlayer().getRotation().set(rewindPos.get(1));
}
if(activeQuest!=null && rewindPos!=null){
//activeSubs.add(activeQuest);
//player.sendPacket(new PacketQuestProgressUpdateNotify(activeQuest));
}
quest.checkProgress();
}
}
public void onTick(){
checkTimeVars();
// trigger game time tick for quests
queueEvent(QuestContent.QUEST_CONTENT_GAME_TIME_TICK,
player.getWorld().getGameTimeHours() , // hours
0);
}
private void checkTimeVars(){
val currentDays = player.getWorld().getTotalGameTimeDays();
val currentHours = player.getWorld().getTotalGameTimeHours();
boolean checkDays = currentDays != lastDayCheck;
boolean checkHours = currentHours != lastHourCheck;
if(!checkDays && !checkHours){
return;
}
this.lastDayCheck = currentDays;
this.lastHourCheck = currentHours;
player.getActiveQuestTimers().forEach(mainQuestId -> {
if(checkHours) {
queueEvent(QuestCond.QUEST_COND_TIME_VAR_GT_EQ, mainQuestId);
queueEvent(QuestContent.QUEST_CONTENT_TIME_VAR_GT_EQ, mainQuestId);
}
if(checkDays) {
queueEvent(QuestCond.QUEST_COND_TIME_VAR_PASS_DAY, mainQuestId);
queueEvent(QuestContent.QUEST_CONTENT_TIME_VAR_PASS_DAY, mainQuestId);
}
});
}
private List<GameMainQuest> addMultMainQuests(Set<Integer> mainQuestIds) {
List<GameMainQuest> newQuests = new ArrayList<>();
for (Integer id : mainQuestIds) {
getMainQuests().put(id.intValue(), new GameMainQuest(this.player, id));
getMainQuests().put(id.intValue(),new GameMainQuest(this.player, id));
getMainQuestById(id).save();
newQuests.add(getMainQuestById(id));
}
return newQuests;
}
public void enableQuests() {
onPlayerBorn();
}
/*
Looking through mainQuests 72201-72208 and 72174, we can infer that a questGlobalVar's default value is 0
*/
public Integer getQuestGlobalVarValue(Integer variable) {
return getPlayer().getQuestGlobalVariables().getOrDefault(variable, 0);
return getPlayer().getQuestGlobalVariables().getOrDefault(variable,0);
}
public void setQuestGlobalVarValue(Integer variable, Integer value) {
Integer previousValue = getPlayer().getQuestGlobalVariables().put(variable, value);
Grasscutter.getLogger().debug("Changed questGlobalVar {} value from {} to {}", variable, previousValue == null ? 0 : previousValue, value);
Integer previousValue = getPlayer().getQuestGlobalVariables().put(variable,value);
Grasscutter.getLogger().debug("Changed questGlobalVar {} value from {} to {}", variable, previousValue==null ? 0: previousValue, value);
}
public void incQuestGlobalVarValue(Integer variable, Integer inc) {
//
Integer previousValue = getPlayer().getQuestGlobalVariables().getOrDefault(variable, 0);
getPlayer().getQuestGlobalVariables().put(variable, previousValue + inc);
Integer previousValue = getPlayer().getQuestGlobalVariables().getOrDefault(variable,0);
getPlayer().getQuestGlobalVariables().put(variable,previousValue + inc);
Grasscutter.getLogger().debug("Incremented questGlobalVar {} value from {} to {}", variable, previousValue, previousValue + inc);
}
//In MainQuest 998, dec is passed as a positive integer
public void decQuestGlobalVarValue(Integer variable, Integer dec) {
//
Integer previousValue = getPlayer().getQuestGlobalVariables().getOrDefault(variable, 0);
getPlayer().getQuestGlobalVariables().put(variable, previousValue - dec);
Integer previousValue = getPlayer().getQuestGlobalVariables().getOrDefault(variable,0);
getPlayer().getQuestGlobalVariables().put(variable,previousValue - dec);
Grasscutter.getLogger().debug("Decremented questGlobalVar {} value from {} to {}", variable, previousValue, previousValue - dec);
}
@@ -137,6 +195,11 @@ public class QuestManager extends BasePlayerManager {
return getMainQuests().get(mainQuestId);
}
public GameMainQuest getMainQuestByTalkId(int talkId) {
int mainQuestId = GameData.getQuestTalkMap().getOrDefault(talkId, talkId / 100);
return getMainQuestById(mainQuestId);
}
public GameQuest getQuestById(int questId) {
QuestData questConfig = GameData.getQuestDataMap().get(questId);
if (questConfig == null) {
@@ -188,6 +251,7 @@ public class QuestManager extends BasePlayerManager {
public GameQuest addQuest(int questId) {
QuestData questConfig = GameData.getQuestDataMap().get(questId);
if (questConfig == null) {
return null;
}
@@ -205,14 +269,7 @@ public class QuestManager extends BasePlayerManager {
// Forcefully start
quest.start();
// Save main quest
mainQuest.save();
// Send packet
getPlayer().sendPacket(new PacketQuestListUpdateNotify(mainQuest.getChildQuests().values().stream()
.filter(p -> p.getState() != QuestState.QUEST_STATE_UNSTARTED)
.toList()));
checkQuestAlreadyFullfilled(quest);
return quest;
}
@@ -228,84 +285,79 @@ public class QuestManager extends BasePlayerManager {
.min(Comparator.comparingInt(MainQuestData.SubQuestData::getOrder))
.map(MainQuestData.SubQuestData::getSubId)
.ifPresent(this::addQuest);
//TODO find a better way then hardcoding to detect needed required quests
if(mainQuestId == 355){
startMainQuest(361);
startMainQuest(418);
startMainQuest(423);
startMainQuest(20509);
}
}
public void queueEvent(QuestCond condType, int... params) {
queueEvent(condType, "", params);
}
public void queueEvent(QuestContent condType, int... params) {
queueEvent(condType, "", params);
}
public void triggerEvent(QuestTrigger condType, int... params) {
triggerEvent(condType, "", params);
public void queueEvent(QuestContent condType, String paramStr, int... params) {
eventExecutor.submit(() -> triggerEvent(condType, paramStr, params));
}
public void queueEvent(QuestCond condType, String paramStr, int... params) {
eventExecutor.submit(() -> triggerEvent(condType, paramStr, params));
}
//TODO
public void triggerEvent(QuestTrigger condType, String paramStr, int... params) {
//QUEST_EXEC are handled directly by each subQuest
public void triggerEvent(QuestCond condType, String paramStr, int... params) {
Grasscutter.getLogger().debug("Trigger Event {}, {}, {}", condType, paramStr, params);
List<GameMainQuest> checkMainQuests = this.getMainQuests().values().stream()
.filter(i -> i.getState() != ParentQuestState.PARENT_QUEST_STATE_FINISHED)
.toList();
switch (condType) {
//accept Conds
case QUEST_COND_STATE_EQUAL:
case QUEST_COND_STATE_NOT_EQUAL:
case QUEST_COND_COMPLETE_TALK:
case QUEST_COND_LUA_NOTIFY:
case QUEST_COND_QUEST_VAR_EQUAL:
case QUEST_COND_QUEST_VAR_GREATER:
case QUEST_COND_QUEST_VAR_LESS:
case QUEST_COND_PLAYER_LEVEL_EQUAL_GREATER:
case QUEST_COND_QUEST_GLOBAL_VAR_EQUAL:
case QUEST_COND_QUEST_GLOBAL_VAR_GREATER:
case QUEST_COND_QUEST_GLOBAL_VAR_LESS:
for (GameMainQuest mainquest : checkMainQuests) {
mainquest.tryAcceptSubQuests(condType, paramStr, params);
}
break;
//fail Conds
case QUEST_CONTENT_NOT_FINISH_PLOT:
for (GameMainQuest mainquest : checkMainQuests) {
mainquest.tryFailSubQuests(condType, paramStr, params);
}
break;
//finish Conds
case QUEST_CONTENT_COMPLETE_TALK:
case QUEST_CONTENT_FINISH_PLOT:
case QUEST_CONTENT_COMPLETE_ANY_TALK:
case QUEST_CONTENT_LUA_NOTIFY:
case QUEST_CONTENT_QUEST_VAR_EQUAL:
case QUEST_CONTENT_QUEST_VAR_GREATER:
case QUEST_CONTENT_QUEST_VAR_LESS:
case QUEST_CONTENT_ENTER_DUNGEON:
case QUEST_CONTENT_ENTER_ROOM:
case QUEST_CONTENT_INTERACT_GADGET:
case QUEST_CONTENT_TRIGGER_FIRE:
case QUEST_CONTENT_UNLOCK_TRANS_POINT:
case QUEST_CONTENT_SKILL:
for (GameMainQuest mainQuest : checkMainQuests) {
mainQuest.tryFinishSubQuests(condType, paramStr, params);
}
break;
//finish Or Fail Conds
case QUEST_CONTENT_GAME_TIME_TICK:
case QUEST_CONTENT_QUEST_STATE_EQUAL:
case QUEST_CONTENT_ADD_QUEST_PROGRESS:
case QUEST_CONTENT_LEAVE_SCENE:
for (GameMainQuest mainQuest : checkMainQuests) {
mainQuest.tryFailSubQuests(condType, paramStr, params);
mainQuest.tryFinishSubQuests(condType, paramStr, params);
}
break;
//QUEST_EXEC are handled directly by each subQuest
//Unused
case QUEST_CONTENT_QUEST_STATE_NOT_EQUAL:
case QUEST_COND_PLAYER_CHOOSE_MALE:
default:
Grasscutter.getLogger().error("Unhandled QuestTrigger {}", condType);
for (GameMainQuest mainquest : checkMainQuests) {
mainquest.tryAcceptSubQuests(condType, paramStr, params);
}
if (this.addToQuestListUpdateNotify.size() != 0) {
this.getPlayer().getSession().send(new PacketQuestListUpdateNotify(this.addToQuestListUpdateNotify));
this.addToQuestListUpdateNotify.clear();
}
public void triggerEvent(QuestContent condType, String paramStr, int... params) {
Grasscutter.getLogger().debug("Trigger Event {}, {}, {}", condType, paramStr, params);
List<GameMainQuest> checkMainQuests = this.getMainQuests().values().stream()
.filter(i -> i.getState() != ParentQuestState.PARENT_QUEST_STATE_FINISHED)
.toList();
for (GameMainQuest mainQuest : checkMainQuests) {
mainQuest.tryFailSubQuests(condType, paramStr, params);
mainQuest.tryFinishSubQuests(condType, paramStr, params);
}
}
/**
* TODO maybe trigger them delayed to allow basic communication finish first
* @param quest
*/
public void checkQuestAlreadyFullfilled(GameQuest quest){
Grasscutter.getGameServer().getScheduler().scheduleDelayedTask(() -> {
for(var condition : quest.getQuestData().getFinishCond()){
switch (condition.getType()) {
case QUEST_CONTENT_OBTAIN_ITEM, QUEST_CONTENT_ITEM_LESS_THAN -> {
//check if we already own enough of the item
var item = getPlayer().getInventory().getItemByGuid(condition.getParam()[0]);
queueEvent(condition.getType(), condition.getParam()[0], item != null ? item.getCount() : 0);
}
case QUEST_CONTENT_UNLOCK_TRANS_POINT -> {
var scenePoints = getPlayer().getUnlockedScenePoints().get(condition.getParam()[0]);
if (scenePoints != null && scenePoints.contains(condition.getParam()[1])) {
queueEvent(condition.getType(), condition.getParam()[0], condition.getParam()[1]);
}
}
case QUEST_CONTENT_UNLOCK_AREA -> {
var sceneAreas = getPlayer().getUnlockedSceneAreas().get(condition.getParam()[0]);
if (sceneAreas != null && sceneAreas.contains(condition.getParam()[1])) {
queueEvent(condition.getType(), condition.getParam()[0], condition.getParam()[1]);
}
}
}
}
}, 1);
}
public List<QuestGroupSuite> getSceneGroupSuite(int sceneId) {
@@ -317,7 +369,6 @@ public class QuestManager extends BasePlayerManager {
.filter(i -> i.getScene() == sceneId)
.toList();
}
public void loadFromDatabase() {
List<GameMainQuest> quests = DatabaseHelper.getAllQuests(getPlayer());

View File

@@ -1,9 +1,13 @@
package emu.grasscutter.game.quest;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.excels.QuestData.QuestCondition;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.data.excels.QuestData.QuestAcceptCondition;
import emu.grasscutter.data.excels.QuestData.QuestContentCondition;
import emu.grasscutter.data.excels.QuestData.QuestExecParam;
import emu.grasscutter.game.quest.handlers.QuestBaseHandler;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.quest.conditions.BaseCondition;
import emu.grasscutter.game.quest.content.BaseContent;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
import emu.grasscutter.server.game.BaseGameSystem;
import emu.grasscutter.server.game.GameServer;
@@ -13,8 +17,8 @@ import org.reflections.Reflections;
@SuppressWarnings("unchecked")
public class QuestSystem extends BaseGameSystem {
private final Int2ObjectMap<QuestBaseHandler> condHandlers;
private final Int2ObjectMap<QuestBaseHandler> contHandlers;
private final Int2ObjectMap<BaseCondition> condHandlers;
private final Int2ObjectMap<BaseContent> contHandlers;
private final Int2ObjectMap<QuestExecHandler> execHandlers;
public QuestSystem(GameServer server) {
@@ -29,9 +33,9 @@ public class QuestSystem extends BaseGameSystem {
public void registerHandlers() {
this.registerHandlers(
this.condHandlers, "emu.grasscutter.game.quest.conditions", QuestBaseHandler.class);
this.condHandlers, "emu.grasscutter.game.quest.conditions", BaseCondition.class);
this.registerHandlers(
this.contHandlers, "emu.grasscutter.game.quest.content", QuestBaseHandler.class);
this.contHandlers, "emu.grasscutter.game.quest.content", BaseContent.class);
this.registerHandlers(
this.execHandlers, "emu.grasscutter.game.quest.exec", QuestExecHandler.class);
}
@@ -47,13 +51,25 @@ public class QuestSystem extends BaseGameSystem {
public <T> void registerPacketHandler(Int2ObjectMap<T> map, Class<? extends T> handlerClass) {
try {
QuestValue opcode = handlerClass.getAnnotation(QuestValue.class);
if (opcode == null || opcode.value().getValue() <= 0) {
int value = 0;
if (handlerClass.isAnnotationPresent(QuestValueExec.class)) {
QuestValueExec opcode = handlerClass.getAnnotation(QuestValueExec.class);
value = opcode.value().getValue();
} else if (handlerClass.isAnnotationPresent(QuestValueContent.class)) {
QuestValueContent opcode = handlerClass.getAnnotation(QuestValueContent.class);
value = opcode.value().getValue();
} else if (handlerClass.isAnnotationPresent(QuestValueCond.class)) {
QuestValueCond opcode = handlerClass.getAnnotation(QuestValueCond.class);
value = opcode.value().getValue();
} else {
return;
}
map.put(opcode.value().getValue(), handlerClass.getDeclaredConstructor().newInstance());
if (value <= 0) {
return;
}
map.put(value, handlerClass.getDeclaredConstructor().newInstance());
} catch (Exception e) {
e.printStackTrace();
}
@@ -62,24 +78,25 @@ public class QuestSystem extends BaseGameSystem {
// TODO make cleaner
public boolean triggerCondition(
GameQuest quest, QuestCondition condition, String paramStr, int... params) {
QuestBaseHandler handler = condHandlers.get(condition.getType().getValue());
Player owner,
QuestData questData,
QuestAcceptCondition condition,
String paramStr,
int... params) {
BaseCondition handler = condHandlers.get(condition.getType().getValue());
if (handler == null || quest.getQuestData() == null) {
if (handler == null || questData == null) {
Grasscutter.getLogger()
.debug(
"Could not trigger condition {} at {}",
condition.getType().getValue(),
quest.getQuestData());
.debug("Could not trigger condition {} at {}", condition.getType().getValue(), questData);
return false;
}
return handler.execute(quest, condition, paramStr, params);
return handler.execute(owner, questData, condition, paramStr, params);
}
public boolean triggerContent(
GameQuest quest, QuestCondition condition, String paramStr, int... params) {
QuestBaseHandler handler = contHandlers.get(condition.getType().getValue());
GameQuest quest, QuestContentCondition condition, String paramStr, int... params) {
BaseContent handler = contHandlers.get(condition.getType().getValue());
if (handler == null || quest.getQuestData() == null) {
Grasscutter.getLogger()
@@ -93,7 +110,7 @@ public class QuestSystem extends BaseGameSystem {
return handler.execute(quest, condition, paramStr, params);
}
public boolean triggerExec(GameQuest quest, QuestExecParam execParam, String... params) {
public void triggerExec(GameQuest quest, QuestExecParam execParam, String... params) {
QuestExecHandler handler = execHandlers.get(execParam.getType().getValue());
if (handler == null || quest.getQuestData() == null) {
@@ -102,9 +119,18 @@ public class QuestSystem extends BaseGameSystem {
"Could not trigger exec {} at {}",
execParam.getType().getValue(),
quest.getQuestData());
return false;
return;
}
return handler.execute(quest, execParam, params);
QuestManager.eventExecutor.submit(
() -> {
if (!handler.execute(quest, execParam, params)) {
Grasscutter.getLogger()
.debug(
"exec trigger failed {} at {}",
execParam.getType().getValue(),
quest.getQuestData());
}
});
}
}

View File

@@ -1,11 +1,10 @@
package emu.grasscutter.game.quest;
import emu.grasscutter.game.quest.enums.QuestCond;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface QuestValueCond {
QuestCond value();
}
package emu.grasscutter.game.quest;
import emu.grasscutter.game.quest.enums.QuestCond;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface QuestValueCond {
QuestCond value();
}

View File

@@ -1,11 +1,10 @@
package emu.grasscutter.game.quest;
import emu.grasscutter.game.quest.enums.QuestContent;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface QuestValueContent {
QuestContent value();
}
package emu.grasscutter.game.quest;
import emu.grasscutter.game.quest.enums.QuestContent;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface QuestValueContent {
QuestContent value();
}

View File

@@ -1,11 +1,10 @@
package emu.grasscutter.game.quest;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import emu.grasscutter.game.quest.enums.QuestExec;
@Retention(RetentionPolicy.RUNTIME)
public @interface QuestValueExec {
QuestExec value();
}
package emu.grasscutter.game.quest;
import emu.grasscutter.game.quest.enums.QuestExec;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface QuestValueExec {
QuestExec value();
}

View File

@@ -15,7 +15,7 @@ public class RewindData {
}
@Data
private static class Npc {
public static class Npc {
private String script;
private int room_id;
private int data_index;

View File

@@ -1,35 +1,35 @@
package emu.grasscutter.game.quest;
import java.util.List;
import lombok.Data;
@Data
public class TeleportData {
List<TransmitPoint> transmit_points;
List<Npc> npcs;
List<Gadget> gadgets;
@Data
public static class TransmitPoint {
private int point_id;
private int scene_id;
private String pos;
}
@Data
public static class Npc {
private int data_index;
private int room_id;
private int scene_id;
private int id;
private String alias;
private String script;
private String pos;
}
@Data
public static class Gadget {
private int id;
private String pos;
}
}
package emu.grasscutter.game.quest;
import java.util.List;
import lombok.Data;
@Data
public class TeleportData {
List<TransmitPoint> transmit_points;
List<Npc> npcs;
List<Gadget> gadgets;
@Data
public static class TransmitPoint {
private int point_id;
private int scene_id;
private String pos;
}
@Data
public static class Npc {
private int data_index;
private int room_id;
private int scene_id;
private int id;
private String alias;
private String script;
private String pos;
}
@Data
public static class Gadget {
private int id;
private String pos;
}
}

View File

@@ -1,18 +1,20 @@
package emu.grasscutter.game.quest.conditions;
import emu.grasscutter.data.excels.QuestData.QuestCondition;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestBaseHandler;
import static emu.grasscutter.game.quest.enums.QuestCond.QUEST_COND_UNKNOWN;
@QuestValue(QuestTrigger.QUEST_CONTENT_NONE)
public class BaseCondition extends QuestBaseHandler {
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.quest.QuestValueCond;
@QuestValueCond(QUEST_COND_UNKNOWN)
public class BaseCondition {
@Override
public boolean execute(
GameQuest quest, QuestCondition condition, String paramStr, int... params) {
// TODO Auto-generated method stub
Player owner,
QuestData questData,
QuestData.QuestAcceptCondition condition,
String paramStr,
int... params) {
return false;
}
}

View File

@@ -1,40 +1,49 @@
package emu.grasscutter.game.quest.conditions;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.player.Player;
import lombok.val;
public abstract class BaseConditionQuestVar extends BaseCondition {
protected abstract boolean doCompare(int variable, int cond);
@Override
public boolean execute(Player owner, QuestData questData, QuestData.QuestAcceptCondition condition, String paramStr, int... params) {
val index = condition.getParam()[0];
val targetValue = condition.getParam()[1];
val questVarValue = getQuestVar(owner, questData, index);
Grasscutter.getLogger().debug("questVar {} : {}", index, questVarValue);
if (questVarValue < 0) {
return false;
}
return doCompare(questVarValue, targetValue);
}
protected int getQuestVar(Player owner, QuestData questData, int index) {
val mainQuest = owner.getQuestManager().getMainQuestById(questData.getMainId());
if (mainQuest == null) {
Grasscutter.getLogger().debug("mainQuest for quest var not available yet");
return -1;
}
val questVars = mainQuest.getQuestVars();
if (index >= questVars.length) {
Grasscutter.getLogger().error("questVar out of bounds for {} index {} size {}", questData.getSubId(), index, questVars.length);
return -2;
}
return questVars[index];
}
}
package emu.grasscutter.game.quest.conditions;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.player.Player;
import lombok.val;
public abstract class BaseConditionQuestVar extends BaseCondition {
protected abstract boolean doCompare(int variable, int cond);
@Override
public boolean execute(
Player owner,
QuestData questData,
QuestData.QuestAcceptCondition condition,
String paramStr,
int... params) {
val index = condition.getParam()[0];
val targetValue = condition.getParam()[1];
val questVarValue = getQuestVar(owner, questData, index);
Grasscutter.getLogger().debug("questVar {} : {}", index, questVarValue);
if (questVarValue < 0) {
return false;
}
return doCompare(questVarValue, targetValue);
}
protected int getQuestVar(Player owner, QuestData questData, int index) {
val mainQuest = owner.getQuestManager().getMainQuestById(questData.getMainId());
if (mainQuest == null) {
Grasscutter.getLogger().debug("mainQuest for quest var not available yet");
return -1;
}
val questVars = mainQuest.getQuestVars();
if (index >= questVars.length) {
Grasscutter.getLogger()
.error(
"questVar out of bounds for {} index {} size {}",
questData.getSubId(),
index,
questVars.length);
return -2;
}
return questVars[index];
}
}

View File

@@ -1,20 +1,24 @@
package emu.grasscutter.game.quest.conditions;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.quest.QuestValueCond;
import lombok.val;
import static emu.grasscutter.game.quest.enums.QuestCond.QUEST_COND_ACTIVITY_COND;
@QuestValueCond(QUEST_COND_ACTIVITY_COND)
public class ConditionActivityCond extends BaseCondition {
@Override
public boolean execute(Player owner, QuestData questData, QuestData.QuestAcceptCondition condition, String paramStr, int... params) {
val activityCondId = condition.getParam()[0];
val targetState = condition.getParam()[1]; // only 1 for now
return owner.getActivityManager().meetsCondition(activityCondId) == (targetState == 1);
}
}
package emu.grasscutter.game.quest.conditions;
import static emu.grasscutter.game.quest.enums.QuestCond.QUEST_COND_ACTIVITY_COND;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.quest.QuestValueCond;
import lombok.val;
@QuestValueCond(QUEST_COND_ACTIVITY_COND)
public class ConditionActivityCond extends BaseCondition {
@Override
public boolean execute(
Player owner,
QuestData questData,
QuestData.QuestAcceptCondition condition,
String paramStr,
int... params) {
val activityCondId = condition.getParam()[0];
val targetState = condition.getParam()[1]; // only 1 for now
return owner.getActivityManager().meetsCondition(activityCondId) == (targetState == 1);
}
}

View File

@@ -1,19 +1,23 @@
package emu.grasscutter.game.quest.conditions;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.quest.QuestValueCond;
import lombok.val;
import static emu.grasscutter.game.quest.enums.QuestCond.QUEST_COND_ACTIVITY_END;
@QuestValueCond(QUEST_COND_ACTIVITY_END)
public class ConditionActivityEnd extends BaseCondition {
@Override
public boolean execute(Player owner, QuestData questData, QuestData.QuestAcceptCondition condition, String paramStr, int... params) {
val activityId = condition.getParam()[0];
return owner.getActivityManager().hasActivityEnded(activityId);
}
}
package emu.grasscutter.game.quest.conditions;
import static emu.grasscutter.game.quest.enums.QuestCond.QUEST_COND_ACTIVITY_END;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.quest.QuestValueCond;
import lombok.val;
@QuestValueCond(QUEST_COND_ACTIVITY_END)
public class ConditionActivityEnd extends BaseCondition {
@Override
public boolean execute(
Player owner,
QuestData questData,
QuestData.QuestAcceptCondition condition,
String paramStr,
int... params) {
val activityId = condition.getParam()[0];
return owner.getActivityManager().hasActivityEnded(activityId);
}
}

View File

@@ -1,19 +1,23 @@
package emu.grasscutter.game.quest.conditions;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.quest.QuestValueCond;
import lombok.val;
import static emu.grasscutter.game.quest.enums.QuestCond.QUEST_COND_ACTIVITY_OPEN;
@QuestValueCond(QUEST_COND_ACTIVITY_OPEN)
public class ConditionActivityOpen extends BaseCondition {
@Override
public boolean execute(Player owner, QuestData questData, QuestData.QuestAcceptCondition condition, String paramStr, int... params) {
val activityId = condition.getParam()[0];
return owner.getActivityManager().isActivityActive(activityId);
}
}
package emu.grasscutter.game.quest.conditions;
import static emu.grasscutter.game.quest.enums.QuestCond.QUEST_COND_ACTIVITY_OPEN;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.quest.QuestValueCond;
import lombok.val;
@QuestValueCond(QUEST_COND_ACTIVITY_OPEN)
public class ConditionActivityOpen extends BaseCondition {
@Override
public boolean execute(
Player owner,
QuestData questData,
QuestData.QuestAcceptCondition condition,
String paramStr,
int... params) {
val activityId = condition.getParam()[0];
return owner.getActivityManager().isActivityActive(activityId);
}
}

View File

@@ -1,33 +1,35 @@
package emu.grasscutter.game.quest.conditions;
import static emu.grasscutter.game.quest.enums.QuestCond.QUEST_COND_COMPLETE_TALK;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.binout.MainQuestData;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameMainQuest;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestBaseHandler;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.quest.QuestValueCond;
import lombok.val;
@QuestValue(QuestTrigger.QUEST_COND_COMPLETE_TALK)
public class ConditionCompleteTalk extends QuestBaseHandler {
@QuestValueCond(QUEST_COND_COMPLETE_TALK)
public class ConditionCompleteTalk extends BaseCondition {
@Override
public boolean execute(
GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) {
GameMainQuest checkMainQuest =
quest.getOwner().getQuestManager().getMainQuestById(condition.getParam()[0] / 100);
Player owner,
QuestData questData,
QuestData.QuestAcceptCondition condition,
String paramStr,
int... params) {
val talkId = condition.getParam()[0];
val unknownParam = condition.getParam()[1]; // e.g. 3 for 7081601
val checkMainQuest = owner.getQuestManager().getMainQuestByTalkId(talkId);
if (checkMainQuest == null
|| GameData.getMainQuestDataMap().get(checkMainQuest.getParentQuestId()).getTalks()
== null) {
Grasscutter.getLogger()
.debug(
"Warning: mainQuest {} hasn't been started yet, or has no talks",
condition.getParam()[0] / 100);
.debug("Warning: mainQuest {} hasn't been started yet, or has no talks", talkId / 100);
return false;
}
MainQuestData.TalkData talkData = checkMainQuest.getTalks().get(Integer.valueOf(params[0]));
return talkData != null || checkMainQuest.getChildQuestById(params[0]) != null;
val talkData = checkMainQuest.getTalks().get(talkId);
return talkData != null || checkMainQuest.getChildQuestById(talkId) != null;
}
}

View File

@@ -1,18 +1,22 @@
package emu.grasscutter.game.quest.conditions;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.quest.QuestValueCond;
import emu.grasscutter.game.quest.enums.QuestCond;
import lombok.val;
@QuestValueCond(QuestCond.QUEST_COND_HISTORY_GOT_ANY_ITEM)
public class ConditionHistoryGotAnyItem extends BaseCondition {
@Override
public boolean execute(Player owner, QuestData questData, QuestData.QuestAcceptCondition condition, String paramStr, int... params) {
val itemId = condition.getParam()[0];
return owner.getPlayerProgress().hasPlayerObtainedItemHistorically(itemId);
}
}
package emu.grasscutter.game.quest.conditions;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.quest.QuestValueCond;
import emu.grasscutter.game.quest.enums.QuestCond;
import lombok.val;
@QuestValueCond(QuestCond.QUEST_COND_HISTORY_GOT_ANY_ITEM)
public class ConditionHistoryGotAnyItem extends BaseCondition {
@Override
public boolean execute(
Player owner,
QuestData questData,
QuestData.QuestAcceptCondition condition,
String paramStr,
int... params) {
val itemId = condition.getParam()[0];
return owner.getPlayerProgress().hasPlayerObtainedItemHistorically(itemId);
}
}

View File

@@ -1,20 +1,24 @@
package emu.grasscutter.game.quest.conditions;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.quest.QuestValueCond;
import emu.grasscutter.game.quest.enums.QuestCond;
import lombok.val;
@QuestValueCond(QuestCond.QUEST_COND_IS_DAYTIME)
public class ConditionIsDaytime extends BaseCondition{
@Override
public boolean execute(Player owner, QuestData questData, QuestData.QuestAcceptCondition condition, String paramStr, int... params) {
val daytime = condition.getParam()[0] == 1;
val currentTime = owner.getWorld().getGameTimeHours();
// TODO is this the real timeframe?
return (currentTime >=6 && currentTime<=18) == daytime;
}
}
package emu.grasscutter.game.quest.conditions;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.quest.QuestValueCond;
import emu.grasscutter.game.quest.enums.QuestCond;
import lombok.val;
@QuestValueCond(QuestCond.QUEST_COND_IS_DAYTIME)
public class ConditionIsDaytime extends BaseCondition {
@Override
public boolean execute(
Player owner,
QuestData questData,
QuestData.QuestAcceptCondition condition,
String paramStr,
int... params) {
val daytime = condition.getParam()[0] == 1;
val currentTime = owner.getWorld().getGameTimeHours();
// TODO is this the real timeframe?
return (currentTime >= 6 && currentTime <= 18) == daytime;
}
}

View File

@@ -1,21 +1,25 @@
package emu.grasscutter.game.quest.conditions;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.quest.QuestValueCond;
import lombok.val;
import static emu.grasscutter.game.quest.enums.QuestCond.QUEST_COND_ITEM_NUM_LESS_THAN;
@QuestValueCond(QUEST_COND_ITEM_NUM_LESS_THAN)
public class ConditionItemNumLessThan extends BaseCondition {
@Override
public boolean execute(Player owner, QuestData questData, QuestData.QuestAcceptCondition condition, String paramStr, int... params) {
val itemId = condition.getParam()[0];
val amount = condition.getParam()[1];
val checkItem = owner.getInventory().getItemByGuid(itemId);
return checkItem == null || checkItem.getCount() < amount;
}
}
package emu.grasscutter.game.quest.conditions;
import static emu.grasscutter.game.quest.enums.QuestCond.QUEST_COND_ITEM_NUM_LESS_THAN;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.quest.QuestValueCond;
import lombok.val;
@QuestValueCond(QUEST_COND_ITEM_NUM_LESS_THAN)
public class ConditionItemNumLessThan extends BaseCondition {
@Override
public boolean execute(
Player owner,
QuestData questData,
QuestData.QuestAcceptCondition condition,
String paramStr,
int... params) {
val itemId = condition.getParam()[0];
val amount = condition.getParam()[1];
val checkItem = owner.getInventory().getItemByGuid(itemId);
return checkItem == null || checkItem.getCount() < amount;
}
}

View File

@@ -1,17 +1,24 @@
package emu.grasscutter.game.quest.conditions;
import emu.grasscutter.data.excels.QuestData.QuestCondition;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestBaseHandler;
import static emu.grasscutter.game.quest.enums.QuestCond.QUEST_COND_LUA_NOTIFY;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.quest.QuestValueCond;
import lombok.val;
@QuestValueCond(QUEST_COND_LUA_NOTIFY)
public class ConditionLuaNotify extends BaseCondition {
@QuestValue(QuestTrigger.QUEST_COND_LUA_NOTIFY)
public class ConditionLuaNotify extends QuestBaseHandler {
// Wrong implementation. Example: 7010226 has no paramStr
@Override
public boolean execute(
GameQuest quest, QuestCondition condition, String paramStr, int... params) {
return condition.getParam()[0] == Integer.parseInt(paramStr);
Player owner,
QuestData questData,
QuestData.QuestAcceptCondition condition,
String paramStr,
int... params) {
val triggerId = Integer.parseInt(paramStr);
val targetTrigger = condition.getParam()[0];
return targetTrigger == triggerId;
}
}

View File

@@ -1,16 +1,20 @@
package emu.grasscutter.game.quest.conditions;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.quest.QuestValueCond;
import emu.grasscutter.game.quest.enums.QuestCond;
@QuestValueCond(QuestCond.QUEST_COND_NONE)
public class ConditionNone extends BaseCondition{
@Override
public boolean execute(Player owner, QuestData questData, QuestData.QuestAcceptCondition condition, String paramStr, int... params) {
return true;
}
}
package emu.grasscutter.game.quest.conditions;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.quest.QuestValueCond;
import emu.grasscutter.game.quest.enums.QuestCond;
@QuestValueCond(QuestCond.QUEST_COND_NONE)
public class ConditionNone extends BaseCondition {
@Override
public boolean execute(
Player owner,
QuestData questData,
QuestData.QuestAcceptCondition condition,
String paramStr,
int... params) {
return true;
}
}

View File

@@ -1,19 +1,23 @@
package emu.grasscutter.game.quest.conditions;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.quest.QuestValueCond;
import emu.grasscutter.game.quest.enums.QuestCond;
import lombok.val;
@QuestValueCond(QuestCond.QUEST_COND_OPEN_STATE_EQUAL)
public class ConditionOpenStateEqual extends BaseCondition {
@Override
public boolean execute(Player owner, QuestData questData, QuestData.QuestAcceptCondition condition, String paramStr, int... params) {
val openStateId = condition.getParam()[0];
val requiredState = condition.getParam()[1];
return owner.getProgressManager().getOpenState(openStateId) == requiredState;
}
}
package emu.grasscutter.game.quest.conditions;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.quest.QuestValueCond;
import emu.grasscutter.game.quest.enums.QuestCond;
import lombok.val;
@QuestValueCond(QuestCond.QUEST_COND_OPEN_STATE_EQUAL)
public class ConditionOpenStateEqual extends BaseCondition {
@Override
public boolean execute(
Player owner,
QuestData questData,
QuestData.QuestAcceptCondition condition,
String paramStr,
int... params) {
val openStateId = condition.getParam()[0];
val requiredState = condition.getParam()[1];
return owner.getProgressManager().getOpenState(openStateId) == requiredState;
}
}

View File

@@ -1,21 +1,25 @@
package emu.grasscutter.game.quest.conditions;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.quest.QuestValueCond;
import lombok.val;
import static emu.grasscutter.game.quest.enums.QuestCond.QUEST_COND_PACK_HAVE_ITEM;
@QuestValueCond(QUEST_COND_PACK_HAVE_ITEM)
public class ConditionPackHaveItem extends BaseCondition {
@Override
public boolean execute(Player owner, QuestData questData, QuestData.QuestAcceptCondition condition, String paramStr, int... params) {
val itemId = condition.getParam()[0];
val targetAmount = condition.getParam()[1];
val checkItem = owner.getInventory().getItemByGuid(itemId);
return checkItem != null && checkItem.getCount() >= targetAmount;
}
}
package emu.grasscutter.game.quest.conditions;
import static emu.grasscutter.game.quest.enums.QuestCond.QUEST_COND_PACK_HAVE_ITEM;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.quest.QuestValueCond;
import lombok.val;
@QuestValueCond(QUEST_COND_PACK_HAVE_ITEM)
public class ConditionPackHaveItem extends BaseCondition {
@Override
public boolean execute(
Player owner,
QuestData questData,
QuestData.QuestAcceptCondition condition,
String paramStr,
int... params) {
val itemId = condition.getParam()[0];
val targetAmount = condition.getParam()[1];
val checkItem = owner.getInventory().getItemByGuid(itemId);
return checkItem != null && checkItem.getCount() >= targetAmount;
}
}

View File

@@ -1,18 +1,22 @@
package emu.grasscutter.game.quest.conditions;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.quest.QuestValueCond;
import emu.grasscutter.game.quest.enums.QuestCond;
import lombok.val;
@QuestValueCond(QuestCond.QUEST_COND_PERSONAL_LINE_UNLOCK)
public class ConditionPersonalLineUnlock extends BaseCondition {
@Override
public boolean execute(Player owner, QuestData questData, QuestData.QuestAcceptCondition condition, String paramStr, int... params) {
val personalLineId = condition.getParam()[0];
return owner.getPersonalLineList().contains(personalLineId);
}
}
package emu.grasscutter.game.quest.conditions;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.quest.QuestValueCond;
import emu.grasscutter.game.quest.enums.QuestCond;
import lombok.val;
@QuestValueCond(QuestCond.QUEST_COND_PERSONAL_LINE_UNLOCK)
public class ConditionPersonalLineUnlock extends BaseCondition {
@Override
public boolean execute(
Player owner,
QuestData questData,
QuestData.QuestAcceptCondition condition,
String paramStr,
int... params) {
val personalLineId = condition.getParam()[0];
return owner.getPersonalLineList().contains(personalLineId);
}
}

View File

@@ -1,17 +1,23 @@
package emu.grasscutter.game.quest.conditions;
import emu.grasscutter.data.excels.QuestData.QuestCondition;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestBaseHandler;
import static emu.grasscutter.game.quest.enums.QuestCond.QUEST_COND_PLAYER_LEVEL_EQUAL_GREATER;
@QuestValue(QuestTrigger.QUEST_COND_PLAYER_LEVEL_EQUAL_GREATER)
public class ConditionPlayerLevelEqualGreater extends QuestBaseHandler {
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.quest.QuestValueCond;
import lombok.val;
@QuestValueCond(QUEST_COND_PLAYER_LEVEL_EQUAL_GREATER)
public class ConditionPlayerLevelEqualGreater extends BaseCondition {
@Override
public boolean execute(
GameQuest quest, QuestCondition condition, String paramStr, int... params) {
return quest.getOwner().getLevel() >= params[0];
Player owner,
QuestData questData,
QuestData.QuestAcceptCondition condition,
String paramStr,
int... params) {
val minLevel = condition.getParam()[0];
return owner.getLevel() >= minLevel;
}
}

View File

@@ -1,21 +1,28 @@
package emu.grasscutter.game.quest.conditions;
import static emu.grasscutter.game.quest.enums.QuestCond.QUEST_COND_QUEST_GLOBAL_VAR_EQUAL;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestBaseHandler;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.quest.QuestValueCond;
import lombok.val;
@QuestValue(QuestTrigger.QUEST_COND_QUEST_GLOBAL_VAR_EQUAL)
public class ConditionQuestGlobalVarEqual extends QuestBaseHandler {
@QuestValueCond(QUEST_COND_QUEST_GLOBAL_VAR_EQUAL)
public class ConditionQuestGlobalVarEqual extends BaseCondition {
@Override
public boolean execute(
GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) {
Integer questGlobalVarValue =
quest.getMainQuest().getQuestManager().getQuestGlobalVarValue(Integer.valueOf(params[0]));
Grasscutter.getLogger().debug("questGlobarVar {} : {}", params[0], questGlobalVarValue);
return questGlobalVarValue.intValue() == params[1];
Player owner,
QuestData questData,
QuestData.QuestAcceptCondition condition,
String paramStr,
int... params) {
val questId = condition.getParam()[0];
val targetValue = condition.getParam()[1];
Integer questGlobalVarValue = owner.getQuestManager().getQuestGlobalVarValue(questId);
Grasscutter.getLogger()
.debug("questGlobarVar {} {} : {}", questId, targetValue, questGlobalVarValue);
return questGlobalVarValue == targetValue;
}
}

View File

@@ -1,21 +1,28 @@
package emu.grasscutter.game.quest.conditions;
import static emu.grasscutter.game.quest.enums.QuestCond.QUEST_COND_QUEST_GLOBAL_VAR_GREATER;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestBaseHandler;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.quest.QuestValueCond;
import lombok.val;
@QuestValue(QuestTrigger.QUEST_COND_QUEST_GLOBAL_VAR_GREATER)
public class ConditionQuestGlobalVarGreater extends QuestBaseHandler {
@QuestValueCond(QUEST_COND_QUEST_GLOBAL_VAR_GREATER)
public class ConditionQuestGlobalVarGreater extends BaseCondition {
@Override
public boolean execute(
GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) {
Integer questGlobalVarValue =
quest.getMainQuest().getQuestManager().getQuestGlobalVarValue(Integer.valueOf(params[0]));
Grasscutter.getLogger().debug("questGlobarVar {} : {}", params[0], questGlobalVarValue);
return questGlobalVarValue.intValue() > params[1];
Player owner,
QuestData questData,
QuestData.QuestAcceptCondition condition,
String paramStr,
int... params) {
val questId = condition.getParam()[0];
val minValue = condition.getParam()[1];
Integer questGlobalVarValue = owner.getQuestManager().getQuestGlobalVarValue(questId);
Grasscutter.getLogger()
.debug("questGlobarVar {} {} : {}", questId, minValue, questGlobalVarValue);
return questGlobalVarValue > minValue;
}
}

View File

@@ -1,21 +1,28 @@
package emu.grasscutter.game.quest.conditions;
import static emu.grasscutter.game.quest.enums.QuestCond.QUEST_COND_QUEST_GLOBAL_VAR_LESS;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestBaseHandler;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.quest.QuestValueCond;
import lombok.val;
@QuestValue(QuestTrigger.QUEST_COND_QUEST_GLOBAL_VAR_LESS)
public class ConditionQuestGlobalVarLess extends QuestBaseHandler {
@QuestValueCond(QUEST_COND_QUEST_GLOBAL_VAR_LESS)
public class ConditionQuestGlobalVarLess extends BaseCondition {
@Override
public boolean execute(
GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) {
Integer questGlobalVarValue =
quest.getMainQuest().getQuestManager().getQuestGlobalVarValue(Integer.valueOf(params[0]));
Grasscutter.getLogger().debug("questGlobarVar {} : {}", params[0], questGlobalVarValue);
return questGlobalVarValue.intValue() < params[1];
Player owner,
QuestData questData,
QuestData.QuestAcceptCondition condition,
String paramStr,
int... params) {
val questId = condition.getParam()[0];
val maxValue = condition.getParam()[1];
Integer questGlobalVarValue = owner.getQuestManager().getQuestGlobalVarValue(questId);
Grasscutter.getLogger()
.debug("questGlobarVar {} {} : {}", questId, maxValue, questGlobalVarValue);
return questGlobalVarValue < maxValue;
}
}

View File

@@ -1,20 +1,14 @@
package emu.grasscutter.game.quest.conditions;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestBaseHandler;
import static emu.grasscutter.game.quest.enums.QuestCond.QUEST_COND_QUEST_VAR_EQUAL;
@QuestValue(QuestTrigger.QUEST_COND_QUEST_VAR_EQUAL)
public class ConditionQuestVarEqual extends QuestBaseHandler {
import emu.grasscutter.game.quest.QuestValueCond;
@QuestValueCond(QUEST_COND_QUEST_VAR_EQUAL)
public class ConditionQuestVarEqual extends BaseConditionQuestVar {
@Override
public boolean execute(
GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) {
int questVarValue = quest.getMainQuest().getQuestVars()[params[0]];
Grasscutter.getLogger().debug("questVar {} : {}", params[0], questVarValue);
return questVarValue == params[1];
protected boolean doCompare(int variable, int cond) {
return variable == cond;
}
}

View File

@@ -1,20 +1,14 @@
package emu.grasscutter.game.quest.conditions;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestBaseHandler;
import static emu.grasscutter.game.quest.enums.QuestCond.QUEST_COND_QUEST_VAR_GREATER;
@QuestValue(QuestTrigger.QUEST_COND_QUEST_VAR_GREATER)
public class ConditionQuestVarGreater extends QuestBaseHandler {
import emu.grasscutter.game.quest.QuestValueCond;
@QuestValueCond(QUEST_COND_QUEST_VAR_GREATER)
public class ConditionQuestVarGreater extends BaseConditionQuestVar {
@Override
public boolean execute(
GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) {
int questVarValue = quest.getMainQuest().getQuestVars()[params[0]];
Grasscutter.getLogger().debug("questVar {} : {}", params[0], questVarValue);
return questVarValue > params[1];
protected boolean doCompare(int variable, int cond) {
return variable > cond;
}
}

View File

@@ -1,20 +1,14 @@
package emu.grasscutter.game.quest.conditions;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestBaseHandler;
import static emu.grasscutter.game.quest.enums.QuestCond.QUEST_COND_QUEST_VAR_LESS;
@QuestValue(QuestTrigger.QUEST_COND_QUEST_VAR_LESS)
public class ConditionQuestVarLess extends QuestBaseHandler {
import emu.grasscutter.game.quest.QuestValueCond;
@QuestValueCond(QUEST_COND_QUEST_VAR_LESS)
public class ConditionQuestVarLess extends BaseConditionQuestVar {
@Override
public boolean execute(
GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) {
int questVarValue = quest.getMainQuest().getQuestVars()[params[0]];
Grasscutter.getLogger().debug("questVar {} : {}", params[0], questVarValue);
return questVarValue < params[1];
protected boolean doCompare(int variable, int cond) {
return variable < cond;
}
}

View File

@@ -1,26 +1,34 @@
package emu.grasscutter.game.quest.conditions;
import emu.grasscutter.data.excels.QuestData.QuestCondition;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestBaseHandler;
import static emu.grasscutter.game.quest.enums.QuestCond.QUEST_COND_STATE_EQUAL;
@QuestValue(QuestTrigger.QUEST_COND_STATE_EQUAL)
public class ConditionStateEqual extends QuestBaseHandler {
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueCond;
import lombok.val;
@QuestValueCond(QUEST_COND_STATE_EQUAL)
public class ConditionStateEqual extends BaseCondition {
@Override
public boolean execute(
GameQuest quest, QuestCondition condition, String paramStr, int... params) {
GameQuest checkQuest = quest.getOwner().getQuestManager().getQuestById(condition.getParam()[0]);
Player owner,
QuestData questData,
QuestData.QuestAcceptCondition condition,
String paramStr,
int... params) {
val questId = condition.getParam()[0];
val questStateValue = condition.getParam()[1];
GameQuest checkQuest = owner.getQuestManager().getQuestById(questId);
if (checkQuest == null) {
/*
Will spam the console
//Grasscutter.getLogger().debug("Warning: quest {} hasn't been started yet!", condition.getParam()[0]);
*/
// Grasscutter.getLogger().debug("Warning: quest {} hasn't been started yet!",
// condition.getParam()[0]);
return false;
}
return checkQuest.getState().getValue() == condition.getParam()[1];
return checkQuest.getState().getValue() == questStateValue;
}
}

View File

@@ -1,26 +1,35 @@
package emu.grasscutter.game.quest.conditions;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestBaseHandler;
import static emu.grasscutter.game.quest.enums.QuestCond.QUEST_COND_STATE_NOT_EQUAL;
@QuestValue(QuestTrigger.QUEST_COND_STATE_NOT_EQUAL)
public class ConditionStateNotEqual extends QuestBaseHandler {
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueCond;
import lombok.val;
@QuestValueCond(QUEST_COND_STATE_NOT_EQUAL)
public class ConditionStateNotEqual extends BaseCondition {
@Override
public boolean execute(
GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) {
GameQuest checkQuest = quest.getOwner().getQuestManager().getQuestById(condition.getParam()[0]);
Player owner,
QuestData questData,
QuestData.QuestAcceptCondition condition,
String paramStr,
int... params) {
val questId = condition.getParam()[0];
val questStateValue = condition.getParam()[1];
GameQuest checkQuest = owner.getQuestManager().getQuestById(questId);
if (checkQuest == null) {
/*
Will spam the console
//Grasscutter.getLogger().debug("Warning: quest {} hasn't been started yet!", condition.getParam()[0]);
*/
// Grasscutter.getLogger().debug("Warning: quest {} hasn't been started yet!",
// condition.getParam()[0]);
return false;
}
return checkQuest.getState().getValue() != condition.getParam()[1];
return checkQuest.getState().getValue() != questStateValue;
}
}

View File

@@ -1,25 +1,30 @@
package emu.grasscutter.game.quest.conditions;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.quest.QuestValueCond;
import emu.grasscutter.game.quest.enums.QuestCond;
import lombok.val;
@QuestValueCond(QuestCond.QUEST_COND_TIME_VAR_GT_EQ)
public class ConditionTimeVarGreaterOrEqual extends BaseCondition{
@Override
public boolean execute(Player owner, QuestData questData, QuestData.QuestAcceptCondition condition, String paramStr, int... params) {
val mainQuestId = condition.getParam()[0];
val timeVarIndex = condition.getParam()[1];
val minTime = condition.getParam()[2];
val mainQuest = owner.getQuestManager().getMainQuestById(mainQuestId);
if(mainQuest == null){
return false;
}
return mainQuest.getHoursSinceTimeVar(timeVarIndex) >= minTime;
}
}
package emu.grasscutter.game.quest.conditions;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.quest.QuestValueCond;
import emu.grasscutter.game.quest.enums.QuestCond;
import lombok.val;
@QuestValueCond(QuestCond.QUEST_COND_TIME_VAR_GT_EQ)
public class ConditionTimeVarGreaterOrEqual extends BaseCondition {
@Override
public boolean execute(
Player owner,
QuestData questData,
QuestData.QuestAcceptCondition condition,
String paramStr,
int... params) {
val mainQuestId = condition.getParam()[0];
val timeVarIndex = condition.getParam()[1];
val minTime = condition.getParam()[2];
val mainQuest = owner.getQuestManager().getMainQuestById(mainQuestId);
if (mainQuest == null) {
return false;
}
return mainQuest.getHoursSinceTimeVar(timeVarIndex) >= minTime;
}
}

View File

@@ -1,30 +1,35 @@
package emu.grasscutter.game.quest.conditions;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.quest.QuestValueCond;
import emu.grasscutter.game.quest.enums.QuestCond;
import lombok.val;
@QuestValueCond(QuestCond.QUEST_COND_TIME_VAR_PASS_DAY)
public class ConditionTimeVarPassDay extends BaseCondition{
@Override
public boolean execute(Player owner, QuestData questData, QuestData.QuestAcceptCondition condition, String paramStr, int... params) {
val mainQuestId = condition.getParam()[0];
val timeVarIndex = condition.getParam()[1];
val minDays = condition.getParam()[2];
val mainQuest = owner.getQuestManager().getMainQuestById(mainQuestId);
if(mainQuest == null){
return false;
}
val daysSinceTimeVar = mainQuest.getDaysSinceTimeVar(timeVarIndex);
if(daysSinceTimeVar == -1){
return false;
}
return daysSinceTimeVar >= minDays;
}
}
package emu.grasscutter.game.quest.conditions;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.quest.QuestValueCond;
import emu.grasscutter.game.quest.enums.QuestCond;
import lombok.val;
@QuestValueCond(QuestCond.QUEST_COND_TIME_VAR_PASS_DAY)
public class ConditionTimeVarPassDay extends BaseCondition {
@Override
public boolean execute(
Player owner,
QuestData questData,
QuestData.QuestAcceptCondition condition,
String paramStr,
int... params) {
val mainQuestId = condition.getParam()[0];
val timeVarIndex = condition.getParam()[1];
val minDays = condition.getParam()[2];
val mainQuest = owner.getQuestManager().getMainQuestById(mainQuestId);
if (mainQuest == null) {
return false;
}
val daysSinceTimeVar = mainQuest.getDaysSinceTimeVar(timeVarIndex);
if (daysSinceTimeVar == -1) {
return false;
}
return daysSinceTimeVar >= minDays;
}
}

View File

@@ -1,17 +1,17 @@
package emu.grasscutter.game.quest.content;
import emu.grasscutter.data.excels.QuestData.QuestCondition;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.QuestValueContent;
import emu.grasscutter.game.quest.enums.QuestContent;
import emu.grasscutter.game.quest.handlers.QuestBaseHandler;
@QuestValue(QuestTrigger.QUEST_CONTENT_NONE)
public class BaseContent extends QuestBaseHandler {
@QuestValueContent(QuestContent.QUEST_CONTENT_NONE)
public class BaseContent extends QuestBaseHandler<QuestData.QuestContentCondition> {
@Override
public boolean execute(
GameQuest quest, QuestCondition condition, String paramStr, int... params) {
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
// TODO Auto-generated method stub
return false;
}

View File

@@ -1,22 +1,23 @@
package emu.grasscutter.game.quest.content;
import emu.grasscutter.data.excels.QuestData.QuestCondition;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestBaseHandler;
@QuestValue(QuestTrigger.QUEST_CONTENT_ADD_QUEST_PROGRESS)
public class ContentAddQuestProgress extends QuestBaseHandler {
@Override
public boolean execute(GameQuest quest, QuestCondition condition, String paramStr, int... params) {
/*
//paramStr is a lua group, params[0] may also be a lua group!
questid = xxxxxx lua group = xxxxxxyy
count seems relevant only for lua group
*/
return condition.getParam()[0] == params[0]; //missing params[1], paramStr, and count
}
}
package emu.grasscutter.game.quest.content;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_ADD_QUEST_PROGRESS;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
import lombok.val;
@QuestValueContent(QUEST_CONTENT_ADD_QUEST_PROGRESS)
public class ContentAddQuestProgress extends BaseContent {
@Override
public boolean execute(
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
val progressId = condition.getParam()[0];
val currentCount = quest.getOwner().getPlayerProgress().getCurrentProgress(progressId);
// if the condition count is 0 I think it is safe to assume that the
// condition count from EXEC only needs to be 1
return currentCount >= condition.getCount();
}
}

View File

@@ -1,15 +1,16 @@
package emu.grasscutter.game.quest.content;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_ANY_MANUAL_TRANSPORT;
@QuestValueContent(QUEST_CONTENT_ANY_MANUAL_TRANSPORT)
public class ContentAnyManualTransport extends BaseContent {
@Override
public boolean execute(GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
return true;
}
}
package emu.grasscutter.game.quest.content;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_ANY_MANUAL_TRANSPORT;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
@QuestValueContent(QUEST_CONTENT_ANY_MANUAL_TRANSPORT)
public class ContentAnyManualTransport extends BaseContent {
@Override
public boolean execute(
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
return true;
}
}

View File

@@ -1,19 +1,20 @@
package emu.grasscutter.game.quest.content;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
import lombok.val;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_CLEAR_GROUP_MONSTER;
@QuestValueContent(QUEST_CONTENT_CLEAR_GROUP_MONSTER)
public class ContentClearGroupMonster extends BaseContent {
@Override
public boolean execute(GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
val groupId = condition.getParam()[0];
return quest.getOwner().getScene().getScriptManager().isClearedGroupMonsters(groupId);
}
}
package emu.grasscutter.game.quest.content;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_CLEAR_GROUP_MONSTER;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
import lombok.val;
@QuestValueContent(QUEST_CONTENT_CLEAR_GROUP_MONSTER)
public class ContentClearGroupMonster extends BaseContent {
@Override
public boolean execute(
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
val groupId = condition.getParam()[0];
return quest.getOwner().getScene().getScriptManager().isClearedGroupMonsters(groupId);
}
}

View File

@@ -1,27 +1,33 @@
package emu.grasscutter.game.quest.content;
import emu.grasscutter.data.binout.MainQuestData;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameMainQuest;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestBaseHandler;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_COMPLETE_ANY_TALK;
@QuestValue(QuestTrigger.QUEST_CONTENT_COMPLETE_ANY_TALK)
public class ContentCompleteAnyTalk extends QuestBaseHandler {
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
import java.util.Arrays;
import lombok.val;
@QuestValueContent(QUEST_CONTENT_COMPLETE_ANY_TALK)
public class ContentCompleteAnyTalk extends BaseContent {
@Override
public boolean execute(
GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) {
GameMainQuest checkMainQuest =
quest.getOwner().getQuestManager().getMainQuestById(params[0] / 100);
if (checkMainQuest == null) {
return false;
}
MainQuestData.TalkData talkData = checkMainQuest.getTalks().get(Integer.valueOf(paramStr));
return talkData == null
|| condition.getParamStr().contains(paramStr)
|| checkMainQuest.getChildQuestById(params[0]) != null;
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
val talkId = params[0];
val conditionTalk =
Arrays.stream(condition.getParamStr().split(",")).mapToInt(Integer::parseInt).toArray();
return Arrays.stream(conditionTalk).anyMatch(tids -> tids == talkId)
|| Arrays.stream(conditionTalk)
.anyMatch(
tids -> {
val checkMainQuest =
quest.getOwner().getQuestManager().getMainQuestByTalkId(tids);
if (checkMainQuest == null) {
return false;
}
val talkData = checkMainQuest.getTalks().get(talkId);
return talkData != null;
});
}
}

View File

@@ -1,30 +1,25 @@
package emu.grasscutter.game.quest.content;
import emu.grasscutter.data.binout.MainQuestData;
import emu.grasscutter.data.excels.QuestData.QuestCondition;
import emu.grasscutter.game.quest.GameMainQuest;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestBaseHandler;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_COMPLETE_TALK;
@QuestValue(QuestTrigger.QUEST_CONTENT_COMPLETE_TALK)
public class ContentCompleteTalk extends QuestBaseHandler {
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
import lombok.val;
@QuestValueContent(QUEST_CONTENT_COMPLETE_TALK)
public class ContentCompleteTalk extends BaseContent {
@Override
public boolean execute(
GameQuest quest, QuestCondition condition, String paramStr, int... params) {
GameMainQuest checkMainQuest =
quest.getOwner().getQuestManager().getMainQuestById(params[0] / 100);
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
val talkId = condition.getParam()[0];
val checkMainQuest = quest.getOwner().getQuestManager().getMainQuestByTalkId(talkId);
if (checkMainQuest == null) {
return false;
}
MainQuestData.TalkData talkData = checkMainQuest.getTalks().get(condition.getParam()[0]);
val talkData = checkMainQuest.getTalks().get(talkId);
return talkData != null;
// This expression makes zero sense.
// return talkData == null || condition.getParamStr().contains(paramStr) ||
// checkMainQuest.getChildQuestById(params[0]) != null;
}
}

View File

@@ -1,15 +1,16 @@
package emu.grasscutter.game.quest.content;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_DESTROY_GADGET;
@QuestValueContent(QUEST_CONTENT_DESTROY_GADGET)
public class ContentDestroyGadget extends BaseContent {
@Override
public boolean execute(GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
return condition.getParam()[0] == params[0];
}
}
package emu.grasscutter.game.quest.content;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_DESTROY_GADGET;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
@QuestValueContent(QUEST_CONTENT_DESTROY_GADGET)
public class ContentDestroyGadget extends BaseContent {
@Override
public boolean execute(
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
return condition.getParam()[0] == params[0];
}
}

View File

@@ -1,17 +1,17 @@
package emu.grasscutter.game.quest.content;
import emu.grasscutter.data.excels.QuestData.QuestCondition;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestBaseHandler;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_ENTER_DUNGEON;
@QuestValue(QuestTrigger.QUEST_CONTENT_ENTER_DUNGEON)
public class ContentEnterDungeon extends QuestBaseHandler {
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
@QuestValueContent(QUEST_CONTENT_ENTER_DUNGEON)
public class ContentEnterDungeon extends BaseContent {
@Override
public boolean execute(
GameQuest quest, QuestCondition condition, String paramStr, int... params) {
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
return condition.getParam()[0] == params[0]; // missing params[1]
}
}

View File

@@ -1,17 +1,17 @@
package emu.grasscutter.game.quest.content;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_ENTER_MY_WORLD;
@QuestValueContent(QUEST_CONTENT_ENTER_MY_WORLD)
public class ContentEnterMyWorld extends BaseContent {
// params[0] scene ID
@Override
public boolean execute(GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
return condition.getParam()[0] == params[0];
}
}
package emu.grasscutter.game.quest.content;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_ENTER_MY_WORLD;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
@QuestValueContent(QUEST_CONTENT_ENTER_MY_WORLD)
public class ContentEnterMyWorld extends BaseContent {
// params[0] scene ID
@Override
public boolean execute(
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
return condition.getParam()[0] == params[0];
}
}

View File

@@ -1,17 +1,17 @@
package emu.grasscutter.game.quest.content;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_ENTER_MY_WORLD_SCENE;
@QuestValueContent(QUEST_CONTENT_ENTER_MY_WORLD_SCENE)
public class ContentEnterMyWorldScene extends BaseContent {
// params[0] scene ID
@Override
public boolean execute(GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
return condition.getParam()[0] == params[0];
}
}
package emu.grasscutter.game.quest.content;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_ENTER_MY_WORLD_SCENE;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
@QuestValueContent(QUEST_CONTENT_ENTER_MY_WORLD_SCENE)
public class ContentEnterMyWorldScene extends BaseContent {
// params[0] scene ID
@Override
public boolean execute(
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
return condition.getParam()[0] == params[0];
}
}

View File

@@ -1,17 +1,17 @@
package emu.grasscutter.game.quest.content;
import emu.grasscutter.data.excels.QuestData.QuestCondition;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestBaseHandler;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_ENTER_ROOM;
@QuestValue(QuestTrigger.QUEST_CONTENT_ENTER_ROOM)
public class ContentEnterRoom extends QuestBaseHandler {
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
@QuestValueContent(QUEST_CONTENT_ENTER_ROOM)
public class ContentEnterRoom extends BaseContent {
@Override
public boolean execute(
GameQuest quest, QuestCondition condition, String paramStr, int... params) {
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
return condition.getParam()[0] == params[0];
}
}

View File

@@ -1,15 +1,16 @@
package emu.grasscutter.game.quest.content;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_ENTER_VEHICLE;
@QuestValueContent(QUEST_CONTENT_ENTER_VEHICLE)
public class ContentEnterVehicle extends BaseContent {
@Override
public boolean execute(GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
return condition.getParam()[0] == params[0];
}
}
package emu.grasscutter.game.quest.content;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_ENTER_VEHICLE;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
@QuestValueContent(QUEST_CONTENT_ENTER_VEHICLE)
public class ContentEnterVehicle extends BaseContent {
@Override
public boolean execute(
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
return condition.getParam()[0] == params[0];
}
}

View File

@@ -1,18 +1,18 @@
package emu.grasscutter.game.quest.content;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_FAIL_DUNGEON;
@QuestValueContent(QUEST_CONTENT_FAIL_DUNGEON)
public class ContentFailDungeon extends BaseContent {
// params[0] dungeon ID
@Override
public boolean execute(GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
return condition.getParam()[0] == params[0];
}
}
package emu.grasscutter.game.quest.content;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_FAIL_DUNGEON;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
@QuestValueContent(QUEST_CONTENT_FAIL_DUNGEON)
public class ContentFailDungeon extends BaseContent {
// params[0] dungeon ID
@Override
public boolean execute(
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
return condition.getParam()[0] == params[0];
}
}

View File

@@ -1,18 +1,18 @@
package emu.grasscutter.game.quest.content;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_FINISH_DUNGEON;
@QuestValueContent(QUEST_CONTENT_FINISH_DUNGEON)
public class ContentFinishDungeon extends BaseContent {
// params[0] dungeon ID, params[1] unknown
@Override
public boolean execute(GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
return condition.getParam()[0] == params[0];
}
}
package emu.grasscutter.game.quest.content;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_FINISH_DUNGEON;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
@QuestValueContent(QUEST_CONTENT_FINISH_DUNGEON)
public class ContentFinishDungeon extends BaseContent {
// params[0] dungeon ID, params[1] unknown
@Override
public boolean execute(
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
return condition.getParam()[0] == params[0];
}
}

View File

@@ -1,21 +1,22 @@
package emu.grasscutter.game.quest.content;
import emu.grasscutter.data.binout.MainQuestData;
import emu.grasscutter.data.excels.QuestData.QuestCondition;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestBaseHandler;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_FINISH_PLOT;
@QuestValue(QuestTrigger.QUEST_CONTENT_FINISH_PLOT)
public class ContentFinishPlot extends QuestBaseHandler {
import emu.grasscutter.data.binout.MainQuestData;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
@QuestValueContent(QUEST_CONTENT_FINISH_PLOT)
public class ContentFinishPlot extends BaseContent {
@Override
public boolean execute(
GameQuest quest, QuestCondition condition, String paramStr, int... params) {
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
MainQuestData.TalkData talkData =
quest.getMainQuest().getTalks().get(Integer.valueOf(params[0]));
GameQuest subQuest = quest.getMainQuest().getChildQuestById(params[0]);
return talkData != null || subQuest != null;
return talkData != null && subQuest != null
|| condition.getParamStr().equals(paramStr) && condition.getParam()[0] == params[0];
}
}

View File

@@ -1,22 +1,38 @@
package emu.grasscutter.game.quest.content;
import emu.grasscutter.data.excels.QuestData.QuestCondition;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestBaseHandler;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_GAME_TIME_TICK;
@QuestValue(QuestTrigger.QUEST_CONTENT_GAME_TIME_TICK)
public class ContentGameTimeTick extends QuestBaseHandler {
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
import lombok.val;
@QuestValueContent(QUEST_CONTENT_GAME_TIME_TICK)
public class ContentGameTimeTick extends BaseContent {
@Override
public boolean execute(
GameQuest quest, QuestCondition condition, String paramStr, int... params) {
var range = condition.getParamStr().split(",");
var min = Math.min(Integer.parseInt(range[0]), Integer.parseInt(range[1]));
var max = Math.max(Integer.parseInt(range[0]), Integer.parseInt(range[1]));
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
val daysSinceStart =
quest.getOwner().getWorld().getTotalGameTimeDays() - quest.getStartGameDay();
val currentHour = quest.getOwner().getWorld().getGameTimeHours();
// params[0] is clock, params[1] is day
return params[0] >= min && params[0] <= max && params[1] >= condition.getParam()[0];
// params[0] is days since start, str is hours of day
val range = condition.getParamStr().split(",");
val from = Integer.parseInt(range[0]);
val to = Integer.parseInt(range[1]);
val daysToPass = condition.getParam()[0];
// if to is at the beginning of the day, we need to pass it one more time
val daysMod = to < from && daysToPass > 0 && currentHour < to ? 1 : 0;
val isTimeMet =
from < to
? currentHour >= from && currentHour < to
: currentHour < to || currentHour >= from;
val isDaysSinceMet = daysSinceStart >= daysToPass + daysMod;
return isTimeMet && isDaysSinceMet;
}
}

View File

@@ -1,17 +1,17 @@
package emu.grasscutter.game.quest.content;
import emu.grasscutter.data.excels.QuestData.QuestCondition;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestBaseHandler;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_INTERACT_GADGET;
@QuestValue(QuestTrigger.QUEST_CONTENT_INTERACT_GADGET)
public class ContentInteractGadget extends QuestBaseHandler {
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
@QuestValueContent(QUEST_CONTENT_INTERACT_GADGET)
public class ContentInteractGadget extends BaseContent {
@Override
public boolean execute(
GameQuest quest, QuestCondition condition, String paramStr, int... params) {
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
return params[0] == condition.getParam()[0];
}
}

View File

@@ -1,15 +1,16 @@
package emu.grasscutter.game.quest.content;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_ITEM_LESS_THAN;
@QuestValueContent(QUEST_CONTENT_ITEM_LESS_THAN)
public class ContentItemLessThan extends BaseContent {
@Override
public boolean execute(GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
return condition.getParam()[0] == params[0] && condition.getCount() > params[1];
}
}
package emu.grasscutter.game.quest.content;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_ITEM_LESS_THAN;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
@QuestValueContent(QUEST_CONTENT_ITEM_LESS_THAN)
public class ContentItemLessThan extends BaseContent {
@Override
public boolean execute(
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
return condition.getParam()[0] == params[0] && condition.getCount() > params[1];
}
}

View File

@@ -1,15 +1,16 @@
package emu.grasscutter.game.quest.content;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_KILL_MONSTER;
@QuestValueContent(QUEST_CONTENT_KILL_MONSTER)
public class ContentKillMonster extends BaseContent {
@Override
public boolean execute(GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
return condition.getParam()[0] == params[0];
}
}
package emu.grasscutter.game.quest.content;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_KILL_MONSTER;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
@QuestValueContent(QUEST_CONTENT_KILL_MONSTER)
public class ContentKillMonster extends BaseContent {
@Override
public boolean execute(
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
return condition.getParam()[0] == params[0];
}
}

View File

@@ -1,17 +1,17 @@
package emu.grasscutter.game.quest.content;
import emu.grasscutter.data.excels.QuestData.QuestCondition;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestBaseHandler;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_LEAVE_SCENE;
@QuestValue(QuestTrigger.QUEST_CONTENT_LEAVE_SCENE)
public class ContentLeaveScene extends QuestBaseHandler {
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
@QuestValueContent(QUEST_CONTENT_LEAVE_SCENE)
public class ContentLeaveScene extends BaseContent {
@Override
public boolean execute(
GameQuest quest, QuestCondition condition, String paramStr, int... params) {
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
return quest.getOwner().getScene().getPrevScene() == params[0];
}
}

View File

@@ -1,17 +1,17 @@
package emu.grasscutter.game.quest.content;
import emu.grasscutter.data.excels.QuestData.QuestCondition;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestBaseHandler;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_LUA_NOTIFY;
@QuestValue(QuestTrigger.QUEST_CONTENT_LUA_NOTIFY)
public class ContentLuaNotify extends QuestBaseHandler {
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
@QuestValueContent(QUEST_CONTENT_LUA_NOTIFY)
public class ContentLuaNotify extends BaseContent {
@Override
public boolean execute(
GameQuest quest, QuestCondition condition, String paramStr, int... params) {
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
return condition.getParamStr().equals(paramStr);
}
}

View File

@@ -1,15 +1,16 @@
package emu.grasscutter.game.quest.content;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_MONSTER_DIE;
@QuestValueContent(QUEST_CONTENT_MONSTER_DIE)
public class ContentMonsterDie extends BaseContent {
@Override
public boolean execute(GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
return condition.getParam()[0] == params[0];
}
}
package emu.grasscutter.game.quest.content;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_MONSTER_DIE;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
@QuestValueContent(QUEST_CONTENT_MONSTER_DIE)
public class ContentMonsterDie extends BaseContent {
@Override
public boolean execute(
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
return condition.getParam()[0] == params[0];
}
}

View File

@@ -1,25 +1,24 @@
package emu.grasscutter.game.quest.content;
import emu.grasscutter.data.binout.MainQuestData;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameMainQuest;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestBaseHandler;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_NOT_FINISH_PLOT;
@QuestValue(QuestTrigger.QUEST_CONTENT_NOT_FINISH_PLOT)
public class ContentNotFinishPlot extends QuestBaseHandler {
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
import lombok.val;
@QuestValueContent(QUEST_CONTENT_NOT_FINISH_PLOT)
public class ContentNotFinishPlot extends BaseContent {
@Override
public boolean execute(
GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) {
GameMainQuest checkMainQuest =
quest.getOwner().getQuestManager().getMainQuestById(params[0] / 100);
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
val talkId = condition.getParam()[0];
val checkMainQuest = quest.getOwner().getQuestManager().getMainQuestByTalkId(talkId);
if (checkMainQuest == null) {
return false;
return true;
}
MainQuestData.TalkData talkData = checkMainQuest.getTalks().get(Integer.valueOf(params[0]));
val talkData = checkMainQuest.getTalks().get(talkId);
return talkData == null;
}
}

View File

@@ -1,19 +1,20 @@
package emu.grasscutter.game.quest.content;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_OBTAIN_ITEM;
@QuestValueContent(QUEST_CONTENT_OBTAIN_ITEM)
public class ContentObtainItem extends BaseContent {
@Override
public boolean execute(GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
var targetCount = condition.getCount();
if (targetCount == 0) {
targetCount = 1;
}
return condition.getParam()[0] == params[0] && targetCount <= params[1];
}
}
package emu.grasscutter.game.quest.content;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_OBTAIN_ITEM;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
@QuestValueContent(QUEST_CONTENT_OBTAIN_ITEM)
public class ContentObtainItem extends BaseContent {
@Override
public boolean execute(
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
var targetCount = condition.getCount();
if (targetCount == 0) {
targetCount = 1;
}
return condition.getParam()[0] == params[0] && targetCount <= params[1];
}
}

View File

@@ -1,15 +1,16 @@
package emu.grasscutter.game.quest.content;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_PLAYER_LEVEL_UP;
@QuestValueContent(QUEST_CONTENT_PLAYER_LEVEL_UP)
public class ContentPlayerLevelUp extends BaseContent {
@Override
public boolean execute(GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
return quest.getOwner().getLevel() >= condition.getCount();
}
}
package emu.grasscutter.game.quest.content;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_PLAYER_LEVEL_UP;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
@QuestValueContent(QUEST_CONTENT_PLAYER_LEVEL_UP)
public class ContentPlayerLevelUp extends BaseContent {
@Override
public boolean execute(
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
return quest.getOwner().getLevel() >= condition.getCount();
}
}

View File

@@ -1,17 +1,17 @@
package emu.grasscutter.game.quest.content;
import emu.grasscutter.data.excels.QuestData.QuestCondition;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestBaseHandler;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_QUEST_STATE_EQUAL;
@QuestValue(QuestTrigger.QUEST_CONTENT_QUEST_STATE_EQUAL)
public class ContentQuestStateEqual extends QuestBaseHandler {
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
@QuestValueContent(QUEST_CONTENT_QUEST_STATE_EQUAL)
public class ContentQuestStateEqual extends BaseContent {
@Override
public boolean execute(
GameQuest quest, QuestCondition condition, String paramStr, int... params) {
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
GameQuest checkQuest = quest.getOwner().getQuestManager().getQuestById(condition.getParam()[0]);
if (checkQuest == null) {
return false;

View File

@@ -1,17 +1,17 @@
package emu.grasscutter.game.quest.content;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_QUEST_STATE_NOT_EQUAL;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestBaseHandler;
import emu.grasscutter.game.quest.QuestValueContent;
@QuestValue(QuestTrigger.QUEST_CONTENT_QUEST_STATE_NOT_EQUAL)
public class ContentQuestStateNotEqual extends QuestBaseHandler {
@QuestValueContent(QUEST_CONTENT_QUEST_STATE_NOT_EQUAL)
public class ContentQuestStateNotEqual extends BaseContent {
@Override
public boolean execute(
GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) {
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
GameQuest checkQuest = quest.getOwner().getQuestManager().getQuestById(params[0]);
if (checkQuest != null) {

View File

@@ -1,18 +1,18 @@
package emu.grasscutter.game.quest.content;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_QUEST_VAR_EQUAL;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestBaseHandler;
import emu.grasscutter.game.quest.QuestValueContent;
@QuestValue(QuestTrigger.QUEST_CONTENT_QUEST_VAR_EQUAL)
public class ContentQuestVarEqual extends QuestBaseHandler {
@QuestValueContent(QUEST_CONTENT_QUEST_VAR_EQUAL)
public class ContentQuestVarEqual extends BaseContent {
@Override
public boolean execute(
GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) {
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
int questVarValue = quest.getMainQuest().getQuestVars()[params[0]];
Grasscutter.getLogger().debug("questVar {} : {}", params[0], questVarValue);
return questVarValue == params[1];

View File

@@ -1,18 +1,18 @@
package emu.grasscutter.game.quest.content;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_QUEST_VAR_GREATER;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestBaseHandler;
import emu.grasscutter.game.quest.QuestValueContent;
@QuestValue(QuestTrigger.QUEST_CONTENT_QUEST_VAR_GREATER)
public class ContentQuestVarGreater extends QuestBaseHandler {
@QuestValueContent(QUEST_CONTENT_QUEST_VAR_GREATER)
public class ContentQuestVarGreater extends BaseContent {
@Override
public boolean execute(
GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) {
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
int questVarValue = quest.getMainQuest().getQuestVars()[params[0]];
Grasscutter.getLogger().debug("questVar {} : {}", params[0], questVarValue);
return questVarValue > params[1];

View File

@@ -1,18 +1,18 @@
package emu.grasscutter.game.quest.content;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_QUEST_VAR_LESS;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestBaseHandler;
import emu.grasscutter.game.quest.QuestValueContent;
@QuestValue(QuestTrigger.QUEST_CONTENT_QUEST_VAR_LESS)
public class ContentQuestVarLess extends QuestBaseHandler {
@QuestValueContent(QUEST_CONTENT_QUEST_VAR_LESS)
public class ContentQuestVarLess extends BaseContent {
@Override
public boolean execute(
GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) {
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
int questVarValue = quest.getMainQuest().getQuestVars()[params[0]];
Grasscutter.getLogger().debug("questVar {} : {}", params[0], questVarValue);
return questVarValue < params[1];

View File

@@ -1,15 +1,16 @@
package emu.grasscutter.game.quest.content;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_SKILL;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.QuestValueContent;
@QuestValue(QuestTrigger.QUEST_CONTENT_SKILL)
@QuestValueContent(QUEST_CONTENT_SKILL)
public class ContentSkill extends BaseContent {
@Override
public boolean execute(
GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) {
return (condition.getParam()[0] == params[0]) && (condition.getParam()[1] == params[1]);
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
return condition.getParam()[0] == params[0];
}
}

View File

@@ -1,25 +1,26 @@
package emu.grasscutter.game.quest.content;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
import emu.grasscutter.game.quest.enums.QuestContent;
import lombok.val;
@QuestValueContent(QuestContent.QUEST_CONTENT_TIME_VAR_GT_EQ)
public class ContentTimeVarMoreOrEqual extends BaseContent{
@Override
public boolean execute(GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
val mainQuestId = condition.getParam()[0];
val timeVarIndex = condition.getParam()[1];
val minTime = Integer.parseInt(condition.getParamStr());
val mainQuest = quest.getOwner().getQuestManager().getMainQuestById(mainQuestId);
if(mainQuest == null){
return false;
}
return mainQuest.getHoursSinceTimeVar(timeVarIndex) >= minTime;
}
}
package emu.grasscutter.game.quest.content;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
import emu.grasscutter.game.quest.enums.QuestContent;
import lombok.val;
@QuestValueContent(QuestContent.QUEST_CONTENT_TIME_VAR_GT_EQ)
public class ContentTimeVarMoreOrEqual extends BaseContent {
@Override
public boolean execute(
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
val mainQuestId = condition.getParam()[0];
val timeVarIndex = condition.getParam()[1];
val minTime = Integer.parseInt(condition.getParamStr());
val mainQuest = quest.getOwner().getQuestManager().getMainQuestById(mainQuestId);
if (mainQuest == null) {
return false;
}
return mainQuest.getHoursSinceTimeVar(timeVarIndex) >= minTime;
}
}

View File

@@ -1,30 +1,31 @@
package emu.grasscutter.game.quest.content;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
import emu.grasscutter.game.quest.enums.QuestContent;
import lombok.val;
@QuestValueContent(QuestContent.QUEST_CONTENT_TIME_VAR_PASS_DAY)
public class ContentTimeVarPassDay extends BaseContent{
@Override
public boolean execute(GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
val mainQuestId = condition.getParam()[0];
val timeVarIndex = condition.getParam()[1];
val minDays = Integer.parseInt(condition.getParamStr());
val mainQuest = quest.getOwner().getQuestManager().getMainQuestById(mainQuestId);
if(mainQuest == null){
return false;
}
val daysSinceTimeVar = mainQuest.getDaysSinceTimeVar(timeVarIndex);
if(daysSinceTimeVar == -1){
return false;
}
return daysSinceTimeVar >= minDays;
}
}
package emu.grasscutter.game.quest.content;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
import emu.grasscutter.game.quest.enums.QuestContent;
import lombok.val;
@QuestValueContent(QuestContent.QUEST_CONTENT_TIME_VAR_PASS_DAY)
public class ContentTimeVarPassDay extends BaseContent {
@Override
public boolean execute(
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
val mainQuestId = condition.getParam()[0];
val timeVarIndex = condition.getParam()[1];
val minDays = Integer.parseInt(condition.getParamStr());
val mainQuest = quest.getOwner().getQuestManager().getMainQuestById(mainQuestId);
if (mainQuest == null) {
return false;
}
val daysSinceTimeVar = mainQuest.getDaysSinceTimeVar(timeVarIndex);
if (daysSinceTimeVar == -1) {
return false;
}
return daysSinceTimeVar >= minDays;
}
}

View File

@@ -1,18 +1,18 @@
package emu.grasscutter.game.quest.content;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_TRIGGER_FIRE;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestBaseHandler;
import emu.grasscutter.game.quest.QuestValueContent;
@QuestValue(QuestTrigger.QUEST_CONTENT_TRIGGER_FIRE)
public class ContentTriggerFire extends QuestBaseHandler {
@QuestValueContent(QUEST_CONTENT_TRIGGER_FIRE)
public class ContentTriggerFire extends BaseContent {
@Override
public boolean execute(
GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) {
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
if (quest.getTriggers().containsKey(quest.getTriggerNameById(params[0]))) {
// We don't want to put a new key here
return quest.getTriggers().get(quest.getTriggerNameById(params[0]));

View File

@@ -1,15 +1,16 @@
package emu.grasscutter.game.quest.content;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_UNLOCK_AREA;
@QuestValueContent(QUEST_CONTENT_UNLOCK_AREA)
public class ContentUnlockArea 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];
}
}
package emu.grasscutter.game.quest.content;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_UNLOCK_AREA;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
@QuestValueContent(QUEST_CONTENT_UNLOCK_AREA)
public class ContentUnlockArea 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];
}
}

View File

@@ -1,16 +1,16 @@
package emu.grasscutter.game.quest.content;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_UNLOCK_TRANS_POINT;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestBaseHandler;
import emu.grasscutter.game.quest.QuestValueContent;
@QuestValue(QuestTrigger.QUEST_CONTENT_UNLOCK_TRANS_POINT)
public class ContentUnlockTransPoint extends QuestBaseHandler {
@QuestValueContent(QUEST_CONTENT_UNLOCK_TRANS_POINT)
public class ContentUnlockTransPoint extends BaseContent {
@Override
public boolean execute(
GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) {
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
return condition.getParam()[0] == params[0] && condition.getParam()[1] == params[1];
}
}

View File

@@ -1,15 +1,16 @@
package emu.grasscutter.game.quest.content;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_USE_ITEM;
@QuestValueContent(QUEST_CONTENT_USE_ITEM)
public class ContentUseItem extends BaseContent {
@Override
public boolean execute(GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
return condition.getParam()[0] == params[0];
}
}
package emu.grasscutter.game.quest.content;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_USE_ITEM;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
@QuestValueContent(QUEST_CONTENT_USE_ITEM)
public class ContentUseItem extends BaseContent {
@Override
public boolean execute(
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
return condition.getParam()[0] == params[0];
}
}

View File

@@ -1,15 +1,16 @@
package emu.grasscutter.game.quest.content;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_WORKTOP_SELECT;
@QuestValueContent(QUEST_CONTENT_WORKTOP_SELECT)
public class ContentWorktopSelect 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];
}
}
package emu.grasscutter.game.quest.content;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_WORKTOP_SELECT;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
@QuestValueContent(QUEST_CONTENT_WORKTOP_SELECT)
public class ContentWorktopSelect 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];
}
}

View File

@@ -1,6 +1,10 @@
package emu.grasscutter.game.quest.enums;
import emu.grasscutter.Grasscutter;
import java.util.Arrays;
import java.util.List;
import java.util.function.BooleanSupplier;
import org.jetbrains.annotations.NotNull;
public enum LogicType {
LOGIC_NONE(0),
@@ -20,6 +24,10 @@ public enum LogicType {
}
public static boolean calculate(LogicType logicType, int[] progress) {
if (progress.length == 0) {
return true;
}
if (logicType == null) {
return progress[0] == 1;
}
@@ -31,12 +39,57 @@ public enum LogicType {
case LOGIC_OR -> {
return Arrays.stream(progress).anyMatch(i -> i == 1);
}
case LOGIC_NOT -> {
return Arrays.stream(progress).noneMatch(i -> i == 1);
}
case LOGIC_A_AND_ETCOR -> {
return progress[0] == 1 && Arrays.stream(progress).skip(1).anyMatch(i -> i == 1);
}
case LOGIC_A_AND_B_AND_ETCOR -> {
return progress[0] == 1
&& progress[1] == 1
&& Arrays.stream(progress).skip(2).anyMatch(i -> i == 1);
}
case LOGIC_A_OR_ETCAND -> {
return progress[0] == 1 || Arrays.stream(progress).skip(1).allMatch(i -> i == 1);
}
case LOGIC_A_OR_B_OR_ETCAND -> {
return progress[0] == 1
|| progress[1] == 1
|| Arrays.stream(progress).skip(2).allMatch(i -> i == 1);
}
case LOGIC_A_AND_B_OR_ETCAND -> {
return progress[0] == 1 && progress[1] == 1
|| Arrays.stream(progress).skip(2).allMatch(i -> i == 1);
}
default -> {
return Arrays.stream(progress).anyMatch(i -> i == 1);
}
}
}
/**
* Apply logic type to all predicates
*
* @param logicType type of logic that should be applied to predicates
* @param predicates list of predicates for which logicType will be applied
* @return result of applying logicType to predicates
*/
public static boolean calculate(@NotNull LogicType logicType, List<BooleanSupplier> predicates) {
switch (logicType) {
case LOGIC_AND -> {
return predicates.stream().allMatch(BooleanSupplier::getAsBoolean);
}
case LOGIC_OR -> {
return predicates.stream().anyMatch(BooleanSupplier::getAsBoolean);
}
default -> {
Grasscutter.getLogger().error("Unimplemented logic operation was called");
return false;
}
}
}
public int getValue() {
return value;
}

View File

@@ -1,121 +1,120 @@
package emu.grasscutter.game.quest.enums;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;
public enum QuestCond implements QuestTrigger {
QUEST_COND_NONE (0),
QUEST_COND_STATE_EQUAL (1),
QUEST_COND_STATE_NOT_EQUAL (2),
QUEST_COND_PACK_HAVE_ITEM (3),
QUEST_COND_AVATAR_ELEMENT_EQUAL (4), // missing, currently unused
QUEST_COND_AVATAR_ELEMENT_NOT_EQUAL (5), // missing, only NPC groups
QUEST_COND_AVATAR_CAN_CHANGE_ELEMENT (6), // missing, only NPC groups
QUEST_COND_CITY_LEVEL_EQUAL_GREATER (7), // missing, currently unused
QUEST_COND_ITEM_NUM_LESS_THAN (8),
QUEST_COND_DAILY_TASK_START (9), // missing
QUEST_COND_OPEN_STATE_EQUAL (10),
QUEST_COND_DAILY_TASK_OPEN (11), // missing, only NPC groups
QUEST_COND_DAILY_TASK_REWARD_CAN_GET (12), // missing, only NPC groups/talks
QUEST_COND_DAILY_TASK_REWARD_RECEIVED (13), // missing, only NPC groups/talks
QUEST_COND_PLAYER_LEVEL_REWARD_CAN_GET (14), // missing, only NPC groups/talks
QUEST_COND_EXPLORATION_REWARD_CAN_GET (15), // missing, only NPC groups/talks
QUEST_COND_IS_WORLD_OWNER (16), // missing, only NPC groups/talks
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_IS_DAYTIME (21), // only NPC groups
QUEST_COND_CURRENT_AVATAR (22), // missing
QUEST_COND_CURRENT_AREA (23), // missing
QUEST_COND_QUEST_VAR_EQUAL (24),
QUEST_COND_QUEST_VAR_GREATER (25),
QUEST_COND_QUEST_VAR_LESS (26),
QUEST_COND_FORGE_HAVE_FINISH (27), // missing, only NPC groups
QUEST_COND_DAILY_TASK_IN_PROGRESS (28), // missing
QUEST_COND_DAILY_TASK_FINISHED (29), // missing, currently unused
QUEST_COND_ACTIVITY_COND (30),
QUEST_COND_ACTIVITY_OPEN (31),
QUEST_COND_DAILY_TASK_VAR_GT (32), // missing
QUEST_COND_DAILY_TASK_VAR_EQ (33), // missing
QUEST_COND_DAILY_TASK_VAR_LT (34), // missing
QUEST_COND_BARGAIN_ITEM_GT (35), // missing, currently unused
QUEST_COND_BARGAIN_ITEM_EQ (36), // missing, currently unused
QUEST_COND_BARGAIN_ITEM_LT (37), // missing, currently unused
QUEST_COND_COMPLETE_TALK (38),
QUEST_COND_NOT_HAVE_BLOSSOM_TALK (39), // missing, only NPC groups
QUEST_COND_IS_CUR_BLOSSOM_TALK (40), // missing, only Blossom groups
QUEST_COND_QUEST_NOT_RECEIVE (41), // missing
QUEST_COND_QUEST_SERVER_COND_VALID (42), // missing, only NPC groups
QUEST_COND_ACTIVITY_CLIENT_COND (43), // missing, only NPC and Activity groups
QUEST_COND_QUEST_GLOBAL_VAR_EQUAL (44),
QUEST_COND_QUEST_GLOBAL_VAR_GREATER (45),
QUEST_COND_QUEST_GLOBAL_VAR_LESS (46),
QUEST_COND_PERSONAL_LINE_UNLOCK (47),
QUEST_COND_CITY_REPUTATION_REQUEST (48), // missing
QUEST_COND_MAIN_COOP_START (49), // missing
QUEST_COND_MAIN_COOP_ENTER_SAVE_POINT (50), // missing
QUEST_COND_CITY_REPUTATION_LEVEL (51), // missing, only NPC groups
QUEST_COND_CITY_REPUTATION_UNLOCK (52), // missing, currently unused
QUEST_COND_LUA_NOTIFY (53),
QUEST_COND_CUR_CLIMATE (54),
QUEST_COND_ACTIVITY_END (55),
QUEST_COND_COOP_POINT_RUNNING (56), // missing, currently unused
QUEST_COND_GADGET_TALK_STATE_EQUAL (57), // missing, only Gadget groups
QUEST_COND_AVATAR_FETTER_GT (58), // missing, only NPC groups/talks
QUEST_COND_AVATAR_FETTER_EQ (59), // missing, only talks
QUEST_COND_AVATAR_FETTER_LT (60), // missing, only talks
QUEST_COND_NEW_HOMEWORLD_MOUDLE_UNLOCK (61), // missing, only Gadget groups
QUEST_COND_NEW_HOMEWORLD_LEVEL_REWARD (62), // missing, only Gadget groups
QUEST_COND_NEW_HOMEWORLD_MAKE_FINISH (63), // missing, only Gadget groups
QUEST_COND_HOMEWORLD_NPC_EVENT (64), // missing, only NPC groups
QUEST_COND_TIME_VAR_GT_EQ (65), // currently unused
QUEST_COND_TIME_VAR_PASS_DAY (66),
QUEST_COND_HOMEWORLD_NPC_NEW_TALK (67), // missing, only NPC groups
QUEST_COND_PLAYER_CHOOSE_MALE (68), // missing, only talks
QUEST_COND_HISTORY_GOT_ANY_ITEM (69),
QUEST_COND_LEARNED_RECIPE (70), // missing, currently unused
QUEST_COND_LUNARITE_REGION_UNLOCKED (71), // missing, only NPC groups
QUEST_COND_LUNARITE_HAS_REGION_HINT_COUNT (72), // missing, only NPC groups
QUEST_COND_LUNARITE_COLLECT_FINISH (73), // missing, only NPC groups
QUEST_COND_LUNARITE_MARK_ALL_FINISH (74), // missing, only NPC groups
QUEST_COND_NEW_HOMEWORLD_SHOP_ITEM (75), // missing, only Gadget groups
QUEST_COND_SCENE_POINT_UNLOCK (76), // missing, only NPC groups
QUEST_COND_SCENE_LEVEL_TAG_EQ (77), // missing
QUEST_COND_PLAYER_ENTER_REGION (78), // missing
QUEST_COND_UNKNOWN (9999);
private final int value;
QuestCond(int id) {
this.value = id;
}
public int getValue() {
return value;
}
private static final Int2ObjectMap<QuestCond> contentMap = new Int2ObjectOpenHashMap<>();
private static final Map<String, QuestCond> contentStringMap = new HashMap<>();
static {
Stream.of(values())
.forEach(e -> {
contentMap.put(e.getValue(), e);
contentStringMap.put(e.name(), e);
});
}
public static QuestCond getContentTriggerByValue(int value) {
return contentMap.getOrDefault(value, QUEST_COND_NONE);
}
public static QuestCond getContentTriggerByName(String name) {
return contentStringMap.getOrDefault(name, QUEST_COND_NONE);
}
}
package emu.grasscutter.game.quest.enums;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;
public enum QuestCond implements QuestTrigger {
QUEST_COND_NONE(0),
QUEST_COND_STATE_EQUAL(1),
QUEST_COND_STATE_NOT_EQUAL(2),
QUEST_COND_PACK_HAVE_ITEM(3),
QUEST_COND_AVATAR_ELEMENT_EQUAL(4), // missing, currently unused
QUEST_COND_AVATAR_ELEMENT_NOT_EQUAL(5), // missing, only NPC groups
QUEST_COND_AVATAR_CAN_CHANGE_ELEMENT(6), // missing, only NPC groups
QUEST_COND_CITY_LEVEL_EQUAL_GREATER(7), // missing, currently unused
QUEST_COND_ITEM_NUM_LESS_THAN(8),
QUEST_COND_DAILY_TASK_START(9), // missing
QUEST_COND_OPEN_STATE_EQUAL(10),
QUEST_COND_DAILY_TASK_OPEN(11), // missing, only NPC groups
QUEST_COND_DAILY_TASK_REWARD_CAN_GET(12), // missing, only NPC groups/talks
QUEST_COND_DAILY_TASK_REWARD_RECEIVED(13), // missing, only NPC groups/talks
QUEST_COND_PLAYER_LEVEL_REWARD_CAN_GET(14), // missing, only NPC groups/talks
QUEST_COND_EXPLORATION_REWARD_CAN_GET(15), // missing, only NPC groups/talks
QUEST_COND_IS_WORLD_OWNER(16), // missing, only NPC groups/talks
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_IS_DAYTIME(21), // only NPC groups
QUEST_COND_CURRENT_AVATAR(22), // missing
QUEST_COND_CURRENT_AREA(23), // missing
QUEST_COND_QUEST_VAR_EQUAL(24),
QUEST_COND_QUEST_VAR_GREATER(25),
QUEST_COND_QUEST_VAR_LESS(26),
QUEST_COND_FORGE_HAVE_FINISH(27), // missing, only NPC groups
QUEST_COND_DAILY_TASK_IN_PROGRESS(28), // missing
QUEST_COND_DAILY_TASK_FINISHED(29), // missing, currently unused
QUEST_COND_ACTIVITY_COND(30),
QUEST_COND_ACTIVITY_OPEN(31),
QUEST_COND_DAILY_TASK_VAR_GT(32), // missing
QUEST_COND_DAILY_TASK_VAR_EQ(33), // missing
QUEST_COND_DAILY_TASK_VAR_LT(34), // missing
QUEST_COND_BARGAIN_ITEM_GT(35), // missing, currently unused
QUEST_COND_BARGAIN_ITEM_EQ(36), // missing, currently unused
QUEST_COND_BARGAIN_ITEM_LT(37), // missing, currently unused
QUEST_COND_COMPLETE_TALK(38),
QUEST_COND_NOT_HAVE_BLOSSOM_TALK(39), // missing, only NPC groups
QUEST_COND_IS_CUR_BLOSSOM_TALK(40), // missing, only Blossom groups
QUEST_COND_QUEST_NOT_RECEIVE(41), // missing
QUEST_COND_QUEST_SERVER_COND_VALID(42), // missing, only NPC groups
QUEST_COND_ACTIVITY_CLIENT_COND(43), // missing, only NPC and Activity groups
QUEST_COND_QUEST_GLOBAL_VAR_EQUAL(44),
QUEST_COND_QUEST_GLOBAL_VAR_GREATER(45),
QUEST_COND_QUEST_GLOBAL_VAR_LESS(46),
QUEST_COND_PERSONAL_LINE_UNLOCK(47),
QUEST_COND_CITY_REPUTATION_REQUEST(48), // missing
QUEST_COND_MAIN_COOP_START(49), // missing
QUEST_COND_MAIN_COOP_ENTER_SAVE_POINT(50), // missing
QUEST_COND_CITY_REPUTATION_LEVEL(51), // missing, only NPC groups
QUEST_COND_CITY_REPUTATION_UNLOCK(52), // missing, currently unused
QUEST_COND_LUA_NOTIFY(53),
QUEST_COND_CUR_CLIMATE(54),
QUEST_COND_ACTIVITY_END(55),
QUEST_COND_COOP_POINT_RUNNING(56), // missing, currently unused
QUEST_COND_GADGET_TALK_STATE_EQUAL(57), // missing, only Gadget groups
QUEST_COND_AVATAR_FETTER_GT(58), // missing, only NPC groups/talks
QUEST_COND_AVATAR_FETTER_EQ(59), // missing, only talks
QUEST_COND_AVATAR_FETTER_LT(60), // missing, only talks
QUEST_COND_NEW_HOMEWORLD_MOUDLE_UNLOCK(61), // missing, only Gadget groups
QUEST_COND_NEW_HOMEWORLD_LEVEL_REWARD(62), // missing, only Gadget groups
QUEST_COND_NEW_HOMEWORLD_MAKE_FINISH(63), // missing, only Gadget groups
QUEST_COND_HOMEWORLD_NPC_EVENT(64), // missing, only NPC groups
QUEST_COND_TIME_VAR_GT_EQ(65), // currently unused
QUEST_COND_TIME_VAR_PASS_DAY(66),
QUEST_COND_HOMEWORLD_NPC_NEW_TALK(67), // missing, only NPC groups
QUEST_COND_PLAYER_CHOOSE_MALE(68), // missing, only talks
QUEST_COND_HISTORY_GOT_ANY_ITEM(69),
QUEST_COND_LEARNED_RECIPE(70), // missing, currently unused
QUEST_COND_LUNARITE_REGION_UNLOCKED(71), // missing, only NPC groups
QUEST_COND_LUNARITE_HAS_REGION_HINT_COUNT(72), // missing, only NPC groups
QUEST_COND_LUNARITE_COLLECT_FINISH(73), // missing, only NPC groups
QUEST_COND_LUNARITE_MARK_ALL_FINISH(74), // missing, only NPC groups
QUEST_COND_NEW_HOMEWORLD_SHOP_ITEM(75), // missing, only Gadget groups
QUEST_COND_SCENE_POINT_UNLOCK(76), // missing, only NPC groups
QUEST_COND_SCENE_LEVEL_TAG_EQ(77), // missing
QUEST_COND_PLAYER_ENTER_REGION(78), // missing
QUEST_COND_UNKNOWN(9999);
private final int value;
QuestCond(int id) {
this.value = id;
}
public int getValue() {
return value;
}
private static final Int2ObjectMap<QuestCond> contentMap = new Int2ObjectOpenHashMap<>();
private static final Map<String, QuestCond> contentStringMap = new HashMap<>();
static {
Stream.of(values())
.forEach(
e -> {
contentMap.put(e.getValue(), e);
contentStringMap.put(e.name(), e);
});
}
public static QuestCond getContentTriggerByValue(int value) {
return contentMap.getOrDefault(value, QUEST_COND_NONE);
}
public static QuestCond getContentTriggerByName(String name) {
return contentStringMap.getOrDefault(name, QUEST_COND_NONE);
}
}

View File

@@ -1,117 +1,116 @@
package emu.grasscutter.game.quest.enums;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;
public enum QuestContent implements QuestTrigger {
QUEST_CONTENT_NONE (0),
QUEST_CONTENT_KILL_MONSTER (1), // currently unused
QUEST_CONTENT_COMPLETE_TALK (2),
QUEST_CONTENT_MONSTER_DIE (3),
QUEST_CONTENT_FINISH_PLOT (4),
QUEST_CONTENT_OBTAIN_ITEM (5),
QUEST_CONTENT_TRIGGER_FIRE (6),
QUEST_CONTENT_CLEAR_GROUP_MONSTER (7),
QUEST_CONTENT_NOT_FINISH_PLOT (8), // missing triggers, fail
QUEST_CONTENT_ENTER_DUNGEON (9),
QUEST_CONTENT_ENTER_MY_WORLD (10),
QUEST_CONTENT_FINISH_DUNGEON (11),
QUEST_CONTENT_DESTROY_GADGET (12),
QUEST_CONTENT_OBTAIN_MATERIAL_WITH_SUBTYPE (13), // missing, finish
QUEST_CONTENT_NICK_NAME (14), // missing, currently unused
QUEST_CONTENT_WORKTOP_SELECT (15), // currently unused
QUEST_CONTENT_SEAL_BATTLE_RESULT (16), // missing, currently unused
QUEST_CONTENT_ENTER_ROOM (17),
QUEST_CONTENT_GAME_TIME_TICK (18),
QUEST_CONTENT_FAIL_DUNGEON (19),
QUEST_CONTENT_LUA_NOTIFY (20),
QUEST_CONTENT_TEAM_DEAD (21), // missing, fail
QUEST_CONTENT_COMPLETE_ANY_TALK (22),
QUEST_CONTENT_UNLOCK_TRANS_POINT (23),
QUEST_CONTENT_ADD_QUEST_PROGRESS (24),
QUEST_CONTENT_INTERACT_GADGET (25),
QUEST_CONTENT_DAILY_TASK_COMP_FINISH (26), // missing, currently unused
QUEST_CONTENT_FINISH_ITEM_GIVING (27), // missing, finish
QUEST_CONTENT_SKILL (107),
QUEST_CONTENT_CITY_LEVEL_UP (109), // missing, finish
QUEST_CONTENT_PATTERN_GROUP_CLEAR_MONSTER (110), // missing, finish, for random quests
QUEST_CONTENT_ITEM_LESS_THAN (111),
QUEST_CONTENT_PLAYER_LEVEL_UP (112),
QUEST_CONTENT_DUNGEON_OPEN_STATUE (113), // missing, currently unused
QUEST_CONTENT_UNLOCK_AREA (114), // currently unused
QUEST_CONTENT_OPEN_CHEST_WITH_GADGET_ID (115), // missing, currently unused
QUEST_CONTENT_UNLOCK_TRANS_POINT_WITH_TYPE (116), // missing, currently unused
QUEST_CONTENT_FINISH_DAILY_DUNGEON (117), // missing, currently unused
QUEST_CONTENT_FINISH_WEEKLY_DUNGEON (118), // missing, currently unused
QUEST_CONTENT_QUEST_VAR_EQUAL (119),
QUEST_CONTENT_QUEST_VAR_GREATER (120),
QUEST_CONTENT_QUEST_VAR_LESS (121),
QUEST_CONTENT_OBTAIN_VARIOUS_ITEM (122), // missing, finish
QUEST_CONTENT_FINISH_TOWER_LEVEL (123), // missing, currently unused
QUEST_CONTENT_BARGAIN_SUCC (124), // missing, finish
QUEST_CONTENT_BARGAIN_FAIL (125),// missing, fail
QUEST_CONTENT_ITEM_LESS_THAN_BARGAIN (126),// missing, fail
QUEST_CONTENT_ACTIVITY_TRIGGER_FAILED (127),// missing, fail
QUEST_CONTENT_MAIN_COOP_ENTER_SAVE_POINT (128),// missing, finish
QUEST_CONTENT_ANY_MANUAL_TRANSPORT (129),
QUEST_CONTENT_USE_ITEM (130),
QUEST_CONTENT_MAIN_COOP_ENTER_ANY_SAVE_POINT (131),// missing, finish and fail
QUEST_CONTENT_ENTER_MY_HOME_WORLD (132),// missing, finish and fail
QUEST_CONTENT_ENTER_MY_WORLD_SCENE (133),// missing, finish
QUEST_CONTENT_TIME_VAR_GT_EQ (134),
QUEST_CONTENT_TIME_VAR_PASS_DAY (135),
QUEST_CONTENT_QUEST_STATE_EQUAL (136),
QUEST_CONTENT_QUEST_STATE_NOT_EQUAL (137),
QUEST_CONTENT_UNLOCKED_RECIPE (138),// missing, finish
QUEST_CONTENT_NOT_UNLOCKED_RECIPE (139),// missing, finish
QUEST_CONTENT_FISHING_SUCC (140),// missing, finish
QUEST_CONTENT_ENTER_ROGUE_DUNGEON (141),// missing, finish
QUEST_CONTENT_USE_WIDGET (142),// missing, finish, only in unreleased quest
QUEST_CONTENT_CAPTURE_SUCC (143),// missing, currently unused
QUEST_CONTENT_CAPTURE_USE_CAPTURETAG_LIST (144),// missing, currently unused
QUEST_CONTENT_CAPTURE_USE_MATERIAL_LIST (145),// missing, finish
QUEST_CONTENT_ENTER_VEHICLE (147),
QUEST_CONTENT_SCENE_LEVEL_TAG_EQ (148),// missing, finish
QUEST_CONTENT_LEAVE_SCENE (149),
QUEST_CONTENT_LEAVE_SCENE_RANGE (150),// missing, fail
QUEST_CONTENT_IRODORI_FINISH_FLOWER_COMBINATION (151),// missing, finish
QUEST_CONTENT_IRODORI_POETRY_REACH_MIN_PROGRESS (152),// missing, finish
QUEST_CONTENT_IRODORI_POETRY_FINISH_FILL_POETRY (153),// missing, finish
QUEST_CONTENT_ACTIVITY_TRIGGER_UPDATE(154), // missing
QUEST_CONTENT_GADGET_STATE_CHANGE(155), // missing
QUEST_CONTENT_UNKNOWN (9999);
private final int value;
QuestContent(int id) {
this.value = id;
}
public int getValue() {
return value;
}
private static final Int2ObjectMap<QuestContent> contentMap = new Int2ObjectOpenHashMap<>();
private static final Map<String, QuestContent> contentStringMap = new HashMap<>();
static {
Stream.of(values())
.forEach(e -> {
contentMap.put(e.getValue(), e);
contentStringMap.put(e.name(), e);
});
}
public static QuestContent getContentTriggerByValue(int value) {
return contentMap.getOrDefault(value, QUEST_CONTENT_NONE);
}
public static QuestContent getContentTriggerByName(String name) {
return contentStringMap.getOrDefault(name, QUEST_CONTENT_NONE);
}
}
package emu.grasscutter.game.quest.enums;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;
public enum QuestContent implements QuestTrigger {
QUEST_CONTENT_NONE(0),
QUEST_CONTENT_KILL_MONSTER(1), // currently unused
QUEST_CONTENT_COMPLETE_TALK(2),
QUEST_CONTENT_MONSTER_DIE(3),
QUEST_CONTENT_FINISH_PLOT(4),
QUEST_CONTENT_OBTAIN_ITEM(5),
QUEST_CONTENT_TRIGGER_FIRE(6),
QUEST_CONTENT_CLEAR_GROUP_MONSTER(7),
QUEST_CONTENT_NOT_FINISH_PLOT(8), // missing triggers, fail
QUEST_CONTENT_ENTER_DUNGEON(9),
QUEST_CONTENT_ENTER_MY_WORLD(10),
QUEST_CONTENT_FINISH_DUNGEON(11),
QUEST_CONTENT_DESTROY_GADGET(12),
QUEST_CONTENT_OBTAIN_MATERIAL_WITH_SUBTYPE(13), // missing, finish
QUEST_CONTENT_NICK_NAME(14), // missing, currently unused
QUEST_CONTENT_WORKTOP_SELECT(15), // currently unused
QUEST_CONTENT_SEAL_BATTLE_RESULT(16), // missing, currently unused
QUEST_CONTENT_ENTER_ROOM(17),
QUEST_CONTENT_GAME_TIME_TICK(18),
QUEST_CONTENT_FAIL_DUNGEON(19),
QUEST_CONTENT_LUA_NOTIFY(20),
QUEST_CONTENT_TEAM_DEAD(21), // missing, fail
QUEST_CONTENT_COMPLETE_ANY_TALK(22),
QUEST_CONTENT_UNLOCK_TRANS_POINT(23),
QUEST_CONTENT_ADD_QUEST_PROGRESS(24),
QUEST_CONTENT_INTERACT_GADGET(25),
QUEST_CONTENT_DAILY_TASK_COMP_FINISH(26), // missing, currently unused
QUEST_CONTENT_FINISH_ITEM_GIVING(27), // missing, finish
QUEST_CONTENT_SKILL(107),
QUEST_CONTENT_CITY_LEVEL_UP(109), // missing, finish
QUEST_CONTENT_PATTERN_GROUP_CLEAR_MONSTER(110), // missing, finish, for random quests
QUEST_CONTENT_ITEM_LESS_THAN(111),
QUEST_CONTENT_PLAYER_LEVEL_UP(112),
QUEST_CONTENT_DUNGEON_OPEN_STATUE(113), // missing, currently unused
QUEST_CONTENT_UNLOCK_AREA(114), // currently unused
QUEST_CONTENT_OPEN_CHEST_WITH_GADGET_ID(115), // missing, currently unused
QUEST_CONTENT_UNLOCK_TRANS_POINT_WITH_TYPE(116), // missing, currently unused
QUEST_CONTENT_FINISH_DAILY_DUNGEON(117), // missing, currently unused
QUEST_CONTENT_FINISH_WEEKLY_DUNGEON(118), // missing, currently unused
QUEST_CONTENT_QUEST_VAR_EQUAL(119),
QUEST_CONTENT_QUEST_VAR_GREATER(120),
QUEST_CONTENT_QUEST_VAR_LESS(121),
QUEST_CONTENT_OBTAIN_VARIOUS_ITEM(122), // missing, finish
QUEST_CONTENT_FINISH_TOWER_LEVEL(123), // missing, currently unused
QUEST_CONTENT_BARGAIN_SUCC(124), // missing, finish
QUEST_CONTENT_BARGAIN_FAIL(125), // missing, fail
QUEST_CONTENT_ITEM_LESS_THAN_BARGAIN(126), // missing, fail
QUEST_CONTENT_ACTIVITY_TRIGGER_FAILED(127), // missing, fail
QUEST_CONTENT_MAIN_COOP_ENTER_SAVE_POINT(128), // missing, finish
QUEST_CONTENT_ANY_MANUAL_TRANSPORT(129),
QUEST_CONTENT_USE_ITEM(130),
QUEST_CONTENT_MAIN_COOP_ENTER_ANY_SAVE_POINT(131), // missing, finish and fail
QUEST_CONTENT_ENTER_MY_HOME_WORLD(132), // missing, finish and fail
QUEST_CONTENT_ENTER_MY_WORLD_SCENE(133), // missing, finish
QUEST_CONTENT_TIME_VAR_GT_EQ(134),
QUEST_CONTENT_TIME_VAR_PASS_DAY(135),
QUEST_CONTENT_QUEST_STATE_EQUAL(136),
QUEST_CONTENT_QUEST_STATE_NOT_EQUAL(137),
QUEST_CONTENT_UNLOCKED_RECIPE(138), // missing, finish
QUEST_CONTENT_NOT_UNLOCKED_RECIPE(139), // missing, finish
QUEST_CONTENT_FISHING_SUCC(140), // missing, finish
QUEST_CONTENT_ENTER_ROGUE_DUNGEON(141), // missing, finish
QUEST_CONTENT_USE_WIDGET(142), // missing, finish, only in unreleased quest
QUEST_CONTENT_CAPTURE_SUCC(143), // missing, currently unused
QUEST_CONTENT_CAPTURE_USE_CAPTURETAG_LIST(144), // missing, currently unused
QUEST_CONTENT_CAPTURE_USE_MATERIAL_LIST(145), // missing, finish
QUEST_CONTENT_ENTER_VEHICLE(147),
QUEST_CONTENT_SCENE_LEVEL_TAG_EQ(148), // missing, finish
QUEST_CONTENT_LEAVE_SCENE(149),
QUEST_CONTENT_LEAVE_SCENE_RANGE(150), // missing, fail
QUEST_CONTENT_IRODORI_FINISH_FLOWER_COMBINATION(151), // missing, finish
QUEST_CONTENT_IRODORI_POETRY_REACH_MIN_PROGRESS(152), // missing, finish
QUEST_CONTENT_IRODORI_POETRY_FINISH_FILL_POETRY(153), // missing, finish
QUEST_CONTENT_ACTIVITY_TRIGGER_UPDATE(154), // missing
QUEST_CONTENT_GADGET_STATE_CHANGE(155), // missing
QUEST_CONTENT_UNKNOWN(9999);
private final int value;
QuestContent(int id) {
this.value = id;
}
public int getValue() {
return value;
}
private static final Int2ObjectMap<QuestContent> contentMap = new Int2ObjectOpenHashMap<>();
private static final Map<String, QuestContent> contentStringMap = new HashMap<>();
static {
Stream.of(values())
.forEach(
e -> {
contentMap.put(e.getValue(), e);
contentStringMap.put(e.name(), e);
});
}
public static QuestContent getContentTriggerByValue(int value) {
return contentMap.getOrDefault(value, QUEST_CONTENT_NONE);
}
public static QuestContent getContentTriggerByName(String name) {
return contentStringMap.getOrDefault(name, QUEST_CONTENT_NONE);
}
}

View File

@@ -1,112 +1,114 @@
package emu.grasscutter.game.quest.enums;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;
public enum QuestExec implements QuestTrigger {
QUEST_EXEC_NONE (0),
QUEST_EXEC_DEL_PACK_ITEM (1),
QUEST_EXEC_UNLOCK_POINT (2),
QUEST_EXEC_UNLOCK_AREA (3),
QUEST_EXEC_UNLOCK_FORCE (4), // missing, currently unused
QUEST_EXEC_LOCK_FORCE (5), // missing, currently unused
QUEST_EXEC_CHANGE_AVATAR_ELEMET (6),
QUEST_EXEC_REFRESH_GROUP_MONSTER (7),
QUEST_EXEC_SET_IS_FLYABLE (8), // missing, maybe gives glider
QUEST_EXEC_SET_IS_WEATHER_LOCKED (9), // missing
QUEST_EXEC_SET_IS_GAME_TIME_LOCKED (10), // missing
QUEST_EXEC_SET_IS_TRANSFERABLE (11), // missing, currently unused
QUEST_EXEC_GRANT_TRIAL_AVATAR (12),
QUEST_EXEC_OPEN_BORED (13), // missing, currently unused
QUEST_EXEC_ROLLBACK_QUEST (14),
QUEST_EXEC_NOTIFY_GROUP_LUA (15),
QUEST_EXEC_SET_OPEN_STATE (16),
QUEST_EXEC_LOCK_POINT (17), // missing
QUEST_EXEC_DEL_PACK_ITEM_BATCH (18),
QUEST_EXEC_REFRESH_GROUP_SUITE (19),
QUEST_EXEC_REMOVE_TRIAL_AVATAR (20),
QUEST_EXEC_SET_GAME_TIME (21), // missing
QUEST_EXEC_SET_WEATHER_GADGET (22), // missing
QUEST_EXEC_ADD_QUEST_PROGRESS (23),
QUEST_EXEC_NOTIFY_DAILY_TASK (24), // missing
QUEST_EXEC_CREATE_PATTERN_GROUP (25), // missing, used for random quests
QUEST_EXEC_REMOVE_PATTERN_GROUP (26), // missing, used for random quests
QUEST_EXEC_REFRESH_GROUP_SUITE_RANDOM (27), // missing
QUEST_EXEC_ACTIVE_ITEM_GIVING (28), // missing
QUEST_EXEC_DEL_ALL_SPECIFIC_PACK_ITEM (29), // missing
QUEST_EXEC_ROLLBACK_PARENT_QUEST (30),
QUEST_EXEC_LOCK_AVATAR_TEAM (31), // missing
QUEST_EXEC_UNLOCK_AVATAR_TEAM (32), // missing
QUEST_EXEC_UPDATE_PARENT_QUEST_REWARD_INDEX (33), // missing
QUEST_EXEC_SET_DAILY_TASK_VAR (34), // missing
QUEST_EXEC_INC_DAILY_TASK_VAR (35), // missing
QUEST_EXEC_DEC_DAILY_TASK_VAR (36), // missing, currently unused
QUEST_EXEC_ACTIVE_ACTIVITY_COND_STATE (37), // missing
QUEST_EXEC_INACTIVE_ACTIVITY_COND_STATE (38), // missing
QUEST_EXEC_ADD_CUR_AVATAR_ENERGY (39),
QUEST_EXEC_START_BARGAIN (41), // missing
QUEST_EXEC_STOP_BARGAIN (42), // missing
QUEST_EXEC_SET_QUEST_GLOBAL_VAR (43),
QUEST_EXEC_INC_QUEST_GLOBAL_VAR (44),
QUEST_EXEC_DEC_QUEST_GLOBAL_VAR (45),
QUEST_EXEC_REGISTER_DYNAMIC_GROUP (46), // test, maybe the dynamic should be saved on a list and when you enter the view range this loads it again
QUEST_EXEC_UNREGISTER_DYNAMIC_GROUP (47), // test, same for this
QUEST_EXEC_SET_QUEST_VAR (48),
QUEST_EXEC_INC_QUEST_VAR (49),
QUEST_EXEC_DEC_QUEST_VAR (50),
QUEST_EXEC_RANDOM_QUEST_VAR (51), // missing
QUEST_EXEC_ACTIVATE_SCANNING_PIC (52), // missing, currently unused
QUEST_EXEC_RELOAD_SCENE_TAG (53), // missing
QUEST_EXEC_REGISTER_DYNAMIC_GROUP_ONLY (54), // missing
QUEST_EXEC_CHANGE_SKILL_DEPOT (55), // missing
QUEST_EXEC_ADD_SCENE_TAG (56), // missing
QUEST_EXEC_DEL_SCENE_TAG (57), // missing
QUEST_EXEC_INIT_TIME_VAR (58),
QUEST_EXEC_CLEAR_TIME_VAR (59),
QUEST_EXEC_MODIFY_CLIMATE_AREA (60), // missing
QUEST_EXEC_GRANT_TRIAL_AVATAR_AND_LOCK_TEAM (61), // missing
QUEST_EXEC_CHANGE_MAP_AREA_STATE (62), // missing
QUEST_EXEC_DEACTIVE_ITEM_GIVING (63), // missing
QUEST_EXEC_CHANGE_SCENE_LEVEL_TAG (64), // missing
QUEST_EXEC_UNLOCK_PLAYER_WORLD_SCENE (65), // missing
QUEST_EXEC_LOCK_PLAYER_WORLD_SCENE (66), // missing
QUEST_EXEC_FAIL_MAINCOOP (67), // missing
QUEST_EXEC_MODIFY_WEATHER_AREA (68), // missing
QUEST_EXEC_MODIFY_ARANARA_COLLECTION_STATE (69), // missing
QUEST_EXEC_GRANT_TRIAL_AVATAR_BATCH_AND_LOCK_TEAM (70), // missing
QUEST_EXEC_UNKNOWN (9999);
private final int value;
QuestExec(int id) {
this.value = id;
}
public int getValue() {
return value;
}
private static final Int2ObjectMap<QuestExec> contentMap = new Int2ObjectOpenHashMap<>();
private static final Map<String, QuestExec> contentStringMap = new HashMap<>();
static {
Stream.of(values())
.filter(e -> e.name().startsWith("QUEST_CONTENT_"))
.forEach(e -> {
contentMap.put(e.getValue(), e);
contentStringMap.put(e.name(), e);
});
}
public static QuestExec getContentTriggerByValue(int value) {
return contentMap.getOrDefault(value, QUEST_EXEC_NONE);
}
public static QuestExec getContentTriggerByName(String name) {
return contentStringMap.getOrDefault(name, QUEST_EXEC_NONE);
}
}
package emu.grasscutter.game.quest.enums;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;
public enum QuestExec implements QuestTrigger {
QUEST_EXEC_NONE(0),
QUEST_EXEC_DEL_PACK_ITEM(1),
QUEST_EXEC_UNLOCK_POINT(2),
QUEST_EXEC_UNLOCK_AREA(3),
QUEST_EXEC_UNLOCK_FORCE(4), // missing, currently unused
QUEST_EXEC_LOCK_FORCE(5), // missing, currently unused
QUEST_EXEC_CHANGE_AVATAR_ELEMET(6),
QUEST_EXEC_REFRESH_GROUP_MONSTER(7),
QUEST_EXEC_SET_IS_FLYABLE(8), // missing, maybe gives glider
QUEST_EXEC_SET_IS_WEATHER_LOCKED(9), // missing
QUEST_EXEC_SET_IS_GAME_TIME_LOCKED(10), // missing
QUEST_EXEC_SET_IS_TRANSFERABLE(11), // missing, currently unused
QUEST_EXEC_GRANT_TRIAL_AVATAR(12),
QUEST_EXEC_OPEN_BORED(13), // missing, currently unused
QUEST_EXEC_ROLLBACK_QUEST(14),
QUEST_EXEC_NOTIFY_GROUP_LUA(15),
QUEST_EXEC_SET_OPEN_STATE(16),
QUEST_EXEC_LOCK_POINT(17), // missing
QUEST_EXEC_DEL_PACK_ITEM_BATCH(18),
QUEST_EXEC_REFRESH_GROUP_SUITE(19),
QUEST_EXEC_REMOVE_TRIAL_AVATAR(20),
QUEST_EXEC_SET_GAME_TIME(21), // missing
QUEST_EXEC_SET_WEATHER_GADGET(22), // missing
QUEST_EXEC_ADD_QUEST_PROGRESS(23),
QUEST_EXEC_NOTIFY_DAILY_TASK(24), // missing
QUEST_EXEC_CREATE_PATTERN_GROUP(25), // missing, used for random quests
QUEST_EXEC_REMOVE_PATTERN_GROUP(26), // missing, used for random quests
QUEST_EXEC_REFRESH_GROUP_SUITE_RANDOM(27), // missing
QUEST_EXEC_ACTIVE_ITEM_GIVING(28), // missing
QUEST_EXEC_DEL_ALL_SPECIFIC_PACK_ITEM(29), // missing
QUEST_EXEC_ROLLBACK_PARENT_QUEST(30),
QUEST_EXEC_LOCK_AVATAR_TEAM(31), // missing
QUEST_EXEC_UNLOCK_AVATAR_TEAM(32), // missing
QUEST_EXEC_UPDATE_PARENT_QUEST_REWARD_INDEX(33), // missing
QUEST_EXEC_SET_DAILY_TASK_VAR(34), // missing
QUEST_EXEC_INC_DAILY_TASK_VAR(35), // missing
QUEST_EXEC_DEC_DAILY_TASK_VAR(36), // missing, currently unused
QUEST_EXEC_ACTIVE_ACTIVITY_COND_STATE(37), // missing
QUEST_EXEC_INACTIVE_ACTIVITY_COND_STATE(38), // missing
QUEST_EXEC_ADD_CUR_AVATAR_ENERGY(39),
QUEST_EXEC_START_BARGAIN(41), // missing
QUEST_EXEC_STOP_BARGAIN(42), // missing
QUEST_EXEC_SET_QUEST_GLOBAL_VAR(43),
QUEST_EXEC_INC_QUEST_GLOBAL_VAR(44),
QUEST_EXEC_DEC_QUEST_GLOBAL_VAR(45),
QUEST_EXEC_REGISTER_DYNAMIC_GROUP(
46), // test, maybe the dynamic should be saved on a list and when you enter the view range
// this loads it again
QUEST_EXEC_UNREGISTER_DYNAMIC_GROUP(47), // test, same for this
QUEST_EXEC_SET_QUEST_VAR(48),
QUEST_EXEC_INC_QUEST_VAR(49),
QUEST_EXEC_DEC_QUEST_VAR(50),
QUEST_EXEC_RANDOM_QUEST_VAR(51), // missing
QUEST_EXEC_ACTIVATE_SCANNING_PIC(52), // missing, currently unused
QUEST_EXEC_RELOAD_SCENE_TAG(53), // missing
QUEST_EXEC_REGISTER_DYNAMIC_GROUP_ONLY(54), // missing
QUEST_EXEC_CHANGE_SKILL_DEPOT(55), // missing
QUEST_EXEC_ADD_SCENE_TAG(56), // missing
QUEST_EXEC_DEL_SCENE_TAG(57), // missing
QUEST_EXEC_INIT_TIME_VAR(58),
QUEST_EXEC_CLEAR_TIME_VAR(59),
QUEST_EXEC_MODIFY_CLIMATE_AREA(60), // missing
QUEST_EXEC_GRANT_TRIAL_AVATAR_AND_LOCK_TEAM(61), // missing
QUEST_EXEC_CHANGE_MAP_AREA_STATE(62), // missing
QUEST_EXEC_DEACTIVE_ITEM_GIVING(63), // missing
QUEST_EXEC_CHANGE_SCENE_LEVEL_TAG(64), // missing
QUEST_EXEC_UNLOCK_PLAYER_WORLD_SCENE(65), // missing
QUEST_EXEC_LOCK_PLAYER_WORLD_SCENE(66), // missing
QUEST_EXEC_FAIL_MAINCOOP(67), // missing
QUEST_EXEC_MODIFY_WEATHER_AREA(68), // missing
QUEST_EXEC_MODIFY_ARANARA_COLLECTION_STATE(69), // missing
QUEST_EXEC_GRANT_TRIAL_AVATAR_BATCH_AND_LOCK_TEAM(70), // missing
QUEST_EXEC_UNKNOWN(9999);
private final int value;
QuestExec(int id) {
this.value = id;
}
public int getValue() {
return value;
}
private static final Int2ObjectMap<QuestExec> contentMap = new Int2ObjectOpenHashMap<>();
private static final Map<String, QuestExec> contentStringMap = new HashMap<>();
static {
Stream.of(values())
.filter(e -> e.name().startsWith("QUEST_CONTENT_"))
.forEach(
e -> {
contentMap.put(e.getValue(), e);
contentStringMap.put(e.name(), e);
});
}
public static QuestExec getContentTriggerByValue(int value) {
return contentMap.getOrDefault(value, QUEST_EXEC_NONE);
}
public static QuestExec getContentTriggerByName(String name) {
return contentStringMap.getOrDefault(name, QUEST_EXEC_NONE);
}
}

View File

@@ -1,6 +1,8 @@
package emu.grasscutter.game.quest.enums;
public enum QuestState {
import emu.grasscutter.scripts.constants.IntValueEnum;
public enum QuestState implements IntValueEnum {
QUEST_STATE_NONE(0),
QUEST_STATE_UNSTARTED(1),
QUEST_STATE_UNFINISHED(2),

View File

@@ -1,262 +1,5 @@
package emu.grasscutter.game.quest.enums;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;
public enum QuestTrigger {
QUEST_COND_NONE(0),
QUEST_COND_STATE_EQUAL(1),
QUEST_COND_STATE_NOT_EQUAL(2),
QUEST_COND_PACK_HAVE_ITEM(3),
QUEST_COND_AVATAR_ELEMENT_EQUAL(4),
QUEST_COND_AVATAR_ELEMENT_NOT_EQUAL(5),
QUEST_COND_AVATAR_CAN_CHANGE_ELEMENT(6),
QUEST_COND_CITY_LEVEL_EQUAL_GREATER(7),
QUEST_COND_ITEM_NUM_LESS_THAN(8),
QUEST_COND_DAILY_TASK_START(9),
QUEST_COND_OPEN_STATE_EQUAL(10),
QUEST_COND_DAILY_TASK_OPEN(11),
QUEST_COND_DAILY_TASK_REWARD_CAN_GET(12),
QUEST_COND_DAILY_TASK_REWARD_RECEIVED(13),
QUEST_COND_PLAYER_LEVEL_REWARD_CAN_GET(14),
QUEST_COND_EXPLORATION_REWARD_CAN_GET(15),
QUEST_COND_IS_WORLD_OWNER(16),
QUEST_COND_PLAYER_LEVEL_EQUAL_GREATER(17),
QUEST_COND_SCENE_AREA_UNLOCKED(18),
QUEST_COND_ITEM_GIVING_ACTIVED(19),
QUEST_COND_ITEM_GIVING_FINISHED(20),
QUEST_COND_IS_DAYTIME(21),
QUEST_COND_CURRENT_AVATAR(22),
QUEST_COND_CURRENT_AREA(23),
QUEST_COND_QUEST_VAR_EQUAL(24),
QUEST_COND_QUEST_VAR_GREATER(25),
QUEST_COND_QUEST_VAR_LESS(26),
QUEST_COND_FORGE_HAVE_FINISH(27),
QUEST_COND_DAILY_TASK_IN_PROGRESS(28),
QUEST_COND_DAILY_TASK_FINISHED(29),
QUEST_COND_ACTIVITY_COND(30),
QUEST_COND_ACTIVITY_OPEN(31),
QUEST_COND_DAILY_TASK_VAR_GT(32),
QUEST_COND_DAILY_TASK_VAR_EQ(33),
QUEST_COND_DAILY_TASK_VAR_LT(34),
QUEST_COND_BARGAIN_ITEM_GT(35),
QUEST_COND_BARGAIN_ITEM_EQ(36),
QUEST_COND_BARGAIN_ITEM_LT(37),
QUEST_COND_COMPLETE_TALK(38),
QUEST_COND_NOT_HAVE_BLOSSOM_TALK(39),
QUEST_COND_IS_CUR_BLOSSOM_TALK(40),
QUEST_COND_QUEST_NOT_RECEIVE(41),
QUEST_COND_QUEST_SERVER_COND_VALID(42),
QUEST_COND_ACTIVITY_CLIENT_COND(43),
QUEST_COND_QUEST_GLOBAL_VAR_EQUAL(44),
QUEST_COND_QUEST_GLOBAL_VAR_GREATER(45),
QUEST_COND_QUEST_GLOBAL_VAR_LESS(46),
QUEST_COND_PERSONAL_LINE_UNLOCK(47),
QUEST_COND_CITY_REPUTATION_REQUEST(48),
QUEST_COND_MAIN_COOP_START(49),
QUEST_COND_MAIN_COOP_ENTER_SAVE_POINT(50),
QUEST_COND_CITY_REPUTATION_LEVEL(51),
QUEST_COND_CITY_REPUTATION_UNLOCK(52),
QUEST_COND_LUA_NOTIFY(53),
QUEST_COND_CUR_CLIMATE(54),
QUEST_COND_ACTIVITY_END(55),
QUEST_COND_COOP_POINT_RUNNING(56),
QUEST_COND_GADGET_TALK_STATE_EQUAL(57),
QUEST_COND_AVATAR_FETTER_GT(58),
QUEST_COND_AVATAR_FETTER_EQ(59),
QUEST_COND_AVATAR_FETTER_LT(60),
QUEST_COND_NEW_HOMEWORLD_MOUDLE_UNLOCK(61),
QUEST_COND_NEW_HOMEWORLD_LEVEL_REWARD(62),
QUEST_COND_NEW_HOMEWORLD_MAKE_FINISH(63),
QUEST_COND_HOMEWORLD_NPC_EVENT(64),
QUEST_COND_TIME_VAR_GT_EQ(65),
QUEST_COND_TIME_VAR_PASS_DAY(66),
QUEST_COND_HOMEWORLD_NPC_NEW_TALK(67),
QUEST_COND_PLAYER_CHOOSE_MALE(68),
QUEST_COND_HISTORY_GOT_ANY_ITEM(69),
QUEST_COND_LEARNED_RECIPE(70),
QUEST_COND_LUNARITE_REGION_UNLOCKED(71),
QUEST_COND_LUNARITE_HAS_REGION_HINT_COUNT(72),
QUEST_COND_LUNARITE_COLLECT_FINISH(73),
QUEST_COND_LUNARITE_MARK_ALL_FINISH(74),
QUEST_COND_NEW_HOMEWORLD_SHOP_ITEM(75),
QUEST_COND_SCENE_POINT_UNLOCK(76),
QUEST_COND_SCENE_LEVEL_TAG_EQ(77),
QUEST_CONTENT_NONE(0),
QUEST_CONTENT_KILL_MONSTER(1),
QUEST_CONTENT_COMPLETE_TALK(2),
QUEST_CONTENT_MONSTER_DIE(3),
QUEST_CONTENT_FINISH_PLOT(4),
QUEST_CONTENT_OBTAIN_ITEM(5),
QUEST_CONTENT_TRIGGER_FIRE(6),
QUEST_CONTENT_CLEAR_GROUP_MONSTER(7),
QUEST_CONTENT_NOT_FINISH_PLOT(8),
QUEST_CONTENT_ENTER_DUNGEON(9),
QUEST_CONTENT_ENTER_MY_WORLD(10),
QUEST_CONTENT_FINISH_DUNGEON(11),
QUEST_CONTENT_DESTROY_GADGET(12),
QUEST_CONTENT_OBTAIN_MATERIAL_WITH_SUBTYPE(13),
QUEST_CONTENT_NICK_NAME(14),
QUEST_CONTENT_WORKTOP_SELECT(15),
QUEST_CONTENT_SEAL_BATTLE_RESULT(16),
QUEST_CONTENT_ENTER_ROOM(17),
QUEST_CONTENT_GAME_TIME_TICK(18),
QUEST_CONTENT_FAIL_DUNGEON(19),
QUEST_CONTENT_LUA_NOTIFY(20),
QUEST_CONTENT_TEAM_DEAD(21),
QUEST_CONTENT_COMPLETE_ANY_TALK(22),
QUEST_CONTENT_UNLOCK_TRANS_POINT(23),
QUEST_CONTENT_ADD_QUEST_PROGRESS(24),
QUEST_CONTENT_INTERACT_GADGET(25),
QUEST_CONTENT_DAILY_TASK_COMP_FINISH(26),
QUEST_CONTENT_FINISH_ITEM_GIVING(27),
QUEST_CONTENT_SKILL(107),
QUEST_CONTENT_CITY_LEVEL_UP(109),
QUEST_CONTENT_PATTERN_GROUP_CLEAR_MONSTER(110),
QUEST_CONTENT_ITEM_LESS_THAN(111),
QUEST_CONTENT_PLAYER_LEVEL_UP(112),
QUEST_CONTENT_DUNGEON_OPEN_STATUE(113),
QUEST_CONTENT_UNLOCK_AREA(114),
QUEST_CONTENT_OPEN_CHEST_WITH_GADGET_ID(115),
QUEST_CONTENT_UNLOCK_TRANS_POINT_WITH_TYPE(116),
QUEST_CONTENT_FINISH_DAILY_DUNGEON(117),
QUEST_CONTENT_FINISH_WEEKLY_DUNGEON(118),
QUEST_CONTENT_QUEST_VAR_EQUAL(119),
QUEST_CONTENT_QUEST_VAR_GREATER(120),
QUEST_CONTENT_QUEST_VAR_LESS(121),
QUEST_CONTENT_OBTAIN_VARIOUS_ITEM(122),
QUEST_CONTENT_FINISH_TOWER_LEVEL(123),
QUEST_CONTENT_BARGAIN_SUCC(124),
QUEST_CONTENT_BARGAIN_FAIL(125),
QUEST_CONTENT_ITEM_LESS_THAN_BARGAIN(126),
QUEST_CONTENT_ACTIVITY_TRIGGER_FAILED(127),
QUEST_CONTENT_MAIN_COOP_ENTER_SAVE_POINT(128),
QUEST_CONTENT_ANY_MANUAL_TRANSPORT(129),
QUEST_CONTENT_USE_ITEM(130),
QUEST_CONTENT_MAIN_COOP_ENTER_ANY_SAVE_POINT(131),
QUEST_CONTENT_ENTER_MY_HOME_WORLD(132),
QUEST_CONTENT_ENTER_MY_WORLD_SCENE(133),
QUEST_CONTENT_TIME_VAR_GT_EQ(134),
QUEST_CONTENT_TIME_VAR_PASS_DAY(135),
QUEST_CONTENT_QUEST_STATE_EQUAL(136),
QUEST_CONTENT_QUEST_STATE_NOT_EQUAL(137),
QUEST_CONTENT_UNLOCKED_RECIPE(138),
QUEST_CONTENT_NOT_UNLOCKED_RECIPE(139),
QUEST_CONTENT_FISHING_SUCC(140),
QUEST_CONTENT_ENTER_ROGUE_DUNGEON(141),
QUEST_CONTENT_USE_WIDGET(142),
QUEST_CONTENT_CAPTURE_SUCC(143),
QUEST_CONTENT_CAPTURE_USE_CAPTURETAG_LIST(144),
QUEST_CONTENT_CAPTURE_USE_MATERIAL_LIST(145),
QUEST_CONTENT_ENTER_VEHICLE(147),
QUEST_CONTENT_SCENE_LEVEL_TAG_EQ(148),
QUEST_CONTENT_LEAVE_SCENE(149),
QUEST_CONTENT_LEAVE_SCENE_RANGE(150),
QUEST_CONTENT_IRODORI_FINISH_FLOWER_COMBINATION(151),
QUEST_CONTENT_IRODORI_POETRY_REACH_MIN_PROGRESS(152),
QUEST_CONTENT_IRODORI_POETRY_FINISH_FILL_POETRY(153),
QUEST_EXEC_NONE(0),
QUEST_EXEC_DEL_PACK_ITEM(1),
QUEST_EXEC_UNLOCK_POINT(2),
QUEST_EXEC_UNLOCK_AREA(3),
QUEST_EXEC_UNLOCK_FORCE(4),
QUEST_EXEC_LOCK_FORCE(5),
QUEST_EXEC_CHANGE_AVATAR_ELEMET(6),
QUEST_EXEC_REFRESH_GROUP_MONSTER(7),
QUEST_EXEC_SET_IS_FLYABLE(8),
QUEST_EXEC_SET_IS_WEATHER_LOCKED(9),
QUEST_EXEC_SET_IS_GAME_TIME_LOCKED(10),
QUEST_EXEC_SET_IS_TRANSFERABLE(11),
QUEST_EXEC_GRANT_TRIAL_AVATAR(12),
QUEST_EXEC_OPEN_BORED(13),
QUEST_EXEC_ROLLBACK_QUEST(14),
QUEST_EXEC_NOTIFY_GROUP_LUA(15),
QUEST_EXEC_SET_OPEN_STATE(16),
QUEST_EXEC_LOCK_POINT(17),
QUEST_EXEC_DEL_PACK_ITEM_BATCH(18),
QUEST_EXEC_REFRESH_GROUP_SUITE(19),
QUEST_EXEC_REMOVE_TRIAL_AVATAR(20),
QUEST_EXEC_SET_GAME_TIME(21),
QUEST_EXEC_SET_WEATHER_GADGET(22),
QUEST_EXEC_ADD_QUEST_PROGRESS(23),
QUEST_EXEC_NOTIFY_DAILY_TASK(24),
QUEST_EXEC_CREATE_PATTERN_GROUP(25),
QUEST_EXEC_REMOVE_PATTERN_GROUP(26),
QUEST_EXEC_REFRESH_GROUP_SUITE_RANDOM(27),
QUEST_EXEC_ACTIVE_ITEM_GIVING(28),
QUEST_EXEC_DEL_ALL_SPECIFIC_PACK_ITEM(29),
QUEST_EXEC_ROLLBACK_PARENT_QUEST(30),
QUEST_EXEC_LOCK_AVATAR_TEAM(31),
QUEST_EXEC_UNLOCK_AVATAR_TEAM(32),
QUEST_EXEC_UPDATE_PARENT_QUEST_REWARD_INDEX(33),
QUEST_EXEC_SET_DAILY_TASK_VAR(34),
QUEST_EXEC_INC_DAILY_TASK_VAR(35),
QUEST_EXEC_DEC_DAILY_TASK_VAR(36),
QUEST_EXEC_ACTIVE_ACTIVITY_COND_STATE(37),
QUEST_EXEC_INACTIVE_ACTIVITY_COND_STATE(38),
QUEST_EXEC_ADD_CUR_AVATAR_ENERGY(39),
QUEST_EXEC_START_BARGAIN(41),
QUEST_EXEC_STOP_BARGAIN(42),
QUEST_EXEC_SET_QUEST_GLOBAL_VAR(43),
QUEST_EXEC_INC_QUEST_GLOBAL_VAR(44),
QUEST_EXEC_DEC_QUEST_GLOBAL_VAR(45),
QUEST_EXEC_REGISTER_DYNAMIC_GROUP(46),
QUEST_EXEC_UNREGISTER_DYNAMIC_GROUP(47),
QUEST_EXEC_SET_QUEST_VAR(48),
QUEST_EXEC_INC_QUEST_VAR(49),
QUEST_EXEC_DEC_QUEST_VAR(50),
QUEST_EXEC_RANDOM_QUEST_VAR(51),
QUEST_EXEC_ACTIVATE_SCANNING_PIC(52),
QUEST_EXEC_RELOAD_SCENE_TAG(53),
QUEST_EXEC_REGISTER_DYNAMIC_GROUP_ONLY(54),
QUEST_EXEC_CHANGE_SKILL_DEPOT(55),
QUEST_EXEC_ADD_SCENE_TAG(56),
QUEST_EXEC_DEL_SCENE_TAG(57),
QUEST_EXEC_INIT_TIME_VAR(58),
QUEST_EXEC_CLEAR_TIME_VAR(59),
QUEST_EXEC_MODIFY_CLIMATE_AREA(60),
QUEST_EXEC_GRANT_TRIAL_AVATAR_AND_LOCK_TEAM(61),
QUEST_EXEC_CHANGE_MAP_AREA_STATE(62),
QUEST_EXEC_DEACTIVE_ITEM_GIVING(63),
QUEST_EXEC_CHANGE_SCENE_LEVEL_TAG(64),
QUEST_EXEC_UNLOCK_PLAYER_WORLD_SCENE(65),
QUEST_EXEC_LOCK_PLAYER_WORLD_SCENE(66),
QUEST_EXEC_FAIL_MAINCOOP(67),
QUEST_EXEC_MODIFY_WEATHER_AREA(68);
private static final Int2ObjectMap<QuestTrigger> contentMap = new Int2ObjectOpenHashMap<>();
private static final Map<String, QuestTrigger> contentStringMap = new HashMap<>();
static {
Stream.of(values())
.filter(e -> e.name().startsWith("QUEST_CONTENT_"))
.forEach(
e -> {
contentMap.put(e.getValue(), e);
contentStringMap.put(e.name(), e);
});
}
private final int value;
QuestTrigger(int id) {
this.value = id;
}
public static QuestTrigger getContentTriggerByValue(int value) {
return contentMap.getOrDefault(value, QUEST_CONTENT_NONE);
}
public static QuestTrigger getContentTriggerByName(String name) {
return contentStringMap.getOrDefault(name, QUEST_CONTENT_NONE);
}
public int getValue() {
return value;
}
public interface QuestTrigger {
int getValue();
}

View File

@@ -1,17 +1,17 @@
package emu.grasscutter.game.quest.exec;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueExec;
import emu.grasscutter.game.quest.enums.QuestExec;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
import emu.grasscutter.Grasscutter;
@QuestValueExec(QuestExec.QUEST_EXEC_ADD_CUR_AVATAR_ENERGY)
public class ExecAddCurAvatarEnergy extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
Grasscutter.getLogger().info("Energy refilled");
return quest.getOwner().getEnergyManager().refillEntityAvatarEnergy();
}
}
package emu.grasscutter.game.quest.exec;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueExec;
import emu.grasscutter.game.quest.enums.QuestExec;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
@QuestValueExec(QuestExec.QUEST_EXEC_ADD_CUR_AVATAR_ENERGY)
public class ExecAddCurAvatarEnergy extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
Grasscutter.getLogger().info("Energy refilled");
return quest.getOwner().getEnergyManager().refillEntityAvatarEnergy();
}
}

View File

@@ -2,22 +2,19 @@ package emu.grasscutter.game.quest.exec;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.QuestValueExec;
import emu.grasscutter.game.quest.enums.QuestExec;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
import java.util.Arrays;
@QuestValue(QuestTrigger.QUEST_EXEC_ADD_QUEST_PROGRESS)
@QuestValueExec(QuestExec.QUEST_EXEC_ADD_QUEST_PROGRESS)
public class ExecAddQuestProgress extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
var param =
Arrays.stream(paramStr).filter(i -> !i.isBlank()).mapToInt(Integer::parseInt).toArray();
quest
.getOwner()
.getQuestManager()
.triggerEvent(QuestTrigger.QUEST_CONTENT_ADD_QUEST_PROGRESS, param);
quest.getOwner().getProgressManager().addQuestProgress(param[0], param[1]);
return true;
}

View File

@@ -1,31 +1,34 @@
package emu.grasscutter.game.quest.exec;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.props.ElementType;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueExec;
import emu.grasscutter.game.quest.enums.QuestExec;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
import lombok.val;
/**
* Changes the main avatar's element. First parameter is the elementType id
*/
@QuestValueExec(QuestExec.QUEST_EXEC_CHANGE_AVATAR_ELEMET)
public class ExecChangeAvatarElemet extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
val targetElement = ElementType.getTypeByValue(Integer.parseInt(paramStr[0]));
val owner = quest.getOwner();
val mainAvatar = owner.getAvatars().getAvatarById(owner.getMainCharacterId());
if(mainAvatar == null){
Grasscutter.getLogger().error("Failed to get main avatar for use {}", quest.getOwner().getUid());
return false;
}
Grasscutter.getLogger().info("Changing avatar element to {} for quest {}", targetElement.name(), quest.getSubQuestId());
return mainAvatar.changeElement(targetElement);
}
}
package emu.grasscutter.game.quest.exec;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.props.ElementType;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueExec;
import emu.grasscutter.game.quest.enums.QuestExec;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
import lombok.val;
/** Changes the main avatar's element. First parameter is the elementType id */
@QuestValueExec(QuestExec.QUEST_EXEC_CHANGE_AVATAR_ELEMET)
public class ExecChangeAvatarElemet extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
val targetElement = ElementType.getTypeByValue(Integer.parseInt(paramStr[0]));
val owner = quest.getOwner();
val mainAvatar = owner.getAvatars().getAvatarById(owner.getMainCharacterId());
if (mainAvatar == null) {
Grasscutter.getLogger()
.error("Failed to get main avatar for use {}", quest.getOwner().getUid());
return false;
}
Grasscutter.getLogger()
.info(
"Changing avatar element to {} for quest {}",
targetElement.name(),
quest.getSubQuestId());
return mainAvatar.changeElement(targetElement);
}
}

View File

@@ -1,19 +1,19 @@
package emu.grasscutter.game.quest.exec;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueExec;
import emu.grasscutter.game.quest.enums.QuestExec;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
import lombok.val;
@QuestValueExec(QuestExec.QUEST_EXEC_CLEAR_TIME_VAR)
public class ExecClearTimeVar extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
val mainQuestId = Integer.parseInt(condition.getParam()[0]);
val timeVarId = Integer.parseInt(condition.getParam()[1]);
val mainQuest = quest.getOwner().getQuestManager().getMainQuestById(mainQuestId);
return mainQuest.clearTimeVar(timeVarId);
}
}
package emu.grasscutter.game.quest.exec;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueExec;
import emu.grasscutter.game.quest.enums.QuestExec;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
import lombok.val;
@QuestValueExec(QuestExec.QUEST_EXEC_CLEAR_TIME_VAR)
public class ExecClearTimeVar extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
val mainQuestId = Integer.parseInt(condition.getParam()[0]);
val timeVarId = Integer.parseInt(condition.getParam()[1]);
val mainQuest = quest.getOwner().getQuestManager().getMainQuestById(mainQuestId);
return mainQuest.clearTimeVar(timeVarId);
}
}

View File

@@ -2,11 +2,11 @@ package emu.grasscutter.game.quest.exec;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.QuestValueExec;
import emu.grasscutter.game.quest.enums.QuestExec;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
@QuestValue(QuestTrigger.QUEST_EXEC_DEC_QUEST_GLOBAL_VAR)
@QuestValueExec(QuestExec.QUEST_EXEC_DEC_QUEST_GLOBAL_VAR)
public class ExecDecQuestGlobalVar extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {

View File

@@ -1,16 +1,16 @@
package emu.grasscutter.game.quest.exec;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
@QuestValue(QuestTrigger.QUEST_EXEC_DEC_QUEST_VAR)
public class ExecDecQuestVar extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
quest.getMainQuest().decQuestVar(Integer.parseInt(paramStr[0]), Integer.parseInt(paramStr[1]));
return true;
}
}
package emu.grasscutter.game.quest.exec;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueExec;
import emu.grasscutter.game.quest.enums.QuestExec;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
@QuestValueExec(QuestExec.QUEST_EXEC_DEC_QUEST_VAR)
public class ExecDecQuestVar extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
quest.getMainQuest().decQuestVar(Integer.parseInt(paramStr[0]), Integer.parseInt(paramStr[1]));
return true;
}
}

View File

@@ -1,17 +1,17 @@
package emu.grasscutter.game.quest.exec;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueExec;
import emu.grasscutter.game.quest.enums.QuestExec;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
@QuestValueExec(QuestExec.QUEST_EXEC_DEL_PACK_ITEM)
public class ExecDelPackItem extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
int itemId = Integer.parseInt(paramStr[0]);
int amount = Integer.parseInt(paramStr[1]);
return quest.getOwner().getInventory().removeItem(itemId, amount);
}
}
package emu.grasscutter.game.quest.exec;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueExec;
import emu.grasscutter.game.quest.enums.QuestExec;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
@QuestValueExec(QuestExec.QUEST_EXEC_DEL_PACK_ITEM)
public class ExecDelPackItem extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
int itemId = Integer.parseInt(paramStr[0]);
int amount = Integer.parseInt(paramStr[1]);
return quest.getOwner().getInventory().removeItem(itemId, amount);
}
}

View File

@@ -1,26 +1,26 @@
package emu.grasscutter.game.quest.exec;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueExec;
import emu.grasscutter.game.quest.enums.QuestExec;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
@QuestValueExec(QuestExec.QUEST_EXEC_DEL_PACK_ITEM_BATCH)
public class ExecDelPackItemBatch extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
// input is like this: "100497:999,100498:999,100499:999"
var items = paramStr[0].split(",");
boolean success = true;
for (var itemString : items){
var itemFields = itemString.split(":");
var itemId = Integer.parseInt(itemFields[0]);
var amount = Integer.parseInt(itemFields[1]);
if(!quest.getOwner().getInventory().removeItem(itemId, amount)){
success = false;
}
}
return success;
}
}
package emu.grasscutter.game.quest.exec;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueExec;
import emu.grasscutter.game.quest.enums.QuestExec;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
@QuestValueExec(QuestExec.QUEST_EXEC_DEL_PACK_ITEM_BATCH)
public class ExecDelPackItemBatch extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
// input is like this: "100497:999,100498:999,100499:999"
var items = paramStr[0].split(",");
boolean success = true;
for (var itemString : items) {
var itemFields = itemString.split(":");
var itemId = Integer.parseInt(itemFields[0]);
var amount = Integer.parseInt(itemFields[1]);
if (!quest.getOwner().getInventory().removeItem(itemId, amount)) {
success = false;
}
}
return success;
}
}

View File

@@ -1,21 +1,27 @@
package emu.grasscutter.game.quest.exec;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueExec;
import emu.grasscutter.game.quest.enums.QuestExec;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
@QuestValueExec(QuestExec.QUEST_EXEC_GRANT_TRIAL_AVATAR)
public class ExecGrantTrialAvatar extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
if (quest.getOwner().addTrialAvatarForQuest(Integer.parseInt(paramStr[0]), quest.getMainQuestId())) {
Grasscutter.getLogger().info("Added trial avatar to team for quest {}", quest.getSubQuestId());
return true;
}
return false;
}
}
package emu.grasscutter.game.quest.exec;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueExec;
import emu.grasscutter.game.quest.enums.QuestExec;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
@QuestValueExec(QuestExec.QUEST_EXEC_GRANT_TRIAL_AVATAR)
public class ExecGrantTrialAvatar extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
try {
quest
.getOwner()
.getTeamManager()
.addTrialAvatar(Integer.parseInt(paramStr[0]), quest.getMainQuestId());
Grasscutter.getLogger()
.debug("Added trial avatar to team for quest {}", quest.getSubQuestId());
return true;
} catch (RuntimeException ignored) {
return false;
}
}
}

View File

@@ -2,11 +2,11 @@ package emu.grasscutter.game.quest.exec;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.QuestValueExec;
import emu.grasscutter.game.quest.enums.QuestExec;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
@QuestValue(QuestTrigger.QUEST_EXEC_INC_QUEST_GLOBAL_VAR)
@QuestValueExec(QuestExec.QUEST_EXEC_INC_QUEST_GLOBAL_VAR)
public class ExecIncQuestGlobalVar extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {

View File

@@ -1,16 +1,16 @@
package emu.grasscutter.game.quest.exec;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
@QuestValue(QuestTrigger.QUEST_EXEC_INC_QUEST_VAR)
public class ExecIncQuestVar extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
quest.getMainQuest().incQuestVar(Integer.parseInt(paramStr[0]), Integer.parseInt(paramStr[1]));
return true;
}
}
package emu.grasscutter.game.quest.exec;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueExec;
import emu.grasscutter.game.quest.enums.QuestExec;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
@QuestValueExec(QuestExec.QUEST_EXEC_INC_QUEST_VAR)
public class ExecIncQuestVar extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
quest.getMainQuest().incQuestVar(Integer.parseInt(paramStr[0]), Integer.parseInt(paramStr[1]));
return true;
}
}

View File

@@ -1,18 +1,18 @@
package emu.grasscutter.game.quest.exec;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueExec;
import emu.grasscutter.game.quest.enums.QuestExec;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
import lombok.val;
@QuestValueExec(QuestExec.QUEST_EXEC_INIT_TIME_VAR)
public class ExecInitTimeVar extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
val timeVarId = Integer.parseInt(condition.getParam()[0]);
val mainQuest = quest.getMainQuest();
return mainQuest.initTimeVar(timeVarId);
}
}
package emu.grasscutter.game.quest.exec;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueExec;
import emu.grasscutter.game.quest.enums.QuestExec;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
import lombok.val;
@QuestValueExec(QuestExec.QUEST_EXEC_INIT_TIME_VAR)
public class ExecInitTimeVar extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
val timeVarId = Integer.parseInt(condition.getParam()[0]);
val mainQuest = quest.getMainQuest();
return mainQuest.initTimeVar(timeVarId);
}
}

View File

@@ -1,31 +1,59 @@
package emu.grasscutter.game.quest.exec;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.QuestValueExec;
import emu.grasscutter.game.quest.enums.QuestExec;
import emu.grasscutter.game.quest.enums.QuestState;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
import emu.grasscutter.scripts.constants.EventType;
import emu.grasscutter.scripts.data.ScriptArgs;
import lombok.val;
@QuestValue(QuestTrigger.QUEST_EXEC_NOTIFY_GROUP_LUA)
@QuestValueExec(QuestExec.QUEST_EXEC_NOTIFY_GROUP_LUA)
public class ExecNotifyGroupLua extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
var sceneId = Integer.parseInt(paramStr[0]);
var groupId = Integer.parseInt(paramStr[1]);
val sceneId = Integer.parseInt(paramStr[0]);
val groupId = Integer.parseInt(paramStr[1]);
var scriptManager = quest.getOwner().getScene().getScriptManager();
val scene = quest.getOwner().getScene();
val scriptManager = scene.getScriptManager();
if (quest.getOwner().getScene().getId() == sceneId) {
scriptManager.callEvent(
quest.getState() == QuestState.QUEST_STATE_FINISHED
? EventType.EVENT_QUEST_FINISH
: EventType.EVENT_QUEST_START,
new ScriptArgs());
if (scene.getId() != sceneId) {
return false;
}
scene.runWhenFinished(
() -> {
val groupInstance = scriptManager.getGroupInstanceById(groupId);
if (groupInstance != null) {
// workaround to make sure the triggers are still there todo find better way of trigger
// handling
scriptManager.refreshGroup(groupInstance);
Grasscutter.getLogger()
.debug(
"group: {} \ncondition: {} \nparamStr {}",
groupInstance.getLuaGroup(),
condition,
paramStr);
} else {
Grasscutter.getLogger()
.warn(
"notify, no group instance for:\n group: {} \ncondition: {} \nparamStr {}",
groupId,
condition,
paramStr);
}
val eventType =
quest.getState() == QuestState.QUEST_STATE_FINISHED
? EventType.EVENT_QUEST_FINISH
: EventType.EVENT_QUEST_START;
scriptManager.callEvent(new ScriptArgs(groupId, eventType, quest.getSubQuestId()));
});
return true;
}

View File

@@ -1,19 +1,18 @@
package emu.grasscutter.game.quest.exec;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueExec;
import emu.grasscutter.game.quest.enums.QuestExec;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
@QuestValueExec(QuestExec.QUEST_EXEC_REFRESH_GROUP_MONSTER)
public class ExecRefreshGroupMonster extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
var groupId = Integer.parseInt(paramStr[0]);
return quest.getOwner().getScene().getScriptManager().refreshGroupMonster(groupId);
}
}
package emu.grasscutter.game.quest.exec;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueExec;
import emu.grasscutter.game.quest.enums.QuestExec;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
@QuestValueExec(QuestExec.QUEST_EXEC_REFRESH_GROUP_MONSTER)
public class ExecRefreshGroupMonster extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
var groupId = Integer.parseInt(paramStr[0]);
return quest.getOwner().getScene().getScriptManager().refreshGroupMonster(groupId);
}
}

View File

@@ -2,34 +2,31 @@ package emu.grasscutter.game.quest.exec;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestGroupSuite;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.QuestValueExec;
import emu.grasscutter.game.quest.enums.QuestExec;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
import emu.grasscutter.server.packet.send.PacketGroupSuiteNotify;
import lombok.val;
@QuestValue(QuestTrigger.QUEST_EXEC_REFRESH_GROUP_SUITE)
@QuestValueExec(QuestExec.QUEST_EXEC_REFRESH_GROUP_SUITE)
public class ExecRefreshGroupSuite extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
var sceneId = Integer.parseInt(paramStr[0]);
var groupId = Integer.parseInt(paramStr[1].split(",")[0]);
var suiteId = Integer.parseInt(paramStr[1].split(",")[1]);
val sceneId = Integer.parseInt(paramStr[0]);
val entries = paramStr[1].split(";");
val scriptManager = quest.getOwner().getWorld().getSceneById(sceneId).getScriptManager();
var scriptManager = quest.getOwner().getScene().getScriptManager();
boolean result = true;
for (var entry : entries) {
val entryArray = entry.split(",");
val groupId = Integer.parseInt(entryArray[0]);
val suiteId = Integer.parseInt(entryArray[1]);
quest
.getMainQuest()
.getQuestGroupSuites()
.add(QuestGroupSuite.of().scene(sceneId).group(groupId).suite(suiteId).build());
// refresh immediately if player is in this scene
if (quest.getOwner().getScene().getId() == sceneId) {
scriptManager.refreshGroup(scriptManager.getGroupById(groupId), suiteId);
quest.getOwner().sendPacket(new PacketGroupSuiteNotify(groupId, suiteId));
if (!scriptManager.refreshGroupSuite(groupId, suiteId, quest)) {
result = false;
}
}
return true;
return result;
}
}

View File

@@ -1,39 +1,38 @@
package emu.grasscutter.game.quest.exec;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestGroupSuite;
import emu.grasscutter.game.quest.QuestValueExec;
import emu.grasscutter.game.quest.enums.QuestExec;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
import emu.grasscutter.game.world.Scene;
@QuestValueExec(QuestExec.QUEST_EXEC_REGISTER_DYNAMIC_GROUP)
public class ExecRegisterDynamicGroup extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
var sceneId = Integer.parseInt(paramStr[0]);
var groupId = Integer.parseInt(paramStr[1]);
Grasscutter.getLogger().warn("Registering group {}", groupId);
Scene scene = quest.getOwner().getWorld().getSceneById(sceneId);
if(scene == null) return false;
int suiteId = scene.loadDynamicGroup(groupId);
if(suiteId == -1) return false;
quest.getMainQuest().getQuestGroupSuites().add(QuestGroupSuite.of()
.scene(sceneId)
.group(groupId)
.suite(suiteId)
.build());
Grasscutter.getLogger().warn("Registered group {}, suite {} in scene {}", groupId, suiteId, scene.getId());
return true;
}
}
package emu.grasscutter.game.quest.exec;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestGroupSuite;
import emu.grasscutter.game.quest.QuestValueExec;
import emu.grasscutter.game.quest.enums.QuestExec;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
import emu.grasscutter.game.world.Scene;
@QuestValueExec(QuestExec.QUEST_EXEC_REGISTER_DYNAMIC_GROUP)
public class ExecRegisterDynamicGroup extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
var sceneId = Integer.parseInt(paramStr[0]);
var groupId = Integer.parseInt(paramStr[1]);
Grasscutter.getLogger().warn("Registering group {}", groupId);
Scene scene = quest.getOwner().getWorld().getSceneById(sceneId);
if (scene == null) return false;
int suiteId = scene.loadDynamicGroup(groupId);
if (suiteId == -1) return false;
quest
.getMainQuest()
.getQuestGroupSuites()
.add(QuestGroupSuite.of().scene(sceneId).group(groupId).suite(suiteId).build());
Grasscutter.getLogger()
.warn("Registered group {}, suite {} in scene {}", groupId, suiteId, scene.getId());
return true;
}
}

View File

@@ -1,21 +1,23 @@
package emu.grasscutter.game.quest.exec;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueExec;
import emu.grasscutter.game.quest.enums.QuestExec;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
@QuestValueExec(QuestExec.QUEST_EXEC_REMOVE_TRIAL_AVATAR)
public class ExecRemoveTrialAvatar extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
if (quest.getOwner().removeTrialAvatarForQuest(Integer.parseInt(paramStr[0]))) {
Grasscutter.getLogger().info("Removed trial avatar from team for quest {}", quest.getSubQuestId());
return true;
}
return false;
}
}
package emu.grasscutter.game.quest.exec;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueExec;
import emu.grasscutter.game.quest.enums.QuestExec;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
@QuestValueExec(QuestExec.QUEST_EXEC_REMOVE_TRIAL_AVATAR)
public class ExecRemoveTrialAvatar extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
try {
quest.getOwner().getTeamManager().removeTrialAvatar(Integer.parseInt(paramStr[0]));
Grasscutter.getLogger()
.debug("Removed trial avatar from team for quest {}", quest.getSubQuestId());
return true;
} catch (RuntimeException ignored) {
return false;
}
}
}

View File

@@ -1,24 +1,24 @@
package emu.grasscutter.game.quest.exec;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueExec;
import emu.grasscutter.game.quest.enums.QuestExec;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
import emu.grasscutter.server.packet.send.PacketScenePlayerLocationNotify;
@QuestValueExec(QuestExec.QUEST_EXEC_ROLLBACK_PARENT_QUEST)
public class ExecRollbackParentQuest extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
var targetPosition = quest.getMainQuest().rewind();
if(targetPosition == null){
return false;
}
quest.getOwner().getPosition().set(targetPosition.get(0));
quest.getOwner().getRotation().set(targetPosition.get(1));
quest.getOwner().sendPacket(new PacketScenePlayerLocationNotify(quest.getOwner().getScene()));
// todo proper reset and warp
return true;
}
}
package emu.grasscutter.game.quest.exec;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueExec;
import emu.grasscutter.game.quest.enums.QuestExec;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
import emu.grasscutter.server.packet.send.PacketScenePlayerLocationNotify;
@QuestValueExec(QuestExec.QUEST_EXEC_ROLLBACK_PARENT_QUEST)
public class ExecRollbackParentQuest extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
var targetPosition = quest.getMainQuest().rewind();
if (targetPosition == null) {
return false;
}
quest.getOwner().getPosition().set(targetPosition.get(0));
quest.getOwner().getRotation().set(targetPosition.get(1));
quest.getOwner().sendPacket(new PacketScenePlayerLocationNotify(quest.getOwner().getScene()));
// todo proper reset and warp
return true;
}
}

View File

@@ -1,26 +1,26 @@
package emu.grasscutter.game.quest.exec;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueExec;
import emu.grasscutter.game.quest.enums.QuestExec;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
import emu.grasscutter.server.packet.send.PacketScenePlayerLocationNotify;
@QuestValueExec(QuestExec.QUEST_EXEC_ROLLBACK_QUEST)
public class ExecRollbackQuest extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
var targetQuestId = Integer.parseInt(paramStr[0]);
var targetQuest = quest.getOwner().getQuestManager().getQuestById(targetQuestId);
var targetPosition = targetQuest.getMainQuest().rewindTo(targetQuest, true);
if(targetPosition == null){
return false;
}
quest.getOwner().getPosition().set(targetPosition.get(0));
quest.getOwner().getRotation().set(targetPosition.get(1));
quest.getOwner().sendPacket(new PacketScenePlayerLocationNotify(quest.getOwner().getScene()));
// todo proper reset and warp
return true;
}
}
package emu.grasscutter.game.quest.exec;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueExec;
import emu.grasscutter.game.quest.enums.QuestExec;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
import emu.grasscutter.server.packet.send.PacketScenePlayerLocationNotify;
@QuestValueExec(QuestExec.QUEST_EXEC_ROLLBACK_QUEST)
public class ExecRollbackQuest extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
var targetQuestId = Integer.parseInt(paramStr[0]);
var targetQuest = quest.getOwner().getQuestManager().getQuestById(targetQuestId);
var targetPosition = targetQuest.getMainQuest().rewindTo(targetQuest, true);
if (targetPosition == null) {
return false;
}
quest.getOwner().getPosition().set(targetPosition.get(0));
quest.getOwner().getRotation().set(targetPosition.get(1));
quest.getOwner().sendPacket(new PacketScenePlayerLocationNotify(quest.getOwner().getScene()));
// todo proper reset and warp
return true;
}
}

View File

@@ -1,24 +1,21 @@
package emu.grasscutter.game.quest.exec;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueExec;
import emu.grasscutter.game.quest.enums.QuestExec;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
import lombok.val;
import java.util.Arrays;
@QuestValueExec(QuestExec.QUEST_EXEC_SET_OPEN_STATE)
public class ExecSetOpenState extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
val param = Arrays.stream(paramStr)
.filter(i -> !i.isBlank())
.mapToInt(Integer::parseInt)
.toArray();
quest.getOwner().getProgressManager().forceSetOpenState(param[0], param[1]);
return true;
}
}
package emu.grasscutter.game.quest.exec;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueExec;
import emu.grasscutter.game.quest.enums.QuestExec;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
import java.util.Arrays;
import lombok.val;
@QuestValueExec(QuestExec.QUEST_EXEC_SET_OPEN_STATE)
public class ExecSetOpenState extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
val param =
Arrays.stream(paramStr).filter(i -> !i.isBlank()).mapToInt(Integer::parseInt).toArray();
quest.getOwner().getProgressManager().forceSetOpenState(param[0], param[1]);
return true;
}
}

Some files were not shown because too many files have changed in this diff Show More