Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix mirror tower stages; fix tower time challenge and star scoring #2406

Merged
merged 1 commit into from
Oct 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 59 additions & 10 deletions src/main/java/emu/grasscutter/data/excels/tower/TowerLevelData.java
Original file line number Diff line number Diff line change
@@ -1,33 +1,82 @@
package emu.grasscutter.data.excels.tower;

import emu.grasscutter.data.*;
import java.util.List;
import lombok.*;

@ResourceType(name = "TowerLevelExcelConfigData.json")
@Getter
public class TowerLevelData extends GameResource {

private int levelId;
private int levelIndex;
private int levelGroupId;
private int dungeonId;
private List<TowerLevelCond> conds;

public static class TowerLevelCond {
private TowerCondType towerCondType;
private List<Integer> argumentList;
}

public enum TowerCondType {
TOWER_COND_NONE,
TOWER_COND_CHALLENGE_LEFT_TIME_MORE_THAN,
TOWER_COND_LEFT_HP_GREATER_THAN
}

// Not actual data in TowerLevelExcelConfigData.
// Just packaging condition parameters for convenience.
@Getter
public class TowerCondTimeParams {
private int param1;
private int minimumTimeInSeconds;

public TowerCondTimeParams(int param1, int minimumTimeInSeconds) {
this.param1 = param1;
this.minimumTimeInSeconds = minimumTimeInSeconds;
}
}

@Getter
public class TowerCondHpParams {
private int sceneId;
private int configId;
private int minimumHpPercentage;

public TowerCondHpParams(int sceneId, int configId, int minimumHpPercentage) {
this.sceneId = sceneId;
this.configId = configId;
this.minimumHpPercentage = minimumHpPercentage;
}
}

@Override
public int getId() {
return this.getLevelId();
}

public int getLevelId() {
return levelId;
}

public int getLevelGroupId() {
return levelGroupId;
public TowerCondType getCondType(int star) {
if (star < 0 || conds == null || star >= conds.size()) {
return TowerCondType.TOWER_COND_NONE;
}
var condType = conds.get(star).towerCondType;
return condType == null ? TowerCondType.TOWER_COND_NONE : condType;
}

public int getLevelIndex() {
return levelIndex;
public TowerCondTimeParams getTimeCond(int star) {
if (star < 0 || conds == null || star >= conds.size()) {
return null;
}
var params = conds.get(star).argumentList;
return new TowerCondTimeParams(params.get(0), params.get(1));
}

public int getDungeonId() {
return dungeonId;
public TowerCondHpParams getHpCond(int star) {
if (star < 0 || conds == null || star >= conds.size()) {
return null;
}
var params = conds.get(star).argumentList;
return new TowerCondHpParams(params.get(0), params.get(1), params.get(2));
}
}
22 changes: 19 additions & 3 deletions src/main/java/emu/grasscutter/game/dungeons/DungeonManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public final class DungeonManager {
private boolean ended = false;
private int newestWayPoint = 0;
@Getter private int startSceneTime = 0;
@Setter @Getter private boolean towerDungeon = false;

DungeonTrialTeam trialTeam = null;

Expand Down Expand Up @@ -323,15 +324,30 @@ public void notifyEndDungeon(boolean successfully) {
p.getBattlePassManager().triggerMission(WatcherTriggerType.TRIGGER_FINISH_DUNGEON);
}
});
scene
.getScriptManager()
.callEvent(new ScriptArgs(0, EventType.EVENT_DUNGEON_SETTLE, successfully ? 1 : 0));
var future = scene
.getScriptManager()
.callEvent(new ScriptArgs(0, EventType.EVENT_DUNGEON_SETTLE, successfully ? 1 : 0));
// Note: There is a possible race condition with calling
// EVENT_DUNGEON_SETTLE here asynchronously:
// 1. EVENT_DUNGEON_SETTLE triggers some Lua-side logic,
// which may happen after 2 (below) finishes.
// 2. Some DungeonSettleListener could be comparing some
// Lua variable before its setting in 1 (above) finishes.
// For safety, ensure all events have finished before returning.
try {
future.get();
} catch (Exception e) {
e.printStackTrace();
}
}

public void endDungeon(BaseDungeonResult.DungeonEndReason endReason) {
if (scene.getDungeonSettleListeners() != null) {
scene.getDungeonSettleListeners().forEach(o -> o.onDungeonSettle(this, endReason));
}
if (isTowerDungeon()) {
scene.getPlayers().get(0).getTowerManager().onEnd();
}
ended = true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,9 @@ public boolean handoffDungeon(

if (player.getWorld().transferPlayerToScene(player, data.getSceneId(), data)) {
var scene = player.getScene();
scene.setDungeonManager(new DungeonManager(scene, data));
var dungeonManager = new DungeonManager(scene, data);
dungeonManager.setTowerDungeon(true);
scene.setDungeonManager(dungeonManager);
dungeonSettleListeners.forEach(scene::addDungeonSettleObserver);
}
return true;
Expand Down Expand Up @@ -168,6 +170,7 @@ public void exitDungeon(Player player) {
// clean temp team if it has
player.getTeamManager().cleanTemporaryTeam();
player.getTowerManager().clearEntry();
dungeonManager.setTowerDungeon(false);

// Transfer player back to world
player.getWorld().transferPlayerToScene(player, prevScene, prevPos);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ public class TowerDungeonSettleListener implements DungeonSettleListener {
@Override
public void onDungeonSettle(DungeonManager dungeonManager, DungeonEndReason endReason) {
var scene = dungeonManager.getScene();

var dungeonData = dungeonManager.getDungeonData();
if (scene.getLoadedGroups().stream()
.anyMatch(
Expand All @@ -22,17 +23,18 @@ public void onDungeonSettle(DungeonManager dungeonManager, DungeonEndReason endR
}

var towerManager = scene.getPlayers().get(0).getTowerManager();
var stars = towerManager.getCurLevelStars();

towerManager.notifyCurLevelRecordChangeWhenDone(3);
towerManager.notifyCurLevelRecordChangeWhenDone(stars);
scene.broadcastPacket(
new PacketTowerFloorRecordChangeNotify(
towerManager.getCurrentFloorId(), 3, towerManager.canEnterScheduleFloor()));
towerManager.getCurrentFloorId(), stars, towerManager.canEnterScheduleFloor()));

var challenge = scene.getChallenge();
var dungeonStats =
new DungeonEndStats(
scene.getKilledMonsterCount(), challenge.getFinishedTime(), 0, endReason);
var result = new TowerResult(dungeonData, dungeonStats, towerManager, challenge);
var result = new TowerResult(dungeonData, dungeonStats, towerManager, challenge, stars);

scene.broadcastPacket(new PacketDungeonSettleNotify(result));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,16 @@ public void start() {
return;
}
this.progress = true;
this.startedAt = System.currentTimeMillis();
this.startedAt = getScene().getSceneTimeSeconds();
getScene().broadcastPacket(new PacketDungeonChallengeBeginNotify(this));
challengeTriggers.forEach(t -> t.onBegin(this));

var player = scene.getPlayers().get(0);
var dungeonManager = scene.getDungeonManager();
var towerManager = player.getTowerManager();
if (dungeonManager != null && dungeonManager.isTowerDungeon() && towerManager != null) {
towerManager.onBegin();
}
}

public void done() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,29 @@
package emu.grasscutter.game.dungeons.challenge.trigger;

import emu.grasscutter.game.dungeons.challenge.WorldChallenge;
import emu.grasscutter.server.packet.send.PacketChallengeDataNotify;

public class InTimeTrigger extends ChallengeTrigger {
@Override
public void onBegin(WorldChallenge challenge) {
// Show time remaining UI
var scene = challenge.getScene();
scene.broadcastPacket(
new PacketChallengeDataNotify(
challenge,
2,
// Compensate for time passed so far in scene.
challenge.getTimeLimit() + scene.getSceneTimeSeconds()));
}

@Override
public void onCheckTimeout(WorldChallenge challenge) {
// In Tower challenges, time can run out without
// causing the challenge to fail. (Player just
// gets 0 stars when they ultimately finish.)
var dungeonManager = challenge.getScene().getDungeonManager();
if (dungeonManager != null && dungeonManager.isTowerDungeon()) return;

var current = challenge.getScene().getSceneTimeSeconds();
if (current - challenge.getStartedAt() > challenge.getTimeLimit()) {
challenge.fail();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,20 @@ public class TowerResult extends BaseDungeonResult {
boolean canJump;
boolean hasNextLevel;
int nextFloorId;
int currentStars;

public TowerResult(
DungeonData dungeonData,
DungeonEndStats dungeonStats,
TowerManager towerManager,
WorldChallenge challenge) {
WorldChallenge challenge,
int currentStars) {
super(dungeonData, dungeonStats);
this.challenge = challenge;
this.canJump = towerManager.hasNextFloor();
this.hasNextLevel = towerManager.hasNextLevel();
this.nextFloorId = hasNextLevel ? 0 : towerManager.getNextFloorId();
this.currentStars = currentStars;
}

@Override
Expand All @@ -40,14 +43,16 @@ protected void onProto(DungeonSettleNotifyOuterClass.DungeonSettleNotify.Builder
TowerLevelEndNotify.newBuilder()
.setIsSuccess(challenge.isSuccess())
.setContinueState(continueStatus)
.addFinishedStarCondList(1)
.addFinishedStarCondList(2)
.addFinishedStarCondList(3)
.addRewardItemList(
ItemParamOuterClass.ItemParam.newBuilder().setItemId(201).setCount(1000).build());
ItemParamOuterClass.ItemParam.newBuilder().setItemId(201).setCount(1000));

for (int i = 1; i <= currentStars; i++) {
towerLevelEndNotify.addFinishedStarCondList(i);
}

if (nextFloorId > 0 && canJump) {
towerLevelEndNotify.setNextFloorId(nextFloorId);
}
builder.setTowerLevelEndNotify(towerLevelEndNotify);
builder.setTowerLevelEndNotify(towerLevelEndNotify.build());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ public TowerLevelRecord setLevelStars(int levelId, int stars) {
return this;
}

public int getLevelStars(int levelId) {
return passedLevelMap.get(levelId);
}

public int getStarCount() {
return passedLevelMap.values().stream().mapToInt(Integer::intValue).sum();
}
Expand Down
Loading