Handle Unlocking of Waypoints and Statues (#1608)

Original commits:

* Add necessary protos for scene point/area unlocking.

* Rename PlayerOpenStateManager to PlayerProgressManager and move data to Player.

* Handle unlocking of waypoints.

* Add primo rewards for waypoint unlock.

* Statue unlocking.

* Add statue quest on player login.

* I forgor to add an unlock command.

* Give EXP as reward, fire quest trigger, make EXP UI show up.
This commit is contained in:
GanyusLeftHorn
2022-08-10 12:03:47 +02:00
committed by GitHub
parent 2d48fab799
commit 04f0fae898
25 changed files with 574 additions and 211 deletions

View File

@@ -56,6 +56,7 @@ import emu.grasscutter.net.proto.MpSettingTypeOuterClass.MpSettingType;
import emu.grasscutter.net.proto.OnlinePlayerInfoOuterClass.OnlinePlayerInfo;
import emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo;
import emu.grasscutter.net.proto.ProfilePictureOuterClass.ProfilePicture;
import emu.grasscutter.net.proto.PropChangeReasonOuterClass.PropChangeReason;
import emu.grasscutter.net.proto.SocialDetailOuterClass.SocialDetail;
import emu.grasscutter.net.proto.VisionTypeOuterClass.VisionType;
import emu.grasscutter.scripts.data.SceneRegion;
@@ -122,6 +123,9 @@ public class Player {
@Getter private Map<Integer, Integer> unlockedRecipies;
@Getter private List<ActiveForgeData> activeForges;
@Getter private Map<Integer,Integer> questGlobalVariables;
@Getter private Map<Integer, Integer> openStates;
@Getter @Setter private Map<Integer, List<Integer>> unlockedSceneAreas;
@Getter @Setter private Map<Integer, List<Integer>> unlockedScenePoints;
@Transient private long nextGuid = 0;
@Transient private int peerId;
@@ -151,13 +155,13 @@ public class Player {
@Getter private transient CookingManager cookingManager;
@Getter private transient ActivityManager activityManager;
@Getter private transient PlayerBuffManager buffManager;
@Getter private transient PlayerProgressManager progressManager;
// Manager data (Save-able to the database)
private PlayerProfile playerProfile;
private TeamManager teamManager;
private TowerData towerData;
private PlayerGachaInfo gachaInfo;
private PlayerOpenStateManager openStateManager;
private PlayerCollectionRecords collectionRecordStore;
private ArrayList<ShopLimit> shopLimit;
@@ -221,6 +225,9 @@ public class Player {
this.unlockedFurnitureSuite = new HashSet<>();
this.activeForges = new ArrayList<>();
this.unlockedRecipies = new HashMap<>();
this.openStates = new HashMap<>();
this.unlockedSceneAreas = new HashMap<>();
this.unlockedScenePoints = new HashMap<>();
this.sceneState = SceneLoadState.NONE;
this.attackResults = new LinkedBlockingQueue<>();
@@ -233,7 +240,7 @@ public class Player {
this.rewardedLevels = new HashSet<>();
this.moonCardGetTimes = new HashSet<>();
this.codex = new PlayerCodex(this);
this.openStateManager = new PlayerOpenStateManager(this);
this.progressManager = new PlayerProgressManager(this);
this.shopLimit = new ArrayList<>();
this.expeditionInfo = new HashMap<>();
this.messageHandler = null;
@@ -243,6 +250,7 @@ public class Player {
this.energyManager = new EnergyManager(this);
this.resinManager = new ResinManager(this);
this.forgingManager = new ForgingManager(this);
this.progressManager = new PlayerProgressManager(this);
this.furnitureManager = new FurnitureManager(this);
this.cookingManager = new CookingManager(this);
}
@@ -276,6 +284,7 @@ public class Player {
this.resinManager = new ResinManager(this);
this.deforestationManager = new DeforestationManager(this);
this.forgingManager = new ForgingManager(this);
this.progressManager = new PlayerProgressManager(this);
this.furnitureManager = new FurnitureManager(this);
this.cookingManager = new CookingManager(this);
}
@@ -436,7 +445,7 @@ public class Player {
this.updateProfile();
// Handle open state unlocks from level-up.
this.getOpenStateManager().tryUnlockOpenStates();
this.getProgressManager().tryUnlockOpenStates();
return true;
}
@@ -1191,13 +1200,6 @@ public class Player {
return mapMarks;
}
public PlayerOpenStateManager getOpenStateManager() {
if (this.openStateManager == null) {
this.openStateManager = new PlayerOpenStateManager(this);
}
return openStateManager;
}
public synchronized void onTick() {
// Check ping
if (this.getLastPingTime() > System.currentTimeMillis() + 60000) {
@@ -1297,7 +1299,7 @@ public class Player {
@PostLoad
private void onLoad() {
this.getCodex().setPlayer(this);
this.getOpenStateManager().setPlayer(this);
this.getProgressManager().setPlayer(this);
this.getTeamManager().setPlayer(this);
}
@@ -1356,16 +1358,17 @@ public class Player {
// Execute daily reset logic if this is a new day.
this.doDailyReset();
// Rewind active quests, and put the player to a rewind position it finds (if any) of an active quest
getQuestManager().onLogin();
// Packets
session.send(new PacketPlayerDataNotify(this)); // Player data
session.send(new PacketStoreWeightLimitNotify());
session.send(new PacketPlayerStoreNotify(this));
session.send(new PacketAvatarDataNotify(this));
this.getProgressManager().onPlayerLogin();
session.send(new PacketFinishedParentQuestNotify(this));
session.send(new PacketBattlePassAllDataNotify(this));
session.send(new PacketQuestListNotify(this));
@@ -1376,7 +1379,6 @@ public class Player {
this.forgingManager.sendForgeDataNotify();
this.resinManager.onPlayerLogin();
this.cookingManager.sendCookDataNofity();
this.getOpenStateManager().onPlayerLogin();
getTodayMoonCard(); // The timer works at 0:0, some users log in after that, use this method to check if they have received a reward today or not. If not, send the reward.
@@ -1513,10 +1515,17 @@ public class Player {
int min = this.getPropertyMin(prop);
int max = this.getPropertyMax(prop);
if (min <= value && value <= max) {
int currentValue = this.properties.get(prop.getId());
this.properties.put(prop.getId(), value);
if (sendPacket) {
// Update player with packet
this.sendPacket(new PacketPlayerPropNotify(this, prop));
this.sendPacket(new PacketPlayerPropChangeNotify(this, prop, value - currentValue));
// Make the Adventure EXP pop-up show on screen.
if (prop == PlayerProperty.PROP_PLAYER_EXP) {
this.sendPacket(new PacketPlayerPropChangeReasonNotify(this, prop, currentValue, value, PropChangeReason.PROP_CHANGE_REASON_PLAYER_ADD_EXP));
}
}
return true;
} else {

View File

@@ -1,157 +0,0 @@
package emu.grasscutter.game.player;
import dev.morphia.annotations.Entity;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.excels.OpenStateData;
import emu.grasscutter.data.excels.OpenStateData.OpenStateCondType;
import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode;
import emu.grasscutter.server.packet.send.PacketOpenStateChangeNotify;
import emu.grasscutter.server.packet.send.PacketOpenStateUpdateNotify;
import emu.grasscutter.server.packet.send.PacketSetOpenStateRsp;
import java.util.*;
import java.util.stream.Collectors;
@Entity
public class PlayerOpenStateManager extends BasePlayerDataManager {
// Set of open states that are never unlocked, whether they fulfill the conditions or not.
public static final Set<Integer> BLACKLIST_OPEN_STATES = Set.of(
48 // blacklist OPEN_STATE_LIMIT_REGION_GLOBAL to make Meledy happy. =D Remove this as soon as quest unlocks are fully implemented.
);
// Set of open states that are set per default for all accounts. Can be overwritten by an entry in `map`.
public static final Set<Integer> DEFAULT_OPEN_STATES = GameData.getOpenStateList().stream()
.filter(s ->
s.isDefaultState() // Actual default-opened states.
|| (s.getCond().stream().filter(c -> c.getCondType() == OpenStateCondType.OPEN_STATE_COND_PLAYER_LEVEL).count() == 0) // All states whose unlock we don't handle correctly yet.
|| s.getId() == 1 // Always unlock OPEN_STATE_PAIMON, otherwise the player will not have a working chat.
)
.filter(s -> !BLACKLIST_OPEN_STATES.contains(s.getId())) // Filter out states in the blacklist.
.map(s -> s.getId())
.collect(Collectors.toSet());
// Map of all open states that this player has.
private Map<Integer, Integer> map;
public PlayerOpenStateManager(Player player) {
super(player);
}
public synchronized Map<Integer, Integer> getOpenStateMap() {
// If no map currently exists, we create one.
if (this.map == null) {
this.map = new HashMap<>();
}
return this.map;
}
/**********
Direct getters and setters for open states.
**********/
public int getOpenState(int openState) {
return getOpenStateMap().getOrDefault(openState, 0);
}
private void setOpenState(int openState, int value, boolean sendNotify) {
int previousValue = this.getOpenStateMap().getOrDefault(openState, 0);
if (value != previousValue) {
this.getOpenStateMap().put(openState, value);
if (sendNotify) {
player.getSession().send(new PacketOpenStateChangeNotify(openState, value));
}
}
}
private void setOpenState(int openState, int value) {
this.setOpenState(openState, value, true);
}
/**********
Condition checking for setting open states.
**********/
private boolean areConditionsMet(OpenStateData openState) {
// Check all conditions and test if at least one of them is violated.
for (var condition : openState.getCond()) {
// For level conditions, check if the player has reached the necessary level.
if (condition.getCondType() == OpenStateCondType.OPEN_STATE_COND_PLAYER_LEVEL) {
if (this.player.getLevel() < condition.getParam()) {
return false;
}
}
else if (condition.getCondType() == OpenStateCondType.OPEN_STATE_COND_QUEST) {
// ToDo: Implement.
}
else if (condition.getCondType() == OpenStateCondType.OPEN_STATE_COND_PARENT_QUEST) {
// ToDo: Implement.
}
else if (condition.getCondType() == OpenStateCondType.OPEN_STATE_OFFERING_LEVEL) {
// ToDo: Implement.
}
else if (condition.getCondType() == OpenStateCondType.OPEN_STATE_CITY_REPUTATION_LEVEL) {
// ToDo: Implement.
}
}
// Done. If we didn't find any violations, all conditions are met.
return true;
}
/**********
Setting open states from the client (via `SetOpenStateReq`).
**********/
public void setOpenStateFromClient(int openState, int value) {
// Get the data for this open state.
OpenStateData data = GameData.getOpenStateDataMap().get(openState);
if (data == null) {
this.player.sendPacket(new PacketSetOpenStateRsp(Retcode.RET_FAIL));
return;
}
// Make sure that this is an open state that the client is allowed to set,
// and that it doesn't have any further conditions attached.
if (!data.isAllowClientOpen() || !this.areConditionsMet(data)) {
this.player.sendPacket(new PacketSetOpenStateRsp(Retcode.RET_FAIL));
return;
}
// Set.
this.setOpenState(openState, value);
this.player.sendPacket(new PacketSetOpenStateRsp(openState, value));
}
/**********
Handler for player login.
**********/
public void onPlayerLogin() {
// Try unlocking open states on player login. This handles accounts where unlock conditions were
// already met before certain open state unlocks were implemented.
this.tryUnlockOpenStates(false);
// Send notify to the client.
player.getSession().send(new PacketOpenStateUpdateNotify(this));
}
/**********
Triggered unlocking of open states (unlock states whose conditions have been met.)
**********/
public void tryUnlockOpenStates(boolean sendNotify) {
// Get list of open states that are not yet unlocked.
var lockedStates = GameData.getOpenStateList().stream().filter(s -> this.getOpenStateMap().getOrDefault(s, 0) == 0).toList();
// Try unlocking all of them.
for (var state : lockedStates) {
// To auto-unlock a state, it has to meet three conditions:
// * it can not be a state that is unlocked by the client,
// * it has to meet all its unlock conditions, and
// * it can not be in the blacklist.
if (!state.isAllowClientOpen() && this.areConditionsMet(state) && !BLACKLIST_OPEN_STATES.contains(state.getId())) {
this.setOpenState(state.getId(), 1, sendNotify);
}
}
}
public void tryUnlockOpenStates() {
this.tryUnlockOpenStates(true);
}
}

View File

@@ -0,0 +1,257 @@
package emu.grasscutter.game.player;
import dev.morphia.annotations.Entity;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.binout.ScenePointEntry;
import emu.grasscutter.data.excels.OpenStateData;
import emu.grasscutter.data.excels.OpenStateData.OpenStateCondType;
import emu.grasscutter.game.inventory.GameItem;
import emu.grasscutter.game.props.ActionReason;
import emu.grasscutter.game.props.PlayerProperty;
import emu.grasscutter.game.quest.enums.QuestState;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.net.proto.PropChangeReasonOuterClass.PropChangeReason;
import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode;
import emu.grasscutter.server.packet.send.PacketOpenStateChangeNotify;
import emu.grasscutter.server.packet.send.PacketOpenStateUpdateNotify;
import emu.grasscutter.server.packet.send.PacketSceneAreaUnlockNotify;
import emu.grasscutter.server.packet.send.PacketScenePointUnlockNotify;
import emu.grasscutter.server.packet.send.PacketSetOpenStateRsp;
import emu.grasscutter.server.packet.send.PacketUnlockTransPointRsp;
import java.util.*;
import java.util.stream.Collectors;
// @Entity
public class PlayerProgressManager extends BasePlayerDataManager {
public PlayerProgressManager(Player player) {
super(player);
}
/**********
Handler for player login.
**********/
public void onPlayerLogin() {
// Try unlocking open states on player login. This handles accounts where unlock conditions were
// already met before certain open state unlocks were implemented.
this.tryUnlockOpenStates(false);
// Send notify to the client.
player.getSession().send(new PacketOpenStateUpdateNotify(this.player));
// Add statue quests if necessary.
this.addStatueQuestsOnLogin();
// Auto-unlock the first statue and map area, until we figure out how to make
// that particular statue interactable.
if (!this.player.getUnlockedScenePoints().containsKey(3)) {
this.player.getUnlockedScenePoints().put(3, new ArrayList<>());
}
if (!this.player.getUnlockedScenePoints().get(3).contains(7)) {
this.player.getUnlockedScenePoints().get(3).add(7);
}
if (!this.player.getUnlockedSceneAreas().containsKey(3)) {
this.player.getUnlockedSceneAreas().put(3, new ArrayList<>());
}
if (!this.player.getUnlockedSceneAreas().get(3).contains(1)) {
this.player.getUnlockedSceneAreas().get(3).add(1);
}
}
/******************************************************************************************************************
******************************************************************************************************************
* OPEN STATES
******************************************************************************************************************
*****************************************************************************************************************/
// Set of open states that are never unlocked, whether they fulfill the conditions or not.
public static final Set<Integer> BLACKLIST_OPEN_STATES = Set.of(
48 // blacklist OPEN_STATE_LIMIT_REGION_GLOBAL to make Meledy happy. =D Remove this as soon as quest unlocks are fully implemented.
);
// Set of open states that are set per default for all accounts. Can be overwritten by an entry in `map`.
public static final Set<Integer> DEFAULT_OPEN_STATES = GameData.getOpenStateList().stream()
.filter(s ->
s.isDefaultState() // Actual default-opened states.
// All states whose unlock we don't handle correctly yet.
|| (s.getCond().stream().filter(c -> c.getCondType() == OpenStateCondType.OPEN_STATE_COND_PLAYER_LEVEL).count() == 0)
// Always unlock OPEN_STATE_PAIMON, otherwise the player will not have a working chat.
|| s.getId() == 1
)
.filter(s -> !BLACKLIST_OPEN_STATES.contains(s.getId())) // Filter out states in the blacklist.
.map(s -> s.getId())
.collect(Collectors.toSet());
/**********
Direct getters and setters for open states.
**********/
public int getOpenState(int openState) {
return this.player.getOpenStates().getOrDefault(openState, 0);
}
private void setOpenState(int openState, int value, boolean sendNotify) {
int previousValue = this.player.getOpenStates().getOrDefault(openState, 0);
if (value != previousValue) {
this.player.getOpenStates().put(openState, value);
if (sendNotify) {
player.getSession().send(new PacketOpenStateChangeNotify(openState, value));
}
}
}
private void setOpenState(int openState, int value) {
this.setOpenState(openState, value, true);
}
/**********
Condition checking for setting open states.
**********/
private boolean areConditionsMet(OpenStateData openState) {
// Check all conditions and test if at least one of them is violated.
for (var condition : openState.getCond()) {
// For level conditions, check if the player has reached the necessary level.
if (condition.getCondType() == OpenStateCondType.OPEN_STATE_COND_PLAYER_LEVEL) {
if (this.player.getLevel() < condition.getParam()) {
return false;
}
}
else if (condition.getCondType() == OpenStateCondType.OPEN_STATE_COND_QUEST) {
// ToDo: Implement.
}
else if (condition.getCondType() == OpenStateCondType.OPEN_STATE_COND_PARENT_QUEST) {
// ToDo: Implement.
}
else if (condition.getCondType() == OpenStateCondType.OPEN_STATE_OFFERING_LEVEL) {
// ToDo: Implement.
}
else if (condition.getCondType() == OpenStateCondType.OPEN_STATE_CITY_REPUTATION_LEVEL) {
// ToDo: Implement.
}
}
// Done. If we didn't find any violations, all conditions are met.
return true;
}
/**********
Setting open states from the client (via `SetOpenStateReq`).
**********/
public void setOpenStateFromClient(int openState, int value) {
// Get the data for this open state.
OpenStateData data = GameData.getOpenStateDataMap().get(openState);
if (data == null) {
this.player.sendPacket(new PacketSetOpenStateRsp(Retcode.RET_FAIL));
return;
}
// Make sure that this is an open state that the client is allowed to set,
// and that it doesn't have any further conditions attached.
if (!data.isAllowClientOpen() || !this.areConditionsMet(data)) {
this.player.sendPacket(new PacketSetOpenStateRsp(Retcode.RET_FAIL));
return;
}
// Set.
this.setOpenState(openState, value);
this.player.sendPacket(new PacketSetOpenStateRsp(openState, value));
}
/**********
Triggered unlocking of open states (unlock states whose conditions have been met.)
**********/
public void tryUnlockOpenStates(boolean sendNotify) {
// Get list of open states that are not yet unlocked.
var lockedStates = GameData.getOpenStateList().stream().filter(s -> this.player.getOpenStates().getOrDefault(s, 0) == 0).toList();
// Try unlocking all of them.
for (var state : lockedStates) {
// To auto-unlock a state, it has to meet three conditions:
// * it can not be a state that is unlocked by the client,
// * it has to meet all its unlock conditions, and
// * it can not be in the blacklist.
if (!state.isAllowClientOpen() && this.areConditionsMet(state) && !BLACKLIST_OPEN_STATES.contains(state.getId())) {
this.setOpenState(state.getId(), 1, sendNotify);
}
}
}
public void tryUnlockOpenStates() {
this.tryUnlockOpenStates(true);
}
/******************************************************************************************************************
******************************************************************************************************************
* MAP AREAS AND POINTS
******************************************************************************************************************
*****************************************************************************************************************/
private void addStatueQuestsOnLogin() {
// Get all currently existing subquests for the "unlock all statues" main quest.
var statueMainQuest = GameData.getMainQuestDataMap().get(303);
var statueSubQuests = statueMainQuest.getSubQuests();
// Add the main statue quest if it isn't active yet.
var statueGameMainQuest = this.player.getQuestManager().getMainQuestById(303);
if (statueGameMainQuest == null) {
this.player.getQuestManager().addQuest(30302);
statueGameMainQuest = this.player.getQuestManager().getMainQuestById(303);
}
// Set all subquests to active if they aren't already finished.
for (var subData : statueSubQuests) {
var subGameQuest = statueGameMainQuest.getChildQuestById(subData.getSubId());
if (subGameQuest != null && subGameQuest.getState() == QuestState.QUEST_STATE_UNSTARTED) {
this.player.getQuestManager().addQuest(subData.getSubId());
}
}
}
public void unlockTransPoint(int sceneId, int pointId, boolean isStatue) {
// Check whether the unlocked point exists and whether it is still locked.
String key = sceneId + "_" + pointId;
ScenePointEntry scenePointEntry = GameData.getScenePointEntries().get(key);
if (scenePointEntry == null || this.player.getUnlockedScenePoints().getOrDefault(sceneId, List.of()).contains(pointId)) {
this.player.sendPacket(new PacketUnlockTransPointRsp(Retcode.RET_FAIL));
return;
}
// Add the point to the list of unlocked points for its scene.
if (!this.player.getUnlockedScenePoints().containsKey(sceneId)) {
this.player.getUnlockedScenePoints().put(sceneId, new ArrayList<>());
}
this.player.getUnlockedScenePoints().get(sceneId).add(pointId);
// Give primogems and Adventure EXP for unlocking.
var primos = new GameItem(GameData.getItemDataMap().get(201), 5);
this.player.getInventory().addItem(primos, ActionReason.UnlockPointReward);
var exp = new GameItem(GameData.getItemDataMap().get(102), isStatue ? 50 : 10);
this.player.getInventory().addItem(exp, ActionReason.UnlockPointReward);
// this.player.sendPacket(new PacketPlayerPropChangeReasonNotify(this.player.getProperty(PlayerProperty.PROP_PLAYER_EXP), PlayerProperty.PROP_PLAYER_EXP, PropChangeReason.PROP_CHANGE_REASON_PLAYER_ADD_EXP));
// Fire quest trigger for trans point unlock.
this.player.getQuestManager().triggerEvent(QuestTrigger.QUEST_CONTENT_UNLOCK_TRANS_POINT, sceneId, pointId);
// Send packet.
this.player.sendPacket(new PacketScenePointUnlockNotify(sceneId, pointId));
this.player.sendPacket(new PacketUnlockTransPointRsp(Retcode.RET_SUCC));
}
public void unlockSceneArea(int sceneId, int areaId) {
// Check whether this area is already unlocked.
if (this.player.getUnlockedSceneAreas().getOrDefault(sceneId, List.of()).contains(areaId)) {
return;
}
// Add the area to the list of unlocked areas in its scene.
if (!this.player.getUnlockedSceneAreas().containsKey(sceneId)) {
this.player.getUnlockedSceneAreas().put(sceneId, new ArrayList<>());
}
this.player.getUnlockedSceneAreas().get(sceneId).add(areaId);
// Send packet.
this.player.sendPacket(new PacketSceneAreaUnlockNotify(sceneId, areaId));
}
}

View File

@@ -316,7 +316,7 @@ public class GameMainQuest {
List<QuestData.QuestCondition> finishCond = subQuestWithCond.getQuestData().getFinishCond();
int[] finish = new int[finishCond.size()];
for (int i = 0; i < subQuestWithCond.getQuestData().getFinishCond().size(); i++) {
for (int i = 0; i < finishCond.size(); i++) {
QuestData.QuestCondition condition = finishCond.get(i);
boolean result = this.getOwner().getServer().getQuestSystem().triggerContent(subQuestWithCond, condition, paramStr, params);
finish[i] = result ? 1 : 0;

View File

@@ -13,9 +13,15 @@ public class ContentCompleteTalk extends QuestBaseHandler {
@Override
public boolean execute(GameQuest quest, 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(params[0]));
return talkData == null || condition.getParamStr().contains(paramStr) || checkMainQuest.getChildQuestById(params[0]) != null;
GameMainQuest checkMainQuest = quest.getOwner().getQuestManager().getMainQuestById(params[0] / 100);
if (checkMainQuest == null) {
return false;
}
MainQuestData.TalkData talkData = checkMainQuest.getTalks().get(condition.getParam()[0]);
return talkData != null;
// This expression makes zero sense.
// return talkData == null || condition.getParamStr().contains(paramStr) || checkMainQuest.getChildQuestById(params[0]) != null;
}
}

View File

@@ -0,0 +1,23 @@
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;
import java.util.Arrays;
@QuestValue(QuestTrigger.QUEST_EXEC_UNLOCK_AREA)
public class ExecUnlockArea extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
// Unlock the trans point for the player.
int sceneId = Integer.parseInt(paramStr[0]);
int areaId = Integer.parseInt(paramStr[1]);
quest.getOwner().getProgressManager().unlockSceneArea(sceneId, areaId);
// Done.
return true;
}
}

View File

@@ -0,0 +1,23 @@
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_UNLOCK_POINT)
public class ExecUnlockPoint extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
// Unlock the trans point for the player.
int sceneId = Integer.parseInt(paramStr[0]);
int pointId = Integer.parseInt(paramStr[1]);
boolean isStatue = quest.getMainQuestId() == 303;
quest.getOwner().getProgressManager().unlockTransPoint(sceneId, pointId, isStatue);
// Done.
return true;
}
}