mirror of
https://github.com/Grasscutters/Grasscutter.git
synced 2025-05-08 13:06:02 +08:00
261 lines
9.4 KiB
Java
261 lines
9.4 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;
|
|
}
|
|
|
|
/** floor number: 1 - 12 **/
|
|
public int getCurrentFloorNumber() {
|
|
return GameData.getTowerFloorDataMap().get(getCurrentFloorId()).getFloorIndex();
|
|
}
|
|
|
|
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 (!inProgress || 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 TowerLevelData getCurrentTowerLevelDataMap() {
|
|
return GameData.getTowerLevelDataMap().get(getCurrentLevelId());
|
|
}
|
|
|
|
public int getCurrentMonsterLevel() {
|
|
// monsterLevel given in TowerLevelExcelConfigData.json is off by one.
|
|
return getCurrentTowerLevelDataMap().getMonsterLevel() + 1;
|
|
}
|
|
|
|
public void enterLevel(int enterPointId) {
|
|
var levelData = getCurrentTowerLevelDataMap();
|
|
|
|
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 = getCurrentTowerLevelDataMap();
|
|
// 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) {
|
|
var params = levelData.getHpCond(star);
|
|
var hpPercent = challenge.getGuardEntityHpPercent();
|
|
if (hpPercent >= params.getMinimumHpPercentage()) {
|
|
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());
|
|
}
|
|
}
|