Implement rogue buffs

This commit is contained in:
Melledy
2023-10-26 21:59:18 -07:00
parent 175fc92460
commit 3dd3555e8f
24 changed files with 4840 additions and 17 deletions

View File

@@ -4,10 +4,7 @@ import java.util.ArrayList;
import java.util.List;
import emu.lunarcore.GameConstants;
import emu.lunarcore.data.excel.RelicMainAffixExcel;
import emu.lunarcore.data.excel.RelicSubAffixExcel;
import emu.lunarcore.data.excel.RogueMapExcel;
import emu.lunarcore.data.excel.RogueManagerExcel;
import emu.lunarcore.data.excel.*;
import emu.lunarcore.util.Utils;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
@@ -15,11 +12,13 @@ import lombok.Getter;
// Game data that is parsed by the server goes here
public class GameDepot {
// Relics
private static Int2ObjectMap<List<RelicMainAffixExcel>> relicMainAffixDepot = new Int2ObjectOpenHashMap<>();
private static Int2ObjectMap<List<RelicSubAffixExcel>> relicSubAffixDepot = new Int2ObjectOpenHashMap<>();
@Getter
private static Int2ObjectMap<int[]> rogueMapGen = new Int2ObjectOpenHashMap<>();
// Rogue
@Getter private static Int2ObjectMap<int[]> rogueMapGen = new Int2ObjectOpenHashMap<>();
@Getter private static List<RogueBuffExcel> rogueBuffsList = new ArrayList<>();
private static Int2ObjectMap<List<RogueMapExcel>> rogueMapDepot = new Int2ObjectOpenHashMap<>();
public static void addRelicMainAffix(RelicMainAffixExcel affix) {

View File

@@ -0,0 +1,29 @@
package emu.lunarcore.data.excel;
import emu.lunarcore.data.GameDepot;
import emu.lunarcore.data.GameResource;
import emu.lunarcore.data.ResourceType;
import lombok.Getter;
@Getter
@ResourceType(name = {"RogueBuff.json"})
public class RogueBuffExcel extends GameResource {
private int MazeBuffID;
private int MazeBuffLevel;
private int RogueBuffType;
private int RogueBuffRarity;
private int AeonID;
@Override
public int getId() {
return MazeBuffID;
}
@Override
public void onLoad() {
if (RogueBuffType >= 120 && RogueBuffType <= 126 && RogueBuffRarity >= 1 && RogueBuffRarity <= 3 && MazeBuffLevel == 1 && AeonID == 0) {
GameDepot.getRogueBuffsList().add(this);
}
}
}

View File

@@ -103,8 +103,11 @@ public class Battle {
if (excel == null) return null;
MazeBuff buff = new MazeBuff(excel, ownerIndex, waveFlag);
return addBuff(buff);
}
public MazeBuff addBuff(MazeBuff buff) {
this.buffs.add(buff);
return buff;
}

View File

@@ -140,6 +140,11 @@ public class BattleService extends BaseGameService {
player.getChallengeInstance().onBattleStart(battle);
}
// Rogue
if (player.getRogueInstance() != null) {
player.getRogueInstance().onBattleStart(battle);
}
// Set battle and send rsp packet
player.setBattle(battle);
player.sendPacket(new PacketSceneCastSkillScRsp(battle, attackedGroupId));
@@ -272,6 +277,11 @@ public class BattleService extends BaseGameService {
player.getChallengeInstance().onBattleFinish(battle, result, stats);
}
// Rogue
if (player.getRogueInstance() != null) {
player.getRogueInstance().onBattleFinish(battle, result, stats);
}
// Done - Clear battle object from player
player.setBattle(null);
return battle;

View File

@@ -12,7 +12,8 @@ import lombok.Getter;
@Getter
public class MazeBuff {
private MazeBuffExcel excel;
private int id;
private int level;
private int ownerIndex;
private int waveFlag;
private IntList targetIndex;
@@ -21,7 +22,12 @@ public class MazeBuff {
private Object2DoubleMap<String> dynamicValues;
public MazeBuff(MazeBuffExcel excel, int ownerIndex, int waveFlag) {
this.excel = excel;
this(excel.getBuffId(), excel.getLv(), ownerIndex, waveFlag);
}
public MazeBuff(int id, int level, int ownerIndex, int waveFlag) {
this.id = id;
this.level = level;
this.ownerIndex = ownerIndex;
this.waveFlag = waveFlag;
}
@@ -44,8 +50,8 @@ public class MazeBuff {
public BattleBuff toProto() {
var proto = BattleBuff.newInstance()
.setId(excel.getBuffId())
.setLevel(excel.getLv())
.setId(this.getId())
.setLevel(this.getLevel())
.setOwnerId(this.getOwnerIndex())
.setWaveFlag(this.getWaveFlag());

View File

@@ -0,0 +1,28 @@
package emu.lunarcore.game.rogue;
import emu.lunarcore.game.battle.MazeBuff;
import emu.lunarcore.proto.RogueBuffOuterClass.RogueBuff;
import lombok.Getter;
@Getter
public class RogueBuffData {
private int buffId;
private int level;
public RogueBuffData(int buffId, int level) {
this.buffId = buffId;
this.level = level;
}
public MazeBuff toMazeBuff() {
return new MazeBuff(buffId, level, 0, 0xffffffff);
}
public RogueBuff toProto() {
var proto = RogueBuff.newInstance()
.setBuffId(this.getBuffId())
.setLevel(this.getLevel());
return proto;
}
}

View File

@@ -0,0 +1,77 @@
package emu.lunarcore.game.rogue;
import java.util.ArrayList;
import java.util.List;
import emu.lunarcore.data.GameDepot;
import emu.lunarcore.data.excel.RogueBuffExcel;
import emu.lunarcore.proto.RogueBuffSelectInfoOuterClass.RogueBuffSelectInfo;
import emu.lunarcore.util.WeightedList;
import lombok.Getter;
@Getter
public class RogueBuffSelectMenu {
private transient RogueInstance rogue;
private int maxBuffs;
private int rerolls;
private int maxRerolls;
private List<RogueBuffData> buffs;
// Cache
private transient WeightedList<RogueBuffExcel> randomBuffs;
@Deprecated // Morphia only!
public RogueBuffSelectMenu() {}
public RogueBuffSelectMenu(RogueInstance rogue) {
this.rogue = rogue;
this.maxBuffs = 3;
this.buffs = new ArrayList<>();
this.generateRandomBuffs();
}
public void generateRandomBuffs() {
if (this.randomBuffs == null) {
this.randomBuffs = new WeightedList<>();
for (RogueBuffExcel excel : GameDepot.getRogueBuffsList()) {
if (rogue.getBuffs().containsKey(excel.getMazeBuffID())) {
continue;
}
this.randomBuffs.add(10.0 / excel.getRogueBuffRarity(), excel);
};
}
this.getBuffs().clear();
while (this.getBuffs().size() < this.getMaxBuffs()) {
RogueBuffExcel excel = this.randomBuffs.next();
this.getBuffs().add(new RogueBuffData(excel.getMazeBuffID(), 1));
}
}
protected void onLoad(RogueInstance rogue) {
this.rogue = rogue;
}
public RogueBuffSelectInfo toProto() {
var proto = RogueBuffSelectInfo.newInstance();
if (this.getMaxRerolls() > 0) {
proto.setCanRoll(true);
proto.setRollBuffTimes(this.getRerolls());
proto.setRollBuffMaxTimes(this.getMaxRerolls());
}
for (var buff : this.getBuffs()) {
proto.addMazeBuffList(buff.toProto());
}
proto.getMutableRollBuffsCost();
return proto;
}
}

View File

@@ -0,0 +1,22 @@
package emu.lunarcore.game.rogue;
import lombok.Getter;
@Getter
public enum RogueBuffType {
Default (100),
Preservation (120),
Remembrance (121),
Nihility (122),
Abundance (123),
Hunt (124),
Destruction (125),
Elation (126),
Propagation (127);
private final int val;
private RogueBuffType(int val) {
this.val = val;
}
}

View File

@@ -1,16 +1,22 @@
package emu.lunarcore.game.rogue;
import java.util.HashSet;
import java.util.Set;
import java.util.TreeMap;
import java.util.*;
import emu.lunarcore.data.GameData;
import emu.lunarcore.data.config.AnchorInfo;
import emu.lunarcore.data.excel.RogueAreaExcel;
import emu.lunarcore.game.battle.Battle;
import emu.lunarcore.game.player.Player;
import emu.lunarcore.proto.BattleEndStatusOuterClass.BattleEndStatus;
import emu.lunarcore.proto.BattleStatisticsOuterClass.BattleStatistics;
import emu.lunarcore.proto.RogueBuffInfoOuterClass.RogueBuffInfo;
import emu.lunarcore.proto.RogueBuffSourceOuterClass.RogueBuffSource;
import emu.lunarcore.proto.RogueCurrentInfoOuterClass.RogueCurrentInfo;
import emu.lunarcore.proto.RogueMapInfoOuterClass.RogueMapInfo;
import emu.lunarcore.proto.RogueRoomStatusOuterClass.RogueRoomStatus;
import emu.lunarcore.proto.RogueStatusOuterClass.RogueStatus;
import emu.lunarcore.server.packet.send.PacketAddRogueBuffScNotify;
import emu.lunarcore.server.packet.send.PacketSyncRogueBuffSelectInfoScNotify;
import emu.lunarcore.server.packet.send.PacketSyncRogueMapRoomScNotify;
import emu.lunarcore.util.Utils;
import lombok.Getter;
@@ -20,17 +26,28 @@ public class RogueInstance {
private transient Player player;
private transient RogueAreaExcel excel;
private int areaId;
private int currentRoomProgress;
private int currentSiteId;
private int startSiteId;
private Set<Integer> baseAvatarIds;
private TreeMap<Integer, RogueRoomData> rooms;
private Set<Integer> baseAvatarIds;
private Map<Integer, RogueBuffData> buffs;
private RogueBuffSelectMenu buffSelect;
private int pendingBuffSelects;
@Deprecated // Morphia only!
public RogueInstance() {}
public RogueInstance(Player player, RogueAreaExcel excel) {
this.player = player;
this.excel = excel;
this.areaId = excel.getRogueAreaID();
this.currentRoomProgress = 0;
this.baseAvatarIds = new HashSet<>();
this.buffs = new HashMap<>();
this.initRooms();
}
@@ -62,6 +79,43 @@ public class RogueInstance {
return this.getRoomBySiteId(this.getCurrentSiteId());
}
public synchronized void createBuffSelect(int amount) {
this.pendingBuffSelects += amount;
RogueBuffSelectMenu buffSelect = this.updateBuffSelect();
if (buffSelect != null) {
getPlayer().sendPacket(new PacketSyncRogueBuffSelectInfoScNotify(buffSelect));
}
}
public synchronized RogueBuffSelectMenu updateBuffSelect() {
if (this.pendingBuffSelects > 0 && this.getBuffSelect() == null) {
this.buffSelect = new RogueBuffSelectMenu(this);
this.pendingBuffSelects--;
return this.buffSelect;
}
return null;
}
public synchronized RogueBuffData selectBuff(int buffId) {
if (this.getBuffSelect() == null) return null;
RogueBuffData buff = this.getBuffSelect().getBuffs()
.stream()
.filter(b -> b.getBuffId() == buffId)
.findFirst()
.orElse(null);
if (buff == null) return null;
this.buffSelect = null;
this.getBuffs().put(buff.getBuffId(), buff);
getPlayer().sendPacket(new PacketAddRogueBuffScNotify(buff, RogueBuffSource.ROGUE_BUFF_SOURCE_TYPE_SELECT));
return buff;
}
public synchronized RogueRoomData enterRoom(int siteId) {
// Set status on previous room
RogueRoomData prevRoom = getCurrentRoom();
@@ -108,12 +162,37 @@ public class RogueInstance {
return nextRoom;
}
public synchronized void onBattleStart(Battle battle) {
for (var buff : this.getBuffs().values()) {
battle.addBuff(buff.toMazeBuff());
}
}
public synchronized void onBattleFinish(Battle battle, BattleEndStatus result, BattleStatistics stats) {
if (result == BattleEndStatus.BATTLE_END_WIN) {
int amount = battle.getNpcMonsters().size();
this.createBuffSelect(amount);
}
}
// Database
public void onLoad(Player player) {
this.player = player;
this.excel = GameData.getRogueAreaExcelMap().get(areaId);
if (this.getBuffSelect() != null) {
this.getBuffSelect().onLoad(this);
}
}
// Serialization
public RogueCurrentInfo toProto() {
var proto = RogueCurrentInfo.newInstance()
.setStatus(this.getStatus())
.setRoomMap(this.toMapProto());
.setRoomMap(this.toMapProto())
.setRogueBuffInfo(this.toBuffProto());
return proto;
}
@@ -134,4 +213,20 @@ public class RogueInstance {
return proto;
}
public RogueBuffInfo toBuffProto() {
var proto = RogueBuffInfo.newInstance();
if (this.getBuffSelect() != null) {
proto.setBuffSelectInfo(this.getBuffSelect().toProto());
} else {
proto.getMutableBuffSelectInfo();
}
for (var buff : this.getBuffs().values()) {
proto.addMazeBuffList(buff.toProto());
}
return proto;
}
}

View File

@@ -0,0 +1,30 @@
package emu.lunarcore.server.packet.recv;
import emu.lunarcore.game.rogue.RogueBuffData;
import emu.lunarcore.game.rogue.RogueBuffSelectMenu;
import emu.lunarcore.proto.SelectRogueBuffCsReqOuterClass.SelectRogueBuffCsReq;
import emu.lunarcore.server.game.GameSession;
import emu.lunarcore.server.packet.CmdId;
import emu.lunarcore.server.packet.Opcodes;
import emu.lunarcore.server.packet.PacketHandler;
import emu.lunarcore.server.packet.send.PacketSelectRogueBuffScRsp;
@Opcodes(CmdId.SelectRogueBuffCsReq)
public class HandlerSelectRogueBuffCsReq extends PacketHandler {
@Override
public void handle(GameSession session, byte[] header, byte[] data) throws Exception {
var req = SelectRogueBuffCsReq.parseFrom(data);
if (session.getPlayer().getRogueInstance() != null) {
RogueBuffData buff = session.getPlayer().getRogueInstance().selectBuff(req.getMazeBuffId());
if (buff != null) {
RogueBuffSelectMenu buffSelect = session.getPlayer().getRogueInstance().updateBuffSelect();
session.send(new PacketSelectRogueBuffScRsp(buff, buffSelect));
}
}
session.send(CmdId.SelectRogueBuffScRsp);
}
}

View File

@@ -0,0 +1,20 @@
package emu.lunarcore.server.packet.send;
import emu.lunarcore.game.rogue.RogueBuffData;
import emu.lunarcore.proto.AddRogueBuffScNotifyOuterClass.AddRogueBuffScNotify;
import emu.lunarcore.proto.RogueBuffSourceOuterClass.RogueBuffSource;
import emu.lunarcore.server.packet.BasePacket;
import emu.lunarcore.server.packet.CmdId;
public class PacketAddRogueBuffScNotify extends BasePacket {
public PacketAddRogueBuffScNotify(RogueBuffData buff, RogueBuffSource source) {
super(CmdId.AddRogueBuffScNotify);
var data = AddRogueBuffScNotify.newInstance()
.setMazeBuffInfo(buff.toProto())
.setSource(source);
this.setData(data);
}
}

View File

@@ -0,0 +1,26 @@
package emu.lunarcore.server.packet.send;
import emu.lunarcore.game.rogue.RogueBuffData;
import emu.lunarcore.game.rogue.RogueBuffSelectMenu;
import emu.lunarcore.proto.SelectRogueBuffScRspOuterClass.SelectRogueBuffScRsp;
import emu.lunarcore.server.packet.BasePacket;
import emu.lunarcore.server.packet.CmdId;
public class PacketSelectRogueBuffScRsp extends BasePacket {
public PacketSelectRogueBuffScRsp(RogueBuffData buff, RogueBuffSelectMenu buffSelect) {
super(CmdId.SelectRogueBuffScRsp);
var data = SelectRogueBuffScRsp.newInstance()
.setMazeBuffId(buff.getBuffId())
.setMazeBuffLevel(buff.getLevel());
if (buffSelect != null) {
data.setBuffSelectInfo(buffSelect.toProto());
} else {
data.getMutableBuffSelectInfo();
}
this.setData(data);
}
}

View File

@@ -0,0 +1,18 @@
package emu.lunarcore.server.packet.send;
import emu.lunarcore.game.rogue.RogueBuffSelectMenu;
import emu.lunarcore.proto.SyncRogueBuffSelectInfoScNotifyOuterClass.SyncRogueBuffSelectInfoScNotify;
import emu.lunarcore.server.packet.BasePacket;
import emu.lunarcore.server.packet.CmdId;
public class PacketSyncRogueBuffSelectInfoScNotify extends BasePacket {
public PacketSyncRogueBuffSelectInfoScNotify(RogueBuffSelectMenu selectMenu) {
super(CmdId.SyncRogueBuffSelectInfoScNotify);
var data = SyncRogueBuffSelectInfoScNotify.newInstance()
.setBuffSelectInfo(selectMenu.toProto());
this.setData(data);
}
}