mirror of
https://github.com/Grasscutters/Grasscutter.git
synced 2025-12-22 11:54:39 +01:00
Create files from Grasscutter-Quests
these files are NOT directly compatible with Grasscutter, and require additional modifications to the codebase to work.
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
package emu.grasscutter.game.dungeons;
|
||||
|
||||
import emu.grasscutter.game.dungeons.dungeon_results.BaseDungeonResult;
|
||||
import lombok.Getter;
|
||||
|
||||
public class DungeonEndStats {
|
||||
@Getter private int killedMonsters;
|
||||
@Getter private int timeTaken;
|
||||
@Getter private int openChestCount;
|
||||
@Getter private BaseDungeonResult.DungeonEndReason dungeonResult;
|
||||
|
||||
public DungeonEndStats(int killedMonsters, int timeTaken, int openChestCount, BaseDungeonResult.DungeonEndReason dungeonResult){
|
||||
this.killedMonsters = killedMonsters;
|
||||
this.timeTaken = timeTaken;
|
||||
this.dungeonResult = dungeonResult;
|
||||
this.openChestCount = openChestCount;
|
||||
}
|
||||
}
|
||||
315
src/main/java/emu/grasscutter/game/dungeons/DungeonManager.java
Normal file
315
src/main/java/emu/grasscutter/game/dungeons/DungeonManager.java
Normal file
@@ -0,0 +1,315 @@
|
||||
package emu.grasscutter.game.dungeons;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.common.ItemParamData;
|
||||
import emu.grasscutter.data.excels.DungeonData;
|
||||
import emu.grasscutter.data.excels.DungeonPassConfigData;
|
||||
import emu.grasscutter.game.activity.trialavatar.TrialAvatarActivityHandler;
|
||||
import emu.grasscutter.game.dungeons.dungeon_results.BaseDungeonResult;
|
||||
import emu.grasscutter.game.dungeons.enums.DungeonPassConditionType;
|
||||
import emu.grasscutter.game.inventory.GameItem;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.props.ActionReason;
|
||||
import emu.grasscutter.game.props.ActivityType;
|
||||
import emu.grasscutter.game.props.WatcherTriggerType;
|
||||
import emu.grasscutter.game.quest.enums.LogicType;
|
||||
import emu.grasscutter.game.quest.enums.QuestContent;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.scripts.constants.EventType;
|
||||
import emu.grasscutter.scripts.data.ScriptArgs;
|
||||
import emu.grasscutter.server.packet.send.PacketDungeonWayPointNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketGadgetAutoPickDropInfoNotify;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import emu.grasscutter.utils.Utils;
|
||||
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
||||
import it.unimi.dsi.fastutil.ints.IntSet;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.val;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
/**
|
||||
* TODO handle time limits
|
||||
* TODO handle respawn points
|
||||
* TODO handle team wipes and respawns
|
||||
* TODO check monster level and levelConfigMap
|
||||
*/
|
||||
public class DungeonManager {
|
||||
|
||||
@Getter private final Scene scene;
|
||||
@Getter private final DungeonData dungeonData;
|
||||
@Getter private final DungeonPassConfigData passConfigData;
|
||||
|
||||
@Getter private final int[] finishedConditions;
|
||||
private final IntSet rewardedPlayers = new IntOpenHashSet();
|
||||
private final Set<Integer> activeDungeonWayPoints = new HashSet<>();
|
||||
private boolean ended = false;
|
||||
private int newestWayPoint = 0;
|
||||
@Getter private int startSceneTime = 0;
|
||||
|
||||
DungeonTrialTeam trialTeam = null;
|
||||
|
||||
public DungeonManager(@NonNull Scene scene, @NonNull DungeonData dungeonData) {
|
||||
this.scene = scene;
|
||||
this.dungeonData = dungeonData;
|
||||
this.passConfigData = GameData.getDungeonPassConfigDataMap().get(dungeonData.getPassCond());
|
||||
this.finishedConditions = new int[passConfigData.getConds().size()];
|
||||
this.scene.setDungeonManager(this);
|
||||
}
|
||||
|
||||
public void triggerEvent(DungeonPassConditionType conditionType, int... params) {
|
||||
if (ended) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < passConfigData.getConds().size(); i++) {
|
||||
var cond = passConfigData.getConds().get(i);
|
||||
if (conditionType == cond.getCondType()) {
|
||||
if (getScene().getWorld().getServer().getDungeonSystem().triggerCondition(cond, params)) {
|
||||
finishedConditions[i] = 1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (isFinishedSuccessfully()) {
|
||||
finishDungeon();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public boolean isFinishedSuccessfully() {
|
||||
return LogicType.calculate(passConfigData.getLogicType(), finishedConditions);
|
||||
}
|
||||
|
||||
public int getLevelForMonster(int id) {
|
||||
//TODO should use levelConfigMap? and how?
|
||||
return dungeonData.getShowLevel();
|
||||
}
|
||||
|
||||
public boolean activateRespawnPoint(int pointId) {
|
||||
val respawnPoint = GameData.getScenePointEntryById(scene.getId(), pointId);
|
||||
|
||||
if (respawnPoint == null) {
|
||||
Grasscutter.getLogger().warn("trying to activate unknown respawn point {}", pointId);
|
||||
return false;
|
||||
}
|
||||
|
||||
scene.broadcastPacket(new PacketDungeonWayPointNotify(activeDungeonWayPoints.add(pointId), activeDungeonWayPoints));
|
||||
newestWayPoint = pointId;
|
||||
|
||||
Grasscutter.getLogger().debug("[unimplemented respawn] activated respawn point {}", pointId);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Position getRespawnLocation() {
|
||||
if (newestWayPoint == 0) { // validity is checked before setting it, so if != 0 its always valid
|
||||
return null;
|
||||
}
|
||||
val pointData = GameData.getScenePointEntryById(scene.getId(), newestWayPoint).getPointData();
|
||||
return pointData.getTranPos() != null ? pointData.getTranPos() : pointData.getPos();
|
||||
}
|
||||
|
||||
public Position getRespawnRotation() {
|
||||
if (newestWayPoint == 0) { // validity is checked before setting it, so if != 0 its always valid
|
||||
return null;
|
||||
}
|
||||
val pointData = GameData.getScenePointEntryById(scene.getId(), newestWayPoint).getPointData();
|
||||
return pointData.getRot() != null ? pointData.getRot() : null;
|
||||
}
|
||||
|
||||
public boolean getStatueDrops(Player player, boolean useCondensed, int groupId) {
|
||||
if (!isFinishedSuccessfully() || dungeonData.getRewardPreviewData() == null || dungeonData.getRewardPreviewData().getPreviewItems().length == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Already rewarded
|
||||
if (rewardedPlayers.contains(player.getUid())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (!handleCost(player, useCondensed)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get and roll rewards.
|
||||
List<GameItem> rewards = new ArrayList<>(this.rollRewards(useCondensed));
|
||||
// Add rewards to player and send notification.
|
||||
player.getInventory().addItems(rewards, ActionReason.DungeonStatueDrop);
|
||||
player.sendPacket(new PacketGadgetAutoPickDropInfoNotify(rewards));
|
||||
|
||||
rewardedPlayers.add(player.getUid());
|
||||
|
||||
scene.getScriptManager().callEvent(new ScriptArgs(groupId, EventType.EVENT_DUNGEON_REWARD_GET));
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean handleCost(Player player, boolean useCondensed) {
|
||||
int resinCost = dungeonData.getStatueCostCount() != 0 ? dungeonData.getStatueCostCount() : 20;
|
||||
if (resinCost == 0) {
|
||||
return true;
|
||||
}
|
||||
if (useCondensed) {
|
||||
// Check if condensed resin is usable here.
|
||||
// For this, we use the following logic for now:
|
||||
// The normal resin cost of the dungeon has to be 20.
|
||||
if (resinCost != 20) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Spend the condensed resin and only proceed if the transaction succeeds.
|
||||
return player.getResinManager().useCondensedResin(1);
|
||||
} else if (dungeonData.getStatueCostID() == 106) {
|
||||
// Spend the resin and only proceed if the transaction succeeds.
|
||||
return player.getResinManager().useResin(resinCost);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private List<GameItem> rollRewards(boolean useCondensed) {
|
||||
List<GameItem> rewards = new ArrayList<>();
|
||||
int dungeonId = this.dungeonData.getId();
|
||||
// If we have specific drop data for this dungeon, we use it.
|
||||
if (GameData.getDungeonDropDataMap().containsKey(dungeonId)) {
|
||||
List<DungeonDropEntry> dropEntries = GameData.getDungeonDropDataMap().get(dungeonId);
|
||||
|
||||
// Roll for each drop group.
|
||||
for (var entry : dropEntries) {
|
||||
// Determine the number of drops we get for this entry.
|
||||
int start = entry.getCounts().get(0);
|
||||
int end = entry.getCounts().get(entry.getCounts().size() - 1);
|
||||
var candidateAmounts = IntStream.range(start, end + 1).boxed().collect(Collectors.toList());
|
||||
|
||||
int amount = Utils.drawRandomListElement(candidateAmounts, entry.getProbabilities());
|
||||
|
||||
if (useCondensed) {
|
||||
amount += Utils.drawRandomListElement(candidateAmounts, entry.getProbabilities());
|
||||
}
|
||||
|
||||
// Double rewards in multiplay mode, if specified.
|
||||
if (entry.isMpDouble() && this.getScene().getPlayerCount() > 1) {
|
||||
amount *= 2;
|
||||
}
|
||||
|
||||
// Roll items for this group.
|
||||
// Here, we have to handle stacking, or the client will not display results correctly.
|
||||
// For now, we use the following logic: If the possible drop item are a list of multiple items,
|
||||
// we roll them separately. If not, we stack them. This should work out in practice, at least
|
||||
// for the currently existing set of dungeons.
|
||||
if (entry.getItems().size() == 1) {
|
||||
rewards.add(new GameItem(entry.getItems().get(0), amount));
|
||||
} else {
|
||||
for (int i = 0; i < amount; i++) {
|
||||
// int itemIndex = ThreadLocalRandom.current().nextInt(0, entry.getItems().size());
|
||||
// int itemId = entry.getItems().get(itemIndex);
|
||||
int itemId = Utils.drawRandomListElement(entry.getItems(), entry.getItemProbabilities());
|
||||
rewards.add(new GameItem(itemId, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Otherwise, we fall back to the preview data.
|
||||
else {
|
||||
Grasscutter.getLogger().info("No drop data found or dungeon {}, falling back to preview data ...", dungeonId);
|
||||
for (ItemParamData param : dungeonData.getRewardPreviewData().getPreviewItems()) {
|
||||
rewards.add(new GameItem(param.getId(), Math.max(param.getCount(), 1)));
|
||||
}
|
||||
}
|
||||
|
||||
return rewards;
|
||||
}
|
||||
|
||||
public void applyTrialTeam(Player player) {
|
||||
if (getDungeonData() == null) return;
|
||||
|
||||
switch (getDungeonData().getType()) {
|
||||
// case DUNGEON_PLOT is handled by quest execs
|
||||
case DUNGEON_ACTIVITY -> {
|
||||
switch (getDungeonData().getPlayType()) {
|
||||
case DUNGEON_PLAY_TYPE_TRIAL_AVATAR -> {
|
||||
val activityHandler = player.getActivityManager()
|
||||
.getActivityHandlerAs(ActivityType.NEW_ACTIVITY_TRIAL_AVATAR, TrialAvatarActivityHandler.class);
|
||||
activityHandler.ifPresent(trialAvatarActivityHandler ->
|
||||
this.trialTeam = trialAvatarActivityHandler.getTrialAvatarDungeonTeam());
|
||||
}
|
||||
}
|
||||
}
|
||||
case DUNGEON_ELEMENT_CHALLENGE -> {} // TODO
|
||||
}
|
||||
if(this.trialTeam != null) {
|
||||
player.addTrialAvatarsForActivity(trialTeam.trialAvatarIds);
|
||||
}
|
||||
}
|
||||
|
||||
public void unsetTrialTeam(Player player){
|
||||
if(this.trialTeam==null){
|
||||
return;
|
||||
}
|
||||
player.removeTrialAvatarForActivity();
|
||||
this.trialTeam = null;
|
||||
}
|
||||
|
||||
public void startDungeon() {
|
||||
this.startSceneTime = scene.getSceneTimeSeconds();
|
||||
scene.getPlayers().forEach(p -> {
|
||||
p.getQuestManager().queueEvent(QuestContent.QUEST_CONTENT_ENTER_DUNGEON, dungeonData.getId());
|
||||
applyTrialTeam(p);
|
||||
});
|
||||
}
|
||||
|
||||
public void finishDungeon() {
|
||||
notifyEndDungeon(true);
|
||||
endDungeon(BaseDungeonResult.DungeonEndReason.COMPLETED);
|
||||
}
|
||||
|
||||
public void notifyEndDungeon(boolean successfully) {
|
||||
scene.getPlayers().forEach(p -> {
|
||||
// Quest trigger
|
||||
p.getQuestManager().queueEvent(successfully ?
|
||||
QuestContent.QUEST_CONTENT_FINISH_DUNGEON : QuestContent.QUEST_CONTENT_FAIL_DUNGEON,
|
||||
dungeonData.getId());
|
||||
|
||||
// Battle pass trigger
|
||||
if (dungeonData.getType().isCountsToBattlepass() && successfully) {
|
||||
p.getBattlePassManager().triggerMission(WatcherTriggerType.TRIGGER_FINISH_DUNGEON);
|
||||
}
|
||||
});
|
||||
scene.getScriptManager().callEvent(new ScriptArgs(0, EventType.EVENT_DUNGEON_SETTLE, successfully ? 1 : 0));
|
||||
}
|
||||
|
||||
public void quitDungeon() {
|
||||
notifyEndDungeon(false);
|
||||
endDungeon(BaseDungeonResult.DungeonEndReason.QUIT);
|
||||
}
|
||||
|
||||
public void failDungeon() {
|
||||
notifyEndDungeon(false);
|
||||
endDungeon(BaseDungeonResult.DungeonEndReason.FAILED);
|
||||
}
|
||||
|
||||
public void endDungeon(BaseDungeonResult.DungeonEndReason endReason) {
|
||||
if (scene.getDungeonSettleListeners() != null) {
|
||||
scene.getDungeonSettleListeners().forEach(o -> o.onDungeonSettle(this, endReason));
|
||||
}
|
||||
ended = true;
|
||||
}
|
||||
|
||||
public void restartDungeon() {
|
||||
this.scene.setKilledMonsterCount(0);
|
||||
this.rewardedPlayers.clear();
|
||||
Arrays.fill(finishedConditions, 0);
|
||||
this.ended = false;
|
||||
this.activeDungeonWayPoints.clear();
|
||||
}
|
||||
|
||||
public void cleanUpScene() {
|
||||
this.scene.setDungeonManager(null);
|
||||
this.scene.setKilledMonsterCount(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package emu.grasscutter.game.dungeons;
|
||||
|
||||
import emu.grasscutter.net.proto.TrialAvatarGrantRecordOuterClass.TrialAvatarGrantRecord;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class DungeonTrialTeam {
|
||||
List<Integer> trialAvatarIds;
|
||||
TrialAvatarGrantRecord.GrantReason grantReason;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package emu.grasscutter.game.dungeons;
|
||||
|
||||
import emu.grasscutter.game.dungeons.enums.DungeonPassConditionType;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface DungeonValue {
|
||||
DungeonPassConditionType value();
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package emu.grasscutter.game.dungeons.challenge.enums;
|
||||
|
||||
public enum ChallengeCondType {
|
||||
CHALLENGE_COND_NONE, //00
|
||||
CHALLENGE_COND_IN_TIME, //01
|
||||
CHALLENGE_COND_ALL_TIME, //02
|
||||
CHALLENGE_COND_KILL_COUNT, //03
|
||||
CHALLENGE_COND_SURVIVE, //04
|
||||
CHALLENGE_COND_TIME_INC, //05
|
||||
CHALLENGE_COND_KILL_FAST, //06
|
||||
CHALLENGE_COND_DOWN_LESS, //07
|
||||
CHALLENGE_COND_BEATEN_LESS , //08
|
||||
CHALLENGE_COND_UNNATURAL_COUNT , //09
|
||||
CHALLENGE_COND_FROZEN_LESS , //10
|
||||
CHALLENGE_COND_KILL_MONSTER , //11
|
||||
CHALLENGE_COND_TRIGGER , //12
|
||||
CHALLENGE_COND_GUARD_HP , //13
|
||||
CHALLENGE_COND_TIME_DEC , //14
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package emu.grasscutter.game.dungeons.challenge.enums;
|
||||
|
||||
public enum ChallengeEventMarkType {
|
||||
CHALLENGE_EVENT_NONE,
|
||||
FLIGHT_TIME,
|
||||
FLIGHT_GATHER_POINT,
|
||||
SUMMER_TIME_SPRINT_BOAT_TIME,
|
||||
SUMMER_TIME_SPRINT_BOAT_GATHER_POINT,
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package emu.grasscutter.game.dungeons.challenge.enums;
|
||||
|
||||
public enum ChallengeRecordType {
|
||||
CHALLENGE_RECORD_TYPE_NONE,
|
||||
CHALLENGE_RECORD_TYPE_IN_TIME
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package emu.grasscutter.game.dungeons.challenge.enums;
|
||||
|
||||
public enum ChallengeType {
|
||||
CHALLENGE_NONE, //00
|
||||
CHALLENGE_KILL_COUNT, //01
|
||||
CHALLENGE_KILL_COUNT_IN_TIME, //02
|
||||
CHALLENGE_SURVIVE, //03
|
||||
CHALLENGE_TIME_FLY, //04
|
||||
CHALLENGE_KILL_COUNT_FAST, //05
|
||||
CHALLENGE_KILL_COUNT_FROZEN_LESS, //06
|
||||
CHALLENGE_KILL_MONSTER_IN_TIME, //07
|
||||
CHALLENGE_TRIGGER_IN_TIME, //08
|
||||
CHALLENGE_GUARD_HP, //09
|
||||
CHALLENGE_KILL_COUNT_GUARD_HP, //10
|
||||
CHALLENGE_TRIGGER_IN_TIME_FLY , //11
|
||||
//unknown if position and time match from here on
|
||||
CHALLENGE_TRIGGER2_AVOID_TRIGGER1,
|
||||
CHALLENGE_FATHER_SUCC_IN_TIME,
|
||||
CHALLENGE_MONSTER_DAMAGE_COUNT,
|
||||
CHALLENGE_ELEMENT_REACTION_COUNT,
|
||||
CHALLENGE_FREEZE_ENEMY_IN_TIME,
|
||||
CHALLENGE_CRYSTAL_ELEMENT_REACTION_COUNT,
|
||||
CHALLENGE_SHEILD_ABSORB_DAMAGE_COUNT,
|
||||
CHALLENGE_SWIRL_ELEMENT_REACTION_COUNT,
|
||||
CHALLENGE_DIE_LESS_IN_TIME,
|
||||
CHALLENGE_TRIGGER_COUNT,
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package emu.grasscutter.game.dungeons.challenge.enums;
|
||||
|
||||
public enum FatherChallengeProperty {
|
||||
DURATION,
|
||||
CUR_SUCC,
|
||||
CUR_FAIL,
|
||||
SUM_SUCC,
|
||||
SUM_FAIL
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package emu.grasscutter.game.dungeons.challenge.factory;
|
||||
|
||||
import emu.grasscutter.game.dungeons.challenge.WorldChallenge;
|
||||
import emu.grasscutter.game.dungeons.challenge.enums.ChallengeType;
|
||||
import emu.grasscutter.game.dungeons.challenge.trigger.GuardTrigger;
|
||||
import emu.grasscutter.game.dungeons.challenge.trigger.KillMonsterCountTrigger;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.scripts.data.SceneGroup;
|
||||
import lombok.val;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static emu.grasscutter.game.dungeons.challenge.enums.ChallengeType.CHALLENGE_KILL_COUNT_GUARD_HP;
|
||||
|
||||
public class KillAndGuardChallengeFactoryHandler implements ChallengeFactoryHandler{
|
||||
@Override
|
||||
public boolean isThisType(ChallengeType challengeType) {
|
||||
// ActiveChallenge with 1,188,234101003,12,3030,0
|
||||
return challengeType == CHALLENGE_KILL_COUNT_GUARD_HP;
|
||||
}
|
||||
|
||||
@Override /*TODO check param4 == monstesToKill*/
|
||||
public WorldChallenge build(int challengeIndex, int challengeId, int groupId, int monstersToKill, int gadgetCFGId, int unused, Scene scene, SceneGroup group) {
|
||||
val realGroup = scene.getScriptManager().getGroupById(groupId);
|
||||
return new WorldChallenge(
|
||||
scene, realGroup,
|
||||
challengeId, // Id
|
||||
challengeIndex, // Index
|
||||
List.of(monstersToKill, 0),
|
||||
0, // Limit
|
||||
monstersToKill, // Goal
|
||||
List.of(new KillMonsterCountTrigger(), new GuardTrigger(gadgetCFGId)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package emu.grasscutter.game.dungeons.challenge.factory;
|
||||
|
||||
import emu.grasscutter.game.dungeons.challenge.WorldChallenge;
|
||||
import emu.grasscutter.game.dungeons.challenge.enums.ChallengeType;
|
||||
import emu.grasscutter.game.dungeons.challenge.trigger.KillMonsterCountTrigger;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.scripts.data.SceneGroup;
|
||||
import lombok.val;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class KillMonsterCountChallengeFactoryHandler implements ChallengeFactoryHandler{
|
||||
@Override
|
||||
public boolean isThisType(ChallengeType challengeType) {
|
||||
// ActiveChallenge with 1, 1, 241033003, 15, 0, 0
|
||||
return challengeType == ChallengeType.CHALLENGE_KILL_COUNT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldChallenge build(int challengeIndex, int challengeId, int groupId, int goal, int param5, int param6, Scene scene, SceneGroup group) {
|
||||
val realGroup = scene.getScriptManager().getGroupById(groupId);
|
||||
return new WorldChallenge(
|
||||
scene, realGroup,
|
||||
challengeId, // Id
|
||||
challengeIndex, // Index
|
||||
List.of(goal, groupId),
|
||||
0, // Limit
|
||||
goal, // Goal
|
||||
List.of(new KillMonsterCountTrigger())
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package emu.grasscutter.game.dungeons.challenge.factory;
|
||||
|
||||
import emu.grasscutter.game.dungeons.challenge.WorldChallenge;
|
||||
import emu.grasscutter.game.dungeons.challenge.enums.ChallengeType;
|
||||
import emu.grasscutter.game.dungeons.challenge.trigger.InTimeTrigger;
|
||||
import emu.grasscutter.game.dungeons.challenge.trigger.KillMonsterTrigger;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.scripts.data.SceneGroup;
|
||||
import lombok.val;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class KillMonsterInTimeChallengeFactoryHandler implements ChallengeFactoryHandler{
|
||||
@Override
|
||||
public boolean isThisType(ChallengeType challengeType) {
|
||||
// ActiveChallenge with 180, 72, 240, 133220161, 133220161, 0
|
||||
return challengeType == ChallengeType.CHALLENGE_KILL_MONSTER_IN_TIME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldChallenge build(int challengeIndex, int challengeId, int timeLimit, int groupId, int targetCfgId, int param6, Scene scene, SceneGroup group) {
|
||||
val realGroup = scene.getScriptManager().getGroupById(groupId);
|
||||
return new WorldChallenge(
|
||||
scene, realGroup,
|
||||
challengeId, // Id
|
||||
challengeIndex, // Index
|
||||
List.of(timeLimit),
|
||||
timeLimit, // Limit
|
||||
0, // Goal
|
||||
List.of(new KillMonsterTrigger(targetCfgId), new InTimeTrigger())
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package emu.grasscutter.game.dungeons.challenge.factory;
|
||||
|
||||
import emu.grasscutter.game.dungeons.challenge.WorldChallenge;
|
||||
import emu.grasscutter.game.dungeons.challenge.enums.ChallengeType;
|
||||
import emu.grasscutter.game.dungeons.challenge.trigger.InTimeTrigger;
|
||||
import emu.grasscutter.game.dungeons.challenge.trigger.KillMonsterCountTrigger;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.scripts.data.SceneGroup;
|
||||
import lombok.val;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class KillMonsterTimeChallengeFactoryHandler implements ChallengeFactoryHandler{
|
||||
@Override
|
||||
public boolean isThisType(ChallengeType challengeType) {
|
||||
// ActiveChallenge with 180,180,45,133108061,1,0
|
||||
// ActiveChallenge Fast with 1001, 5, 15, 240004005, 10, 0
|
||||
return challengeType == ChallengeType.CHALLENGE_KILL_COUNT_IN_TIME ||
|
||||
challengeType == ChallengeType.CHALLENGE_KILL_COUNT_FAST;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldChallenge build(int challengeIndex, int challengeId, int timeLimit, int groupId, int targetCount, int param6, Scene scene, SceneGroup group) {
|
||||
val realGroup = scene.getScriptManager().getGroupById(groupId);
|
||||
return new WorldChallenge(
|
||||
scene, realGroup,
|
||||
challengeId, // Id
|
||||
challengeIndex, // Index
|
||||
List.of(targetCount, timeLimit),
|
||||
timeLimit, // Limit
|
||||
targetCount, // Goal
|
||||
List.of(new KillMonsterCountTrigger(), new InTimeTrigger())
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package emu.grasscutter.game.dungeons.challenge.factory;
|
||||
|
||||
import emu.grasscutter.game.dungeons.challenge.WorldChallenge;
|
||||
import emu.grasscutter.game.dungeons.challenge.enums.ChallengeType;
|
||||
import emu.grasscutter.game.dungeons.challenge.trigger.ForTimeTrigger;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.scripts.data.SceneGroup;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static emu.grasscutter.game.dungeons.challenge.enums.ChallengeType.CHALLENGE_SURVIVE;
|
||||
|
||||
public class SurviveChallengeFactoryHandler implements ChallengeFactoryHandler {
|
||||
@Override
|
||||
public boolean isThisType(ChallengeType challengeType) {
|
||||
// grp 201055005
|
||||
// ActiveChallenge with 100, 56, 60, 0, 0, 0
|
||||
return challengeType == CHALLENGE_SURVIVE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldChallenge build(int challengeIndex, int challengeId, int timeToSurvive, int unused4, int unused5, int unused6, Scene scene, SceneGroup group) {
|
||||
return new WorldChallenge(
|
||||
scene, group,
|
||||
challengeId, // Id
|
||||
challengeIndex, // Index
|
||||
List.of(timeToSurvive),
|
||||
timeToSurvive, // Limit
|
||||
0, // Goal
|
||||
List.of(new ForTimeTrigger())
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package emu.grasscutter.game.dungeons.challenge.factory;
|
||||
|
||||
import emu.grasscutter.game.dungeons.challenge.WorldChallenge;
|
||||
import emu.grasscutter.game.dungeons.challenge.enums.ChallengeType;
|
||||
import emu.grasscutter.game.dungeons.challenge.trigger.InTimeTrigger;
|
||||
import emu.grasscutter.game.dungeons.challenge.trigger.TriggerGroupTriggerTrigger;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.scripts.data.SceneGroup;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static emu.grasscutter.game.dungeons.challenge.enums.ChallengeType.CHALLENGE_TRIGGER_IN_TIME;
|
||||
|
||||
public class TriggerInTimeChallengeFactoryHandler implements ChallengeFactoryHandler {
|
||||
@Override
|
||||
public boolean isThisType(ChallengeType challengeType) {
|
||||
// kill gadgets(explosive barrel) in time
|
||||
// ActiveChallenge with 56,201,20,2,201,4
|
||||
// open chest in time
|
||||
// ActiveChallenge with 666,202,30,7,202,1
|
||||
return challengeType == CHALLENGE_TRIGGER_IN_TIME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldChallenge build(int challengeIndex, int challengeId, int timeLimit, int param4, int triggerTag, int triggerCount, Scene scene, SceneGroup group) {
|
||||
return new WorldChallenge(
|
||||
scene, group,
|
||||
challengeId, // Id
|
||||
challengeIndex, // Index
|
||||
List.of(timeLimit, triggerCount),
|
||||
timeLimit, // Limit
|
||||
triggerCount, // Goal
|
||||
List.of(new InTimeTrigger(), new TriggerGroupTriggerTrigger(Integer.toString(triggerTag)))
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package emu.grasscutter.game.dungeons.challenge.trigger;
|
||||
|
||||
import emu.grasscutter.game.dungeons.challenge.WorldChallenge;
|
||||
|
||||
public class ForTimeTrigger extends ChallengeTrigger{
|
||||
@Override
|
||||
public void onCheckTimeout(WorldChallenge challenge) {
|
||||
var current = challenge.getScene().getSceneTimeSeconds();
|
||||
if(current - challenge.getStartedAt() > challenge.getTimeLimit()){
|
||||
challenge.done();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package emu.grasscutter.game.dungeons.challenge.trigger;
|
||||
|
||||
import emu.grasscutter.game.dungeons.challenge.WorldChallenge;
|
||||
import emu.grasscutter.game.entity.EntityMonster;
|
||||
import emu.grasscutter.server.packet.send.PacketChallengeDataNotify;
|
||||
|
||||
public class KillMonsterCountTrigger extends ChallengeTrigger{
|
||||
@Override
|
||||
public void onBegin(WorldChallenge challenge) {
|
||||
challenge.getScene().broadcastPacket(new PacketChallengeDataNotify(challenge, 1, challenge.getScore().get()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMonsterDeath(WorldChallenge challenge, EntityMonster monster) {
|
||||
var newScore = challenge.increaseScore();
|
||||
challenge.getScene().broadcastPacket(new PacketChallengeDataNotify(challenge, 1, newScore));
|
||||
|
||||
if(newScore >= challenge.getGoal()){
|
||||
challenge.done();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package emu.grasscutter.game.dungeons.challenge.trigger;
|
||||
|
||||
import emu.grasscutter.game.dungeons.challenge.WorldChallenge;
|
||||
import emu.grasscutter.game.entity.EntityGadget;
|
||||
import emu.grasscutter.scripts.data.SceneTrigger;
|
||||
import emu.grasscutter.server.packet.send.PacketChallengeDataNotify;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
@AllArgsConstructor
|
||||
public class TriggerGroupTriggerTrigger extends ChallengeTrigger{
|
||||
String triggerTag;
|
||||
|
||||
@Override
|
||||
public void onBegin(WorldChallenge challenge) {
|
||||
challenge.getScene().broadcastPacket(new PacketChallengeDataNotify(challenge, 2, challenge.getScore().get()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGroupTrigger(WorldChallenge challenge, SceneTrigger trigger) {
|
||||
if(!triggerTag.equals(trigger.getTag())) {
|
||||
return;
|
||||
}
|
||||
|
||||
var newScore = challenge.increaseScore();
|
||||
challenge.getScene().broadcastPacket(new PacketChallengeDataNotify(challenge, 2, newScore));
|
||||
if(newScore >= challenge.getGoal()){
|
||||
challenge.done();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package emu.grasscutter.game.dungeons.dungeon_results;
|
||||
|
||||
import emu.grasscutter.data.excels.DungeonData;
|
||||
import emu.grasscutter.game.dungeons.DungeonEndStats;
|
||||
import emu.grasscutter.net.proto.DungeonSettleNotifyOuterClass.DungeonSettleNotify;
|
||||
import emu.grasscutter.net.proto.ParamListOuterClass;
|
||||
import emu.grasscutter.utils.Utils;
|
||||
import lombok.Getter;
|
||||
|
||||
public class BaseDungeonResult {
|
||||
@Getter DungeonData dungeonData;
|
||||
@Getter
|
||||
DungeonEndStats dungeonStats;
|
||||
|
||||
public BaseDungeonResult(DungeonData dungeonData, DungeonEndStats dungeonStats){
|
||||
this.dungeonData = dungeonData;
|
||||
this.dungeonStats = dungeonStats;
|
||||
}
|
||||
|
||||
protected void onProto(DungeonSettleNotify.Builder builder){ }
|
||||
|
||||
public final DungeonSettleNotify.Builder getProto(){
|
||||
var success = dungeonStats.getDungeonResult().isSuccess();
|
||||
var builder = DungeonSettleNotify.newBuilder()
|
||||
.setDungeonId(dungeonData.getId())
|
||||
.setIsSuccess(success)
|
||||
.setCloseTime(getCloseTime())
|
||||
.setResult(success ? 1 : 0);
|
||||
|
||||
// TODO check
|
||||
if(dungeonData.getSettleShows()!=null) {
|
||||
for (int i = 0; i < dungeonData.getSettleShows().size(); i++) {
|
||||
var settle = dungeonData.getSettleShows().get(i);
|
||||
builder.putSettleShow(i + 1,switch (settle) {
|
||||
case SETTLE_SHOW_TIME_COST -> ParamListOuterClass.ParamList.newBuilder()
|
||||
.addParamList(settle.getId())
|
||||
.addParamList(dungeonStats.getTimeTaken())
|
||||
.build();
|
||||
case SETTLE_SHOW_KILL_MONSTER_COUNT -> ParamListOuterClass.ParamList.newBuilder()
|
||||
.addParamList(settle.getId())
|
||||
.addParamList(dungeonStats.getKilledMonsters())
|
||||
.build();
|
||||
default -> ParamListOuterClass.ParamList.newBuilder()
|
||||
.addParamList(settle.getId())
|
||||
.build();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//TODO handle settle show
|
||||
|
||||
onProto(builder);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public int getCloseTime(){
|
||||
return Utils.getCurrentSeconds() + switch (dungeonStats.getDungeonResult()){
|
||||
case COMPLETED -> dungeonData.getSettleCountdownTime();
|
||||
case FAILED -> dungeonData.getFailSettleCountdownTime();
|
||||
case QUIT -> dungeonData.getQuitSettleCountdownTime();
|
||||
};
|
||||
}
|
||||
|
||||
public enum DungeonEndReason{
|
||||
COMPLETED,
|
||||
FAILED,
|
||||
QUIT;
|
||||
|
||||
public boolean isSuccess(){
|
||||
return this == COMPLETED;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package emu.grasscutter.game.dungeons.dungeon_results;
|
||||
|
||||
import emu.grasscutter.data.excels.DungeonData;
|
||||
import emu.grasscutter.game.dungeons.DungeonEndStats;
|
||||
import emu.grasscutter.game.dungeons.challenge.WorldChallenge;
|
||||
import emu.grasscutter.game.tower.TowerManager;
|
||||
import emu.grasscutter.net.proto.DungeonSettleExhibitionInfoOuterClass;
|
||||
import emu.grasscutter.net.proto.DungeonSettleNotifyOuterClass;
|
||||
import emu.grasscutter.net.proto.ItemParamOuterClass;
|
||||
import emu.grasscutter.net.proto.TowerLevelEndNotifyOuterClass.TowerLevelEndNotify.ContinueStateType;
|
||||
import emu.grasscutter.net.proto.TowerLevelEndNotifyOuterClass.TowerLevelEndNotify;
|
||||
|
||||
public class TowerResult extends BaseDungeonResult{
|
||||
WorldChallenge challenge;
|
||||
boolean canJump;
|
||||
boolean hasNextLevel;
|
||||
int nextFloorId;
|
||||
public TowerResult(DungeonData dungeonData, DungeonEndStats dungeonStats, TowerManager towerManager, WorldChallenge challenge) {
|
||||
super(dungeonData, dungeonStats);
|
||||
this.challenge = challenge;
|
||||
this.canJump = towerManager.hasNextFloor();
|
||||
this.hasNextLevel = towerManager.hasNextLevel();
|
||||
this.nextFloorId = hasNextLevel ? 0 : towerManager.getNextFloorId();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onProto(DungeonSettleNotifyOuterClass.DungeonSettleNotify.Builder builder) {
|
||||
var continueStatus = ContinueStateType.CONTINUE_STATE_TYPE_CAN_NOT_CONTINUE_VALUE;
|
||||
if(challenge.isSuccess() && canJump){
|
||||
continueStatus = hasNextLevel ? ContinueStateType.CONTINUE_STATE_TYPE_CAN_ENTER_NEXT_LEVEL_VALUE
|
||||
: ContinueStateType.CONTINUE_STATE_TYPE_CAN_ENTER_NEXT_FLOOR_VALUE;
|
||||
}
|
||||
|
||||
var towerLevelEndNotify = TowerLevelEndNotify.newBuilder()
|
||||
.setIsSuccess(challenge.isSuccess())
|
||||
.setContinueState(continueStatus)
|
||||
.addFinishedStarCondList(1)
|
||||
.addFinishedStarCondList(2)
|
||||
.addFinishedStarCondList(3)
|
||||
.addRewardItemList(ItemParamOuterClass.ItemParam.newBuilder()
|
||||
.setItemId(201)
|
||||
.setCount(1000)
|
||||
.build())
|
||||
;
|
||||
if(nextFloorId > 0 && canJump){
|
||||
towerLevelEndNotify.setNextFloorId(nextFloorId);
|
||||
}
|
||||
builder.setTowerLevelEndNotify(towerLevelEndNotify);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package emu.grasscutter.game.dungeons.dungeon_results;
|
||||
|
||||
import emu.grasscutter.data.excels.DungeonData;
|
||||
import emu.grasscutter.game.dungeons.DungeonEndStats;
|
||||
import emu.grasscutter.net.proto.DungeonSettleNotifyOuterClass;
|
||||
import emu.grasscutter.net.proto.TrialAvatarFirstPassDungeonNotifyOuterClass.TrialAvatarFirstPassDungeonNotify;
|
||||
|
||||
public class TrialAvatarDungeonResult extends BaseDungeonResult {
|
||||
int trialCharacterIndexId;
|
||||
|
||||
public TrialAvatarDungeonResult(DungeonData dungeonData, DungeonEndStats dungeonStats, int trialCharacterIndexId) {
|
||||
super(dungeonData, dungeonStats);
|
||||
this.trialCharacterIndexId = trialCharacterIndexId;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onProto(DungeonSettleNotifyOuterClass.DungeonSettleNotify.Builder builder) {
|
||||
if (dungeonStats.getDungeonResult() == DungeonEndReason.COMPLETED) { //TODO check if its the first pass(?)
|
||||
builder.setTrialAvatarFirstPassDungeonNotify(TrialAvatarFirstPassDungeonNotify.newBuilder()
|
||||
.setTrialAvatarIndexId(trialCharacterIndexId));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package emu.grasscutter.game.dungeons.enums;
|
||||
|
||||
public enum DungeonEntrySatisfiedConditionType {
|
||||
DUNGEON_ENTRY_CONDITION_NONE,
|
||||
DUNGEON_ENTRY_CONDITION_LEVEL,
|
||||
DUNGEON_ENTRY_CONDITION_QUEST
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package emu.grasscutter.game.dungeons.enums;
|
||||
|
||||
public enum DungeonInvolveType {
|
||||
INVOLVE_NONE,
|
||||
INVOLVE_ONLY_SINGLE,
|
||||
INVOLVE_SINGLE_MULTIPLE
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package emu.grasscutter.game.dungeons.enums;
|
||||
|
||||
import emu.grasscutter.scripts.constants.IntValueEnum;
|
||||
import lombok.Getter;
|
||||
|
||||
public enum DungeonPassConditionType implements IntValueEnum {
|
||||
DUNGEON_COND_NONE(0),
|
||||
DUNGEON_COND_KILL_MONSTER(3),
|
||||
DUNGEON_COND_KILL_GROUP_MONSTER(5),
|
||||
DUNGEON_COND_KILL_TYPE_MONSTER(7),
|
||||
DUNGEON_COND_FINISH_QUEST(9),
|
||||
DUNGEON_COND_KILL_MONSTER_COUNT(11), // TODO handle count
|
||||
DUNGEON_COND_IN_TIME(13), // Missing triggers and tracking
|
||||
DUNGEON_COND_FINISH_CHALLENGE(14),
|
||||
DUNGEON_COND_END_MULTISTAGE_PLAY(15) // Missing
|
||||
;
|
||||
|
||||
@Getter private final int id;
|
||||
DungeonPassConditionType(int id){
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getValue() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package emu.grasscutter.game.dungeons.enums;
|
||||
public enum DungeonPlayType {
|
||||
DUNGEON_PLAY_TYPE_NONE,
|
||||
DUNGEON_PLAY_TYPE_FOGGY_MAZE,
|
||||
DUNGEON_PLAY_TYPE_MIST_TRIAL,
|
||||
DUNGEON_PLAY_TYPE_TRIAL_AVATAR
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package emu.grasscutter.game.dungeons.enums;
|
||||
|
||||
public enum DungeonSubType {
|
||||
DUNGEON_SUB_NONE,
|
||||
DUNGEON_SUB_BOSS,
|
||||
DUNGEON_SUB_TALENT,
|
||||
DUNGEON_SUB_WEAPON,
|
||||
DUNGEON_SUB_RELIQUARY
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package emu.grasscutter.game.dungeons.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
public enum DungeonType {
|
||||
DUNGEON_NONE(false),
|
||||
DUNGEON_PLOT(true),
|
||||
DUNGEON_FIGHT(true),
|
||||
DUNGEON_DAILY_FIGHT(false),
|
||||
DUNGEON_WEEKLY_FIGHT(true),
|
||||
DUNGEON_DISCARDED(false),
|
||||
DUNGEON_TOWER(false),
|
||||
DUNGEON_BOSS(true),
|
||||
DUNGEON_ACTIVITY(false),
|
||||
DUNGEON_EFFIGY(false),
|
||||
DUNGEON_ELEMENT_CHALLENGE(true),
|
||||
DUNGEON_THEATRE_MECHANICUS(false),
|
||||
DUNGEON_FLEUR_FAIR(false),
|
||||
DUNGEON_CHANNELLER_SLAB_LOOP(false),
|
||||
DUNGEON_CHANNELLER_SLAB_ONE_OFF(false),
|
||||
DUNGEON_BLITZ_RUSH(true),
|
||||
DUNGEON_CHESS(false),
|
||||
DUNGEON_SUMO_COMBAT(false),
|
||||
DUNGEON_ROGUELIKE(false),
|
||||
DUNGEON_HACHI(false),
|
||||
DUNGEON_POTION(false),
|
||||
DUNGEON_MINI_ELDRITCH(false),
|
||||
DUNGEON_UGC(false),
|
||||
DUNGEON_GCG(false),
|
||||
DUNGEON_CRYSTAL_LINK(false),
|
||||
DUNGEON_IRODORI_CHESS(false),
|
||||
DUNGEON_ROGUE_DIARY(false),
|
||||
DUNGEON_DREAMLAND(false),
|
||||
DUNGEON_SUMMER_V2(true),
|
||||
DUNGEON_MUQADAS_POTION(false),
|
||||
DUNGEON_INSTABLE_SPRAY(false),
|
||||
DUNGEON_WIND_FIELD(false),
|
||||
DUNGEON_BIGWORLD_MIRROR(false),
|
||||
DUNGEON_FUNGUS_FIGHTER_TRAINING(false),
|
||||
DUNGEON_FUNGUS_FIGHTER_PLOT(false),
|
||||
DUNGEON_EFFIGY_CHALLENGE_V2(false),
|
||||
DUNGEON_CHAR_AMUSEMENT(false);
|
||||
|
||||
@Getter private final boolean countsToBattlepass;
|
||||
|
||||
DungeonType(boolean countsToBattlepass){
|
||||
this.countsToBattlepass = countsToBattlepass;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package emu.grasscutter.game.dungeons.enums;
|
||||
|
||||
public enum DungunEntryType {
|
||||
DUNGEN_ENTRY_TYPE_NONE ,
|
||||
DUNGEN_ENTRY_TYPE_AVATAR_EXP ,
|
||||
DUNGEN_ENTRY_TYPE_WEAPON_PROMOTE,
|
||||
DUNGEN_ENTRY_TYPE_AVATAR_TALENT ,
|
||||
DUNGEN_ENTRY_TYPE_RELIQUARY ,
|
||||
DUNGEN_ENTRY_TYPE_SCOIN ,
|
||||
DUNGEON_ENTRY_TYPE_OBSCURAE ,
|
||||
DUNGEON_ENTRY_TYPE_NORMAL
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package emu.grasscutter.game.dungeons.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
public enum SettleShowType {
|
||||
SETTLE_SHOW_NONE(0),
|
||||
SETTLE_SHOW_TIME_COST(1),
|
||||
SETTLE_SHOW_OPEN_CHEST_COUNT(2),
|
||||
SETTLE_SHOW_KILL_MONSTER_COUNT(3),
|
||||
SETTLE_SHOW_BLACKSCREEN(4);
|
||||
|
||||
@Getter private final int id;
|
||||
|
||||
SettleShowType(int id){
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package emu.grasscutter.game.dungeons.handlers;
|
||||
|
||||
import emu.grasscutter.data.excels.DungeonPassConfigData;
|
||||
|
||||
public abstract class DungeonBaseHandler {
|
||||
|
||||
public abstract boolean execute(DungeonPassConfigData.DungeonPassCondition condition, int... params);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package emu.grasscutter.game.dungeons.pass_condition;
|
||||
|
||||
import emu.grasscutter.data.excels.DungeonPassConfigData;
|
||||
import emu.grasscutter.game.dungeons.enums.DungeonPassConditionType;
|
||||
import emu.grasscutter.game.dungeons.DungeonValue;
|
||||
import emu.grasscutter.game.dungeons.handlers.DungeonBaseHandler;
|
||||
|
||||
@DungeonValue(DungeonPassConditionType.DUNGEON_COND_NONE)
|
||||
public class BaseCondition extends DungeonBaseHandler {
|
||||
|
||||
@Override
|
||||
public boolean execute(DungeonPassConfigData.DungeonPassCondition condition, int... params) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package emu.grasscutter.game.dungeons.pass_condition;
|
||||
|
||||
import emu.grasscutter.data.excels.DungeonPassConfigData;
|
||||
import emu.grasscutter.game.dungeons.enums.DungeonPassConditionType;
|
||||
import emu.grasscutter.game.dungeons.DungeonValue;
|
||||
import emu.grasscutter.game.dungeons.handlers.DungeonBaseHandler;
|
||||
|
||||
@DungeonValue(DungeonPassConditionType.DUNGEON_COND_FINISH_CHALLENGE)
|
||||
public class ConditionFinishChallenge extends DungeonBaseHandler {
|
||||
|
||||
@Override
|
||||
public boolean execute(DungeonPassConfigData.DungeonPassCondition condition, int... params) {
|
||||
return params[0] == condition.getParam()[0] || params[1] == condition.getParam()[0];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package emu.grasscutter.game.dungeons.pass_condition;
|
||||
|
||||
import emu.grasscutter.data.excels.DungeonPassConfigData;
|
||||
import emu.grasscutter.game.dungeons.enums.DungeonPassConditionType;
|
||||
import emu.grasscutter.game.dungeons.DungeonValue;
|
||||
import emu.grasscutter.game.dungeons.handlers.DungeonBaseHandler;
|
||||
|
||||
@DungeonValue(DungeonPassConditionType.DUNGEON_COND_FINISH_QUEST)
|
||||
public class ConditionFinishQuest extends DungeonBaseHandler {
|
||||
|
||||
@Override
|
||||
public boolean execute(DungeonPassConfigData.DungeonPassCondition condition, int... params) {
|
||||
return params[0] == condition.getParam()[0];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package emu.grasscutter.game.dungeons.pass_condition;
|
||||
|
||||
import emu.grasscutter.data.excels.DungeonPassConfigData;
|
||||
import emu.grasscutter.game.dungeons.enums.DungeonPassConditionType;
|
||||
import emu.grasscutter.game.dungeons.DungeonValue;
|
||||
import emu.grasscutter.game.dungeons.handlers.DungeonBaseHandler;
|
||||
|
||||
@DungeonValue(DungeonPassConditionType.DUNGEON_COND_IN_TIME)
|
||||
public class ConditionInTime extends DungeonBaseHandler {
|
||||
|
||||
@Override
|
||||
public boolean execute(DungeonPassConfigData.DungeonPassCondition condition, int... params) {
|
||||
return params[0] <= condition.getParam()[0];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package emu.grasscutter.game.dungeons.pass_condition;
|
||||
|
||||
import emu.grasscutter.data.excels.DungeonPassConfigData;
|
||||
import emu.grasscutter.game.dungeons.enums.DungeonPassConditionType;
|
||||
import emu.grasscutter.game.dungeons.DungeonValue;
|
||||
import emu.grasscutter.game.dungeons.handlers.DungeonBaseHandler;
|
||||
|
||||
@DungeonValue(DungeonPassConditionType.DUNGEON_COND_KILL_GROUP_MONSTER)
|
||||
public class ConditionKillGroupMonster extends DungeonBaseHandler {
|
||||
|
||||
@Override
|
||||
public boolean execute(DungeonPassConfigData.DungeonPassCondition condition, int... params) {
|
||||
return params[0] == condition.getParam()[0];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package emu.grasscutter.game.dungeons.pass_condition;
|
||||
|
||||
import emu.grasscutter.data.excels.DungeonPassConfigData;
|
||||
import emu.grasscutter.game.dungeons.enums.DungeonPassConditionType;
|
||||
import emu.grasscutter.game.dungeons.DungeonValue;
|
||||
import emu.grasscutter.game.dungeons.handlers.DungeonBaseHandler;
|
||||
|
||||
@DungeonValue(DungeonPassConditionType.DUNGEON_COND_KILL_MONSTER)
|
||||
public class ConditionKillMonster extends DungeonBaseHandler {
|
||||
|
||||
@Override
|
||||
public boolean execute(DungeonPassConfigData.DungeonPassCondition condition, int... params) {
|
||||
return params[0] == condition.getParam()[0];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package emu.grasscutter.game.dungeons.pass_condition;
|
||||
|
||||
import emu.grasscutter.data.excels.DungeonPassConfigData;
|
||||
import emu.grasscutter.game.dungeons.enums.DungeonPassConditionType;
|
||||
import emu.grasscutter.game.dungeons.DungeonValue;
|
||||
import emu.grasscutter.game.dungeons.handlers.DungeonBaseHandler;
|
||||
|
||||
@DungeonValue(DungeonPassConditionType.DUNGEON_COND_KILL_MONSTER_COUNT)
|
||||
public class ConditionKillMonsterCount extends DungeonBaseHandler {
|
||||
|
||||
@Override
|
||||
public boolean execute(DungeonPassConfigData.DungeonPassCondition condition, int... params) {
|
||||
return params[0] >= condition.getParam()[0];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package emu.grasscutter.game.dungeons.pass_condition;
|
||||
|
||||
import emu.grasscutter.data.excels.DungeonPassConfigData;
|
||||
import emu.grasscutter.game.dungeons.enums.DungeonPassConditionType;
|
||||
import emu.grasscutter.game.dungeons.DungeonValue;
|
||||
import emu.grasscutter.game.dungeons.handlers.DungeonBaseHandler;
|
||||
|
||||
@DungeonValue(DungeonPassConditionType.DUNGEON_COND_KILL_TYPE_MONSTER)
|
||||
public class ConditionKillTypeMonster extends DungeonBaseHandler {
|
||||
|
||||
@Override
|
||||
public boolean execute(DungeonPassConfigData.DungeonPassCondition condition, int... params) {
|
||||
return params[0] == condition.getParam()[0];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user