236 lines
8.5 KiB
Java

package emu.grasscutter.game.tower;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.excels.tower.TowerLevelData;
import emu.grasscutter.game.dungeons.*;
import emu.grasscutter.game.player.*;
import emu.grasscutter.server.packet.send.*;
import java.util.*;
import lombok.*;
public class TowerManager extends BasePlayerManager {
private static final List<DungeonSettleListener> towerDungeonSettleListener =
List.of(new TowerDungeonSettleListener());
private int currentPossibleStars = 0;
@Getter private boolean inProgress;
@Getter private int currentTimeLimit;
public TowerManager(Player player) {
super(player);
}
public TowerData getTowerData() {
return this.getPlayer().getTowerData();
}
public int getCurrentFloorId() {
return this.getTowerData().currentFloorId;
}
public int getCurrentLevelId() {
return this.getTowerData().currentLevelId + this.getTowerData().currentLevel;
}
/** form 1-3 */
public int getCurrentLevel() {
return this.getTowerData().currentLevel + 1;
}
public void onTick() {
var challenge = player.getScene().getChallenge();
if (challenge == null || !challenge.inProgress()) return;
// Check star conditions and notify client if any failed.
int stars = getCurLevelStars();
while (stars < currentPossibleStars) {
player
.getSession()
.send(new PacketTowerLevelStarCondNotify(getTowerData().currentFloorId, getCurrentLevel(), currentPossibleStars));
currentPossibleStars--;
}
}
public void onBegin() {
var challenge = player.getScene().getChallenge();
inProgress = true;
currentTimeLimit = challenge.getTimeLimit();
}
public void onEnd() {
inProgress = false;
}
public Map<Integer, TowerLevelRecord> getRecordMap() {
Map<Integer, TowerLevelRecord> recordMap = getTowerData().recordMap;
if (recordMap == null || recordMap.size() == 0) {
recordMap = new HashMap<>();
recordMap.put(1001, new TowerLevelRecord(1001));
getTowerData().recordMap = recordMap;
}
return recordMap;
}
public void teamSelect(int floor, List<List<Long>> towerTeams) {
var floorData = GameData.getTowerFloorDataMap().get(floor);
getTowerData().currentFloorId = floorData.getFloorId();
getTowerData().currentLevel = 0;
getTowerData().currentLevelId =
GameData.getTowerLevelDataMap().values().stream()
.filter(
x -> x.getLevelGroupId() == floorData.getLevelGroupId() && x.getLevelIndex() == 1)
.findFirst()
.map(TowerLevelData::getId)
.orElse(0);
if (getTowerData().entryScene == 0) {
getTowerData().entryScene = player.getSceneId();
}
player.getTeamManager().setupTemporaryTeam(towerTeams);
}
public void enterLevel(int enterPointId) {
var levelData = GameData.getTowerLevelDataMap().get(getCurrentLevelId());
var dungeonId = levelData.getDungeonId();
notifyCurLevelRecordChange();
// use team user choose
player.getTeamManager().useTemporaryTeam(0);
player
.getServer()
.getDungeonSystem()
.handoffDungeon(player, dungeonId, towerDungeonSettleListener);
// make sure user can exit dungeon correctly
player.getScene().setPrevScene(getTowerData().entryScene);
player.getScene().setPrevScenePoint(enterPointId);
player
.getSession()
.send(new PacketTowerEnterLevelRsp(getTowerData().currentFloorId, getCurrentLevel()));
// stop using skill
player.getSession().send(new PacketCanUseSkillNotify(false));
// notify the cond of stars
currentPossibleStars = 3;
player
.getSession()
.send(new PacketTowerLevelStarCondNotify(getTowerData().currentFloorId, getCurrentLevel(), currentPossibleStars + 1));
}
public void notifyCurLevelRecordChange() {
player
.getSession()
.send(
new PacketTowerCurLevelRecordChangeNotify(
getTowerData().currentFloorId, getCurrentLevel()));
}
public int getCurLevelStars() {
var scene = player.getScene();
var challenge = scene.getChallenge();
if (challenge == null) {
Grasscutter.getLogger().error("getCurLevelStars: no challenge registered!");
return 0;
}
var levelData = GameData.getTowerLevelDataMap().get(getCurrentLevelId());
// 0-based indexing. "star" = 0 means checking for 1-star conditions.
int star;
for (star = 2; star >= 0; star--) {
var cond = levelData.getCondType(star);
if (cond == TowerLevelData.TowerCondType.TOWER_COND_CHALLENGE_LEFT_TIME_MORE_THAN) {
var params = levelData.getTimeCond(star);
var timeRemaining = challenge.getTimeLimit() - (scene.getSceneTimeSeconds() - challenge.getStartedAt());
if (timeRemaining >= params.getMinimumTimeInSeconds()) {
break;
}
} else if (cond == TowerLevelData.TowerCondType.TOWER_COND_LEFT_HP_GREATER_THAN) {
// TODO: Check monolith health
break;
} else {
Grasscutter.getLogger().error("getCurLevelStars: Tower level {} has no or unknown condition defined for {} stars", getCurrentLevelId(), star + 1);
continue;
}
}
return star + 1;
}
public void notifyCurLevelRecordChangeWhenDone(int stars) {
Map<Integer, TowerLevelRecord> recordMap = this.getRecordMap();
int currentFloorId = getTowerData().currentFloorId;
if (!recordMap.containsKey(currentFloorId)) {
recordMap.put(
currentFloorId,
new TowerLevelRecord(currentFloorId).setLevelStars(getCurrentLevelId(), stars));
} else {
// Only update record if better than previous
var prevRecord = recordMap.get(currentFloorId);
var passedLevelMap = prevRecord.getPassedLevelMap();
int prevStars = 0;
if (passedLevelMap.containsKey(getCurrentLevelId())) {
prevStars = prevRecord.getLevelStars(getCurrentLevelId());
}
if (stars > prevStars) {
recordMap.put(
currentFloorId, prevRecord.setLevelStars(getCurrentLevelId(), stars));
}
}
this.getTowerData().currentLevel++;
if (!this.hasNextLevel()) {
// set up the next floor
var nextFloorId = this.getNextFloorId();
recordMap.computeIfAbsent(nextFloorId, TowerLevelRecord::new);
player.getSession().send(new PacketTowerCurLevelRecordChangeNotify(nextFloorId, 1));
} else {
player
.getSession()
.send(new PacketTowerCurLevelRecordChangeNotify(currentFloorId, getCurrentLevel()));
}
}
public boolean hasNextLevel() {
return getTowerData().currentLevel < 3;
}
public int getNextFloorId() {
return this.player
.getServer()
.getTowerSystem()
.getNextFloorId(this.getTowerData().currentFloorId);
}
public boolean hasNextFloor() {
return this.player
.getServer()
.getTowerSystem()
.getNextFloorId(this.getTowerData().currentFloorId)
> 0;
}
public void clearEntry() {
getTowerData().entryScene = 0;
}
public boolean canEnterScheduleFloor() {
Map<Integer, TowerLevelRecord> recordMap = this.getRecordMap();
if (!recordMap.containsKey(this.player.getServer().getTowerSystem().getLastEntranceFloor())) {
return false;
}
return recordMap
.get(this.player.getServer().getTowerSystem().getLastEntranceFloor())
.getStarCount()
>= 6;
}
public void mirrorTeamSetUp(int teamId) {
// use team user choose
player.getTeamManager().useTemporaryTeam(teamId);
player.sendPacket(new PacketTowerMiddleLevelChangeTeamNotify());
}
}